@adia-ai/llm 0.5.21 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/adapters/anthropic.d.ts +82 -0
- package/adapters/anthropic.d.ts.map +1 -0
- package/adapters/anthropic.js +94 -96
- package/adapters/anthropic.js.map +1 -0
- package/adapters/gemini.d.ts +32 -0
- package/adapters/gemini.d.ts.map +1 -0
- package/adapters/gemini.js +76 -89
- package/adapters/gemini.js.map +1 -0
- package/adapters/index.d.ts +94 -0
- package/adapters/index.d.ts.map +1 -0
- package/adapters/index.js +91 -103
- package/adapters/index.js.map +1 -0
- package/adapters/openai.d.ts +32 -0
- package/adapters/openai.d.ts.map +1 -0
- package/adapters/openai.js +76 -75
- package/adapters/openai.js.map +1 -0
- package/adapters/sse.d.ts +11 -0
- package/adapters/sse.d.ts.map +1 -0
- package/adapters/sse.js +46 -39
- package/adapters/sse.js.map +1 -0
- package/index.d.ts +14 -0
- package/index.d.ts.map +1 -0
- package/index.js +11 -20
- package/index.js.map +1 -0
- package/llm-bridge.d.ts +102 -0
- package/llm-bridge.d.ts.map +1 -0
- package/llm-bridge.js +204 -219
- package/llm-bridge.js.map +1 -0
- package/llm-stub.d.ts +38 -0
- package/llm-stub.d.ts.map +1 -0
- package/llm-stub.js +43 -57
- package/llm-stub.js.map +1 -0
- package/models.d.ts +25 -0
- package/models.d.ts.map +1 -0
- package/models.js +20 -21
- package/models.js.map +1 -0
- package/package.json +22 -3
package/index.js
CHANGED
|
@@ -1,23 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @adia-ai/llm — provider-agnostic LLM client.
|
|
2
|
+
* @adia-ai/llm — provider-agnostic LLM client for AdiaUI.
|
|
3
3
|
*
|
|
4
|
-
* Re-exports the
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* import { MODELS, DEFAULT_MODEL } from '@adia-ai/llm/models';
|
|
10
|
-
* import { createAdapter } from '@adia-ai/llm/bridge';
|
|
11
|
-
* import { StubLLMAdapter } from '@adia-ai/llm/stub';
|
|
4
|
+
* Re-exports the public API surface:
|
|
5
|
+
* - chat, streamChat, createClient — standalone functions + factory
|
|
6
|
+
* - MODELS, DEFAULT_MODEL — model catalog
|
|
7
|
+
* - StubLLMAdapter — deterministic test stub
|
|
8
|
+
* - createAdapter — AdiaUI pipeline bridge
|
|
12
9
|
*/
|
|
13
|
-
|
|
14
|
-
export {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} from './adapters/index.js';
|
|
19
|
-
|
|
20
|
-
export {
|
|
21
|
-
MODELS,
|
|
22
|
-
DEFAULT_MODEL,
|
|
23
|
-
} from './models.js';
|
|
10
|
+
export { chat, streamChat, createClient } from './adapters/index.js';
|
|
11
|
+
export { MODELS, DEFAULT_MODEL } from './models.js';
|
|
12
|
+
export { StubLLMAdapter } from './llm-stub.js';
|
|
13
|
+
export { createAdapter } from './llm-bridge.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
package/llm-bridge.d.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM Bridge — Wraps AdiaUI's llm module into the AdiaUI createAdapter() API.
|
|
3
|
+
*
|
|
4
|
+
* This is the single integration point between the AdiaUI pipeline and the
|
|
5
|
+
* LLM module. It handles:
|
|
6
|
+
* - Env var reading (VITE_* in browser, process.env in Node)
|
|
7
|
+
* - CORS proxy routing in browser (Vite dev server at /api/llm/*)
|
|
8
|
+
* - API translation (AdiaUI's simple { messages, systemPrompt } → llm module's interface)
|
|
9
|
+
*
|
|
10
|
+
* Consumers call createAdapter() and get an object with .complete() and .stream()
|
|
11
|
+
* matching the AdiaUI pipeline interface.
|
|
12
|
+
*/
|
|
13
|
+
import { StubLLMAdapter } from './llm-stub.js';
|
|
14
|
+
import type { LLMClient } from './adapters/index.js';
|
|
15
|
+
/**
|
|
16
|
+
* Create an LLM adapter for the AdiaUI pipeline.
|
|
17
|
+
*
|
|
18
|
+
* Auto-detects provider from env vars. Returns an object with .complete()
|
|
19
|
+
* and .stream() that match the AdiaUI interface (simple messages + systemPrompt).
|
|
20
|
+
*
|
|
21
|
+
* @param opts
|
|
22
|
+
* @param opts.provider — 'anthropic' | 'openai' | 'google' | 'stub'
|
|
23
|
+
* @param opts.apiKey — explicit API key (overrides env)
|
|
24
|
+
* @param opts.model — model override
|
|
25
|
+
* @returns {StubLLMAdapter | AdiaUILLMBridge}
|
|
26
|
+
*/
|
|
27
|
+
export declare function createAdapter(opts?: {
|
|
28
|
+
provider?: string;
|
|
29
|
+
apiKey?: string;
|
|
30
|
+
model?: string;
|
|
31
|
+
}): Promise<StubLLMAdapter | AdiaUILLMBridge>;
|
|
32
|
+
/**
|
|
33
|
+
* Wraps the AdiaUI llm client to match the AdiaUI pipeline's simpler interface.
|
|
34
|
+
*
|
|
35
|
+
* AdiaUI calls: adapter.complete({ messages, systemPrompt })
|
|
36
|
+
* LLM module expects: client.chat({ model, messages, system, ... })
|
|
37
|
+
*/
|
|
38
|
+
declare class AdiaUILLMBridge {
|
|
39
|
+
#private;
|
|
40
|
+
constructor(client: LLMClient, model: string, provider: string);
|
|
41
|
+
/**
|
|
42
|
+
* Non-streaming completion. Matches AdiaUI interface.
|
|
43
|
+
*
|
|
44
|
+
* 32k max_tokens: A2UI JSON for moderately complex UIs (kanban, dashboard,
|
|
45
|
+
* pricing table) routinely exceeds 8k. Truncation produced silent fallbacks
|
|
46
|
+
* that the validator rubber-stamped at ~89/100 — see diagnosis report
|
|
47
|
+
* 2026-04-19. Modern Claude/GPT/Gemini all support ≥32k output cleanly.
|
|
48
|
+
*
|
|
49
|
+
* @param opts
|
|
50
|
+
* @param opts.messages
|
|
51
|
+
* @param opts.systemPrompt
|
|
52
|
+
*/
|
|
53
|
+
complete({ messages, systemPrompt }: {
|
|
54
|
+
messages: Array<{
|
|
55
|
+
role: string;
|
|
56
|
+
content: string;
|
|
57
|
+
}>;
|
|
58
|
+
systemPrompt?: string;
|
|
59
|
+
}): Promise<{
|
|
60
|
+
content: string;
|
|
61
|
+
stopReason: string;
|
|
62
|
+
usage: {
|
|
63
|
+
inputTokens: number;
|
|
64
|
+
outputTokens: number;
|
|
65
|
+
cacheCreationTokens: number;
|
|
66
|
+
cacheReadTokens: number;
|
|
67
|
+
};
|
|
68
|
+
}>;
|
|
69
|
+
/**
|
|
70
|
+
* Streaming completion. Matches AdiaUI interface.
|
|
71
|
+
*
|
|
72
|
+
* @param opts
|
|
73
|
+
* @param opts.messages
|
|
74
|
+
* @param opts.systemPrompt
|
|
75
|
+
* @yields {{ type: 'text', content: string } | { type: 'done', stopReason: string, usage: { inputTokens: number, outputTokens: number, cacheCreationTokens: number, cacheReadTokens: number } }}
|
|
76
|
+
*/
|
|
77
|
+
stream({ messages, systemPrompt }: {
|
|
78
|
+
messages: Array<{
|
|
79
|
+
role: string;
|
|
80
|
+
content: string;
|
|
81
|
+
}>;
|
|
82
|
+
systemPrompt?: string;
|
|
83
|
+
}): AsyncGenerator<{
|
|
84
|
+
type: 'text';
|
|
85
|
+
content: string;
|
|
86
|
+
} | {
|
|
87
|
+
type: 'done';
|
|
88
|
+
stopReason: string;
|
|
89
|
+
usage: {
|
|
90
|
+
inputTokens: number;
|
|
91
|
+
outputTokens: number;
|
|
92
|
+
cacheCreationTokens: number;
|
|
93
|
+
cacheReadTokens: number;
|
|
94
|
+
};
|
|
95
|
+
}>;
|
|
96
|
+
/** Expose the underlying client for advanced use. */
|
|
97
|
+
get adapter(): LLMClient;
|
|
98
|
+
/** Expose provider name for detection. */
|
|
99
|
+
get provider(): string;
|
|
100
|
+
}
|
|
101
|
+
export {};
|
|
102
|
+
//# sourceMappingURL=llm-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-bridge.d.ts","sourceRoot":"","sources":["src/llm-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAY,SAAS,EAAE,MAAM,qBAAqB,CAAC;AA2F/D;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,cAAc,GAAG,eAAe,CAAC,CA+DhJ;AAkBD;;;;;GAKG;AACH,cAAM,eAAe;;gBAKP,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAM9D;;;;;;;;;;;OAWG;IACG,QAAQ,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE;QAAE,QAAQ,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,YAAY,EAAE,MAAM,CAAC;YAAC,mBAAmB,EAAE,MAAM,CAAC;YAAC,eAAe,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAsBvR;;;;;;;OAOG;IACI,MAAM,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE;QAAE,QAAQ,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,cAAc,CACpI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GACjC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,YAAY,EAAE,MAAM,CAAC;YAAC,mBAAmB,EAAE,MAAM,CAAC;YAAC,eAAe,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CACnJ;IA8BD,qDAAqD;IACrD,IAAI,OAAO,cAA2B;IAEtC,0CAA0C;IAC1C,IAAI,QAAQ,WAA6B;CAC1C"}
|
package/llm-bridge.js
CHANGED
|
@@ -10,51 +10,48 @@
|
|
|
10
10
|
* Consumers call createAdapter() and get an object with .complete() and .stream()
|
|
11
11
|
* matching the AdiaUI pipeline interface.
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
13
|
import { StubLLMAdapter } from './llm-stub.js';
|
|
15
|
-
|
|
16
14
|
// Lazy-loaded — ../llm/index.js uses Vite aliases that don't resolve in Node
|
|
17
15
|
let _createClient = null;
|
|
18
16
|
async function getCreateClient() {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
if (!_createClient) {
|
|
18
|
+
try {
|
|
19
|
+
const mod = await import('./adapters/index.js');
|
|
20
|
+
_createClient = mod.createClient;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
_createClient = null;
|
|
24
|
+
}
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
return _createClient;
|
|
26
|
+
return _createClient;
|
|
28
27
|
}
|
|
29
|
-
|
|
30
28
|
// ── Environment ──────────────────────────────────────────────────────────
|
|
31
|
-
|
|
32
29
|
function getEnv(key) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
try {
|
|
31
|
+
const env = import.meta.env;
|
|
32
|
+
if (env) {
|
|
33
|
+
const val = env[`VITE_${key}`] || env[key];
|
|
34
|
+
if (val)
|
|
35
|
+
return val;
|
|
36
|
+
}
|
|
38
37
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
catch { }
|
|
39
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
40
|
+
return process.env[key] || '';
|
|
41
|
+
}
|
|
42
|
+
return '';
|
|
44
43
|
}
|
|
45
|
-
|
|
46
44
|
const IS_BROWSER = typeof window !== 'undefined';
|
|
47
|
-
|
|
48
45
|
function resolveBaseUrl(provider) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
if (!IS_BROWSER)
|
|
47
|
+
return undefined; // Let the module use its defaults
|
|
48
|
+
const proxyMap = {
|
|
49
|
+
anthropic: '/api/llm/anthropic/v1/messages',
|
|
50
|
+
openai: '/api/llm/openai/v1/chat/completions',
|
|
51
|
+
google: '/api/llm/google',
|
|
52
|
+
};
|
|
53
|
+
return proxyMap[provider];
|
|
56
54
|
}
|
|
57
|
-
|
|
58
55
|
/**
|
|
59
56
|
* §181 (v0.5.5) — Is the browser running on a production host (not a
|
|
60
57
|
* local Vite dev server)? Used by createAdapter() to decide whether
|
|
@@ -62,17 +59,23 @@ function resolveBaseUrl(provider) {
|
|
|
62
59
|
* even when no API key is visible to the browser.
|
|
63
60
|
*/
|
|
64
61
|
function isProductionHost() {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
62
|
+
if (!IS_BROWSER)
|
|
63
|
+
return false;
|
|
64
|
+
const host = window.location?.hostname || '';
|
|
65
|
+
if (!host)
|
|
66
|
+
return false;
|
|
67
|
+
if (host === 'localhost' || host === '127.0.0.1' || host === '0.0.0.0')
|
|
68
|
+
return false;
|
|
69
|
+
if (host.endsWith('.local'))
|
|
70
|
+
return false;
|
|
71
|
+
if (/^10\./.test(host))
|
|
72
|
+
return false;
|
|
73
|
+
if (/^192\.168\./.test(host))
|
|
74
|
+
return false;
|
|
75
|
+
if (/^172\.(1[6-9]|2\d|3[01])\./.test(host))
|
|
76
|
+
return false;
|
|
77
|
+
return true;
|
|
74
78
|
}
|
|
75
|
-
|
|
76
79
|
/**
|
|
77
80
|
* §181 (v0.5.5) — Build a bridge for the production-browser case
|
|
78
81
|
* where there's no client-side API key but the page can reach a
|
|
@@ -84,117 +87,102 @@ function isProductionHost() {
|
|
|
84
87
|
* reaches the upstream provider — the proxy discards it.
|
|
85
88
|
*/
|
|
86
89
|
async function createBrowserProxyBridge(provider, modelOpt) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
90
|
+
const createClient = await getCreateClient();
|
|
91
|
+
if (!createClient) {
|
|
92
|
+
console.warn('LLM Bridge: LLM module not available. Using stub adapter.');
|
|
93
|
+
return new StubLLMAdapter();
|
|
94
|
+
}
|
|
95
|
+
const model = modelOpt || DEFAULT_MODELS[provider] || 'claude-haiku-4-5-20251001';
|
|
96
|
+
const proxyUrl = resolveBaseUrl(provider);
|
|
97
|
+
const client = createClient({
|
|
98
|
+
provider,
|
|
99
|
+
apiKey: 'browser-uses-server-side-proxy-key', // sentinel; proxy ignores it
|
|
100
|
+
model,
|
|
101
|
+
...(proxyUrl ? { proxyUrl } : {}),
|
|
102
|
+
});
|
|
103
|
+
return new AdiaUILLMBridge(client, model, provider);
|
|
101
104
|
}
|
|
102
|
-
|
|
103
105
|
// ── Factory ──────────────────────────────────────────────────────────────
|
|
104
|
-
|
|
105
106
|
/**
|
|
106
107
|
* Create an LLM adapter for the AdiaUI pipeline.
|
|
107
108
|
*
|
|
108
109
|
* Auto-detects provider from env vars. Returns an object with .complete()
|
|
109
110
|
* and .stream() that match the AdiaUI interface (simple messages + systemPrompt).
|
|
110
111
|
*
|
|
111
|
-
* @param
|
|
112
|
-
* @param
|
|
113
|
-
* @param
|
|
114
|
-
* @param
|
|
112
|
+
* @param opts
|
|
113
|
+
* @param opts.provider — 'anthropic' | 'openai' | 'google' | 'stub'
|
|
114
|
+
* @param opts.apiKey — explicit API key (overrides env)
|
|
115
|
+
* @param opts.model — model override
|
|
115
116
|
* @returns {StubLLMAdapter | AdiaUILLMBridge}
|
|
116
117
|
*/
|
|
117
118
|
export async function createAdapter(opts = {}) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
119
|
+
const provider = opts.provider || getEnv('LLM_PROVIDER') || detectProvider();
|
|
120
|
+
const model = opts.model || getEnv('LLM_MODEL') || undefined;
|
|
121
|
+
if (provider === 'stub') {
|
|
122
|
+
// §181 (v0.5.5) — browser on a production host: even though
|
|
123
|
+
// detectProvider() returned 'stub' (no env vars in the browser),
|
|
124
|
+
// the page can still make real LLM calls via the same-origin
|
|
125
|
+
// proxy at /api/llm/<provider>/<rest>. The proxy strips the
|
|
126
|
+
// incoming x-api-key / Authorization header and re-injects its
|
|
127
|
+
// own server-side key. The sentinel below is a non-empty
|
|
128
|
+
// placeholder so the bridge passes the !apiKey gate; it never
|
|
129
|
+
// reaches the upstream provider.
|
|
130
|
+
if (IS_BROWSER && isProductionHost()) {
|
|
131
|
+
return createBrowserProxyBridge('anthropic', opts.model);
|
|
132
|
+
}
|
|
133
|
+
return new StubLLMAdapter();
|
|
134
|
+
}
|
|
135
|
+
// Resolve API key for the detected provider
|
|
136
|
+
const apiKey = opts.apiKey || getEnv(`${provider.toUpperCase()}_API_KEY`) || getEnv('ANTHROPIC_API_KEY') || getEnv('OPENAI_API_KEY') || getEnv('GOOGLE_API_KEY');
|
|
137
|
+
// Browser-only safety reminder: when running through the dev-server's
|
|
138
|
+
// passthrough proxy, the API key is sent verbatim in `x-api-key` /
|
|
139
|
+
// `Authorization` headers from the browser. Anyone with DevTools open
|
|
140
|
+
// can read it from the Network panel — fine for local dev, **never**
|
|
141
|
+
// deploy this shape. We log once per session (deduplicated via a
|
|
142
|
+
// window-scoped flag) when a key is present and we're in the browser.
|
|
143
|
+
// Journal entry 2026-05-11 §22 documents the root cause.
|
|
144
|
+
if (IS_BROWSER && apiKey && typeof window !== 'undefined' && !window.__adia_llm_key_warning_shown) {
|
|
145
|
+
window.__adia_llm_key_warning_shown = true;
|
|
146
|
+
const masked = apiKey.length > 12 ? `${apiKey.slice(0, 8)}…${apiKey.slice(-4)}` : '••••';
|
|
147
|
+
console.warn(`%c[@adia-ai/llm] %cAPI key in browser:%c ${provider} key (${masked}) will be sent in request headers via the Vite passthrough proxy. ` +
|
|
148
|
+
`Anyone with DevTools access on this dev server can read it. Local-dev only — never deploy this shape. ` +
|
|
149
|
+
`Rotate at the provider console if this transcript leaves your machine.`, 'color: #a78bfa; font-weight: bold;', 'color: #f59e0b; font-weight: bold;', 'color: inherit;');
|
|
132
150
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
`Anyone with DevTools access on this dev server can read it. Local-dev only — never deploy this shape. ` +
|
|
152
|
-
`Rotate at the provider console if this transcript leaves your machine.`,
|
|
153
|
-
'color: #a78bfa; font-weight: bold;',
|
|
154
|
-
'color: #f59e0b; font-weight: bold;',
|
|
155
|
-
'color: inherit;'
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// No key found → fall back to stub
|
|
160
|
-
if (!apiKey) {
|
|
161
|
-
console.warn('LLM Bridge: No API keys found. Using stub adapter.');
|
|
162
|
-
return new StubLLMAdapter();
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const createClient = await getCreateClient();
|
|
166
|
-
if (!createClient) {
|
|
167
|
-
console.warn('LLM Bridge: LLM module not available. Using stub adapter.');
|
|
168
|
-
return new StubLLMAdapter();
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const proxyUrl = resolveBaseUrl(provider);
|
|
172
|
-
const client = createClient({
|
|
173
|
-
provider,
|
|
174
|
-
apiKey,
|
|
175
|
-
model: model || DEFAULT_MODELS[provider] || 'claude-sonnet-4-20250514',
|
|
176
|
-
...(proxyUrl ? { proxyUrl } : {}),
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
return new AdiaUILLMBridge(client, model || DEFAULT_MODELS[provider] || 'claude-sonnet-4-20250514', provider);
|
|
151
|
+
// No key found → fall back to stub
|
|
152
|
+
if (!apiKey) {
|
|
153
|
+
console.warn('LLM Bridge: No API keys found. Using stub adapter.');
|
|
154
|
+
return new StubLLMAdapter();
|
|
155
|
+
}
|
|
156
|
+
const createClient = await getCreateClient();
|
|
157
|
+
if (!createClient) {
|
|
158
|
+
console.warn('LLM Bridge: LLM module not available. Using stub adapter.');
|
|
159
|
+
return new StubLLMAdapter();
|
|
160
|
+
}
|
|
161
|
+
const proxyUrl = resolveBaseUrl(provider);
|
|
162
|
+
const client = createClient({
|
|
163
|
+
provider,
|
|
164
|
+
apiKey,
|
|
165
|
+
model: model || DEFAULT_MODELS[provider] || 'claude-sonnet-4-20250514',
|
|
166
|
+
...(proxyUrl ? { proxyUrl } : {}),
|
|
167
|
+
});
|
|
168
|
+
return new AdiaUILLMBridge(client, model || DEFAULT_MODELS[provider] || 'claude-sonnet-4-20250514', provider);
|
|
180
169
|
}
|
|
181
|
-
|
|
182
170
|
function detectProvider() {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
171
|
+
if (getEnv('ANTHROPIC_API_KEY'))
|
|
172
|
+
return 'anthropic';
|
|
173
|
+
if (getEnv('OPENAI_API_KEY'))
|
|
174
|
+
return 'openai';
|
|
175
|
+
if (getEnv('GOOGLE_API_KEY'))
|
|
176
|
+
return 'google';
|
|
177
|
+
return 'stub';
|
|
187
178
|
}
|
|
188
|
-
|
|
189
179
|
// ── Bridge class ─────────────────────────────────────────────────────────
|
|
190
|
-
|
|
191
180
|
/** Default models per provider */
|
|
192
181
|
const DEFAULT_MODELS = {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
182
|
+
anthropic: 'claude-sonnet-4-20250514',
|
|
183
|
+
openai: 'gpt-4o',
|
|
184
|
+
google: 'gemini-2.0-flash',
|
|
196
185
|
};
|
|
197
|
-
|
|
198
186
|
/**
|
|
199
187
|
* Wraps the AdiaUI llm client to match the AdiaUI pipeline's simpler interface.
|
|
200
188
|
*
|
|
@@ -202,91 +190,88 @@ const DEFAULT_MODELS = {
|
|
|
202
190
|
* LLM module expects: client.chat({ model, messages, system, ... })
|
|
203
191
|
*/
|
|
204
192
|
class AdiaUILLMBridge {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
outputTokens: response.usage?.output ?? 0,
|
|
245
|
-
cacheCreationTokens: response.usage?.cacheCreation ?? 0,
|
|
246
|
-
cacheReadTokens: response.usage?.cacheRead ?? 0,
|
|
247
|
-
},
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Streaming completion. Matches AdiaUI interface.
|
|
253
|
-
*
|
|
254
|
-
* @param {{ messages: { role: string, content: string }[], systemPrompt?: string }} opts
|
|
255
|
-
* @yields {{ type: 'text', content: string } | { type: 'done', stopReason: string, usage: { inputTokens: number, outputTokens: number, cacheCreationTokens: number, cacheReadTokens: number } }}
|
|
256
|
-
*/
|
|
257
|
-
async *stream({ messages, systemPrompt }) {
|
|
258
|
-
for await (const chunk of this.#client.stream({
|
|
259
|
-
model: this.#model,
|
|
260
|
-
messages,
|
|
261
|
-
system: systemPrompt,
|
|
262
|
-
maxTokens: 32768,
|
|
263
|
-
cache: this.#provider === 'anthropic',
|
|
264
|
-
})) {
|
|
265
|
-
if (chunk.type === 'text') {
|
|
266
|
-
yield { type: 'text', content: chunk.text };
|
|
267
|
-
} else if (chunk.type === 'done') {
|
|
268
|
-
// Surface the terminal stopReason + cache telemetry so the consumer
|
|
269
|
-
// can detect max_tokens truncation and the dialog recorder can log
|
|
270
|
-
// cache hit-rate per turn.
|
|
271
|
-
yield {
|
|
272
|
-
type: 'done',
|
|
273
|
-
stopReason: chunk.stopReason ?? 'end',
|
|
274
|
-
usage: {
|
|
275
|
-
inputTokens: chunk.usage?.input ?? 0,
|
|
276
|
-
outputTokens: chunk.usage?.output ?? 0,
|
|
277
|
-
cacheCreationTokens: chunk.usage?.cacheCreation ?? 0,
|
|
278
|
-
cacheReadTokens: chunk.usage?.cacheRead ?? 0,
|
|
279
|
-
},
|
|
193
|
+
#client;
|
|
194
|
+
#model;
|
|
195
|
+
#provider;
|
|
196
|
+
constructor(client, model, provider) {
|
|
197
|
+
this.#client = client;
|
|
198
|
+
this.#model = model;
|
|
199
|
+
this.#provider = provider;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Non-streaming completion. Matches AdiaUI interface.
|
|
203
|
+
*
|
|
204
|
+
* 32k max_tokens: A2UI JSON for moderately complex UIs (kanban, dashboard,
|
|
205
|
+
* pricing table) routinely exceeds 8k. Truncation produced silent fallbacks
|
|
206
|
+
* that the validator rubber-stamped at ~89/100 — see diagnosis report
|
|
207
|
+
* 2026-04-19. Modern Claude/GPT/Gemini all support ≥32k output cleanly.
|
|
208
|
+
*
|
|
209
|
+
* @param opts
|
|
210
|
+
* @param opts.messages
|
|
211
|
+
* @param opts.systemPrompt
|
|
212
|
+
*/
|
|
213
|
+
async complete({ messages, systemPrompt }) {
|
|
214
|
+
const response = await this.#client.chat({
|
|
215
|
+
model: this.#model,
|
|
216
|
+
messages,
|
|
217
|
+
...(systemPrompt != null ? { system: systemPrompt } : {}),
|
|
218
|
+
maxTokens: 32768,
|
|
219
|
+
cache: this.#provider === 'anthropic',
|
|
220
|
+
});
|
|
221
|
+
return {
|
|
222
|
+
content: response.text,
|
|
223
|
+
// 'max_tokens' / 'length' / 'MAX_TOKENS' (Gemini) signal truncation;
|
|
224
|
+
// downstream parser uses this to refuse silent fallback rendering.
|
|
225
|
+
stopReason: response.stopReason ?? 'end',
|
|
226
|
+
usage: {
|
|
227
|
+
inputTokens: response.usage?.input ?? 0,
|
|
228
|
+
outputTokens: response.usage?.output ?? 0,
|
|
229
|
+
cacheCreationTokens: response.usage?.cacheCreation ?? 0,
|
|
230
|
+
cacheReadTokens: response.usage?.cacheRead ?? 0,
|
|
231
|
+
},
|
|
280
232
|
};
|
|
281
|
-
}
|
|
282
|
-
// Other chunk types (thinking, error) are still available on the
|
|
283
|
-
// underlying adapter but the AdiaUI pipeline doesn't consume them yet.
|
|
284
233
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
234
|
+
/**
|
|
235
|
+
* Streaming completion. Matches AdiaUI interface.
|
|
236
|
+
*
|
|
237
|
+
* @param opts
|
|
238
|
+
* @param opts.messages
|
|
239
|
+
* @param opts.systemPrompt
|
|
240
|
+
* @yields {{ type: 'text', content: string } | { type: 'done', stopReason: string, usage: { inputTokens: number, outputTokens: number, cacheCreationTokens: number, cacheReadTokens: number } }}
|
|
241
|
+
*/
|
|
242
|
+
async *stream({ messages, systemPrompt }) {
|
|
243
|
+
for await (const chunk of this.#client.stream({
|
|
244
|
+
model: this.#model,
|
|
245
|
+
messages,
|
|
246
|
+
...(systemPrompt != null ? { system: systemPrompt } : {}),
|
|
247
|
+
maxTokens: 32768,
|
|
248
|
+
cache: this.#provider === 'anthropic',
|
|
249
|
+
})) {
|
|
250
|
+
if (chunk.type === 'text') {
|
|
251
|
+
yield { type: 'text', content: chunk.text };
|
|
252
|
+
}
|
|
253
|
+
else if (chunk.type === 'done') {
|
|
254
|
+
// Surface the terminal stopReason + cache telemetry so the consumer
|
|
255
|
+
// can detect max_tokens truncation and the dialog recorder can log
|
|
256
|
+
// cache hit-rate per turn.
|
|
257
|
+
yield {
|
|
258
|
+
type: 'done',
|
|
259
|
+
stopReason: chunk.stopReason ?? 'end',
|
|
260
|
+
usage: {
|
|
261
|
+
inputTokens: chunk.usage?.input ?? 0,
|
|
262
|
+
outputTokens: chunk.usage?.output ?? 0,
|
|
263
|
+
cacheCreationTokens: chunk.usage?.cacheCreation ?? 0,
|
|
264
|
+
cacheReadTokens: chunk.usage?.cacheRead ?? 0,
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
// Other chunk types (thinking, error) are still available on the
|
|
269
|
+
// underlying adapter but the AdiaUI pipeline doesn't consume them yet.
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/** Expose the underlying client for advanced use. */
|
|
273
|
+
get adapter() { return this.#client; }
|
|
274
|
+
/** Expose provider name for detection. */
|
|
275
|
+
get provider() { return this.#provider; }
|
|
292
276
|
}
|
|
277
|
+
//# sourceMappingURL=llm-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-bridge.js","sourceRoot":"","sources":["src/llm-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,6EAA6E;AAC7E,IAAI,aAAa,GAAyD,IAAI,CAAC;AAC/E,KAAK,UAAU,eAAe;IAC5B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;YAChD,aAAa,GAAG,GAAG,CAAC,YAAY,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,aAAa,GAAG,IAAI,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,4EAA4E;AAE5E,SAAS,MAAM,CAAC,GAAW;IACzB,IAAI,CAAC;QACH,MAAM,GAAG,GAAI,MAAM,CAAC,IAAqD,CAAC,GAAG,CAAC;QAC9E,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;YAC3C,IAAI,GAAG;gBAAE,OAAO,GAAG,CAAC;QACtB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAClD,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC;AAEjD,SAAS,cAAc,CAAC,QAAgB;IACtC,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC,CAAC,kCAAkC;IACrE,MAAM,QAAQ,GAA2B;QACvC,SAAS,EAAE,gCAAgC;QAC3C,MAAM,EAAE,qCAAqC;QAC7C,MAAM,EAAE,iBAAiB;KAC1B,CAAC;IACF,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB;IACvB,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,EAAE,QAAQ,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACrF,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,IAAI,4BAA4B,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1D,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;GASG;AACH,KAAK,UAAU,wBAAwB,CAAC,QAAgB,EAAE,QAA4B;IACpF,MAAM,YAAY,GAAG,MAAM,eAAe,EAAE,CAAC;IAC7C,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;QAC1E,OAAO,IAAI,cAAc,EAAE,CAAC;IAC9B,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,2BAA2B,CAAC;IAClF,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,YAAY,CAAC;QAC1B,QAAQ;QACR,MAAM,EAAE,oCAAoC,EAAG,6BAA6B;QAC5E,KAAK;QACL,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClC,CAAC,CAAC;IACH,OAAO,IAAI,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAED,4EAA4E;AAE5E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA+D,EAAE;IACnG,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,cAAc,EAAE,CAAC;IAC7E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC;IAE7D,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,4DAA4D;QAC5D,iEAAiE;QACjE,6DAA6D;QAC7D,4DAA4D;QAC5D,+DAA+D;QAC/D,yDAAyD;QACzD,8DAA8D;QAC9D,iCAAiC;QACjC,IAAI,UAAU,IAAI,gBAAgB,EAAE,EAAE,CAAC;YACrC,OAAO,wBAAwB,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO,IAAI,cAAc,EAAE,CAAC;IAC9B,CAAC;IAED,4CAA4C;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,GAAG,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,mBAAmB,CAAC,IAAI,MAAM,CAAC,gBAAgB,CAAC,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAEjK,sEAAsE;IACtE,mEAAmE;IACnE,sEAAsE;IACtE,qEAAqE;IACrE,iEAAiE;IACjE,sEAAsE;IACtE,yDAAyD;IACzD,IAAI,UAAU,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAE,MAA8D,CAAC,4BAA4B,EAAE,CAAC;QAC1J,MAA8D,CAAC,4BAA4B,GAAG,IAAI,CAAC;QACpG,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACzF,OAAO,CAAC,IAAI,CACV,4CAA4C,QAAQ,SAAS,MAAM,oEAAoE;YACvI,wGAAwG;YACxG,wEAAwE,EACxE,oCAAoC,EACpC,oCAAoC,EACpC,iBAAiB,CAClB,CAAC;IACJ,CAAC;IAED,mCAAmC;IACnC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;QACnE,OAAO,IAAI,cAAc,EAAE,CAAC;IAC9B,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,eAAe,EAAE,CAAC;IAC7C,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;QAC1E,OAAO,IAAI,cAAc,EAAE,CAAC;IAC9B,CAAC;IAED,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,YAAY,CAAC;QAC1B,QAAQ;QACR,MAAM;QACN,KAAK,EAAE,KAAK,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,0BAA0B;QACtE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClC,CAAC,CAAC;IAEH,OAAO,IAAI,eAAe,CAAC,MAAM,EAAE,KAAK,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,0BAA0B,EAAE,QAAQ,CAAC,CAAC;AAChH,CAAC;AAED,SAAS,cAAc;IACrB,IAAI,MAAM,CAAC,mBAAmB,CAAC;QAAE,OAAO,WAAW,CAAC;IACpD,IAAI,MAAM,CAAC,gBAAgB,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9C,IAAI,MAAM,CAAC,gBAAgB,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,4EAA4E;AAE5E,kCAAkC;AAClC,MAAM,cAAc,GAA2B;IAC7C,SAAS,EAAE,0BAA0B;IACrC,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,kBAAkB;CAC3B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,eAAe;IACnB,OAAO,CAAY;IACnB,MAAM,CAAS;IACf,SAAS,CAAS;IAElB,YAAY,MAAiB,EAAE,KAAa,EAAE,QAAgB;QAC5D,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAiF;QACtH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACvC,KAAK,EAAE,IAAI,CAAC,MAAM;YAClB,QAAQ;YACR,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,SAAS,EAAE,KAAK;YAChB,KAAK,EAAE,IAAI,CAAC,SAAS,KAAK,WAAW;SACtC,CAAC,CAAC;QACH,OAAO;YACL,OAAO,EAAE,QAAQ,CAAC,IAAI;YACtB,qEAAqE;YACrE,mEAAmE;YACnE,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,KAAK;YACxC,KAAK,EAAE;gBACL,WAAW,EAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,IAAI,CAAC;gBACvC,YAAY,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;gBACzC,mBAAmB,EAAE,QAAQ,CAAC,KAAK,EAAE,aAAa,IAAI,CAAC;gBACvD,eAAe,EAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,CAAC;aAChD;SACF,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAiF;QAIrH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YAC5C,KAAK,EAAE,IAAI,CAAC,MAAM;YAClB,QAAQ;YACR,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzD,SAAS,EAAE,KAAK;YAChB,KAAK,EAAE,IAAI,CAAC,SAAS,KAAK,WAAW;SACtC,CAAC,EAAE,CAAC;YACH,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC1B,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;YAC9C,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACjC,oEAAoE;gBACpE,mEAAmE;gBACnE,2BAA2B;gBAC3B,MAAM;oBACJ,IAAI,EAAE,MAAM;oBACZ,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,KAAK;oBACrC,KAAK,EAAE;wBACL,WAAW,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,IAAI,CAAC;wBACpC,YAAY,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;wBACtC,mBAAmB,EAAE,KAAK,CAAC,KAAK,EAAE,aAAa,IAAI,CAAC;wBACpD,eAAe,EAAE,KAAK,CAAC,KAAK,EAAE,SAAS,IAAI,CAAC;qBAC7C;iBACF,CAAC;YACJ,CAAC;YACD,iEAAiE;YACjE,uEAAuE;QACzE,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,IAAI,OAAO,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAEtC,0CAA0C;IAC1C,IAAI,QAAQ,KAAK,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;CAC1C"}
|