@adhd/sox-embedding-provider 0.5.1 → 0.5.2
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/dist/embedHostConfig.d.ts +120 -0
- package/dist/embedHostConfig.d.ts.map +1 -0
- package/dist/embedHostConfig.js +180 -0
- package/dist/embedHostConfig.js.map +1 -0
- package/dist/embedHostMain.d.ts +46 -0
- package/dist/embedHostMain.d.ts.map +1 -0
- package/dist/embedHostMain.js +192 -0
- package/dist/embedHostMain.js.map +1 -0
- package/dist/errors.d.ts +25 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +35 -0
- package/dist/errors.js.map +1 -0
- package/dist/fastembed.d.ts.map +1 -1
- package/dist/fastembed.js +3 -0
- package/dist/fastembed.js.map +1 -1
- package/dist/fastembedProcessHost.d.ts.map +1 -1
- package/dist/fastembedProcessHost.js +11 -10
- package/dist/fastembedProcessHost.js.map +1 -1
- package/dist/funnelClient.d.ts +97 -0
- package/dist/funnelClient.d.ts.map +1 -0
- package/dist/funnelClient.js +311 -0
- package/dist/funnelClient.js.map +1 -0
- package/dist/index.d.ts +27 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -39
- package/dist/index.js.map +1 -1
- package/dist/onnxStderrFilter.d.ts +2 -1
- package/dist/onnxStderrFilter.d.ts.map +1 -1
- package/dist/onnxStderrFilter.js +2 -1
- package/dist/onnxStderrFilter.js.map +1 -1
- package/dist/package.json +8 -2
- package/dist/sharedFastembedProcess.d.ts +59 -32
- package/dist/sharedFastembedProcess.d.ts.map +1 -1
- package/dist/sharedFastembedProcess.js +100 -41
- package/dist/sharedFastembedProcess.js.map +1 -1
- package/package.json +9 -3
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* embedHostConfig.ts — config + stable socket/singleton-key resolution for the
|
|
3
|
+
* embedding funnel (SPEC-EMBEDDING-FUNNEL.md §B).
|
|
4
|
+
*
|
|
5
|
+
* The funnel collapses N consumer processes onto ONE peer-spawned, self-reaping
|
|
6
|
+
* ONNX host per `(model, execution-provider, cacheDir)`. That requires a
|
|
7
|
+
* deterministic, machine-wide identity for "the one host for this workload":
|
|
8
|
+
*
|
|
9
|
+
* - {@link embedHostSingletonKey} — the [def:singleton-key] every consumer
|
|
10
|
+
* computes identically, so `ensureBackend()`'s O_EXCL spawn-lock collapses a
|
|
11
|
+
* thundering herd to one spawn.
|
|
12
|
+
* - {@link embedHostSocketPath} — the UDS path derived from that key via
|
|
13
|
+
* `backendSocketPath()` (the SAME derivation the service-proxy uses, so
|
|
14
|
+
* there is never a port-selection problem and never a clash).
|
|
15
|
+
*
|
|
16
|
+
* ── Host selection is typed config, never an env toggle (ADR-0013) ─────────────
|
|
17
|
+
*
|
|
18
|
+
* `host` is a closed union (`'shared' | 'private'`) carried on
|
|
19
|
+
* `EmbeddingProviderConfig.host` and reported in `health()`. There is
|
|
20
|
+
* deliberately NO `SOX_EMBED_HOST=shared|private` variable: a behavior switch
|
|
21
|
+
* must be visible, validated, and auditable, not an ambient string. The only
|
|
22
|
+
* env reads here are ADR-0013 D3/D5 shapes:
|
|
23
|
+
*
|
|
24
|
+
* - `SOX_EMBED_HOST_IDLE_GRACE_MS` — a numeric tuning constant (D3): how long
|
|
25
|
+
* the host lingers after its last client leaves. Additive/numeric only.
|
|
26
|
+
* - `SOX_ECOSYSTEM_HOME` — host config (D5): where the socket lives.
|
|
27
|
+
* - `SOX_EMBED_HOST_MAIN` / `SOX_EMBED_HOST_SOCKET` — host-injected transport
|
|
28
|
+
* config (D5) / test seams; they select a path, they never enable a feature.
|
|
29
|
+
*
|
|
30
|
+
* Leaf module — node builtins only (fs, os, path, url, crypto, module) plus
|
|
31
|
+
* `backendSocketPath` from `@adhd/sox-service-proxy`.
|
|
32
|
+
*/
|
|
33
|
+
/** The host-selection closed union (ADR-0013). `'shared'` is the default. */
|
|
34
|
+
export type EmbedHostMode = 'shared' | 'private';
|
|
35
|
+
/** Resolved funnel configuration. */
|
|
36
|
+
export interface EmbedHostConfig {
|
|
37
|
+
/** `'shared'` (default): funnel through the peer-spawned host. `'private'`: the pre-funnel per-process fork (CI/diagnostics). */
|
|
38
|
+
host: EmbedHostMode;
|
|
39
|
+
/** The directory the host UDS is created under (ADR-0004: `$SOX_ECOSYSTEM_HOME/run`). */
|
|
40
|
+
socketDir: string;
|
|
41
|
+
/** How long the host lingers with zero clients and zero in-flight work before it reaps itself. */
|
|
42
|
+
idleGraceMs: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Bumped whenever the host's wire protocol or behavior changes incompatibly.
|
|
46
|
+
*
|
|
47
|
+
* Open question #4 in SPEC-EMBEDDING-FUNNEL.md ("a running host is an old
|
|
48
|
+
* build") is resolved with this constant rather than the npm package version.
|
|
49
|
+
* Rationale: the real hazard is a host whose `embedding.*` contract the new
|
|
50
|
+
* consumer cannot speak — a *protocol* change — not every cosmetic patch. Keying
|
|
51
|
+
* on the npm version would spawn a brand-new host on every patch bump (briefly
|
|
52
|
+
* two hosts, defeating the funnel across an upgrade window) while the explicit
|
|
53
|
+
* protocol version forces a new socket exactly when compatibility actually
|
|
54
|
+
* breaks. Bump this with any change to the `embedding.*` method set, the payload
|
|
55
|
+
* shape, or the response shape in `embedHostMain.ts`.
|
|
56
|
+
*/
|
|
57
|
+
export declare const EMBED_HOST_PROTOCOL_VERSION = 1;
|
|
58
|
+
/** Default grace before a zero-client host reaps itself. Sized to the short-lived-CLI arrival cadence. */
|
|
59
|
+
export declare const DEFAULT_EMBED_HOST_IDLE_GRACE_MS = 30000;
|
|
60
|
+
/**
|
|
61
|
+
* Apply the typed `host` field from an `EmbeddingProviderConfig`. Passing
|
|
62
|
+
* `undefined` leaves the current posture unchanged (so a `remote` provider
|
|
63
|
+
* without a `host` field never resets a deliberate `'private'` selection).
|
|
64
|
+
*/
|
|
65
|
+
export declare function configureEmbedHostHost(host: EmbedHostMode | undefined): void;
|
|
66
|
+
/** TEST-ONLY: clear the process-wide host override back to the `'shared'` default. */
|
|
67
|
+
export declare function __resetEmbedHostConfigForTests(): void;
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the funnel configuration. `host` defaults to `'shared'`; `idleGraceMs`
|
|
70
|
+
* is a numeric tuning constant (ADR-0013 D3) with a hard default.
|
|
71
|
+
*/
|
|
72
|
+
export declare function resolveEmbedHostConfig(): EmbedHostConfig;
|
|
73
|
+
/**
|
|
74
|
+
* ADR-0013 D3 tuning constant: `SOX_EMBED_HOST_IDLE_GRACE_MS`. A non-positive or
|
|
75
|
+
* non-numeric value is rejected loudly (never silently treated as "off").
|
|
76
|
+
*/
|
|
77
|
+
export declare function resolveEmbedHostIdleGraceMs(): number;
|
|
78
|
+
/**
|
|
79
|
+
* ADR-0004 D5: the host socket lives under `$SOX_ECOSYSTEM_HOME/run` (the user
|
|
80
|
+
* data root's `run/` dir). Mirrors `@adhd/sox-host-runtime`'s `runDir()` without
|
|
81
|
+
* importing it — this package is a low-tier leaf and must not gain a
|
|
82
|
+
* host-runtime dependency. `SOX_ECOSYSTEM_HOME` defaults to `~/.adhd/sox-ecosystem`
|
|
83
|
+
* exactly as `data-paths.ts`'s `DATA_SUBDIR` does.
|
|
84
|
+
*/
|
|
85
|
+
export declare function resolveEmbedHostSocketDir(): string;
|
|
86
|
+
/**
|
|
87
|
+
* The machine-wide [def:singleton-key] for the host serving `(modelId, ep,
|
|
88
|
+
* cacheDir)`. Identical inputs ⇒ identical key ⇒ identical socket ⇒ one host,
|
|
89
|
+
* across every consumer process on the box.
|
|
90
|
+
*
|
|
91
|
+
* `cacheDirDigest` is a short sha256 of the ABSOLUTE cache dir, so two stores
|
|
92
|
+
* pointed at different model caches never collide onto one host. The protocol
|
|
93
|
+
* version is appended (see {@link EMBED_HOST_PROTOCOL_VERSION}).
|
|
94
|
+
*/
|
|
95
|
+
export declare function embedHostSingletonKey(modelId: string, ep: string, cacheDir: string): string;
|
|
96
|
+
/** Derive the host UDS path from the resolved config and singleton key. */
|
|
97
|
+
export declare function embedHostSocketPath(cfg: EmbedHostConfig, key: string): string;
|
|
98
|
+
/**
|
|
99
|
+
* Resolve the runnable host entrypoint to spawn.
|
|
100
|
+
*
|
|
101
|
+
* Order:
|
|
102
|
+
* 1. `SOX_EMBED_HOST_MAIN` (D5/test seam) — a path injection, never a feature
|
|
103
|
+
* toggle. Used by the funnel teeth suite to run the host from source via a
|
|
104
|
+
* tsx shim without a prior build.
|
|
105
|
+
* 2. A `__dirname` sibling (`dist/embedHostMain.js`) — the npm AND bundled
|
|
106
|
+
* case. The literal `join(__dirname, 'embedHostMain.js')` is load-bearing:
|
|
107
|
+
* `bundle-extension.cjs`'s `verifySidecarReferences()` scans emitted files
|
|
108
|
+
* for exactly this shape, so the sidecar can never ship missing (BL-259).
|
|
109
|
+
* 3. `src/../dist/embedHostMain.js` — vitest's `src/`-resident `__dirname`.
|
|
110
|
+
* 4. `require.resolve('@adhd/sox-embedding-provider/embed-host')` — the
|
|
111
|
+
* package `exports` subpath, when self-reference is available.
|
|
112
|
+
*/
|
|
113
|
+
export declare function resolveEmbedHostMainPath(): string;
|
|
114
|
+
/**
|
|
115
|
+
* Where the detached host's stderr is redirected (its stdout/stdin are severed).
|
|
116
|
+
* Kept beside the socket so a wedged host's startup diagnostics are greppable
|
|
117
|
+
* without inheriting any caller fd ([inv:no-fd-inherit], BL-67).
|
|
118
|
+
*/
|
|
119
|
+
export declare function resolveEmbedHostStderrLogPath(cfg: EmbedHostConfig): string;
|
|
120
|
+
//# sourceMappingURL=embedHostConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedHostConfig.d.ts","sourceRoot":"","sources":["../src/embedHostConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAYH,6EAA6E;AAC7E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjD,qCAAqC;AACrC,MAAM,WAAW,eAAe;IAC9B,iIAAiI;IACjI,IAAI,EAAE,aAAa,CAAC;IACpB,yFAAyF;IACzF,SAAS,EAAE,MAAM,CAAC;IAClB,kGAAkG;IAClG,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,0GAA0G;AAC1G,eAAO,MAAM,gCAAgC,QAAS,CAAC;AAcvD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,GAAG,IAAI,CAM5E;AAED,sFAAsF;AACtF,wBAAgB,8BAA8B,IAAI,IAAI,CAErD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,eAAe,CAMxD;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,CAUpD;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAIlD;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG3F;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAgBjD;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAE1E"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* embedHostConfig.ts — config + stable socket/singleton-key resolution for the
|
|
3
|
+
* embedding funnel (SPEC-EMBEDDING-FUNNEL.md §B).
|
|
4
|
+
*
|
|
5
|
+
* The funnel collapses N consumer processes onto ONE peer-spawned, self-reaping
|
|
6
|
+
* ONNX host per `(model, execution-provider, cacheDir)`. That requires a
|
|
7
|
+
* deterministic, machine-wide identity for "the one host for this workload":
|
|
8
|
+
*
|
|
9
|
+
* - {@link embedHostSingletonKey} — the [def:singleton-key] every consumer
|
|
10
|
+
* computes identically, so `ensureBackend()`'s O_EXCL spawn-lock collapses a
|
|
11
|
+
* thundering herd to one spawn.
|
|
12
|
+
* - {@link embedHostSocketPath} — the UDS path derived from that key via
|
|
13
|
+
* `backendSocketPath()` (the SAME derivation the service-proxy uses, so
|
|
14
|
+
* there is never a port-selection problem and never a clash).
|
|
15
|
+
*
|
|
16
|
+
* ── Host selection is typed config, never an env toggle (ADR-0013) ─────────────
|
|
17
|
+
*
|
|
18
|
+
* `host` is a closed union (`'shared' | 'private'`) carried on
|
|
19
|
+
* `EmbeddingProviderConfig.host` and reported in `health()`. There is
|
|
20
|
+
* deliberately NO `SOX_EMBED_HOST=shared|private` variable: a behavior switch
|
|
21
|
+
* must be visible, validated, and auditable, not an ambient string. The only
|
|
22
|
+
* env reads here are ADR-0013 D3/D5 shapes:
|
|
23
|
+
*
|
|
24
|
+
* - `SOX_EMBED_HOST_IDLE_GRACE_MS` — a numeric tuning constant (D3): how long
|
|
25
|
+
* the host lingers after its last client leaves. Additive/numeric only.
|
|
26
|
+
* - `SOX_ECOSYSTEM_HOME` — host config (D5): where the socket lives.
|
|
27
|
+
* - `SOX_EMBED_HOST_MAIN` / `SOX_EMBED_HOST_SOCKET` — host-injected transport
|
|
28
|
+
* config (D5) / test seams; they select a path, they never enable a feature.
|
|
29
|
+
*
|
|
30
|
+
* Leaf module — node builtins only (fs, os, path, url, crypto, module) plus
|
|
31
|
+
* `backendSocketPath` from `@adhd/sox-service-proxy`.
|
|
32
|
+
*/
|
|
33
|
+
import { existsSync } from 'node:fs';
|
|
34
|
+
import { createHash } from 'node:crypto';
|
|
35
|
+
import { createRequire } from 'node:module';
|
|
36
|
+
import { homedir } from 'node:os';
|
|
37
|
+
import { dirname, join } from 'node:path';
|
|
38
|
+
import { fileURLToPath } from 'node:url';
|
|
39
|
+
import { backendSocketPath } from '@adhd/sox-service-proxy';
|
|
40
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
41
|
+
/**
|
|
42
|
+
* Bumped whenever the host's wire protocol or behavior changes incompatibly.
|
|
43
|
+
*
|
|
44
|
+
* Open question #4 in SPEC-EMBEDDING-FUNNEL.md ("a running host is an old
|
|
45
|
+
* build") is resolved with this constant rather than the npm package version.
|
|
46
|
+
* Rationale: the real hazard is a host whose `embedding.*` contract the new
|
|
47
|
+
* consumer cannot speak — a *protocol* change — not every cosmetic patch. Keying
|
|
48
|
+
* on the npm version would spawn a brand-new host on every patch bump (briefly
|
|
49
|
+
* two hosts, defeating the funnel across an upgrade window) while the explicit
|
|
50
|
+
* protocol version forces a new socket exactly when compatibility actually
|
|
51
|
+
* breaks. Bump this with any change to the `embedding.*` method set, the payload
|
|
52
|
+
* shape, or the response shape in `embedHostMain.ts`.
|
|
53
|
+
*/
|
|
54
|
+
export const EMBED_HOST_PROTOCOL_VERSION = 1;
|
|
55
|
+
/** Default grace before a zero-client host reaps itself. Sized to the short-lived-CLI arrival cadence. */
|
|
56
|
+
export const DEFAULT_EMBED_HOST_IDLE_GRACE_MS = 30_000;
|
|
57
|
+
/**
|
|
58
|
+
* Process-wide host-selection override. `null` ⇒ `'shared'`.
|
|
59
|
+
*
|
|
60
|
+
* Deliberately NOT an env var (ADR-0013): the typed
|
|
61
|
+
* `EmbeddingProviderConfig.host` field is applied here by
|
|
62
|
+
* `createEmbeddingProvider()` before the accessor singleton is constructed.
|
|
63
|
+
* Host selection is a process-wide posture — once a consumer has resolved its
|
|
64
|
+
* accessor, changing this does not retroactively re-point it (documented, not
|
|
65
|
+
* hidden).
|
|
66
|
+
*/
|
|
67
|
+
let _hostOverride = null;
|
|
68
|
+
/**
|
|
69
|
+
* Apply the typed `host` field from an `EmbeddingProviderConfig`. Passing
|
|
70
|
+
* `undefined` leaves the current posture unchanged (so a `remote` provider
|
|
71
|
+
* without a `host` field never resets a deliberate `'private'` selection).
|
|
72
|
+
*/
|
|
73
|
+
export function configureEmbedHostHost(host) {
|
|
74
|
+
if (host === undefined)
|
|
75
|
+
return;
|
|
76
|
+
if (host !== 'shared' && host !== 'private') {
|
|
77
|
+
throw new TypeError(`EmbedHostMode must be 'shared' or 'private', got ${String(host)}`);
|
|
78
|
+
}
|
|
79
|
+
_hostOverride = host;
|
|
80
|
+
}
|
|
81
|
+
/** TEST-ONLY: clear the process-wide host override back to the `'shared'` default. */
|
|
82
|
+
export function __resetEmbedHostConfigForTests() {
|
|
83
|
+
_hostOverride = null;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolve the funnel configuration. `host` defaults to `'shared'`; `idleGraceMs`
|
|
87
|
+
* is a numeric tuning constant (ADR-0013 D3) with a hard default.
|
|
88
|
+
*/
|
|
89
|
+
export function resolveEmbedHostConfig() {
|
|
90
|
+
return {
|
|
91
|
+
host: _hostOverride ?? 'shared',
|
|
92
|
+
socketDir: resolveEmbedHostSocketDir(),
|
|
93
|
+
idleGraceMs: resolveEmbedHostIdleGraceMs(),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* ADR-0013 D3 tuning constant: `SOX_EMBED_HOST_IDLE_GRACE_MS`. A non-positive or
|
|
98
|
+
* non-numeric value is rejected loudly (never silently treated as "off").
|
|
99
|
+
*/
|
|
100
|
+
export function resolveEmbedHostIdleGraceMs() {
|
|
101
|
+
const raw = process.env['SOX_EMBED_HOST_IDLE_GRACE_MS'];
|
|
102
|
+
if (raw === undefined || raw === '')
|
|
103
|
+
return DEFAULT_EMBED_HOST_IDLE_GRACE_MS;
|
|
104
|
+
const parsed = Number(raw);
|
|
105
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
106
|
+
throw new TypeError(`SOX_EMBED_HOST_IDLE_GRACE_MS must be a positive number, got ${JSON.stringify(raw)}`);
|
|
107
|
+
}
|
|
108
|
+
return parsed;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* ADR-0004 D5: the host socket lives under `$SOX_ECOSYSTEM_HOME/run` (the user
|
|
112
|
+
* data root's `run/` dir). Mirrors `@adhd/sox-host-runtime`'s `runDir()` without
|
|
113
|
+
* importing it — this package is a low-tier leaf and must not gain a
|
|
114
|
+
* host-runtime dependency. `SOX_ECOSYSTEM_HOME` defaults to `~/.adhd/sox-ecosystem`
|
|
115
|
+
* exactly as `data-paths.ts`'s `DATA_SUBDIR` does.
|
|
116
|
+
*/
|
|
117
|
+
export function resolveEmbedHostSocketDir() {
|
|
118
|
+
const home = process.env['SOX_ECOSYSTEM_HOME'];
|
|
119
|
+
const root = home !== undefined && home !== '' ? home : join(homedir(), '.adhd', 'sox-ecosystem');
|
|
120
|
+
return join(root, 'run');
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The machine-wide [def:singleton-key] for the host serving `(modelId, ep,
|
|
124
|
+
* cacheDir)`. Identical inputs ⇒ identical key ⇒ identical socket ⇒ one host,
|
|
125
|
+
* across every consumer process on the box.
|
|
126
|
+
*
|
|
127
|
+
* `cacheDirDigest` is a short sha256 of the ABSOLUTE cache dir, so two stores
|
|
128
|
+
* pointed at different model caches never collide onto one host. The protocol
|
|
129
|
+
* version is appended (see {@link EMBED_HOST_PROTOCOL_VERSION}).
|
|
130
|
+
*/
|
|
131
|
+
export function embedHostSingletonKey(modelId, ep, cacheDir) {
|
|
132
|
+
const digest = createHash('sha256').update(cacheDir, 'utf8').digest('hex').slice(0, 12);
|
|
133
|
+
return `embedding-host:v${EMBED_HOST_PROTOCOL_VERSION}:${modelId}:${ep}:${digest}`;
|
|
134
|
+
}
|
|
135
|
+
/** Derive the host UDS path from the resolved config and singleton key. */
|
|
136
|
+
export function embedHostSocketPath(cfg, key) {
|
|
137
|
+
return backendSocketPath(cfg.socketDir, key);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Resolve the runnable host entrypoint to spawn.
|
|
141
|
+
*
|
|
142
|
+
* Order:
|
|
143
|
+
* 1. `SOX_EMBED_HOST_MAIN` (D5/test seam) — a path injection, never a feature
|
|
144
|
+
* toggle. Used by the funnel teeth suite to run the host from source via a
|
|
145
|
+
* tsx shim without a prior build.
|
|
146
|
+
* 2. A `__dirname` sibling (`dist/embedHostMain.js`) — the npm AND bundled
|
|
147
|
+
* case. The literal `join(__dirname, 'embedHostMain.js')` is load-bearing:
|
|
148
|
+
* `bundle-extension.cjs`'s `verifySidecarReferences()` scans emitted files
|
|
149
|
+
* for exactly this shape, so the sidecar can never ship missing (BL-259).
|
|
150
|
+
* 3. `src/../dist/embedHostMain.js` — vitest's `src/`-resident `__dirname`.
|
|
151
|
+
* 4. `require.resolve('@adhd/sox-embedding-provider/embed-host')` — the
|
|
152
|
+
* package `exports` subpath, when self-reference is available.
|
|
153
|
+
*/
|
|
154
|
+
export function resolveEmbedHostMainPath() {
|
|
155
|
+
const override = process.env['SOX_EMBED_HOST_MAIN'];
|
|
156
|
+
if (override !== undefined && override !== '')
|
|
157
|
+
return override;
|
|
158
|
+
const sibling = join(__dirname, 'embedHostMain.js');
|
|
159
|
+
if (existsSync(sibling))
|
|
160
|
+
return sibling;
|
|
161
|
+
const distSibling = join(__dirname, '..', 'dist', 'embedHostMain.js');
|
|
162
|
+
if (existsSync(distSibling))
|
|
163
|
+
return distSibling;
|
|
164
|
+
try {
|
|
165
|
+
return createRequire(import.meta.url).resolve('@adhd/sox-embedding-provider/embed-host');
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
// Last resort: name the path that was actually attempted in any later error.
|
|
169
|
+
return sibling;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Where the detached host's stderr is redirected (its stdout/stdin are severed).
|
|
174
|
+
* Kept beside the socket so a wedged host's startup diagnostics are greppable
|
|
175
|
+
* without inheriting any caller fd ([inv:no-fd-inherit], BL-67).
|
|
176
|
+
*/
|
|
177
|
+
export function resolveEmbedHostStderrLogPath(cfg) {
|
|
178
|
+
return join(cfg.socketDir, 'logs', 'embed-host.stderr.log');
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=embedHostConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedHostConfig.js","sourceRoot":"","sources":["../src/embedHostConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* embedHostMain.ts — the peer-spawned, self-reaping embedding host process
|
|
3
|
+
* (SPEC-EMBEDDING-FUNNEL.md §C).
|
|
4
|
+
*
|
|
5
|
+
* This is the compute backend of the funnel: a plain, DETACHED Node process,
|
|
6
|
+
* spawned on demand by the first consumer through `ensureBackend()`'s O_EXCL
|
|
7
|
+
* singleton spawn-lock. It is **never supervised** (no launchd/KeepAlive) and it
|
|
8
|
+
* **reaps itself** — a debounced, ref-counted teardown retires it
|
|
9
|
+
* `idleGraceMs` after the last cross-process client disconnects and in-flight
|
|
10
|
+
* work drains.
|
|
11
|
+
*
|
|
12
|
+
* ── Compute-only (ADR-0012) ────────────────────────────────────────────────────
|
|
13
|
+
*
|
|
14
|
+
* The host holds NO store connection. It forwards `embedding.*` payloads 1:1 to
|
|
15
|
+
* its private ONNX pool and never opens a database. It therefore cannot
|
|
16
|
+
* serialize store access and must never be described as single-writer or as a
|
|
17
|
+
* store serialization point; concurrent store writers are unaffected.
|
|
18
|
+
*
|
|
19
|
+
* ── No recursion ───────────────────────────────────────────────────────────────
|
|
20
|
+
*
|
|
21
|
+
* The handler forwards to `getPrivateFastembedProcess()` — the PRIVATE pool — and
|
|
22
|
+
* NEVER to `getSharedFastembedProcess()`, which under `host: 'shared'` would
|
|
23
|
+
* return a `FunneledFastembedClient` and dial this very host (infinite
|
|
24
|
+
* recursion). The import graph is arranged so that mistake is a type error, not
|
|
25
|
+
* a runtime hang.
|
|
26
|
+
*
|
|
27
|
+
* ── Teardown inputs are CROSS-PROCESS ─────────────────────────────────────────
|
|
28
|
+
*
|
|
29
|
+
* - `activeClients` — live UDS client connections, from `serveBackend`'s
|
|
30
|
+
* `onClientCountChange` hook (the cross-process half);
|
|
31
|
+
* - `privateClient.pendingCount` — this host's own in-flight requests (the
|
|
32
|
+
* in-process half).
|
|
33
|
+
*
|
|
34
|
+
* `activeClients === 0 && pendingCount === 0` arms the grace timer; a new client
|
|
35
|
+
* or request cancels it. On expiry the private pool is terminated, the listener
|
|
36
|
+
* closed (which unlinks the socket), and the process exits 0. The private pool's
|
|
37
|
+
* ONNX child is forked `detached: false`, so it dies with the host — no orphans.
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* Start the host: bind the UDS, serve `embedding.*`, and arm the debounced
|
|
41
|
+
* self-reap. Resolves once the listener is up (so a caller/test can await
|
|
42
|
+
* readiness); the process stays alive until the teardown fires or a signal
|
|
43
|
+
* arrives.
|
|
44
|
+
*/
|
|
45
|
+
export declare function runEmbedHost(): Promise<void>;
|
|
46
|
+
//# sourceMappingURL=embedHostMain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedHostMain.d.ts","sourceRoot":"","sources":["../src/embedHostMain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAyBH;;;;;GAKG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA2GlD"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* embedHostMain.ts — the peer-spawned, self-reaping embedding host process
|
|
3
|
+
* (SPEC-EMBEDDING-FUNNEL.md §C).
|
|
4
|
+
*
|
|
5
|
+
* This is the compute backend of the funnel: a plain, DETACHED Node process,
|
|
6
|
+
* spawned on demand by the first consumer through `ensureBackend()`'s O_EXCL
|
|
7
|
+
* singleton spawn-lock. It is **never supervised** (no launchd/KeepAlive) and it
|
|
8
|
+
* **reaps itself** — a debounced, ref-counted teardown retires it
|
|
9
|
+
* `idleGraceMs` after the last cross-process client disconnects and in-flight
|
|
10
|
+
* work drains.
|
|
11
|
+
*
|
|
12
|
+
* ── Compute-only (ADR-0012) ────────────────────────────────────────────────────
|
|
13
|
+
*
|
|
14
|
+
* The host holds NO store connection. It forwards `embedding.*` payloads 1:1 to
|
|
15
|
+
* its private ONNX pool and never opens a database. It therefore cannot
|
|
16
|
+
* serialize store access and must never be described as single-writer or as a
|
|
17
|
+
* store serialization point; concurrent store writers are unaffected.
|
|
18
|
+
*
|
|
19
|
+
* ── No recursion ───────────────────────────────────────────────────────────────
|
|
20
|
+
*
|
|
21
|
+
* The handler forwards to `getPrivateFastembedProcess()` — the PRIVATE pool — and
|
|
22
|
+
* NEVER to `getSharedFastembedProcess()`, which under `host: 'shared'` would
|
|
23
|
+
* return a `FunneledFastembedClient` and dial this very host (infinite
|
|
24
|
+
* recursion). The import graph is arranged so that mistake is a type error, not
|
|
25
|
+
* a runtime hang.
|
|
26
|
+
*
|
|
27
|
+
* ── Teardown inputs are CROSS-PROCESS ─────────────────────────────────────────
|
|
28
|
+
*
|
|
29
|
+
* - `activeClients` — live UDS client connections, from `serveBackend`'s
|
|
30
|
+
* `onClientCountChange` hook (the cross-process half);
|
|
31
|
+
* - `privateClient.pendingCount` — this host's own in-flight requests (the
|
|
32
|
+
* in-process half).
|
|
33
|
+
*
|
|
34
|
+
* `activeClients === 0 && pendingCount === 0` arms the grace timer; a new client
|
|
35
|
+
* or request cancels it. On expiry the private pool is terminated, the listener
|
|
36
|
+
* closed (which unlinks the socket), and the process exits 0. The private pool's
|
|
37
|
+
* ONNX child is forked `detached: false`, so it dies with the host — no orphans.
|
|
38
|
+
*/
|
|
39
|
+
import { fileURLToPath } from 'node:url';
|
|
40
|
+
import { resolve } from 'node:path';
|
|
41
|
+
import { serveBackend } from '@adhd/sox-service-proxy';
|
|
42
|
+
import { resolveEmbedHostIdleGraceMs } from './embedHostConfig.js';
|
|
43
|
+
import { getPrivateFastembedProcess, resetPrivateFastembedProcess } from './sharedFastembedProcess.js';
|
|
44
|
+
/** The `embedding.*` methods the host serves. */
|
|
45
|
+
const HOST_METHODS = new Set([
|
|
46
|
+
'embedding.init',
|
|
47
|
+
'embedding.embed',
|
|
48
|
+
'embedding.embedBatch',
|
|
49
|
+
'embedding.reset',
|
|
50
|
+
'embedding.health',
|
|
51
|
+
]);
|
|
52
|
+
function ok(id, result) {
|
|
53
|
+
return { jsonrpc: '2.0', id: id ?? null, result };
|
|
54
|
+
}
|
|
55
|
+
function fail(id, code, message) {
|
|
56
|
+
return { jsonrpc: '2.0', id: id ?? null, error: { code, message } };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Start the host: bind the UDS, serve `embedding.*`, and arm the debounced
|
|
60
|
+
* self-reap. Resolves once the listener is up (so a caller/test can await
|
|
61
|
+
* readiness); the process stays alive until the teardown fires or a signal
|
|
62
|
+
* arrives.
|
|
63
|
+
*/
|
|
64
|
+
export async function runEmbedHost() {
|
|
65
|
+
const socketPath = process.env['SOX_EMBED_HOST_SOCKET'];
|
|
66
|
+
if (!socketPath) {
|
|
67
|
+
process.stderr.write('[embed-host] SOX_EMBED_HOST_SOCKET is not set — the host is spawned by the funnel client, not run directly.\n');
|
|
68
|
+
process.exit(2);
|
|
69
|
+
}
|
|
70
|
+
const idleGraceMs = resolveEmbedHostIdleGraceMs();
|
|
71
|
+
const privateClient = getPrivateFastembedProcess();
|
|
72
|
+
let activeClients = 0;
|
|
73
|
+
let idleTimer = null;
|
|
74
|
+
let shuttingDown = false;
|
|
75
|
+
let handle = null;
|
|
76
|
+
const cancelIdle = () => {
|
|
77
|
+
if (idleTimer) {
|
|
78
|
+
clearTimeout(idleTimer);
|
|
79
|
+
idleTimer = null;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const teardown = async () => {
|
|
83
|
+
if (shuttingDown)
|
|
84
|
+
return;
|
|
85
|
+
shuttingDown = true;
|
|
86
|
+
cancelIdle();
|
|
87
|
+
try {
|
|
88
|
+
await privateClient.terminate();
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
/* best-effort — the ONNX child dies with us regardless (detached:false) */
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
await handle?.close();
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
/* best-effort — the socket unlink happens inside close() */
|
|
98
|
+
}
|
|
99
|
+
process.exit(0);
|
|
100
|
+
};
|
|
101
|
+
const armIfIdle = () => {
|
|
102
|
+
if (shuttingDown || idleTimer)
|
|
103
|
+
return;
|
|
104
|
+
if (activeClients !== 0 || privateClient.pendingCount !== 0)
|
|
105
|
+
return;
|
|
106
|
+
idleTimer = setTimeout(() => {
|
|
107
|
+
idleTimer = null;
|
|
108
|
+
void teardown();
|
|
109
|
+
}, idleGraceMs);
|
|
110
|
+
// The listener keeps the loop alive; the timer itself must not.
|
|
111
|
+
idleTimer.unref?.();
|
|
112
|
+
};
|
|
113
|
+
const handler = async (req) => {
|
|
114
|
+
// Any inbound request is demand — cancel a pending reap.
|
|
115
|
+
cancelIdle();
|
|
116
|
+
const id = req.id;
|
|
117
|
+
const method = req.method;
|
|
118
|
+
if (!HOST_METHODS.has(method)) {
|
|
119
|
+
return fail(id, -32601, `method not found: ${method}`);
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
if (method === 'embedding.health') {
|
|
123
|
+
return ok(id, {
|
|
124
|
+
started: privateClient.started,
|
|
125
|
+
pendingCount: privateClient.pendingCount,
|
|
126
|
+
activeClients,
|
|
127
|
+
idleGraceMs,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
if (method === 'embedding.reset') {
|
|
131
|
+
await resetPrivateFastembedProcess();
|
|
132
|
+
return ok(id, { reset: true });
|
|
133
|
+
}
|
|
134
|
+
// embedding.init | embedding.embed | embedding.embedBatch — forward the
|
|
135
|
+
// payload 1:1 to the PRIVATE pool (never the funnel accessor).
|
|
136
|
+
const params = (req.params ?? {});
|
|
137
|
+
const result = await privateClient.request(params);
|
|
138
|
+
return ok(id, result);
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
return fail(id, -32603, e instanceof Error ? e.message : String(e));
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
// A request may have drained the last in-flight work with no clients
|
|
145
|
+
// attached (e.g. a one-shot embed) — re-arm the reap.
|
|
146
|
+
if (activeClients === 0)
|
|
147
|
+
armIfIdle();
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
handle = await serveBackend({
|
|
151
|
+
socketPath,
|
|
152
|
+
handler,
|
|
153
|
+
onDiagnostic: (line) => process.stderr.write(line + '\n'),
|
|
154
|
+
onClientCountChange: (active) => {
|
|
155
|
+
activeClients = active;
|
|
156
|
+
if (active > 0)
|
|
157
|
+
cancelIdle();
|
|
158
|
+
else
|
|
159
|
+
armIfIdle();
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
// Arm immediately: if no client ever connects (e.g. the spawner died between
|
|
163
|
+
// spawn and dial), the host must still reap rather than linger forever.
|
|
164
|
+
armIfIdle();
|
|
165
|
+
// A detached host can still be signalled directly (kill, OS teardown).
|
|
166
|
+
process.on('SIGTERM', () => void teardown());
|
|
167
|
+
process.on('SIGINT', () => void teardown());
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* True when this module is the process entrypoint (`node dist/embedHostMain.js`).
|
|
171
|
+
* `ensureBackend` spawns exactly that. A test shim that imports this module and
|
|
172
|
+
* calls `runEmbedHost()` explicitly is NOT the entrypoint, so it does not
|
|
173
|
+
* double-start.
|
|
174
|
+
*/
|
|
175
|
+
function isEntrypoint() {
|
|
176
|
+
const argv1 = process.argv[1];
|
|
177
|
+
if (!argv1)
|
|
178
|
+
return false;
|
|
179
|
+
try {
|
|
180
|
+
return resolve(fileURLToPath(import.meta.url)) === resolve(argv1);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (isEntrypoint()) {
|
|
187
|
+
runEmbedHost().catch((err) => {
|
|
188
|
+
process.stderr.write(`[embed-host] fatal: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
|
|
189
|
+
process.exit(1);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=embedHostMain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedHostMain.js","sourceRoot":"","sources":["../src/embedHostMain.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* errors.ts — the embedding error taxonomy, extracted so internal modules
|
|
3
|
+
* (notably `funnelClient.ts`) can throw typed errors without importing the
|
|
4
|
+
* public `index.ts` barrel and creating an import cycle.
|
|
5
|
+
*
|
|
6
|
+
* The classes are re-exported verbatim from `index.ts`, so the public surface is
|
|
7
|
+
* unchanged: `import { TransientEmbeddingError } from '@adhd/sox-embedding-provider'`
|
|
8
|
+
* keeps working, and `instanceof` identity is preserved (one class, one home).
|
|
9
|
+
*
|
|
10
|
+
* Three tiers, no silent degradation:
|
|
11
|
+
* - TransientEmbeddingError — the caller may retry (has `retryAfterMs`).
|
|
12
|
+
* - PermanentEmbeddingError — the caller must not retry.
|
|
13
|
+
* - ResolutionError — factory-time only (bad config / unknown model), never mid-call.
|
|
14
|
+
*/
|
|
15
|
+
export declare class TransientEmbeddingError extends Error {
|
|
16
|
+
readonly retryAfterMs: number | undefined;
|
|
17
|
+
constructor(message: string, retryAfterMs?: number);
|
|
18
|
+
}
|
|
19
|
+
export declare class PermanentEmbeddingError extends Error {
|
|
20
|
+
constructor(message: string);
|
|
21
|
+
}
|
|
22
|
+
export declare class ResolutionError extends Error {
|
|
23
|
+
constructor(message: string);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;gBAC9B,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM;CAKnD;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* errors.ts — the embedding error taxonomy, extracted so internal modules
|
|
3
|
+
* (notably `funnelClient.ts`) can throw typed errors without importing the
|
|
4
|
+
* public `index.ts` barrel and creating an import cycle.
|
|
5
|
+
*
|
|
6
|
+
* The classes are re-exported verbatim from `index.ts`, so the public surface is
|
|
7
|
+
* unchanged: `import { TransientEmbeddingError } from '@adhd/sox-embedding-provider'`
|
|
8
|
+
* keeps working, and `instanceof` identity is preserved (one class, one home).
|
|
9
|
+
*
|
|
10
|
+
* Three tiers, no silent degradation:
|
|
11
|
+
* - TransientEmbeddingError — the caller may retry (has `retryAfterMs`).
|
|
12
|
+
* - PermanentEmbeddingError — the caller must not retry.
|
|
13
|
+
* - ResolutionError — factory-time only (bad config / unknown model), never mid-call.
|
|
14
|
+
*/
|
|
15
|
+
export class TransientEmbeddingError extends Error {
|
|
16
|
+
retryAfterMs;
|
|
17
|
+
constructor(message, retryAfterMs) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = 'TransientEmbeddingError';
|
|
20
|
+
this.retryAfterMs = retryAfterMs;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export class PermanentEmbeddingError extends Error {
|
|
24
|
+
constructor(message) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.name = 'PermanentEmbeddingError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export class ResolutionError extends Error {
|
|
30
|
+
constructor(message) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = 'ResolutionError';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACvC,YAAY,CAAqB;IAC1C,YAAY,OAAe,EAAE,YAAqB;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF"}
|
package/dist/fastembed.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fastembed.d.ts","sourceRoot":"","sources":["../src/fastembed.ts"],"names":[],"mappings":"AACA,OAAO,EAA6B,KAAK,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"fastembed.d.ts","sourceRoot":"","sources":["../src/fastembed.ts"],"names":[],"mappings":"AACA,OAAO,EAA6B,KAAK,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEpG,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAO3G,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAgBrD,0DAA0D;AAC1D,QAAA,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAEtC,CAAC;AAEF,gEAAgE;AAChE,QAAA,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAE5C,CAAC;AAEF,QAAA,MAAM,aAAa,qBAAqB,CAAC;AACzC,QAAA,MAAM,kBAAkB,MAAM,CAAC;AAE/B;;;;;;;;;GASG;AACH,qBAAa,iBAAkB,YAAW,iBAAiB;IACzD,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,CAAC;IAC7C,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAS;IASzB,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,YAAY,CAAO;IAC3B,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,kBAAkB,CAAiB;IAE3C;;;;;OAKG;gBAED,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,GAAE,qBAAmD;IAkBnE,MAAM,IAAI,eAAe;IAqBnB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC;IAkBlE,UAAU,CACf,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,SAAS,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9C,aAAa,CAAC,YAAY,CAAC;IAuBxB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5C;;;OAGG;IACH,OAAO,CAAC,cAAc;IAItB;;;OAGG;IACH,OAAO,CAAC,SAAS;IAmBjB;;;OAGG;IACH,OAAO,CAAC,QAAQ;IA0BhB;;;OAGG;IACH,OAAO,CAAC,WAAW;YAQL,SAAS;YA2CT,SAAS;IAKvB,OAAO,CAAC,mBAAmB;CAc5B;AAED,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,kBAAkB,EAAE,CAAC"}
|