@chipmobilesdk/rn-ai 0.3.0 → 0.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 +146 -0
- package/README.md +65 -24
- package/lib/commonjs/config/behaviorConfig.js +283 -0
- package/lib/commonjs/config/behaviorConfig.js.map +1 -0
- package/lib/commonjs/contract/gateway.js +60 -0
- package/lib/commonjs/contract/gateway.js.map +1 -0
- package/lib/commonjs/core/aiClient.js +330 -0
- package/lib/commonjs/core/aiClient.js.map +1 -0
- package/lib/commonjs/core/quotaRequest.js +105 -0
- package/lib/commonjs/core/quotaRequest.js.map +1 -0
- package/lib/commonjs/diagnostics/errors.js +108 -0
- package/lib/commonjs/diagnostics/errors.js.map +1 -0
- package/lib/commonjs/diagnostics/messageKeys.js +68 -0
- package/lib/commonjs/diagnostics/messageKeys.js.map +1 -0
- package/lib/commonjs/index.js +102 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/react/hooks.js +170 -0
- package/lib/commonjs/react/hooks.js.map +1 -0
- package/lib/commonjs/transport/sseClient.js +151 -0
- package/lib/commonjs/transport/sseClient.js.map +1 -0
- package/lib/commonjs/transport/timeouts.js +46 -0
- package/lib/commonjs/transport/timeouts.js.map +1 -0
- package/lib/module/config/behaviorConfig.js +275 -0
- package/lib/module/config/behaviorConfig.js.map +1 -0
- package/lib/module/contract/gateway.js +56 -0
- package/lib/module/contract/gateway.js.map +1 -0
- package/lib/module/core/aiClient.js +327 -0
- package/lib/module/core/aiClient.js.map +1 -0
- package/lib/module/core/quotaRequest.js +102 -0
- package/lib/module/core/quotaRequest.js.map +1 -0
- package/lib/module/diagnostics/errors.js +99 -0
- package/lib/module/diagnostics/errors.js.map +1 -0
- package/lib/module/diagnostics/messageKeys.js +61 -0
- package/lib/module/diagnostics/messageKeys.js.map +1 -0
- package/lib/module/index.js +19 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/react/hooks.js +164 -0
- package/lib/module/react/hooks.js.map +1 -0
- package/lib/module/transport/sseClient.js +146 -0
- package/lib/module/transport/sseClient.js.map +1 -0
- package/lib/module/transport/timeouts.js +41 -0
- package/lib/module/transport/timeouts.js.map +1 -0
- package/lib/typescript/commonjs/config/behaviorConfig.d.ts +119 -0
- package/lib/typescript/commonjs/config/behaviorConfig.d.ts.map +1 -0
- package/lib/typescript/commonjs/contract/gateway.d.ts +64 -0
- package/lib/typescript/commonjs/contract/gateway.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/aiClient.d.ts +104 -0
- package/lib/typescript/commonjs/core/aiClient.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/quotaRequest.d.ts +45 -0
- package/lib/typescript/commonjs/core/quotaRequest.d.ts.map +1 -0
- package/lib/typescript/commonjs/diagnostics/errors.d.ts +38 -0
- package/lib/typescript/commonjs/diagnostics/errors.d.ts.map +1 -0
- package/lib/typescript/commonjs/diagnostics/messageKeys.d.ts +46 -0
- package/lib/typescript/commonjs/diagnostics/messageKeys.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +21 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/react/hooks.d.ts +37 -0
- package/lib/typescript/commonjs/react/hooks.d.ts.map +1 -0
- package/lib/typescript/commonjs/transport/sseClient.d.ts +57 -0
- package/lib/typescript/commonjs/transport/sseClient.d.ts.map +1 -0
- package/lib/typescript/commonjs/transport/timeouts.d.ts +28 -0
- package/lib/typescript/commonjs/transport/timeouts.d.ts.map +1 -0
- package/lib/typescript/module/config/behaviorConfig.d.ts +119 -0
- package/lib/typescript/module/config/behaviorConfig.d.ts.map +1 -0
- package/lib/typescript/module/contract/gateway.d.ts +64 -0
- package/lib/typescript/module/contract/gateway.d.ts.map +1 -0
- package/lib/typescript/module/core/aiClient.d.ts +104 -0
- package/lib/typescript/module/core/aiClient.d.ts.map +1 -0
- package/lib/typescript/module/core/quotaRequest.d.ts +45 -0
- package/lib/typescript/module/core/quotaRequest.d.ts.map +1 -0
- package/lib/typescript/module/diagnostics/errors.d.ts +38 -0
- package/lib/typescript/module/diagnostics/errors.d.ts.map +1 -0
- package/lib/typescript/module/diagnostics/messageKeys.d.ts +46 -0
- package/lib/typescript/module/diagnostics/messageKeys.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +21 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/react/hooks.d.ts +37 -0
- package/lib/typescript/module/react/hooks.d.ts.map +1 -0
- package/lib/typescript/module/transport/sseClient.d.ts +57 -0
- package/lib/typescript/module/transport/sseClient.d.ts.map +1 -0
- package/lib/typescript/module/transport/timeouts.d.ts +28 -0
- package/lib/typescript/module/transport/timeouts.d.ts.map +1 -0
- package/package.json +40 -12
- package/skills/sdk-rn-ai/SKILL.md +43 -4
- package/src/config/behaviorConfig.ts +158 -37
- package/src/contract/gateway.ts +91 -0
- package/src/core/aiClient.ts +194 -96
- package/src/core/quotaRequest.ts +125 -0
- package/src/diagnostics/errors.ts +85 -23
- package/src/diagnostics/messageKeys.ts +3 -0
- package/src/index.ts +28 -1
- package/src/react/hooks.ts +86 -14
- package/src/transport/sseClient.ts +58 -11
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.SSE_DONE_SENTINEL = exports.RETRY_AFTER_HEADER = exports.QUOTA_HEADERS = exports.GATEWAY_ERROR_STATUS = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* The gateway↔client contract: error codes, quota headers, stream events.
|
|
9
|
+
*
|
|
10
|
+
* One definition, imported by both sides (GW-13). The gateway's own codes and
|
|
11
|
+
* the client's map of them were two hand-maintained lists, and they had already
|
|
12
|
+
* drifted: `BAD_REQUEST`, `ENDPOINT_RETIRED` and `INTERNAL` existed on the
|
|
13
|
+
* server and were unknown to the client, which fell back to a guess from the
|
|
14
|
+
* status. Adding a code now fails to compile on whichever side has not handled
|
|
15
|
+
* it.
|
|
16
|
+
*
|
|
17
|
+
* Types and plain constants only, and no import of anything: the gateway runs
|
|
18
|
+
* on Node and imports this file for its types alone.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** Every error the gateway answers with (`error.code` in the body). */
|
|
22
|
+
|
|
23
|
+
/** The HTTP status each code is sent with. */
|
|
24
|
+
const GATEWAY_ERROR_STATUS = exports.GATEWAY_ERROR_STATUS = {
|
|
25
|
+
BAD_REQUEST: 400,
|
|
26
|
+
AUTH_INVALID: 401,
|
|
27
|
+
NOT_ENTITLED: 403,
|
|
28
|
+
USER_BLOCKED: 403,
|
|
29
|
+
APP_UNKNOWN: 404,
|
|
30
|
+
ENDPOINT_RETIRED: 410,
|
|
31
|
+
PAYLOAD_TOO_LARGE: 413,
|
|
32
|
+
MODALITY_NOT_ALLOWED: 415,
|
|
33
|
+
RATE_LIMITED: 429,
|
|
34
|
+
UPSTREAM_BUSY: 429,
|
|
35
|
+
UPSTREAM_ERROR: 500,
|
|
36
|
+
INTERNAL: 500
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/** The error body. `message` is safe to log; it never carries upstream detail. */
|
|
40
|
+
|
|
41
|
+
/** The quota headers, by name. A rename here breaks both sides' compile. */
|
|
42
|
+
const QUOTA_HEADERS = exports.QUOTA_HEADERS = {
|
|
43
|
+
minuteRemaining: 'X-Quota-Minute-Remaining',
|
|
44
|
+
dayRemaining: 'X-Quota-Day-Remaining',
|
|
45
|
+
dayTokensRemaining: 'X-Quota-Day-Tokens-Remaining'
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/** The names field by field, so a side declaring its own literals is checked exactly. */
|
|
49
|
+
|
|
50
|
+
/** What is left of an app's allowance, as the gateway reports it. */
|
|
51
|
+
|
|
52
|
+
/** What one answer cost. */
|
|
53
|
+
|
|
54
|
+
/** The `data:` payloads of a chat stream, before the `[DONE]` sentinel. */
|
|
55
|
+
|
|
56
|
+
/** The last `data:` line of a stream that completed. */
|
|
57
|
+
const SSE_DONE_SENTINEL = exports.SSE_DONE_SENTINEL = '[DONE]';
|
|
58
|
+
/** The `Retry-After` header, which a 429 always carries. */
|
|
59
|
+
const RETRY_AFTER_HEADER = exports.RETRY_AFTER_HEADER = 'Retry-After';
|
|
60
|
+
//# sourceMappingURL=gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["GATEWAY_ERROR_STATUS","exports","BAD_REQUEST","AUTH_INVALID","NOT_ENTITLED","USER_BLOCKED","APP_UNKNOWN","ENDPOINT_RETIRED","PAYLOAD_TOO_LARGE","MODALITY_NOT_ALLOWED","RATE_LIMITED","UPSTREAM_BUSY","UPSTREAM_ERROR","INTERNAL","QUOTA_HEADERS","minuteRemaining","dayRemaining","dayTokensRemaining","SSE_DONE_SENTINEL","RETRY_AFTER_HEADER"],"sourceRoot":"../../../src","sources":["contract/gateway.ts"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAeA;AACO,MAAMA,oBAAgE,GAAAC,OAAA,CAAAD,oBAAA,GAAG;EAC/EE,WAAW,EAAE,GAAG;EAChBC,YAAY,EAAE,GAAG;EACjBC,YAAY,EAAE,GAAG;EACjBC,YAAY,EAAE,GAAG;EACjBC,WAAW,EAAE,GAAG;EAChBC,gBAAgB,EAAE,GAAG;EACrBC,iBAAiB,EAAE,GAAG;EACtBC,oBAAoB,EAAE,GAAG;EACzBC,YAAY,EAAE,GAAG;EACjBC,aAAa,EAAE,GAAG;EAClBC,cAAc,EAAE,GAAG;EACnBC,QAAQ,EAAE;AACX,CAAC;;AAED;;AASA;AACO,MAAMC,aAAa,GAAAb,OAAA,CAAAa,aAAA,GAAG;EAC5BC,eAAe,EAAE,0BAA0B;EAC3CC,YAAY,EAAE,uBAAuB;EACrCC,kBAAkB,EAAE;AACrB,CAAU;;AAEV;;AAIA;;AAOA;;AAOA;;AAMA;AACO,MAAMC,iBAAiB,GAAAjB,OAAA,CAAAiB,iBAAA,GAAG,QAAQ;AAGzC;AACO,MAAMC,kBAAkB,GAAAlB,OAAA,CAAAkB,kBAAA,GAAG,aAAa","ignoreList":[]}
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createAiClient = createAiClient;
|
|
7
|
+
var _rnCore = require("@chipmobilesdk/rn-core");
|
|
8
|
+
var _behaviorConfig = require("../config/behaviorConfig.js");
|
|
9
|
+
var _gateway = require("../contract/gateway.js");
|
|
10
|
+
var _errors = require("../diagnostics/errors.js");
|
|
11
|
+
var _sseClient = require("../transport/sseClient.js");
|
|
12
|
+
var _quotaRequest = require("./quotaRequest.js");
|
|
13
|
+
var _timeouts = require("../transport/timeouts.js");
|
|
14
|
+
/** Every failure a caller receives also goes to the app's SDK sinks (CORE-08). */
|
|
15
|
+
const channel = (0, _rnCore.createDiagnosticChannel)('rn-ai');
|
|
16
|
+
function report(operation, error) {
|
|
17
|
+
channel.emit(error.code, error.retryable ? 'warn' : 'error', {
|
|
18
|
+
operation,
|
|
19
|
+
retryable: error.retryable
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Minimal slice of the rn-auth `Auth` controller the client needs. */
|
|
24
|
+
|
|
25
|
+
/** What one answer cost, as the gateway reports it. */
|
|
26
|
+
|
|
27
|
+
/** What is left of the app's allowance. */
|
|
28
|
+
|
|
29
|
+
/** Ceiling on one remote-configured backoff step, so a bad document cannot stall a chat. */
|
|
30
|
+
const MAX_RETRY_BACKOFF_MS = 30_000;
|
|
31
|
+
|
|
32
|
+
/** The wait before silent retry `index` (0-based); the last configured step repeats. */
|
|
33
|
+
function backoffBefore(steps, index) {
|
|
34
|
+
const step = steps[Math.min(index, steps.length - 1)] ?? 0;
|
|
35
|
+
return Math.min(Math.max(0, step), MAX_RETRY_BACKOFF_MS);
|
|
36
|
+
}
|
|
37
|
+
/** A quota from the wire, or nothing: a malformed one is not displayed (AI-13). */
|
|
38
|
+
function asQuota(value) {
|
|
39
|
+
if (typeof value !== 'object' || value === null) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
const candidate = value;
|
|
43
|
+
const fields = [candidate.minuteRemaining, candidate.dayRemaining, candidate.dayTokensRemaining];
|
|
44
|
+
if (!fields.every(field => typeof field === 'number' && Number.isFinite(field))) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
minuteRemaining: candidate.minuteRemaining,
|
|
49
|
+
dayRemaining: candidate.dayRemaining,
|
|
50
|
+
dayTokensRemaining: candidate.dayTokensRemaining
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function createAiClient(clientConfig) {
|
|
54
|
+
const resourceKey = clientConfig.resourceKey ?? 'ai-gateway';
|
|
55
|
+
const transport = clientConfig.transport ?? _sseClient.requestSse;
|
|
56
|
+
const fetchFn = clientConfig.fetchFn ?? fetch;
|
|
57
|
+
const timeouts = {
|
|
58
|
+
..._timeouts.DEFAULT_AI_TIMEOUTS,
|
|
59
|
+
...clientConfig.timeouts
|
|
60
|
+
};
|
|
61
|
+
const scheduler = clientConfig.scheduler ?? _rnCore.realScheduler;
|
|
62
|
+
const configManager = new _behaviorConfig.BehaviorConfigManager({
|
|
63
|
+
configUrl: clientConfig.configUrl,
|
|
64
|
+
appId: clientConfig.appId,
|
|
65
|
+
cache: clientConfig.storage,
|
|
66
|
+
fetchFn: clientConfig.fetchFn,
|
|
67
|
+
timeoutMs: timeouts.configMs,
|
|
68
|
+
...(clientConfig.allowedHosts ? {
|
|
69
|
+
allowedHosts: clientConfig.allowedHosts
|
|
70
|
+
} : {})
|
|
71
|
+
});
|
|
72
|
+
let lastConfig;
|
|
73
|
+
const behaviorListeners = (0, _rnCore.createListenerSet)();
|
|
74
|
+
let snapshot;
|
|
75
|
+
let quota;
|
|
76
|
+
|
|
77
|
+
/** Rebuilt only when a field changes, so useSyncExternalStore sees a stable object. */
|
|
78
|
+
function behaviorState() {
|
|
79
|
+
const config = configManager.state;
|
|
80
|
+
const aiEnabled = lastConfig?.features.aiEnabled ?? true;
|
|
81
|
+
if (!snapshot || snapshot.config !== config || snapshot.aiEnabled !== aiEnabled) {
|
|
82
|
+
snapshot = {
|
|
83
|
+
config,
|
|
84
|
+
aiEnabled
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return snapshot;
|
|
88
|
+
}
|
|
89
|
+
function setLastConfig(next) {
|
|
90
|
+
const wasEnabled = lastConfig?.features.aiEnabled ?? true;
|
|
91
|
+
lastConfig = next;
|
|
92
|
+
if (next.features.aiEnabled !== wasEnabled) behaviorListeners.notify();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** One place records the quota, whichever call learned it (AI-13). */
|
|
96
|
+
function setQuota(next) {
|
|
97
|
+
if (!next || quota && shallowSameQuota(quota, next)) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
quota = next;
|
|
101
|
+
behaviorListeners.notify();
|
|
102
|
+
}
|
|
103
|
+
async function acquire(options = {}) {
|
|
104
|
+
const config = await configManager.getConfig();
|
|
105
|
+
setLastConfig(config);
|
|
106
|
+
if (!config.features.aiEnabled) {
|
|
107
|
+
throw new _errors.AiError('config-unavailable', 'AI is disabled for this app', {
|
|
108
|
+
recoverable: false
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
const tokenResult = await clientConfig.auth.requestAccessToken(resourceKey, {
|
|
112
|
+
forceRefresh: options.forceRefresh === true
|
|
113
|
+
});
|
|
114
|
+
if (tokenResult.status !== 'success' || !tokenResult.token) {
|
|
115
|
+
// What the auth layer called it, kept as the cause: a screen has to tell
|
|
116
|
+
// "sign in again" from "you are offline" (AI-11).
|
|
117
|
+
throw tokenError(tokenResult.status, tokenResult.errorCode);
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
config,
|
|
121
|
+
token: tokenResult.token
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const endpoint = (config, path) => `${config.api.baseUrl}/api/v1/apps/${clientConfig.appId}/${path}`;
|
|
125
|
+
function chat(request, handlers) {
|
|
126
|
+
let cancelled = false;
|
|
127
|
+
let settled = false;
|
|
128
|
+
let inner;
|
|
129
|
+
|
|
130
|
+
// Every callback to the app goes through here. Nothing is delivered after
|
|
131
|
+
// cancel() — an acquire() or config reload that failed after the user
|
|
132
|
+
// cancelled (or sent the next message) used to flip that screen to
|
|
133
|
+
// `error` — and exactly one terminal callback is delivered.
|
|
134
|
+
const emit = {
|
|
135
|
+
delta(text) {
|
|
136
|
+
if (!cancelled && !settled) handlers.onDelta(text);
|
|
137
|
+
},
|
|
138
|
+
done(result) {
|
|
139
|
+
if (cancelled || settled) return;
|
|
140
|
+
settled = true;
|
|
141
|
+
setQuota(result.quota);
|
|
142
|
+
handlers.onDone(result);
|
|
143
|
+
},
|
|
144
|
+
error(error) {
|
|
145
|
+
if (cancelled || settled) return;
|
|
146
|
+
settled = true;
|
|
147
|
+
inner?.cancel();
|
|
148
|
+
report('chat', error);
|
|
149
|
+
handlers.onError(error);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// Any exception on the way becomes a reported error. Each path used to end
|
|
154
|
+
// in `.catch(() => undefined)`, so a transport that threw (a bad URL from
|
|
155
|
+
// remote config, say) left the UI in `loading` with nothing to show.
|
|
156
|
+
const fail = e => emit.error(e instanceof _errors.AiError ? e : new _errors.AiError('internal', e instanceof Error ? e.message : String(e)));
|
|
157
|
+
const guarded = fn => (...args) => {
|
|
158
|
+
try {
|
|
159
|
+
fn(...args);
|
|
160
|
+
} catch (e) {
|
|
161
|
+
fail(e);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
const attempt = async state => {
|
|
165
|
+
const {
|
|
166
|
+
config,
|
|
167
|
+
token
|
|
168
|
+
} = await acquire({
|
|
169
|
+
forceRefresh: state.authRetries > 0
|
|
170
|
+
});
|
|
171
|
+
if (cancelled) return;
|
|
172
|
+
let done;
|
|
173
|
+
let streamErrorCode;
|
|
174
|
+
inner = transport({
|
|
175
|
+
url: endpoint(config, 'chat'),
|
|
176
|
+
method: 'POST',
|
|
177
|
+
headers: {
|
|
178
|
+
Authorization: `Bearer ${token}`,
|
|
179
|
+
'Content-Type': 'application/json'
|
|
180
|
+
},
|
|
181
|
+
body: JSON.stringify(request),
|
|
182
|
+
connectTimeoutMs: timeouts.connectMs,
|
|
183
|
+
idleTimeoutMs: timeouts.idleMs
|
|
184
|
+
}, {
|
|
185
|
+
onData: guarded(payload => {
|
|
186
|
+
if (payload === _gateway.SSE_DONE_SENTINEL) return;
|
|
187
|
+
let event;
|
|
188
|
+
try {
|
|
189
|
+
event = JSON.parse(payload);
|
|
190
|
+
} catch {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (event.type === 'delta' && typeof event.text === 'string') {
|
|
194
|
+
emit.delta(event.text);
|
|
195
|
+
} else if (event.type === 'done' && event.usage) {
|
|
196
|
+
done = {
|
|
197
|
+
usage: event.usage,
|
|
198
|
+
quota: asQuota(event.quota)
|
|
199
|
+
};
|
|
200
|
+
} else if (event.type === 'error') {
|
|
201
|
+
streamErrorCode = event.code ?? 'UPSTREAM_ERROR';
|
|
202
|
+
}
|
|
203
|
+
}),
|
|
204
|
+
onEnd: guarded(() => {
|
|
205
|
+
if (streamErrorCode) {
|
|
206
|
+
emit.error(new _errors.AiError('upstream-error', 'the AI service failed mid-response', {
|
|
207
|
+
cause: streamErrorCode
|
|
208
|
+
}));
|
|
209
|
+
} else if (done) {
|
|
210
|
+
emit.done(done);
|
|
211
|
+
} else {
|
|
212
|
+
// Headers said 200 and the body stopped short: the connection
|
|
213
|
+
// dropped mid-answer, which is a network failure, not a fault
|
|
214
|
+
// of the service.
|
|
215
|
+
emit.error(new _errors.AiError('network', 'the stream ended before it completed'));
|
|
216
|
+
}
|
|
217
|
+
}),
|
|
218
|
+
onError: guarded((status, bodyText, response) => {
|
|
219
|
+
if (cancelled) return;
|
|
220
|
+
recover(status, bodyText, state, {
|
|
221
|
+
...(response ? {
|
|
222
|
+
getHeader: name => response.getHeader(name)
|
|
223
|
+
} : {})
|
|
224
|
+
}, next => attempt(next).catch(fail), fail, emit.error);
|
|
225
|
+
})
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
attempt({
|
|
229
|
+
configReloads: 0,
|
|
230
|
+
authRetries: 0
|
|
231
|
+
}).catch(fail);
|
|
232
|
+
return {
|
|
233
|
+
cancel() {
|
|
234
|
+
cancelled = true;
|
|
235
|
+
inner?.cancel();
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* The two recoveries the contract promises, in one place so chat and quota
|
|
242
|
+
* cannot drift (AI-13): a designated status reloads the configuration and
|
|
243
|
+
* retries after the configured backoff, and a 401 retries once with a token
|
|
244
|
+
* the provider had to fetch again.
|
|
245
|
+
*/
|
|
246
|
+
function recover(status, bodyText, state, context, retry, onFailure, onGiveUp) {
|
|
247
|
+
const config = lastConfig;
|
|
248
|
+
if (config && config.recovery.reloadOnHttpStatus.includes(status) && state.configReloads < config.recovery.maxSilentRetries) {
|
|
249
|
+
// Waits `recovery.retryBackoffMs` first (AI-05): a gateway mid-rollout
|
|
250
|
+
// that answered 410 a moment ago may well answer it again at once.
|
|
251
|
+
const retryAfter = backoffBefore(config.recovery.retryBackoffMs, state.configReloads);
|
|
252
|
+
configManager.getConfig({
|
|
253
|
+
forceReload: true
|
|
254
|
+
}).then(reloaded => {
|
|
255
|
+
setLastConfig(reloaded);
|
|
256
|
+
scheduler.setTimeout(() => retry({
|
|
257
|
+
...state,
|
|
258
|
+
configReloads: state.configReloads + 1
|
|
259
|
+
}), retryAfter);
|
|
260
|
+
}, e => onFailure(e instanceof _errors.AiError ? e : new _errors.AiError('config-unavailable', String(e))));
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
// Expired server-side session → one retry with a token the provider
|
|
264
|
+
// actually re-fetched.
|
|
265
|
+
if (status === 401 && state.authRetries < 1) {
|
|
266
|
+
retry({
|
|
267
|
+
...state,
|
|
268
|
+
authRetries: state.authRetries + 1
|
|
269
|
+
});
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
onGiveUp((0, _errors.errorFromHttp)(status, bodyText, context));
|
|
273
|
+
}
|
|
274
|
+
const {
|
|
275
|
+
getQuota
|
|
276
|
+
} = (0, _quotaRequest.createQuotaRequest)({
|
|
277
|
+
fetchFn,
|
|
278
|
+
timeouts,
|
|
279
|
+
acquire,
|
|
280
|
+
endpoint,
|
|
281
|
+
asQuota,
|
|
282
|
+
recover,
|
|
283
|
+
report: error => report('quota', error),
|
|
284
|
+
setQuota
|
|
285
|
+
});
|
|
286
|
+
return {
|
|
287
|
+
chat,
|
|
288
|
+
getQuota,
|
|
289
|
+
lastQuota: () => quota,
|
|
290
|
+
getBehaviorState: () => behaviorState(),
|
|
291
|
+
subscribe: listener => {
|
|
292
|
+
const fromManager = configManager.subscribe(listener);
|
|
293
|
+
const fromClient = behaviorListeners.add(listener);
|
|
294
|
+
return () => {
|
|
295
|
+
fromManager();
|
|
296
|
+
fromClient();
|
|
297
|
+
};
|
|
298
|
+
},
|
|
299
|
+
reloadConfig: async () => {
|
|
300
|
+
setLastConfig(await configManager.getConfig({
|
|
301
|
+
forceReload: true
|
|
302
|
+
}));
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function shallowSameQuota(a, b) {
|
|
307
|
+
return a.minuteRemaining === b.minuteRemaining && a.dayRemaining === b.dayRemaining && a.dayTokensRemaining === b.dayTokensRemaining;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* What the auth layer's refusal means for a chat. The code rn-auth gave is kept
|
|
312
|
+
* as the cause, and it decides the copy: "sign in again" and "you are offline"
|
|
313
|
+
* are different answers, and both used to arrive as `auth-invalid` (AI-11).
|
|
314
|
+
*/
|
|
315
|
+
function tokenError(status, errorCode) {
|
|
316
|
+
const cause = errorCode ? {
|
|
317
|
+
cause: errorCode
|
|
318
|
+
} : {};
|
|
319
|
+
switch (errorCode) {
|
|
320
|
+
case 'session-expired':
|
|
321
|
+
return new _errors.AiError('session-expired', 'the session ended; sign in again', cause);
|
|
322
|
+
case 'network-unavailable':
|
|
323
|
+
return new _errors.AiError('network', 'no connection to the identity provider', cause);
|
|
324
|
+
case 'consent-denied':
|
|
325
|
+
return new _errors.AiError('not-entitled', 'access to the AI resource was denied', cause);
|
|
326
|
+
default:
|
|
327
|
+
return new _errors.AiError('auth-invalid', status === 'denied' ? 'access to the AI resource was refused' : 'could not acquire an access token', cause);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
//# sourceMappingURL=aiClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_rnCore","require","_behaviorConfig","_gateway","_errors","_sseClient","_quotaRequest","_timeouts","channel","createDiagnosticChannel","report","operation","error","emit","code","retryable","MAX_RETRY_BACKOFF_MS","backoffBefore","steps","index","step","Math","min","length","max","asQuota","value","undefined","candidate","fields","minuteRemaining","dayRemaining","dayTokensRemaining","every","field","Number","isFinite","createAiClient","clientConfig","resourceKey","transport","requestSse","fetchFn","fetch","timeouts","DEFAULT_AI_TIMEOUTS","scheduler","realScheduler","configManager","BehaviorConfigManager","configUrl","appId","cache","storage","timeoutMs","configMs","allowedHosts","lastConfig","behaviorListeners","createListenerSet","snapshot","quota","behaviorState","config","state","aiEnabled","features","setLastConfig","next","wasEnabled","notify","setQuota","shallowSameQuota","acquire","options","getConfig","AiError","recoverable","tokenResult","auth","requestAccessToken","forceRefresh","status","token","tokenError","errorCode","endpoint","path","api","baseUrl","chat","request","handlers","cancelled","settled","inner","delta","text","onDelta","done","result","onDone","cancel","onError","fail","e","Error","message","String","guarded","fn","args","attempt","authRetries","streamErrorCode","url","method","headers","Authorization","body","JSON","stringify","connectTimeoutMs","connectMs","idleTimeoutMs","idleMs","onData","payload","SSE_DONE_SENTINEL","event","parse","type","usage","onEnd","cause","bodyText","response","recover","getHeader","name","catch","configReloads","context","retry","onFailure","onGiveUp","recovery","reloadOnHttpStatus","includes","maxSilentRetries","retryAfter","retryBackoffMs","forceReload","then","reloaded","setTimeout","errorFromHttp","getQuota","createQuotaRequest","lastQuota","getBehaviorState","subscribe","listener","fromManager","fromClient","add","reloadConfig","a","b"],"sourceRoot":"../../../src","sources":["core/aiClient.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createQuotaRequest = createQuotaRequest;
|
|
7
|
+
var _errors = require("../diagnostics/errors.js");
|
|
8
|
+
var _timeouts = require("../transport/timeouts.js");
|
|
9
|
+
/**
|
|
10
|
+
* The quota request, and the recovery it shares with a chat (AI-13).
|
|
11
|
+
*
|
|
12
|
+
* `getQuota` used to be the one call with no recovery at all: a gateway that
|
|
13
|
+
* had moved answered 404 for quota while chats silently re-routed, so the
|
|
14
|
+
* figure on screen failed while the feature worked. It now goes through the
|
|
15
|
+
* same `recover` the chat stream does — a designated status reloads the
|
|
16
|
+
* configuration and retries, a 401 retries once with a token the provider had
|
|
17
|
+
* to fetch again.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/** Where the quota request is in its recovery, shared with the chat path. */
|
|
21
|
+
|
|
22
|
+
/** What is left of the app's allowance. */
|
|
23
|
+
|
|
24
|
+
function createQuotaRequest(deps) {
|
|
25
|
+
const {
|
|
26
|
+
fetchFn,
|
|
27
|
+
timeouts,
|
|
28
|
+
endpoint,
|
|
29
|
+
asQuota,
|
|
30
|
+
recover,
|
|
31
|
+
setQuota
|
|
32
|
+
} = deps;
|
|
33
|
+
const acquire = deps.acquire;
|
|
34
|
+
async function getQuota() {
|
|
35
|
+
try {
|
|
36
|
+
const snapshotValue = await fetchQuotaWithRecovery({
|
|
37
|
+
configReloads: 0,
|
|
38
|
+
authRetries: 0
|
|
39
|
+
});
|
|
40
|
+
setQuota(snapshotValue);
|
|
41
|
+
return snapshotValue;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
if (error instanceof _errors.AiError) deps.report(error);
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Same recovery as a chat: a retired endpoint reloads the config and retries. */
|
|
49
|
+
function fetchQuotaWithRecovery(state) {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
fetchQuota(state).then(resolve, error => {
|
|
52
|
+
if (!(error instanceof HttpFailure)) {
|
|
53
|
+
reject(error);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
recover(error.status, error.bodyText, state, {
|
|
57
|
+
getHeader: name => error.getHeader(name)
|
|
58
|
+
}, next => fetchQuotaWithRecovery(next).then(resolve, reject), reject, reject);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Carries the response so `recover` can decide; never reaches the caller. */
|
|
64
|
+
class HttpFailure extends Error {
|
|
65
|
+
constructor(status, bodyText, headers) {
|
|
66
|
+
super(`gateway responded ${status}`);
|
|
67
|
+
this.status = status;
|
|
68
|
+
this.bodyText = bodyText;
|
|
69
|
+
this.headers = headers;
|
|
70
|
+
this.name = 'HttpFailure';
|
|
71
|
+
}
|
|
72
|
+
getHeader(name) {
|
|
73
|
+
return this.headers?.get(name) ?? null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function fetchQuota(state) {
|
|
77
|
+
const {
|
|
78
|
+
config,
|
|
79
|
+
token
|
|
80
|
+
} = await acquire({
|
|
81
|
+
forceRefresh: state.authRetries > 0
|
|
82
|
+
});
|
|
83
|
+
return (0, _timeouts.withTimeout)(timeouts.quotaMs, async signal => {
|
|
84
|
+
const response = await fetchFn(endpoint(config, 'quota'), {
|
|
85
|
+
headers: {
|
|
86
|
+
Authorization: `Bearer ${token}`
|
|
87
|
+
},
|
|
88
|
+
signal
|
|
89
|
+
});
|
|
90
|
+
if (!response.ok) {
|
|
91
|
+
throw new HttpFailure(response.status, await response.text(), response.headers);
|
|
92
|
+
}
|
|
93
|
+
const parsed = asQuota(await response.json());
|
|
94
|
+
if (!parsed) {
|
|
95
|
+
// A body that is not the contract's: better no figure than a wrong one.
|
|
96
|
+
throw new _errors.AiError('internal', 'quota response did not match the contract');
|
|
97
|
+
}
|
|
98
|
+
return parsed;
|
|
99
|
+
}, () => new _errors.AiError('network', 'quota request timed out'));
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
getQuota
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=quotaRequest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_errors","require","_timeouts","createQuotaRequest","deps","fetchFn","timeouts","endpoint","asQuota","recover","setQuota","acquire","getQuota","snapshotValue","fetchQuotaWithRecovery","configReloads","authRetries","error","AiError","report","state","Promise","resolve","reject","fetchQuota","then","HttpFailure","status","bodyText","getHeader","name","next","Error","constructor","headers","get","config","token","forceRefresh","withTimeout","quotaMs","signal","response","Authorization","ok","text","parsed","json"],"sourceRoot":"../../../src","sources":["core/quotaRequest.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.AiError = void 0;
|
|
7
|
+
exports.errorFromHttp = errorFromHttp;
|
|
8
|
+
exports.isAiError = isAiError;
|
|
9
|
+
exports.parseRetryAfter = parseRetryAfter;
|
|
10
|
+
var _rnCore = require("@chipmobilesdk/rn-core");
|
|
11
|
+
var _gateway = require("../contract/gateway.js");
|
|
12
|
+
/** Typed client errors (contracts/rn-ai-public-api.md). */
|
|
13
|
+
|
|
14
|
+
/** Codes a retry can fix on its own. */
|
|
15
|
+
const RETRYABLE_BY_DEFAULT = new Set(['rate-limited', 'upstream-busy', 'network']);
|
|
16
|
+
|
|
17
|
+
/** The package's error; an `SdkError` (`@chipmobilesdk/rn-core`) with `pkg: 'rn-ai'`. */
|
|
18
|
+
class AiError extends _rnCore.SdkError {
|
|
19
|
+
/** The underlying code, when one layer down had a name for the failure. */
|
|
20
|
+
|
|
21
|
+
constructor(code, message, options = {}) {
|
|
22
|
+
super('rn-ai', code, {
|
|
23
|
+
message,
|
|
24
|
+
retryable: options.retryable ?? options.recoverable ?? RETRYABLE_BY_DEFAULT.has(code)
|
|
25
|
+
});
|
|
26
|
+
this.name = 'AiError';
|
|
27
|
+
this.retryAfterSeconds = options.retryAfterSeconds;
|
|
28
|
+
this.cause = options.cause;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** @deprecated Use `retryable`, the name every SDK package shares. */
|
|
32
|
+
get recoverable() {
|
|
33
|
+
return this.retryable;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.AiError = AiError;
|
|
37
|
+
function isAiError(value) {
|
|
38
|
+
return value instanceof AiError;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Every gateway code, mapped. Typed as a total record, so a code added to the
|
|
43
|
+
* shared contract does not compile until the client says what it means (GW-13).
|
|
44
|
+
*/
|
|
45
|
+
const HTTP_CODE_MAP = {
|
|
46
|
+
BAD_REQUEST: 'internal',
|
|
47
|
+
AUTH_INVALID: 'auth-invalid',
|
|
48
|
+
NOT_ENTITLED: 'not-entitled',
|
|
49
|
+
USER_BLOCKED: 'user-blocked',
|
|
50
|
+
APP_UNKNOWN: 'app-unknown',
|
|
51
|
+
// The endpoint moved: the client's configuration is the stale part.
|
|
52
|
+
ENDPOINT_RETIRED: 'config-unavailable',
|
|
53
|
+
PAYLOAD_TOO_LARGE: 'payload-too-large',
|
|
54
|
+
MODALITY_NOT_ALLOWED: 'modality-not-allowed',
|
|
55
|
+
RATE_LIMITED: 'rate-limited',
|
|
56
|
+
UPSTREAM_BUSY: 'upstream-busy',
|
|
57
|
+
UPSTREAM_ERROR: 'upstream-error',
|
|
58
|
+
INTERNAL: 'internal'
|
|
59
|
+
};
|
|
60
|
+
function isGatewayCode(value) {
|
|
61
|
+
return typeof value === 'string' && value in HTTP_CODE_MAP;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** `Retry-After` in seconds, from either form the header may take. */
|
|
65
|
+
function parseRetryAfter(value) {
|
|
66
|
+
if (!value) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
const seconds = Number(value);
|
|
70
|
+
if (Number.isFinite(seconds) && seconds >= 0) {
|
|
71
|
+
return seconds;
|
|
72
|
+
}
|
|
73
|
+
const date = Date.parse(value);
|
|
74
|
+
if (Number.isFinite(date)) {
|
|
75
|
+
return Math.max(0, Math.round((date - Date.now()) / 1000));
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
/** Map a gateway error response (status + JSON body) to a typed AiError. */
|
|
80
|
+
function errorFromHttp(status, bodyText, context = {}) {
|
|
81
|
+
// Status 0 is not an answer at all: the request never arrived, or the
|
|
82
|
+
// connection dropped. That is a network failure a retry may well fix, not an
|
|
83
|
+
// upstream fault (AI-11).
|
|
84
|
+
if (status === 0) {
|
|
85
|
+
return new AiError('network', bodyText === 'timeout' ? 'the request timed out' : 'no connection');
|
|
86
|
+
}
|
|
87
|
+
let code = status >= 500 ? 'upstream-error' : 'internal';
|
|
88
|
+
let message = `gateway responded ${status}`;
|
|
89
|
+
let gatewayCode;
|
|
90
|
+
let retryAfterSeconds = parseRetryAfter(context.getHeader?.(_gateway.RETRY_AFTER_HEADER));
|
|
91
|
+
try {
|
|
92
|
+
const parsed = JSON.parse(bodyText);
|
|
93
|
+
if (isGatewayCode(parsed.error?.code)) {
|
|
94
|
+
gatewayCode = parsed.error.code;
|
|
95
|
+
code = HTTP_CODE_MAP[gatewayCode];
|
|
96
|
+
}
|
|
97
|
+
// The gateway's text can quote upstream detail; keep it readable but shaped.
|
|
98
|
+
if (parsed.error?.message) message = (0, _rnCore.redactPatterns)(parsed.error.message);
|
|
99
|
+
retryAfterSeconds = parsed.error?.retryAfterSeconds ?? retryAfterSeconds;
|
|
100
|
+
} catch {
|
|
101
|
+
// A body that is not the contract's: the status is all there is to go on.
|
|
102
|
+
}
|
|
103
|
+
return new AiError(code, message, {
|
|
104
|
+
retryAfterSeconds,
|
|
105
|
+
cause: gatewayCode
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_rnCore","require","_gateway","RETRYABLE_BY_DEFAULT","Set","AiError","SdkError","constructor","code","message","options","retryable","recoverable","has","name","retryAfterSeconds","cause","exports","isAiError","value","HTTP_CODE_MAP","BAD_REQUEST","AUTH_INVALID","NOT_ENTITLED","USER_BLOCKED","APP_UNKNOWN","ENDPOINT_RETIRED","PAYLOAD_TOO_LARGE","MODALITY_NOT_ALLOWED","RATE_LIMITED","UPSTREAM_BUSY","UPSTREAM_ERROR","INTERNAL","isGatewayCode","parseRetryAfter","undefined","seconds","Number","isFinite","date","Date","parse","Math","max","round","now","errorFromHttp","status","bodyText","context","gatewayCode","getHeader","RETRY_AFTER_HEADER","parsed","JSON","error","redactPatterns"],"sourceRoot":"../../../src","sources":["diagnostics/errors.ts"],"mappings":";;;;;;;;;AACA,IAAAA,OAAA,GAAAC,OAAA;AAEA,IAAAC,QAAA,GAAAD,OAAA;AAHA;;AAuCA;AACA,MAAME,oBAA8C,GAAG,IAAIC,GAAG,CAAc,CAC3E,cAAc,EACd,eAAe,EACf,SAAS,CACT,CAAC;;AAEF;AACO,MAAMC,OAAO,SAASC,gBAAQ,CAAc;EAElD;;EAGAC,WAAWA,CAACC,IAAiB,EAAEC,OAAe,EAAEC,OAAuB,GAAG,CAAC,CAAC,EAAE;IAC7E,KAAK,CAAC,OAAO,EAAEF,IAAI,EAAE;MACpBC,OAAO;MACPE,SAAS,EAAED,OAAO,CAACC,SAAS,IAAID,OAAO,CAACE,WAAW,IAAIT,oBAAoB,CAACU,GAAG,CAACL,IAAI;IACrF,CAAC,CAAC;IACF,IAAI,CAACM,IAAI,GAAG,SAAS;IACrB,IAAI,CAACC,iBAAiB,GAAGL,OAAO,CAACK,iBAAiB;IAClD,IAAI,CAACC,KAAK,GAAGN,OAAO,CAACM,KAAK;EAC3B;;EAEA;EACA,IAAIJ,WAAWA,CAAA,EAAY;IAC1B,OAAO,IAAI,CAACD,SAAS;EACtB;AACD;AAACM,OAAA,CAAAZ,OAAA,GAAAA,OAAA;AAEM,SAASa,SAASA,CAACC,KAAc,EAAoB;EAC3D,OAAOA,KAAK,YAAYd,OAAO;AAChC;;AAEA;AACA;AACA;AACA;AACA,MAAMe,aAA8D,GAAG;EACtEC,WAAW,EAAE,UAAU;EACvBC,YAAY,EAAE,cAAc;EAC5BC,YAAY,EAAE,cAAc;EAC5BC,YAAY,EAAE,cAAc;EAC5BC,WAAW,EAAE,aAAa;EAC1B;EACAC,gBAAgB,EAAE,oBAAoB;EACtCC,iBAAiB,EAAE,mBAAmB;EACtCC,oBAAoB,EAAE,sBAAsB;EAC5CC,YAAY,EAAE,cAAc;EAC5BC,aAAa,EAAE,eAAe;EAC9BC,cAAc,EAAE,gBAAgB;EAChCC,QAAQ,EAAE;AACX,CAAC;AAED,SAASC,aAAaA,CAACd,KAAc,EAA6B;EACjE,OAAO,OAAOA,KAAK,KAAK,QAAQ,IAAIA,KAAK,IAAIC,aAAa;AAC3D;;AAEA;AACO,SAASc,eAAeA,CAACf,KAAgC,EAAsB;EACrF,IAAI,CAACA,KAAK,EAAE;IACX,OAAOgB,SAAS;EACjB;EACA,MAAMC,OAAO,GAAGC,MAAM,CAAClB,KAAK,CAAC;EAC7B,IAAIkB,MAAM,CAACC,QAAQ,CAACF,OAAO,CAAC,IAAIA,OAAO,IAAI,CAAC,EAAE;IAC7C,OAAOA,OAAO;EACf;EACA,MAAMG,IAAI,GAAGC,IAAI,CAACC,KAAK,CAACtB,KAAK,CAAC;EAC9B,IAAIkB,MAAM,CAACC,QAAQ,CAACC,IAAI,CAAC,EAAE;IAC1B,OAAOG,IAAI,CAACC,GAAG,CAAC,CAAC,EAAED,IAAI,CAACE,KAAK,CAAC,CAACL,IAAI,GAAGC,IAAI,CAACK,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;EAC3D;EACA,OAAOV,SAAS;AACjB;AAOA;AACO,SAASW,aAAaA,CAC5BC,MAAc,EACdC,QAAgB,EAChBC,OAAyB,GAAG,CAAC,CAAC,EACpB;EACV;EACA;EACA;EACA,IAAIF,MAAM,KAAK,CAAC,EAAE;IACjB,OAAO,IAAI1C,OAAO,CACjB,SAAS,EACT2C,QAAQ,KAAK,SAAS,GAAG,uBAAuB,GAAG,eACpD,CAAC;EACF;EAEA,IAAIxC,IAAiB,GAAGuC,MAAM,IAAI,GAAG,GAAG,gBAAgB,GAAG,UAAU;EACrE,IAAItC,OAAO,GAAG,qBAAqBsC,MAAM,EAAE;EAC3C,IAAIG,WAAyC;EAC7C,IAAInC,iBAAiB,GAAGmB,eAAe,CAACe,OAAO,CAACE,SAAS,GAAGC,2BAAkB,CAAC,CAAC;EAChF,IAAI;IACH,MAAMC,MAAM,GAAGC,IAAI,CAACb,KAAK,CAACO,QAAQ,CAA8B;IAChE,IAAIf,aAAa,CAACoB,MAAM,CAACE,KAAK,EAAE/C,IAAI,CAAC,EAAE;MACtC0C,WAAW,GAAGG,MAAM,CAACE,KAAK,CAAC/C,IAAI;MAC/BA,IAAI,GAAGY,aAAa,CAAC8B,WAAW,CAAC;IAClC;IACA;IACA,IAAIG,MAAM,CAACE,KAAK,EAAE9C,OAAO,EAAEA,OAAO,GAAG,IAAA+C,sBAAc,EAACH,MAAM,CAACE,KAAK,CAAC9C,OAAO,CAAC;IACzEM,iBAAiB,GAAGsC,MAAM,CAACE,KAAK,EAAExC,iBAAiB,IAAIA,iBAAiB;EACzE,CAAC,CAAC,MAAM;IACP;EAAA;EAED,OAAO,IAAIV,OAAO,CAACG,IAAI,EAAEC,OAAO,EAAE;IAAEM,iBAAiB;IAAEC,KAAK,EAAEkC;EAAY,CAAC,CAAC;AAC7E","ignoreList":[]}
|