@deepwatch/dsh-client-settings 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,543 @@
1
+ /**
2
+ * The browser's view of what is configured, assembled from four Host answers.
3
+ *
4
+ * A person saved an OpenRouter credential, saw a green dot and the words
5
+ * "Saved openrouter.", and reasonably concluded the product was ready. It was
6
+ * not: no model had been chosen and nothing had been assigned to anything. The
7
+ * dot was answering "is a credential stored?" while the reader was asking "can
8
+ * I send a message?", and those turn out to be four separate questions.
9
+ *
10
+ * So this store never derives readiness itself. It gathers the four facts —
11
+ * from `llm.providers`, `llm.models`, `credentials.describe` and the stored
12
+ * bindings in `settings.describe` — and hands them to `roleReadiness`, which
13
+ * is the only thing in this product allowed to answer "ready". A surface that
14
+ * wanted to shade a dot green would have to go through the same gate.
15
+ *
16
+ * **Nothing here contacts a provider.** Opening a settings page must not spend
17
+ * somebody's money or rate budget, so reachability stays `unknown` until a
18
+ * person asks for a check. That is why a freshly saved credential reads
19
+ * "Credential saved · not yet assigned" rather than a claim about whether it
20
+ * works: the honest state after a save is *stored*, and the product says so.
21
+ *
22
+ * **No value crosses this boundary.** `credentials.describe` is structurally
23
+ * value-free — it answers `configured`, `source`, `writable` and has no slot
24
+ * for a value — and the binding this store writes holds a reference the Host
25
+ * resolves. There is nowhere in this file for a key to be, which is the
26
+ * property that makes the store safe to render, log and screenshot.
27
+ *
28
+ * @module @deepwatch/dsh-client-settings/binding-state
29
+ */
30
+ import { BINDABLE_ROLES, BINDINGS_NAMESPACE, BINDINGS_VERSION, EMPTY_BINDINGS, PRIMARY_ROLE, ROLE_MODALITIES, assertNoSecretMaterial, bindingFor, readBindings, roleReadiness, withBinding, withoutBinding, } from '@deepwatch/dsh-contracts';
31
+ /**
32
+ * Upstream's own settings section for the selection a new session starts with.
33
+ *
34
+ * Spelled here rather than imported: `AGENT_DEFAULT_MODEL_SETTINGS_NAMESPACE`
35
+ * lives in a Host package, and a browser bundle that imported it would carry
36
+ * the Harness's server-side settings machinery to learn one string.
37
+ * `tests/binding-flow.test.mjs` holds it to the value the pinned baseline
38
+ * composes.
39
+ */
40
+ export const DEFAULT_MODEL_NAMESPACE = 'agent-default-model';
41
+ /**
42
+ * The identity a provider test result belongs to.
43
+ *
44
+ * Provider and model alone are not enough. Rebinding a role to a route served
45
+ * through a different credential must not inherit the previous verdict — that
46
+ * is the same "saved means working" claim this whole file exists to remove,
47
+ * wearing a route it was never asked about. So the credential *reference* is
48
+ * part of the key.
49
+ *
50
+ * What it deliberately cannot see: a value rotated behind a reference that
51
+ * did not change. No credential value crosses this boundary, so the browser
52
+ * half has nothing to compare. A result therefore lives only as long as the
53
+ * session that produced it, and is never persisted or restored — an untested
54
+ * binding after a reload reads as untested, which is the truthful answer.
55
+ */
56
+ export function providerTestKey(provider, model, credentialRef) {
57
+ return [provider, model, credentialRef ?? ''].join('\u0000');
58
+ }
59
+ const EMPTY = {
60
+ status: 'idle',
61
+ error: null,
62
+ writable: false,
63
+ providers: [],
64
+ roles: [],
65
+ bindings: EMPTY_BINDINGS,
66
+ saving: false,
67
+ testingRole: null,
68
+ testMessage: null,
69
+ };
70
+ /* ── deriving the four facts ────────────────────────────────────────────── */
71
+ /**
72
+ * The credential reference a provider's own settings section names.
73
+ *
74
+ * Walked out of the described value rather than asked for separately: the
75
+ * settings domain already returns each namespace's resolved value, and
76
+ * `apiKeyEnv` is a field in it. The walk is plain property access because the
77
+ * described value is plain JSON — the secret slots have already been removed
78
+ * by the seam, which is what makes reading this safe.
79
+ */
80
+ export function credentialRefOf(view, path) {
81
+ if (view === undefined)
82
+ return null;
83
+ let cursor = view.value;
84
+ for (const step of path) {
85
+ if (typeof cursor !== 'object' || cursor === null)
86
+ return null;
87
+ cursor = cursor[step];
88
+ }
89
+ if (typeof cursor !== 'object' || cursor === null)
90
+ return null;
91
+ const ref = cursor['apiKeyEnv'];
92
+ return typeof ref === 'string' && ref !== '' ? ref : null;
93
+ }
94
+ /**
95
+ * What is known about a provider's credential.
96
+ *
97
+ * `configured_unverified` rather than `verified` is the whole point. The Host
98
+ * can say a value resolves; only a provider can say it works, and nothing here
99
+ * has asked one. Calling a stored credential verified is the claim that sent a
100
+ * prompt to a provider nobody had configured.
101
+ */
102
+ export function credentialStatusOf(ref, described, readable) {
103
+ if (ref === null)
104
+ return 'absent';
105
+ // A store that could not be read is a fault to report, not an empty slot to
106
+ // fill: telling somebody to add a credential they already added is how a
107
+ // person ends up entering a key three times.
108
+ if (!readable)
109
+ return 'inaccessible';
110
+ return described[ref]?.configured === true ? 'configured_unverified' : 'absent';
111
+ }
112
+ /** The route capability a provider row amounts to. */
113
+ function routeOf(row, role) {
114
+ if (row === undefined || !row.active)
115
+ return null;
116
+ return {
117
+ provider: row.provider,
118
+ // Every bindable role, because DSH's directory describes routes rather
119
+ // than roles: a chat-completions endpoint is not annotated with which of
120
+ // this product's capabilities it could serve. Narrowing it here would
121
+ // invent a restriction the provider never stated.
122
+ roles: [...BINDABLE_ROLES],
123
+ modalities: ROLE_MODALITIES[role],
124
+ // Null, not empty, when the provider advertised nothing: "nobody asked" and
125
+ // "the provider offers no models" are different, and only the second one
126
+ // should make a stored model read as unavailable.
127
+ models: row.models.length === 0 ? null : row.models.map(model => model.id),
128
+ };
129
+ }
130
+ /** Everything known about one role, folded through the single readiness gate. */
131
+ export function roleRowOf(role, bindings, providers, tests = new Map()) {
132
+ const binding = bindingFor(bindings, role);
133
+ const row = binding === null
134
+ ? undefined
135
+ : providers.find(entry => entry.provider === binding.provider);
136
+ const route = routeOf(row, role);
137
+ const known = route?.models ?? null;
138
+ const tested = binding === null
139
+ ? undefined
140
+ : tests.get(providerTestKey(binding.provider, binding.model, row?.credentialRef ?? null));
141
+ const readiness = roleReadiness(role, {
142
+ binding,
143
+ credential: tested?.credential ?? row?.credential ?? 'absent',
144
+ // Never probed from a settings page. A person asks for a check; opening a
145
+ // screen is not asking.
146
+ reachability: tested?.reachability ?? 'unknown',
147
+ model: binding === null
148
+ ? 'none'
149
+ : known === null || known.includes(binding.model) ? 'selected' : 'unavailable',
150
+ route,
151
+ consentGranted: true,
152
+ policyPermits: true,
153
+ contractMatches: true,
154
+ });
155
+ return {
156
+ role,
157
+ provider: binding?.provider ?? null,
158
+ model: binding?.model ?? null,
159
+ readiness,
160
+ };
161
+ }
162
+ /* ── the store ──────────────────────────────────────────────────────────── */
163
+ /**
164
+ * The binding store, shaped for `useSyncExternalStore`.
165
+ *
166
+ * Deliberately a plain object with `subscribe`/`getSnapshot` rather than a
167
+ * framework store: this package's browser half is loaded into somebody else's
168
+ * React tree, and bringing a state library into a plugin bundle to hold six
169
+ * fields is how a distribution ends up shipping two of them.
170
+ */
171
+ export class BindingStore {
172
+ api;
173
+ providerTester;
174
+ readinessReader;
175
+ snapshot = EMPTY;
176
+ listeners = new Set();
177
+ /** Guards against a slow load landing after a newer one. */
178
+ generation = 0;
179
+ revision;
180
+ defaultRevision;
181
+ providerTests = new Map();
182
+ providerTestAbort = null;
183
+ constructor(api, providerTester, readinessReader) {
184
+ this.api = api;
185
+ this.providerTester = providerTester;
186
+ this.readinessReader = readinessReader;
187
+ }
188
+ /**
189
+ * Replace what this tab believes about tested routes with what the Host says.
190
+ *
191
+ * The browser used to be the only place a provider-test verdict lived, and a
192
+ * tab cannot see a Host restart, an edit made in another tab, or a key
193
+ * rotated behind a reference that did not change. It drew a tested badge over
194
+ * routes the Host had already stopped being willing to serve, and the
195
+ * composer that badge unlocks opened onto a refusal.
196
+ *
197
+ * So the Host is asked, per bound route, and its answer wins in both
198
+ * directions: a route it still proves is tested even in a tab that has just
199
+ * been reloaded and ran no test, and a route it no longer proves stops being
200
+ * tested here the moment this is read.
201
+ */
202
+ async reconcileReadiness(bindings, providers, signal) {
203
+ if (this.readinessReader === undefined)
204
+ return;
205
+ for (const role of BINDABLE_ROLES) {
206
+ const binding = bindingFor(bindings, role);
207
+ if (binding === null)
208
+ continue;
209
+ const credentialRef = providers
210
+ .find(entry => entry.provider === binding.provider)?.credentialRef ?? null;
211
+ const key = providerTestKey(binding.provider, binding.model, credentialRef);
212
+ let verdict;
213
+ try {
214
+ verdict = await this.readinessReader(binding.provider, binding.model, signal);
215
+ }
216
+ catch {
217
+ // A read that failed says nothing about the route, and inventing
218
+ // either answer would be the defect. The tab keeps what it has.
219
+ continue;
220
+ }
221
+ if (signal.aborted)
222
+ return;
223
+ if (verdict.proved) {
224
+ this.providerTests.set(key, {
225
+ provider: binding.provider,
226
+ model: binding.model,
227
+ ok: true,
228
+ credential: 'verified',
229
+ reachability: 'reachable',
230
+ // Deliberately not "the provider test succeeded": this tab did not
231
+ // run one. What is true is that the Host still holds the proof.
232
+ message: 'The Host still holds a proof for this route.',
233
+ });
234
+ }
235
+ else {
236
+ this.providerTests.delete(key);
237
+ }
238
+ }
239
+ }
240
+ /** @returns the current snapshot; stable between changes. */
241
+ getSnapshot = () => this.snapshot;
242
+ /** @param listener - called after every change. @returns the unsubscriber. */
243
+ subscribe = (listener) => {
244
+ this.listeners.add(listener);
245
+ return () => { this.listeners.delete(listener); };
246
+ };
247
+ publish(next) {
248
+ this.snapshot = { ...this.snapshot, ...next };
249
+ for (const listener of this.listeners)
250
+ listener();
251
+ }
252
+ /**
253
+ * Ask the Host everything, and fold it into one snapshot.
254
+ *
255
+ * The three reads run together because they are independent and a settings
256
+ * page that took three round trips in series felt broken on a slow link.
257
+ * Their failures are not equal, though: providers and settings are the page,
258
+ * so losing either is an error, while a credential describe that fails
259
+ * downgrades those providers to `inaccessible` and leaves the rest readable.
260
+ */
261
+ async load() {
262
+ const generation = ++this.generation;
263
+ this.publish({ status: 'loading', error: null });
264
+ let providers;
265
+ let namespaces;
266
+ let groups = [];
267
+ let failures = [];
268
+ let writable = false;
269
+ try {
270
+ const [directory, settings, catalogue] = await Promise.all([
271
+ this.api.llm.providers({}),
272
+ this.api.settings.describe({}),
273
+ // A catalogue read can fail per provider without failing the page, so
274
+ // its rejection is absorbed rather than allowed to take the load down.
275
+ this.api.llm.models({}).catch(() => null),
276
+ ]);
277
+ if (!directory.result.ok)
278
+ throw new Error(directory.result.error.message);
279
+ if (!settings.result.ok)
280
+ throw new Error(settings.result.error.message);
281
+ providers = directory.result.value.providers;
282
+ namespaces = settings.result.value.namespaces;
283
+ writable = settings.result.value.writable;
284
+ if (catalogue !== null && catalogue.result.ok) {
285
+ groups = catalogue.result.value.groups;
286
+ failures = catalogue.result.value.failures;
287
+ }
288
+ }
289
+ catch (error) {
290
+ if (generation !== this.generation)
291
+ return;
292
+ this.publish({
293
+ status: 'error',
294
+ error: error instanceof Error ? error.message : String(error),
295
+ });
296
+ return;
297
+ }
298
+ const byNs = new Map(namespaces.map(view => [view.ns, view]));
299
+ const stored = byNs.get(BINDINGS_NAMESPACE);
300
+ this.revision = stored?.revision;
301
+ const bindings = readBindings(stored?.value);
302
+ const refs = new Map();
303
+ for (const entry of providers) {
304
+ refs.set(entry.provider, credentialRefOf(byNs.get(entry.settingsNs), entry.settingsPath));
305
+ }
306
+ const wanted = [...new Set([...refs.values()].filter((ref) => ref !== null))];
307
+ let credentials = {};
308
+ let readable = true;
309
+ if (wanted.length > 0) {
310
+ try {
311
+ const answer = await this.api.credentials.describe({ refs: wanted });
312
+ if (answer.result.ok)
313
+ credentials = answer.result.value.credentials;
314
+ else
315
+ readable = false;
316
+ }
317
+ catch {
318
+ readable = false;
319
+ }
320
+ }
321
+ if (generation !== this.generation)
322
+ return;
323
+ const catalogByProvider = new Map(groups.map(group => [group.id, group]));
324
+ const failureByProvider = new Map(failures.map(entry => [entry.id, entry.message]));
325
+ const rows = providers.map((entry) => {
326
+ const ref = refs.get(entry.provider) ?? null;
327
+ return {
328
+ provider: entry.provider,
329
+ displayName: entry.displayName,
330
+ active: entry.active,
331
+ credentialRef: ref,
332
+ credential: credentialStatusOf(ref, credentials, readable),
333
+ models: catalogByProvider.get(entry.provider)?.models ?? [],
334
+ catalogError: failureByProvider.get(entry.provider) ?? null,
335
+ };
336
+ });
337
+ // Before the first publish, so no frame is ever drawn from this tab's own
338
+ // memory when the Host has a different answer.
339
+ const readiness = new AbortController();
340
+ await this.reconcileReadiness(bindings, rows, readiness.signal);
341
+ if (generation !== this.generation)
342
+ return;
343
+ this.publish({
344
+ status: 'ready',
345
+ error: null,
346
+ writable,
347
+ providers: rows,
348
+ bindings,
349
+ roles: BINDABLE_ROLES.map(role => roleRowOf(role, bindings, rows, this.providerTests)),
350
+ });
351
+ // The binding is the authority; the Harness selection is a projection of
352
+ // it. Reconciling on read rather than only on write means a profile bound
353
+ // by an earlier build -- or a settings file somebody edited by hand -- is
354
+ // repaired by being looked at, instead of staying in the state this whole
355
+ // subsystem exists to prevent: a decision recorded, and a runtime that
356
+ // never heard about it.
357
+ if (writable)
358
+ await this.reconcileDefaultSelection(bindings, byNs.get(DEFAULT_MODEL_NAMESPACE));
359
+ }
360
+ /**
361
+ * Write the Harness selection only when it disagrees with the binding.
362
+ *
363
+ * Guarded on disagreement because this runs on every load: rewriting an
364
+ * already-correct section would bump its revision, invalidate every other
365
+ * open editor's `expectedRevision`, and turn a read into a source of write
366
+ * conflicts.
367
+ */
368
+ async reconcileDefaultSelection(bindings, view) {
369
+ this.defaultRevision = view?.revision;
370
+ const chat = bindings.roles[PRIMARY_ROLE];
371
+ const wanted = chat === undefined
372
+ ? { provider: '', model: '' }
373
+ : { provider: chat.provider, model: chat.model };
374
+ const current = (view?.value ?? {});
375
+ if (current.provider === wanted.provider && current.model === wanted.model)
376
+ return;
377
+ await this.syncDefaultSelection(bindings);
378
+ }
379
+ /**
380
+ * Bind one role to one provider and model, and persist the decision.
381
+ *
382
+ * `replace` rather than `update`, because unbinding has to be expressible:
383
+ * a merge cannot remove a key, and a role that could be added but not
384
+ * removed is a role somebody is stuck with. The whole document is rewritten
385
+ * from the snapshot the caller is looking at, and `expectedRevision` is what
386
+ * turns a concurrent edit into a refusal rather than a silent overwrite.
387
+ */
388
+ async bind(role, provider, model) {
389
+ const row = this.snapshot.providers.find(entry => entry.provider === provider);
390
+ await this.write(withBinding(this.snapshot.bindings, role, {
391
+ provider,
392
+ model,
393
+ credentialRef: row?.credentialRef ?? null,
394
+ boundAt: new Date().toISOString(),
395
+ // This path is reached only from Role Bindings, where somebody chose a
396
+ // provider and a model and pressed Save. Nothing else in the product
397
+ // calls it, and a writer that cannot say this truthfully must leave the
398
+ // field alone rather than claim it.
399
+ boundBy: 'person',
400
+ }));
401
+ }
402
+ /** Remove one role's binding. The role becomes unbound, never inherited. */
403
+ async unbind(role) {
404
+ await this.write(withoutBinding(this.snapshot.bindings, role));
405
+ }
406
+ /** Run the exact bound route once; saving a credential never calls this. */
407
+ async testRole(role) {
408
+ const binding = bindingFor(this.snapshot.bindings, role);
409
+ if (binding === null || this.providerTester === undefined) {
410
+ this.publish({ testMessage: 'Assign a provider and model before running the test.' });
411
+ return;
412
+ }
413
+ const credentialRef = this.snapshot.providers
414
+ .find(entry => entry.provider === binding.provider)?.credentialRef ?? null;
415
+ const controller = new AbortController();
416
+ this.providerTestAbort?.abort();
417
+ this.providerTestAbort = controller;
418
+ this.publish({ testingRole: role, testMessage: null });
419
+ try {
420
+ const facts = await this.providerTester(binding.provider, binding.model, controller.signal);
421
+ if (controller.signal.aborted)
422
+ return;
423
+ this.providerTests.set(providerTestKey(binding.provider, binding.model, credentialRef), facts);
424
+ this.publish({
425
+ testingRole: null,
426
+ testMessage: facts.message,
427
+ roles: BINDABLE_ROLES.map(current => roleRowOf(current, this.snapshot.bindings, this.snapshot.providers, this.providerTests)),
428
+ });
429
+ }
430
+ catch {
431
+ if (controller.signal.aborted)
432
+ return;
433
+ this.publish({
434
+ testingRole: null,
435
+ testMessage: 'The provider test could not be started. Check Diagnostics and try again.',
436
+ });
437
+ }
438
+ finally {
439
+ if (this.providerTestAbort === controller)
440
+ this.providerTestAbort = null;
441
+ }
442
+ }
443
+ /** Cancel only the explicit provider probe; no Chat turn is involved. */
444
+ cancelProviderTest() {
445
+ if (this.providerTestAbort === null)
446
+ return;
447
+ this.providerTestAbort.abort();
448
+ this.providerTestAbort = null;
449
+ this.publish({
450
+ testingRole: null,
451
+ testMessage: 'Provider test cancelled. This binding remains not tested.',
452
+ });
453
+ }
454
+ /**
455
+ * Point the Harness's own default selection at what Chat is bound to.
456
+ *
457
+ * The link this subsystem was missing, and the failure it caused is worth
458
+ * stating plainly: a person added a provider, chose a model and assigned it
459
+ * to Chat, and still could not send. Every DeepWatch surface agreed the
460
+ * binding existed. It did — in DeepWatch's document. But the thing that
461
+ * actually routes a prompt is the Harness's model selection, which this
462
+ * distribution had *emptied* so that nothing would be chosen for anybody,
463
+ * and binding Chat never filled it in. Two records of one decision, and the
464
+ * one the runtime reads was the one nobody was writing.
465
+ *
466
+ * So a Chat binding writes both. `agent-default-model` is upstream's own
467
+ * settings section, read live by `AgentDefaultModelConfig` and re-read by a
468
+ * blank session on every look — so a session opened before the binding
469
+ * picks it up without being told.
470
+ *
471
+ * Only Chat. The other roles are DeepWatch's own concepts and have no
472
+ * upstream selection to keep in step; writing one for them would point the
473
+ * conversation at a model chosen for something else.
474
+ */
475
+ async syncDefaultSelection(next) {
476
+ const chat = next.roles[PRIMARY_ROLE];
477
+ const section = chat === undefined
478
+ // Emptied rather than removed: the row stays mounted and its schema
479
+ // requires both keys, so "nothing chosen" is two empty strings -- which
480
+ // is exactly the value a fresh profile composes.
481
+ ? { provider: '', model: '' }
482
+ : { provider: chat.provider, model: chat.model };
483
+ try {
484
+ const response = await this.api.settings.replace({
485
+ ns: DEFAULT_MODEL_NAMESPACE,
486
+ section,
487
+ ...this.defaultRevision === undefined ? {} : { expectedRevision: this.defaultRevision },
488
+ });
489
+ if (response.result.ok)
490
+ this.defaultRevision = response.result.value.revision;
491
+ else
492
+ this.publish({ error: response.result.error.message });
493
+ }
494
+ catch (error) {
495
+ this.publish({ error: error instanceof Error ? error.message : String(error) });
496
+ }
497
+ }
498
+ async write(next) {
499
+ // Before the document leaves the browser, not after somebody reports it in
500
+ // a screenshot. Every write path builds this from a picker, so a value
501
+ // matching a credential shape means a code path started copying one.
502
+ assertNoSecretMaterial('the binding document', next);
503
+ this.publish({ saving: true, error: null });
504
+ try {
505
+ const response = await this.api.settings.replace({
506
+ ns: BINDINGS_NAMESPACE,
507
+ section: { version: BINDINGS_VERSION, roles: next.roles },
508
+ ...this.revision === undefined ? {} : { expectedRevision: this.revision },
509
+ });
510
+ if (!response.result.ok) {
511
+ this.publish({ saving: false, error: response.result.error.message });
512
+ return;
513
+ }
514
+ this.revision = response.result.value.revision;
515
+ const bindings = readBindings(response.result.value.value);
516
+ // After the binding is durable, never before: a default pointing at a
517
+ // binding that failed to save would route somewhere the record does not
518
+ // admit to.
519
+ await this.syncDefaultSelection(bindings);
520
+ this.publish({
521
+ saving: false,
522
+ bindings,
523
+ roles: BINDABLE_ROLES.map(role => roleRowOf(role, bindings, this.snapshot.providers, this.providerTests)),
524
+ });
525
+ }
526
+ catch (error) {
527
+ this.publish({
528
+ saving: false,
529
+ error: error instanceof Error ? error.message : String(error),
530
+ });
531
+ }
532
+ }
533
+ }
534
+ /**
535
+ * Whether the capability a conversation needs can actually run.
536
+ *
537
+ * The one question the composer asks, given its own name so no surface has to
538
+ * remember which role Chat is or re-derive readiness to find out.
539
+ */
540
+ export function chatReadiness(snapshot) {
541
+ return snapshot.roles.find(row => row.role === PRIMARY_ROLE)?.readiness ?? null;
542
+ }
543
+ //# sourceMappingURL=binding-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding-state.js","sourceRoot":"","sources":["../../src/client/binding-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EACL,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAClF,eAAe,EAAE,sBAAsB,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAChF,WAAW,EAAE,cAAc,GAC5B,MAAM,0BAA0B,CAAA;AAMjC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,qBAAqB,CAAA;AA6E5D;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAAE,KAAa,EAAE,aAA4B;IAE7D,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AAC9D,CAAC;AA4ED,MAAM,KAAK,GAAoB;IAC7B,MAAM,EAAE,MAAM;IACd,KAAK,EAAE,IAAI;IACX,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,EAAE;IACb,KAAK,EAAE,EAAE;IACT,QAAQ,EAAE,cAAc;IACxB,MAAM,EAAE,KAAK;IACb,WAAW,EAAE,IAAI;IACjB,WAAW,EAAE,IAAI;CAClB,CAAA;AAED,+EAA+E;AAE/E;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,IAA+B,EAAE,IAAuB;IAExD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACnC,IAAI,MAAM,GAAY,IAAI,CAAC,KAAK,CAAA;IAChC,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,IAAI,CAAA;QAC9D,MAAM,GAAI,MAAkC,CAAC,IAAI,CAAC,CAAA;IACpD,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAC9D,MAAM,GAAG,GAAI,MAAkC,CAAC,WAAW,CAAC,CAAA;IAC5D,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA;AAC3D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,GAAkB,EAAE,SAAyC,EAAE,QAAiB;IAEhF,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,QAAQ,CAAA;IACjC,4EAA4E;IAC5E,yEAAyE;IACzE,6CAA6C;IAC7C,IAAI,CAAC,QAAQ;QAAE,OAAO,cAAc,CAAA;IACpC,OAAO,SAAS,CAAC,GAAG,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,QAAQ,CAAA;AACjF,CAAC;AAED,sDAAsD;AACtD,SAAS,OAAO,CAAC,GAA4B,EAAE,IAAkB;IAC/D,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IACjD,OAAO;QACL,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,uEAAuE;QACvE,yEAAyE;QACzE,sEAAsE;QACtE,kDAAkD;QAClD,KAAK,EAAE,CAAC,GAAG,cAAc,CAAC;QAC1B,UAAU,EAAE,eAAe,CAAC,IAAI,CAAC;QACjC,4EAA4E;QAC5E,yEAAyE;QACzE,kDAAkD;QAClD,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;KAC3E,CAAA;AACH,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,SAAS,CACvB,IAAkB,EAAE,QAAuB,EAAE,SAAiC,EAC9E,QAAgD,IAAI,GAAG,EAAE;IAEzD,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAC1C,MAAM,GAAG,GAAG,OAAO,KAAK,IAAI;QAC1B,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IAChE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAChC,MAAM,KAAK,GAAG,KAAK,EAAE,MAAM,IAAI,IAAI,CAAA;IACnC,MAAM,MAAM,GAAG,OAAO,KAAK,IAAI;QAC7B,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,aAAa,IAAI,IAAI,CAAC,CAAC,CAAA;IAC3F,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,EAAE;QACpC,OAAO;QACP,UAAU,EAAE,MAAM,EAAE,UAAU,IAAI,GAAG,EAAE,UAAU,IAAI,QAAQ;QAC7D,0EAA0E;QAC1E,wBAAwB;QACxB,YAAY,EAAE,MAAM,EAAE,YAAY,IAAI,SAAS;QAC/C,KAAK,EAAE,OAAO,KAAK,IAAI;YACrB,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa;QAChF,KAAK;QACL,cAAc,EAAE,IAAI;QACpB,aAAa,EAAE,IAAI;QACnB,eAAe,EAAE,IAAI;KACtB,CAAC,CAAA;IACF,OAAO;QACL,IAAI;QACJ,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,IAAI;QACnC,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI;QAC7B,SAAS;KACV,CAAA;AACH,CAAC;AAED,+EAA+E;AAE/E;;;;;;;GAOG;AACH,MAAM,OAAO,YAAY;IAWJ;IACA;IACA;IAZX,QAAQ,GAAoB,KAAK,CAAA;IACxB,SAAS,GAAG,IAAI,GAAG,EAAc,CAAA;IAClD,4DAA4D;IACpD,UAAU,GAAG,CAAC,CAAA;IACd,QAAQ,CAAoB;IAC5B,eAAe,CAAoB;IAC1B,aAAa,GAAG,IAAI,GAAG,EAA6B,CAAA;IAC7D,iBAAiB,GAA2B,IAAI,CAAA;IAExD,YACmB,GAAY,EACZ,cAA+B,EAC/B,eAAsC;QAFtC,QAAG,GAAH,GAAG,CAAS;QACZ,mBAAc,GAAd,cAAc,CAAiB;QAC/B,oBAAe,GAAf,eAAe,CAAuB;IACtD,CAAC;IAEJ;;;;;;;;;;;;;OAaG;IACK,KAAK,CAAC,kBAAkB,CAC9B,QAAuB,EAAE,SAAiC,EAAE,MAAmB;QAE/E,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS;YAAE,OAAM;QAC9C,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;YAClC,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;YAC1C,IAAI,OAAO,KAAK,IAAI;gBAAE,SAAQ;YAC9B,MAAM,aAAa,GAAG,SAAS;iBAC5B,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC,EAAE,aAAa,IAAI,IAAI,CAAA;YAC5E,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,aAAa,CAAC,CAAA;YAC3E,IAAI,OAA4B,CAAA;YAChC,IAAI,CAAC;gBACH,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;YAC/E,CAAC;YAAC,MAAM,CAAC;gBACP,iEAAiE;gBACjE,gEAAgE;gBAChE,SAAQ;YACV,CAAC;YACD,IAAI,MAAM,CAAC,OAAO;gBAAE,OAAM;YAC1B,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE;oBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,EAAE,EAAE,IAAI;oBACR,UAAU,EAAE,UAAU;oBACtB,YAAY,EAAE,WAAW;oBACzB,mEAAmE;oBACnE,gEAAgE;oBAChE,OAAO,EAAE,8CAA8C;iBACxD,CAAC,CAAA;YACJ,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAChC,CAAC;QACH,CAAC;IACH,CAAC;IAED,6DAA6D;IAC7D,WAAW,GAAG,GAAoB,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAA;IAElD,8EAA8E;IAC9E,SAAS,GAAG,CAAC,QAAoB,EAAgB,EAAE;QACjD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC5B,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA,CAAC,CAAC,CAAA;IAClD,CAAC,CAAA;IAEO,OAAO,CAAC,IAA8B;QAC5C,IAAI,CAAC,QAAQ,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,EAAE,CAAA;QAC7C,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS;YAAE,QAAQ,EAAE,CAAA;IACnD,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,UAAU,GAAG,EAAE,IAAI,CAAC,UAAU,CAAA;QACpC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAEhD,IAAI,SAAkC,CAAA;QACtC,IAAI,UAAoC,CAAA;QACxC,IAAI,MAAM,GAA0B,EAAE,CAAA;QACtC,IAAI,QAAQ,GAA+C,EAAE,CAAA;QAC7D,IAAI,QAAQ,GAAG,KAAK,CAAA;QACpB,IAAI,CAAC;YACH,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBACzD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9B,sEAAsE;gBACtE,uEAAuE;gBACvE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;aAC1C,CAAC,CAAA;YACF,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACzE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACvE,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAA;YAC5C,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAA;YAC7C,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAA;YACzC,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBAC9C,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAA;gBACtC,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAA;YAC5C,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,UAAU,KAAK,IAAI,CAAC,UAAU;gBAAE,OAAM;YAC1C,IAAI,CAAC,OAAO,CAAC;gBACX,MAAM,EAAE,OAAO;gBACf,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAA;YACF,OAAM;QACR,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;QAC3C,IAAI,CAAC,QAAQ,GAAG,MAAM,EAAE,QAAQ,CAAA;QAChC,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QAE5C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAyB,CAAA;QAC7C,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAA;QAC3F,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAiB,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAA;QAE5F,IAAI,WAAW,GAAmC,EAAE,CAAA;QACpD,IAAI,QAAQ,GAAG,IAAI,CAAA;QACnB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;gBACpE,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE;oBAAE,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAA;;oBAC9D,QAAQ,GAAG,KAAK,CAAA;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,QAAQ,GAAG,KAAK,CAAA;YAClB,CAAC;QACH,CAAC;QACD,IAAI,UAAU,KAAK,IAAI,CAAC,UAAU;YAAE,OAAM;QAE1C,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;QACzE,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QACnF,MAAM,IAAI,GAAkB,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YAClD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAA;YAC5C,OAAO;gBACL,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,aAAa,EAAE,GAAG;gBAClB,UAAU,EAAE,kBAAkB,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,CAAC;gBAC1D,MAAM,EAAE,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,EAAE;gBAC3D,YAAY,EAAE,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,IAAI;aAC5D,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,0EAA0E;QAC1E,+CAA+C;QAC/C,MAAM,SAAS,GAAG,IAAI,eAAe,EAAE,CAAA;QACvC,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAA;QAC/D,IAAI,UAAU,KAAK,IAAI,CAAC,UAAU;YAAE,OAAM;QAE1C,IAAI,CAAC,OAAO,CAAC;YACX,MAAM,EAAE,OAAO;YACf,KAAK,EAAE,IAAI;YACX,QAAQ;YACR,SAAS,EAAE,IAAI;YACf,QAAQ;YACR,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;SACvF,CAAC,CAAA;QAEF,yEAAyE;QACzE,0EAA0E;QAC1E,0EAA0E;QAC1E,0EAA0E;QAC1E,uEAAuE;QACvE,wBAAwB;QACxB,IAAI,QAAQ;YAAE,MAAM,IAAI,CAAC,yBAAyB,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,CAAA;IACjG,CAAC;IAED;;;;;;;OAOG;IACK,KAAK,CAAC,yBAAyB,CACrC,QAAuB,EAAE,IAA+B;QAExD,IAAI,CAAC,eAAe,GAAG,IAAI,EAAE,QAAQ,CAAA;QACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;QACzC,MAAM,MAAM,GAAG,IAAI,KAAK,SAAS;YAC/B,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;YAC7B,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAA;QAClD,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAA4C,CAAA;QAC9E,IAAI,OAAO,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK;YAAE,OAAM;QAClF,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IAC3C,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAI,CAAC,IAAkB,EAAE,QAAgB,EAAE,KAAa;QAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAA;QAC9E,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE;YACzD,QAAQ;YACR,KAAK;YACL,aAAa,EAAE,GAAG,EAAE,aAAa,IAAI,IAAI;YACzC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACjC,uEAAuE;YACvE,qEAAqE;YACrE,wEAAwE;YACxE,oCAAoC;YACpC,OAAO,EAAE,QAAQ;SAClB,CAAC,CAAC,CAAA;IACL,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,MAAM,CAAC,IAAkB;QAC7B,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAA;IAChE,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,QAAQ,CAAC,IAAkB;QAC/B,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QACxD,IAAI,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;YAC1D,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC,CAAA;YACrF,OAAM;QACR,CAAC;QACD,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS;aAC1C,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC,EAAE,aAAa,IAAI,IAAI,CAAA;QAC5E,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;QACxC,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE,CAAA;QAC/B,IAAI,CAAC,iBAAiB,GAAG,UAAU,CAAA;QACnC,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;QACtD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;YAC3F,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAM;YACrC,IAAI,CAAC,aAAa,CAAC,GAAG,CACpB,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,KAAK,CAAC,CAAA;YACzE,IAAI,CAAC,OAAO,CAAC;gBACX,WAAW,EAAE,IAAI;gBACjB,WAAW,EAAE,KAAK,CAAC,OAAO;gBAC1B,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAC5C,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAC7E,CAAC;aACH,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAM;YACrC,IAAI,CAAC,OAAO,CAAC;gBACX,WAAW,EAAE,IAAI;gBACjB,WAAW,EAAE,0EAA0E;aACxF,CAAC,CAAA;QACJ,CAAC;gBAAS,CAAC;YACT,IAAI,IAAI,CAAC,iBAAiB,KAAK,UAAU;gBAAE,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAA;QAC1E,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,kBAAkB;QAChB,IAAI,IAAI,CAAC,iBAAiB,KAAK,IAAI;YAAE,OAAM;QAC3C,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAA;QAC9B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAA;QAC7B,IAAI,CAAC,OAAO,CAAC;YACX,WAAW,EAAE,IAAI;YACjB,WAAW,EAAE,2DAA2D;SACzE,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACK,KAAK,CAAC,oBAAoB,CAAC,IAAmB;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;QACrC,MAAM,OAAO,GAAG,IAAI,KAAK,SAAS;YAChC,oEAAoE;YACpE,wEAAwE;YACxE,iDAAiD;YACjD,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;YAC7B,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAA;QAClD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAC/C,EAAE,EAAE,uBAAuB;gBAC3B,OAAO;gBACP,GAAG,IAAI,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,eAAe,EAAE;aACxF,CAAC,CAAA;YACF,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE;gBAAE,IAAI,CAAC,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAA;;gBACxE,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAC7D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QACjF,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,IAAmB;QACrC,2EAA2E;QAC3E,uEAAuE;QACvE,qEAAqE;QACrE,sBAAsB,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAA;QACpD,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAC/C,EAAE,EAAE,kBAAkB;gBACtB,OAAO,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;gBACzD,GAAG,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,QAAQ,EAAE;aAC1E,CAAC,CAAA;YACF,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;gBACrE,OAAM;YACR,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAA;YAC9C,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;YAC1D,sEAAsE;YACtE,wEAAwE;YACxE,YAAY;YACZ,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAA;YACzC,IAAI,CAAC,OAAO,CAAC;gBACX,MAAM,EAAE,KAAK;gBACb,QAAQ;gBACR,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CACzC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAC5D,CAAC;aACH,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,CAAC;gBACX,MAAM,EAAE,KAAK;gBACb,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,QAAyB;IACrD,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,EAAE,SAAS,IAAI,IAAI,CAAA;AACjF,CAAC"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * The composer, closed until something is actually bound to Chat — and the
3
+ * fastest way to bind it, offered where the person is standing.
4
+ *
5
+ * A person typed a message into a composer that looked ready, pressed send,
6
+ * and the prompt was routed to a provider they had never configured. Nothing
7
+ * about the composer had told them otherwise: the model chip named a DeepSeek
8
+ * model they had not chosen, the send button was live, and the first thing
9
+ * that disagreed was a failed turn.
10
+ *
11
+ * This is the client half of preflight. It raises the block upstream provides
12
+ * for exactly this — *"Composer blocks: the one way another plugin stops a
13
+ * session's input"* — so the textarea goes inert, the send button stops
14
+ * accepting, and the placeholder says why in the words of whoever knows.
15
+ *
16
+ * **This is an affordance, and it is not the enforcement.** It lives in a
17
+ * browser tab. The Host refuses an unbound route regardless of what any client
18
+ * disables (`@deepwatch/dsh-technology/routing`), and the composed default
19
+ * names no route so the Harness's own admission boundary refuses a turn before
20
+ * one exists. The value of this layer is not that it makes refusal certain — it
21
+ * is that a person finds out *before* typing rather than after sending.
22
+ *
23
+ * **The draft survives.** Blocking is one inert textarea, never a second tree:
24
+ * the composer keeps its DOM, so whatever was typed is still there when the
25
+ * binding is fixed. That is upstream's design and this file's reason for using
26
+ * it rather than rendering a replacement.
27
+ *
28
+ * **The way out is here, not somewhere else.** The settings panel's open state
29
+ * is component-local to `SettingsRoot`, so no plugin can navigate to a section
30
+ * — and a button that names a screen it cannot open is worse than no button.
31
+ * So the fix is offered inline: the same provider-and-model picker the Role
32
+ * Bindings screen uses, writing through the same store, so the two surfaces
33
+ * cannot disagree about what a provider offers.
34
+ *
35
+ * @module @deepwatch/dsh-client-settings/chat-gate
36
+ */
37
+ import type { ReactNode } from 'react';
38
+ import type { BindingSnapshot, BindingStore } from './binding-state.js';
39
+ /** The block registry, as `ctx.conversation.blocks` exposes it. */
40
+ export interface ComposerBlocks {
41
+ set(sessionId: string, block: {
42
+ readonly reason: string;
43
+ } | undefined): void;
44
+ }
45
+ /** What the gate needs to do its job. */
46
+ export interface ChatGateProps {
47
+ /** The session whose composer this gate governs. */
48
+ readonly sessionId: string;
49
+ readonly store: BindingStore;
50
+ /**
51
+ * The block registry, resolved when the gate renders rather than when the
52
+ * plugin loads.
53
+ *
54
+ * A getter, and the reason is a bug this had. Registering the seat behind
55
+ * `ctx.inject(['conversation'], …)` parked the registration on a service
56
+ * that arrives with the conversation plugin, and the callback never ran --
57
+ * so the card never drew and the composer was never blocked, silently, while
58
+ * every other surface in this package worked. Upstream's own model-selection
59
+ * plugin reaches the same registry with a plain `ctx.get('conversation')` at
60
+ * the moment it needs it, which is late enough to be there and cheap enough
61
+ * to repeat.
62
+ */
63
+ readonly blocks: () => ComposerBlocks | undefined;
64
+ }
65
+ /**
66
+ * The placeholder an inert composer carries.
67
+ *
68
+ * The blocker's own sentence, prefixed with the capability it is about. A
69
+ * placeholder reading only "Not configured" leaves a person guessing which of
70
+ * six things is missing, which is the failure the ordered blocker list exists
71
+ * to prevent.
72
+ */
73
+ export declare function blockReason(detail: string): string;
74
+ /**
75
+ * The block this snapshot calls for, or undefined when the composer may open.
76
+ *
77
+ * A pure function rather than a branch inside the effect, so the decision can
78
+ * be tested as the decision. A test that re-derived the same condition beside
79
+ * the component would agree with itself and prove nothing about what a person
80
+ * gets.
81
+ *
82
+ * `idle` and `loading` deliberately produce nothing. Blocking a composer
83
+ * because an answer has not arrived yet would make every reload look like a
84
+ * misconfiguration — and the Host refuses an unbound route regardless, so the
85
+ * safe direction here is to say nothing until something is known.
86
+ *
87
+ * @param snapshot - what the store currently knows.
88
+ * @returns the block to raise, or undefined to lift any standing one.
89
+ */
90
+ export declare function blockFor(snapshot: BindingSnapshot): {
91
+ readonly reason: string;
92
+ } | undefined;
93
+ /**
94
+ * Raise or clear this session's composer block, and offer the way out.
95
+ *
96
+ * @param props - see {@link ChatGateProps}.
97
+ * @returns the setup card while Chat cannot run, and nothing once it can.
98
+ */
99
+ export declare function ChatGate({ sessionId, store, blocks }: ChatGateProps): ReactNode;
100
+ //# sourceMappingURL=chat-gate.d.ts.map