@lvy-jsd/dsh-tool-manager 0.2.0 → 0.4.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.
Files changed (52) hide show
  1. package/README.md +99 -2
  2. package/cordis.patch.yml +13 -0
  3. package/lib/exempt.d.ts +45 -0
  4. package/lib/exempt.d.ts.map +1 -0
  5. package/lib/exempt.js +122 -0
  6. package/lib/exempt.js.map +1 -0
  7. package/lib/index.d.ts +1 -0
  8. package/lib/index.d.ts.map +1 -1
  9. package/lib/index.js +243 -34
  10. package/lib/index.js.map +1 -1
  11. package/lib/manifest.d.ts +21 -0
  12. package/lib/manifest.d.ts.map +1 -0
  13. package/lib/manifest.js +112 -0
  14. package/lib/manifest.js.map +1 -0
  15. package/lib/metadata.d.ts +38 -0
  16. package/lib/metadata.d.ts.map +1 -0
  17. package/lib/metadata.js +102 -0
  18. package/lib/metadata.js.map +1 -0
  19. package/lib/router/bm25.d.ts +21 -0
  20. package/lib/router/bm25.d.ts.map +1 -0
  21. package/lib/router/bm25.js +63 -0
  22. package/lib/router/bm25.js.map +1 -0
  23. package/lib/router/index.d.ts +9 -0
  24. package/lib/router/index.d.ts.map +1 -0
  25. package/lib/router/index.js +422 -0
  26. package/lib/router/index.js.map +1 -0
  27. package/lib/router/sidecar.d.ts +34 -0
  28. package/lib/router/sidecar.d.ts.map +1 -0
  29. package/lib/router/sidecar.js +156 -0
  30. package/lib/router/sidecar.js.map +1 -0
  31. package/lib/router/types.d.ts +164 -0
  32. package/lib/router/types.d.ts.map +1 -0
  33. package/lib/router/types.js +7 -0
  34. package/lib/router/types.js.map +1 -0
  35. package/lib/settings.d.ts +32 -0
  36. package/lib/settings.d.ts.map +1 -0
  37. package/lib/settings.js +93 -0
  38. package/lib/settings.js.map +1 -0
  39. package/lib/types.d.ts +137 -1
  40. package/lib/types.d.ts.map +1 -1
  41. package/package.json +8 -4
  42. package/sidecar/bin/tool-router-sidecar +0 -0
  43. package/src/exempt.ts +148 -0
  44. package/src/index.ts +245 -35
  45. package/src/manifest.ts +116 -0
  46. package/src/metadata.ts +123 -0
  47. package/src/router/bm25.ts +68 -0
  48. package/src/router/index.ts +440 -0
  49. package/src/router/sidecar.ts +159 -0
  50. package/src/router/types.ts +149 -0
  51. package/src/settings.ts +108 -0
  52. package/src/types.ts +134 -3
package/README.md CHANGED
@@ -14,6 +14,8 @@ tools_ls({ query: "pull request" }) # search the whole tree in one step
14
14
  tools_load(["/code/github"]) # callable from the next step, for the rest of the session
15
15
  tools_load(["mcp__github__get_me"]) # or one tool by exact name
16
16
  tools_unload(["/code/github"])
17
+ tools_find("send an email") # ranked matches by intent (BM25), no loading
18
+ tools_route("send an email") # retrieve, re-rank with the model, then load
17
19
  ```
18
20
 
19
21
  Loaded tools are **native**: the model receives their full parameter schema
@@ -35,7 +37,15 @@ built-in rules and config overrides, or write your own classifier.
35
37
  - Loading a group subscribes to it: tools the group gains later become visible
36
38
  too.
37
39
  - Restrictions from other plugins intersect with this one, so a hard deny (for
38
- example the MCP connector's governance policy) always wins.
40
+ example the MCP connector's governance policy) always wins. A pinned or
41
+ loaded tool that another layer still hides is marked `[denied]` in
42
+ `tools_ls`, and `tools_load` reports it as not callable instead of listing it
43
+ (with one log warning per tool, pointing at connector governance rules and
44
+ per-session injection).
45
+ - DSH's PTC mode (`DSH_TOOLS_MODE=ptc`) works unchanged: the model gets only
46
+ `run_code`, and the SDK the host declares for it is built from the same
47
+ narrowed view, so loads show up there from the next step. `run_code` itself
48
+ is a host transport and never enters the directory.
39
49
  - Every agent is restricted separately. A subagent starts from the pinned set
40
50
  plus whatever the parent loaded with `forSubagents: true`.
41
51
  - Loaded state is in memory. Install
@@ -44,6 +54,38 @@ built-in rules and config overrides, or write your own classifier.
44
54
  - If the plugin is unloaded, all its restrictions are lifted (fail open to
45
55
  "every tool visible", never to "no tools").
46
56
 
57
+ ## Finding and routing by intent
58
+
59
+ The directory above is browsable, but the model still has to guess the right
60
+ keywords and spend turns searching. The core now ships a retrieval + routing
61
+ layer that makes an unbounded catalog usable without that guesswork:
62
+
63
+ ```
64
+ tools_find("send an email") # ranked matches (BM25), no loading
65
+ tools_route("send an email") # retrieve, re-rank with the model, then load
66
+ skills_find("write a PR") # ranked skills, no loading
67
+ skills_route("write a PR") # retrieve, re-rank, then load the top skill's body
68
+ ```
69
+
70
+ Retrieval is BM25 by default: no model, no network, works offline, and scales
71
+ to a large catalog. The BM25 index lives in a Rust sidecar process
72
+ (`sidecar/`, tantivy over a Unix socket) for headroom — the hot path is native
73
+ and the TypeScript here is a thin client. A dependency-free JS BM25 index is
74
+ kept as the always-available fallback, so retrieval never breaks if the sidecar
75
+ binary is missing or the process dies.
76
+
77
+ When a model is configured (`config.model { provider, model }`), `tools_route`
78
+ and `skills_route` re-rank the BM25 candidates with the model, so a
79
+ natural-language intent that shares no words with a tool name still finds it —
80
+ the RAG-MCP pattern: retrieve a small candidate set, then rank it. Any model
81
+ failure falls back to the BM25 order, so the router never breaks on a model
82
+ hiccup.
83
+
84
+ The router reuses the core's `toolCatalog` service: it indexes the same
85
+ catalog, loads through the same path, and reports the same token budget. The
86
+ sidecar is spawned by the plugin and exits with it (a parent-process monitor
87
+ kills it on a DSH restart).
88
+
47
89
  ## Configuration
48
90
 
49
91
  ```yaml
@@ -56,6 +98,60 @@ built-in rules and config overrides, or write your own classifier.
56
98
  highRisk: [] # never included in group loads; load individually
57
99
  ```
58
100
 
101
+ ### Override files
102
+
103
+ Three files under `$DSH_HOME/tool-manager/` override the config above. Each is
104
+ read at startup and re-read when the settings panel saves through the API (or
105
+ `reload*` is called); write them from the panel, or by hand and then reload.
106
+
107
+ | File | Config key it replaces | What it holds |
108
+ |---|---|---|
109
+ | `settings.json` | `pinned`, `unpin`, `highRisk` | the lists an operator edits most often |
110
+ | `metadata.json` | `annotate()` for the same tool | `{ "<tool>": { "group", "category", "risk", "summary" } }` |
111
+ | `exempt.json` | `exemptProviders` | `{ "providers": [...], "sessions": [...] }` |
112
+
113
+ ### The tool manifest
114
+
115
+ A client that receives its tool list once per session — Claude Code, driven by
116
+ `dsh-oh-my-claude` — cannot discover the directory by asking, because nothing
117
+ tells it the directory exists. So the catalog is also written out as text, to
118
+ `~/.claude/dsh-tool-catalog.md`, after every rebuild:
119
+
120
+ ```
121
+ ## device (14 tools, Devices)
122
+
123
+ ### adb — load with `tools_load({ targets: ["/device/adb"] })`
124
+ - adb_install — Install an APK on a device.
125
+ - adb_shell ! — Run a shell command on a device.
126
+ ```
127
+
128
+ The file opens by saying the listed tools are **not callable yet**, then gives
129
+ the two calls that change that (`tools_ls`, `tools_load`) and the rule to load
130
+ the smallest thing that covers the task. A `!` marks a high-risk tool. Reading
131
+ it runs nothing.
132
+
133
+ Add one line to `~/.claude/CLAUDE.md` so every Claude session reads it:
134
+
135
+ ```
136
+ @~/.claude/dsh-tool-catalog.md
137
+ ```
138
+
139
+ The write is skipped when the text did not change, so a rebuild that moves
140
+ nothing does not cost a prompt re-read. `manifestFile` points it elsewhere, and
141
+ `''` turns it off.
142
+
143
+ The files win as a whole, not key by key: once `exempt.json` exists, the config
144
+ list is ignored rather than merged, so what the file shows is what is in force.
145
+ A missing file means "no opinion, use the config"; a corrupt file is reported as
146
+ a warning and treated as empty rather than silently restoring the config.
147
+ `sessions` exempts one session by id for its remaining lifetime, for checking
148
+ whether a client handles late loading without de-exempting the whole route.
149
+
150
+ A tool's `metadata.json` entry replaces the previous entry as a whole:
151
+ submitting the form with a field blank drops that override, and the package
152
+ declaration (or a classifier) applies again. `parameters` are deliberately not
153
+ part of it — the host owns the schema sent to the model.
154
+
59
155
  ## Extending: the `toolCatalog` service
60
156
 
61
157
  Declare `inject: ['toolCatalog']` (or use `ctx.inject(['toolCatalog'], …)` for
@@ -193,7 +289,8 @@ ctx.effect(() => ctx.toolCatalog.registerVisibilityFilter({
193
289
  ### Reading the catalog
194
290
 
195
291
  `ctx.toolCatalog.get()` returns `{ tools, groups, categories }`;
196
- `resolve(target)`, `stateOf(agent)`, `allowFor(agent)`, `isExempt(agent)`,
292
+ `resolve(target)`, `stateOf(agent)`, `allowFor(agent)`, `deniedFor(agent)`
293
+ (allowed here but hidden by another layer), `isExempt(agent)`,
197
294
  `packages()` (enabled plugin packages: `{ name, dir, manifest }`) and
198
295
  `refresh()` are also available.
199
296
 
package/cordis.patch.yml CHANGED
@@ -14,3 +14,16 @@
14
14
  # Loading high-risk tools also needs a risk gate plugin
15
15
  # (@lvy-jsd/dsh-tool-manager-risk-gate) to confirm them.
16
16
  highRisk: []
17
+ # The catalog as text, for a client that cannot lazy-load (Claude Code
18
+ # reads it through a ~/.claude/CLAUDE.md `@` line). '' turns it off.
19
+ # manifestFile: ~/.claude/dsh-tool-catalog.md
20
+ # --- retrieval + routing (tools_find / tools_route / skills_find / skills_route) ---
21
+ # Model used to re-rank tools_route / skills_route candidates. Leave
22
+ # unset for pure BM25 (no model, works offline).
23
+ # model: { provider: deepseek, model: deepseek-chat }
24
+ # maxTokens: 24
25
+ # topK: 8
26
+ # maxBudget: 20000
27
+ # k1: 1.5
28
+ # b: 0.75
29
+ # sidecar: { bin: '', socket: '', timeoutMs: 2000 }
@@ -0,0 +1,45 @@
1
+ import type { Logger } from './types.js';
2
+ /** An exemption list: routes and sessions. Both may be empty. */
3
+ export interface ExemptConfig {
4
+ providers: string[];
5
+ sessions: string[];
6
+ }
7
+ /** Where the exemption file lives unless a deployment points elsewhere. */
8
+ export declare function defaultExemptFile(): string;
9
+ /** The whole file, with unknown keys dropped. */
10
+ export declare function pickExempt(raw: unknown): ExemptConfig;
11
+ /** Read the exemption file; missing or corrupt is "no opinion", never a crash. */
12
+ export declare function readExemptFile(file: string, logger?: Logger): ExemptConfig | undefined;
13
+ /** Write the file atomically, so a crash cannot leave a half-written list. */
14
+ export declare function writeExemptFile(file: string, config: ExemptConfig, logger?: Logger): void;
15
+ /** Why a session is exempt, for the panel to show. */
16
+ export interface ExemptReason {
17
+ exempt: boolean;
18
+ /** 'file:provider' | 'file:session' | 'config:provider' | '' */
19
+ source: string;
20
+ }
21
+ export interface ExemptStore {
22
+ /** File the store reads and writes; the file itself is the override switch. */
23
+ file: string;
24
+ /** True when the file exists, so the config provider list is ignored. */
25
+ present(): boolean;
26
+ /** The lists in force: the file when it exists, else the plugin config. */
27
+ effective(): ExemptConfig;
28
+ /** Why one session is exempt, if it is. */
29
+ reasonFor(provider: string | undefined, sessionId: string | undefined): ExemptReason;
30
+ /** Add or remove one session, writing the file. Returns the lists in force. */
31
+ setSession(sessionId: string, exempt: boolean): ExemptConfig;
32
+ /** Re-read the file, for after an external edit. Returns the lists in force. */
33
+ reload(): ExemptConfig;
34
+ }
35
+ /**
36
+ * Exemption store over one file, with the plugin config as the fallback layer.
37
+ * The file wins as a whole rather than per key: an operator writing the file
38
+ * means it, and a partial merge would leave entries they cannot see.
39
+ */
40
+ export declare function createExemptStore({ file, configProviders, logger }: {
41
+ file: string;
42
+ configProviders?: readonly string[];
43
+ logger?: Logger;
44
+ }): ExemptStore;
45
+ //# sourceMappingURL=exempt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exempt.d.ts","sourceRoot":"","sources":["../src/exempt.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAExC,iEAAiE;AACjE,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,2EAA2E;AAC3E,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C;AAQD,iDAAiD;AACjD,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAMrD;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAkBtF;AAED,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAUzF;AAED,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,OAAO,CAAA;IACf,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAA;IACZ,yEAAyE;IACzE,OAAO,IAAI,OAAO,CAAA;IAClB,2EAA2E;IAC3E,SAAS,IAAI,YAAY,CAAA;IACzB,2CAA2C;IAC3C,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAAA;IACpF,+EAA+E;IAC/E,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,YAAY,CAAA;IAC5D,gFAAgF;IAChF,MAAM,IAAI,YAAY,CAAA;CACvB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,eAAoB,EAAE,MAAM,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CA+B7J"}
package/lib/exempt.js ADDED
@@ -0,0 +1,122 @@
1
+ // File-based exemption list for dsh-tool-manager.
2
+ //
3
+ // An exempt session is never narrowed: a route whose tool list is handed to an
4
+ // external client once at session start (Claude Code, say) cannot load a tool
5
+ // that was hidden from the first request, so hiding anything there only loses
6
+ // tools. The provider list originally came from `exemptProviders` in
7
+ // cordis.patch.yml, which a user cannot edit from the browser and which is
8
+ // awkward to change per session.
9
+ //
10
+ // This file replaces it: when <DSH_HOME>/tool-manager/exempt.json exists it wins
11
+ // over the plugin config, the same way the settings file does. Two entry forms
12
+ // are supported, because they answer different questions:
13
+ //
14
+ // { "providers": ["claude-code"], "sessions": ["s_abc123"] }
15
+ //
16
+ // providers model routes never narrowed, for every session (durable)
17
+ // sessions one session exempted for its remaining lifetime, e.g. while the
18
+ // user checks whether a client handles lazy loading (temporary)
19
+ //
20
+ // Sessions are matched against the agent's session id and, as a fallback, the
21
+ // agent id, so an entry can be removed by hand without knowing which of the two
22
+ // the host populated.
23
+ import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
24
+ import { homedir } from 'node:os';
25
+ import { dirname, join } from 'node:path';
26
+ /** Where the exemption file lives unless a deployment points elsewhere. */
27
+ export function defaultExemptFile() {
28
+ const dshHome = process.env.DSH_HOME || join(homedir(), '.config', 'deepseek-harness');
29
+ return join(dshHome, 'tool-manager', 'exempt.json');
30
+ }
31
+ /** Keep only non-empty strings; a number or object in the file is a typo, not a name. */
32
+ function pickNames(value) {
33
+ if (!Array.isArray(value))
34
+ return [];
35
+ return value.filter((name) => typeof name === 'string' && name.trim().length > 0).map((name) => name.trim());
36
+ }
37
+ /** The whole file, with unknown keys dropped. */
38
+ export function pickExempt(raw) {
39
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
40
+ return { providers: [], sessions: [] };
41
+ const record = raw;
42
+ // `providers` is required: a file that omits it says "no route is exempt",
43
+ // not "keep the old config list", because the file is the override.
44
+ return { providers: pickNames(record.providers), sessions: pickNames(record.sessions) };
45
+ }
46
+ /** Read the exemption file; missing or corrupt is "no opinion", never a crash. */
47
+ export function readExemptFile(file, logger) {
48
+ let text;
49
+ try {
50
+ text = readFileSync(file, 'utf8');
51
+ }
52
+ catch (caught) {
53
+ const error = caught;
54
+ // ENOENT is the normal first run: no file means the plugin config decides.
55
+ if (error.code !== 'ENOENT')
56
+ logger?.warn?.(`tool-manager: ignoring unreadable exemptions ${file}: ${error.message}`);
57
+ return undefined;
58
+ }
59
+ try {
60
+ return pickExempt(JSON.parse(text));
61
+ }
62
+ catch (caught) {
63
+ // A corrupt file must not silently restore the config list: the user
64
+ // intended the file to be in charge, so report and treat it as "no exempt".
65
+ logger?.warn?.(`tool-manager: unreadable exemptions ${file}: ${caught.message}`);
66
+ return { providers: [], sessions: [] };
67
+ }
68
+ }
69
+ /** Write the file atomically, so a crash cannot leave a half-written list. */
70
+ export function writeExemptFile(file, config, logger) {
71
+ mkdirSync(dirname(file), { recursive: true });
72
+ const tmp = `${file}.tmp`;
73
+ try {
74
+ writeFileSync(tmp, `${JSON.stringify({ providers: config.providers, sessions: config.sessions }, null, 2)}\n`);
75
+ renameSync(tmp, file);
76
+ }
77
+ catch (caught) {
78
+ logger?.warn?.(`tool-manager: writing exemptions ${file} failed: ${caught.message}`);
79
+ throw caught;
80
+ }
81
+ }
82
+ /**
83
+ * Exemption store over one file, with the plugin config as the fallback layer.
84
+ * The file wins as a whole rather than per key: an operator writing the file
85
+ * means it, and a partial merge would leave entries they cannot see.
86
+ */
87
+ export function createExemptStore({ file, configProviders = [], logger }) {
88
+ let fromFile = readExemptFile(file, logger);
89
+ const effective = () => fromFile ?? { providers: [...configProviders], sessions: [] };
90
+ return {
91
+ file,
92
+ present: () => fromFile !== undefined,
93
+ effective,
94
+ reasonFor(provider, sessionId) {
95
+ const current = effective();
96
+ if (provider !== undefined && current.providers.includes(provider)) {
97
+ return { exempt: true, source: fromFile !== undefined ? 'file:provider' : 'config:provider' };
98
+ }
99
+ if (sessionId !== undefined && current.sessions.includes(sessionId))
100
+ return { exempt: true, source: 'file:session' };
101
+ return { exempt: false, source: '' };
102
+ },
103
+ setSession(sessionId, exempt) {
104
+ // Editing starts from what is in force, so the first panel click writes a
105
+ // file that keeps the exemptions the user could already see.
106
+ const current = effective();
107
+ const sessions = new Set(current.sessions);
108
+ if (exempt)
109
+ sessions.add(sessionId);
110
+ else
111
+ sessions.delete(sessionId);
112
+ fromFile = { providers: [...current.providers], sessions: [...sessions] };
113
+ writeExemptFile(file, fromFile, logger);
114
+ return effective();
115
+ },
116
+ reload() {
117
+ fromFile = readExemptFile(file, logger);
118
+ return effective();
119
+ },
120
+ };
121
+ }
122
+ //# sourceMappingURL=exempt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exempt.js","sourceRoot":"","sources":["../src/exempt.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export type { VisibilityController, VisibilityOptions } from './visibility.js';
7
7
  export declare const name = "tool-manager";
8
8
  export declare const inject: string[];
9
9
  export declare const ENTRY_TOOLS: string[];
10
+ export declare const HOST_RESERVED: string[];
10
11
  export declare const DEFAULT_PINNED: string[];
11
12
  export declare function apply(ctx: HostContext, config?: CoreConfig): void;
12
13
  /** Options for toolCatalog.load / tools_load. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAA2C,UAAU,EAAY,WAAW,EAAgF,MAAM,YAAY,CAAA;AAE1L,mBAAmB,YAAY,CAAA;AAC/B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,kBAAkB,EAAE,aAAa,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAC7L,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,YAAY,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC1E,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAE9E,eAAO,MAAM,IAAI,iBAAiB,CAAA;AAClC,eAAO,MAAM,MAAM,UAAY,CAAA;AAE/B,eAAO,MAAM,WAAW,UAA6C,CAAA;AAKrE,eAAO,MAAM,cAAc,UAY1B,CAAA;AAeD,wBAAgB,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,GAAE,UAAe,QA4gB9D;AAED,iDAAiD;AACjD,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;;;;;;AAOD,wBAAsC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAA2C,UAAU,EAAY,WAAW,EAA0F,MAAM,YAAY,CAAA;AAEpM,mBAAmB,YAAY,CAAA;AAC/B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,kBAAkB,EAAE,aAAa,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAC7L,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,YAAY,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC1E,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAE9E,eAAO,MAAM,IAAI,iBAAiB,CAAA;AAClC,eAAO,MAAM,MAAM,UAAY,CAAA;AAE/B,eAAO,MAAM,WAAW,UAA6C,CAAA;AAMrE,eAAO,MAAM,aAAa,UAAe,CAAA;AAKzC,eAAO,MAAM,cAAc,UAY1B,CAAA;AAeD,wBAAgB,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,GAAE,UAAe,QAmtB9D;AAED,iDAAiD;AACjD,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;;;;;;AAOD,wBAAsC"}