@lvy-jsd/dsh-tool-manager 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 lvy-jsd and contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,206 @@
1
- # Temporary Holding Version
1
+ # @lvy-jsd/dsh-tool-manager
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Browse every DeepSeek Harness tool as a directory and load tools on demand.
4
+
5
+ A DSH host with many plugins and MCP connectors sends every tool schema to the
6
+ model on every request. This plugin hides everything except a small always-on
7
+ set and gives the model three entry tools to find and load the rest:
8
+
9
+ ```
10
+ tools_ls("/") # categories
11
+ tools_ls("/code") # groups (a connector or plugin)
12
+ tools_ls("/code/github") # tools, with a one-line summary and schema size
13
+ tools_ls({ query: "pull request" }) # search the whole tree in one step
14
+ tools_load(["/code/github"]) # callable from the next step, for the rest of the session
15
+ tools_load(["mcp__github__get_me"]) # or one tool by exact name
16
+ tools_unload(["/code/github"])
17
+ ```
18
+
19
+ Loaded tools are **native**: the model receives their full parameter schema
20
+ and calls them directly. Nothing is proxied.
21
+
22
+ The core ships **no placement rules**. Without an extension every group is
23
+ listed under `uncategorized/` — still fully browsable and loadable. Install
24
+ [`dsh-tool-manager-classifier-rules`](../dsh-tool-manager-classifier-rules) for
25
+ built-in rules and config overrides, or write your own classifier.
26
+
27
+ ## How it works
28
+
29
+ - Visibility is a per-agent allowlist installed with the host's
30
+ `agent.ctx.tools.restrict({ allow })`:
31
+ `allow = (pinned ∪ loaded tools ∪ tools of loaded groups) ∩ registered tools`,
32
+ then narrowed by any registered visibility filters.
33
+ Tools that appear later (an MCP server reconnecting, a new plugin, a renamed
34
+ tool) stay hidden until loaded.
35
+ - Loading a group subscribes to it: tools the group gains later become visible
36
+ too.
37
+ - Restrictions from other plugins intersect with this one, so a hard deny (for
38
+ example the MCP connector's governance policy) always wins.
39
+ - Every agent is restricted separately. A subagent starts from the pinned set
40
+ plus whatever the parent loaded with `forSubagents: true`.
41
+ - Loaded state is in memory. Install
42
+ [`dsh-tool-manager-persist`](../dsh-tool-manager-persist) to save it per
43
+ session and restore it when the session resumes.
44
+ - If the plugin is unloaded, all its restrictions are lifted (fail open to
45
+ "every tool visible", never to "no tools").
46
+
47
+ ## Configuration
48
+
49
+ ```yaml
50
+ - id: tool-manager
51
+ name: '@lvy-jsd/dsh-tool-manager'
52
+ config:
53
+ pinned: [] # extra always-on tools (core DSH tools are built in)
54
+ unpin: [] # built-in always-on tools to move into the directory
55
+ exemptProviders: [claude-code] # routes never narrowed (tool list fixed at session start)
56
+ highRisk: [] # never included in group loads; load individually
57
+ ```
58
+
59
+ ## Extending: the `toolCatalog` service
60
+
61
+ Declare `inject: ['toolCatalog']` (or use `ctx.inject(['toolCatalog'], …)` for
62
+ an optional dependency) and register inside an effect so that unloading your
63
+ plugin undoes the registration.
64
+
65
+ ### Classifiers
66
+
67
+ A classifier may place tools into groups and/or groups into categories.
68
+ Return `undefined` to pass.
69
+
70
+ ```js
71
+ export const name = 'my-classifier'
72
+ export const inject = ['toolCatalog']
73
+ export function apply(ctx) {
74
+ ctx.effect(() => ctx.toolCatalog.registerClassifier({
75
+ name: 'my-classifier',
76
+ priority: 200,
77
+ group: (tool) => (tool.name.startsWith('lingshu_') ? 'lingshu' : undefined),
78
+ categorize: (group) => (group.name === 'lingshu' ? 'system' : undefined),
79
+ }))
80
+ }
81
+ ```
82
+
83
+ Resolution order: classifiers with `priority >= 1000` (user overrides) →
84
+ plugin declarations → other classifiers, highest priority first → structural
85
+ fallback (`mcp__server__…` → `server`, shared `prefix_` → `prefix`, else
86
+ `misc`; category `uncategorized`). A classifier that throws is skipped.
87
+
88
+ ### Declaring your own tools
89
+
90
+ Plugin authors know their tools best. Declare them in your `package.json`:
91
+
92
+ ```json
93
+ {
94
+ "dsh": {
95
+ "toolCatalog": {
96
+ "match": "^adb_",
97
+ "group": "adb",
98
+ "category": "device",
99
+ "tools": { "adb_install": { "risk": "high", "summary": "Install an APK." } }
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ or at runtime:
106
+
107
+ ```js
108
+ ctx.effect(() => ctx.toolCatalog.annotate('^adb_', { category: 'device' }))
109
+ ctx.effect(() => ctx.toolCatalog.annotate('adb_install', { risk: 'high' }))
110
+ ```
111
+
112
+ Fields: `group`, `category`, `risk` (`"high"`), `summary`. Exact-name entries
113
+ win over `match`; runtime annotations win over `package.json`.
114
+
115
+ ### New categories
116
+
117
+ ```js
118
+ ctx.effect(() => ctx.toolCatalog.defineCategory('games', 'Game servers and bots'))
119
+ ```
120
+
121
+ ### High-risk gates
122
+
123
+ A gate declares that a plugin confirms high-risk loads (normally by returning
124
+ `{ kind: 'ask' }` from `tools/pre-execute` for `tools_load`). **With no gate
125
+ registered, high-risk tools cannot be loaded at all** — they are skipped in
126
+ group loads and refused individually. That is deliberate: a deployment without
127
+ an approval path should not be able to arm them.
128
+
129
+ ```js
130
+ ctx.effect(() => ctx.toolCatalog.registerRiskGate({ name: 'my-policy' }))
131
+ ctx.effect(() => ctx.on('tools/pre-execute', async (exec, next) => {
132
+ if (exec.name !== 'tools_load' || !needsConfirmation(exec.arguments)) return next()
133
+ return { kind: 'ask', reason: 'Loading a high-risk tool' }
134
+ }))
135
+ ```
136
+
137
+ See [`dsh-tool-manager-risk-gate`](../dsh-tool-manager-risk-gate).
138
+
139
+ ### Persistence
140
+
141
+ Loaded state lives in memory; a state provider makes it outlive the process.
142
+
143
+ ```js
144
+ ctx.effect(() => ctx.toolCatalog.registerStateProvider({
145
+ name: 'my-store',
146
+ load: (agent) => readFromMyStore(agent.id), // serialized state or null
147
+ save: (agent, state) => writeToMyStore(agent.id, state),
148
+ }))
149
+ ```
150
+
151
+ Providers are consulted in registration order (first non-null wins) and all
152
+ receive every save. `exportState(agent)` / `importState(agent, state)` are the
153
+ plain-JSON equivalents. See
154
+ [`dsh-tool-manager-persist`](../dsh-tool-manager-persist).
155
+
156
+ ### Hooks
157
+
158
+ Plain Cordis events on the host context:
159
+
160
+ | Event | Kind | Payload |
161
+ |---|---|---|
162
+ | `tool-catalog/before-load` | serial; throw to veto | `{ agent, targets, names }` |
163
+ | `tool-catalog/after-load` | emit | `{ agent, targets, added }` |
164
+ | `tool-catalog/before-unload` | serial; throw to veto | `{ agent, targets }` |
165
+ | `tool-catalog/after-unload` | emit | `{ agent, targets, removed }` |
166
+ | `tool-catalog/before-rebuild` | emit | `{}` |
167
+ | `tool-catalog/after-rebuild` | emit | `{ catalog }` |
168
+ | `tool-catalog/state-changed` | emit | `{ agent, state }` (plain JSON, after every load/unload) |
169
+
170
+ ```js
171
+ // A per-session quota: at most 60 visible tools.
172
+ ctx.on('tool-catalog/before-load', ({ agent, names }) => {
173
+ const now = ctx.toolCatalog.allowFor(agent)?.length ?? 0
174
+ if (now + names.length > 60) throw new Error('tool quota reached; unload something first')
175
+ })
176
+ ```
177
+
178
+ ### Visibility filters
179
+
180
+ A filter receives the agent and the computed allowlist and returns the names
181
+ to keep. It can only narrow; it can never add tools or hide the entry tools.
182
+
183
+ ```js
184
+ // Keep GitHub write tools away from bot sessions.
185
+ ctx.effect(() => ctx.toolCatalog.registerVisibilityFilter({
186
+ name: 'no-github-writes-for-bots',
187
+ filter: (agent, names) => (agent.id.startsWith('bot-')
188
+ ? names.filter((n) => !/^mcp__github__(create|delete|merge|push|update)/.test(n))
189
+ : names),
190
+ }))
191
+ ```
192
+
193
+ ### Reading the catalog
194
+
195
+ `ctx.toolCatalog.get()` returns `{ tools, groups, categories }`;
196
+ `resolve(target)`, `stateOf(agent)`, `allowFor(agent)`, `isExempt(agent)`,
197
+ `packages()` (enabled plugin packages: `{ name, dir, manifest }`) and
198
+ `refresh()` are also available.
199
+
200
+ ## Tests
201
+
202
+ See the repository root.
203
+
204
+ ## License
205
+
206
+ MIT
@@ -0,0 +1,16 @@
1
+ # @lvy-jsd/dsh-tool-manager bundle patch: one loader entry.
2
+ - insert:
3
+ - id: tool-manager
4
+ name: '@lvy-jsd/dsh-tool-manager'
5
+ config:
6
+ # Extra always-visible tools on top of the built-in core list.
7
+ pinned: []
8
+ # Built-in always-visible tools to move into the directory instead.
9
+ unpin: []
10
+ # Model routes never narrowed: their tool list is handed to an external
11
+ # client once per session and not refreshed (Claude Code's MCP bridge).
12
+ exemptProviders: [claude-code]
13
+ # Tools excluded from group loads; must be loaded on their own.
14
+ # Loading high-risk tools also needs a risk gate plugin
15
+ # (@lvy-jsd/dsh-tool-manager-risk-gate) to confirm them.
16
+ highRisk: []
@@ -0,0 +1,35 @@
1
+ import type { Annotation, Catalog, CatalogNode, Classifier, RegisteredResolver, ToolEntry, ToolSchema } from './types.js';
2
+ export declare const UNCATEGORIZED = "uncategorized";
3
+ export declare const MISC_GROUP = "misc";
4
+ export declare const OVERRIDE_PRIORITY = 1000;
5
+ export declare const DEFAULT_CATEGORIES: Record<string, string>;
6
+ /**
7
+ * Structural group for a tool name, used when nothing else places it:
8
+ * `mcp__server__tool` -> server, `mcp__server__sub__tool` -> server-sub,
9
+ * `prefix_rest` -> prefix when at least two tools share a non-verb prefix, else misc.
10
+ */
11
+ export declare function structuralGroup(name: string, prefixCounts: Map<string, number>): string;
12
+ /** Short form of a tool name inside its group (drops the MCP routing prefix). */
13
+ export declare function shortName(name: string): string;
14
+ /** First sentence of a description, capped for one-line listings. */
15
+ export declare function summary(text: string | undefined, max?: number): string;
16
+ /** Rough token cost of one schema as the model receives it. */
17
+ export declare function estimateTokens(schema: unknown): number;
18
+ export interface BuildOptions {
19
+ /** Placement rules; priority >= OVERRIDE_PRIORITY beats plugin declarations. */
20
+ classifiers?: readonly Classifier[];
21
+ annotations?: readonly Annotation[];
22
+ /** Category vocabulary (name -> description). */
23
+ categories?: Record<string, string>;
24
+ /** Tool names configured as high risk. */
25
+ highRisk?: readonly string[];
26
+ }
27
+ /**
28
+ * Build the directory index.
29
+ * @param schemas - catalog tools (pinned already removed)
30
+ */
31
+ export declare function buildCatalog(schemas: readonly ToolSchema[], { classifiers, annotations, categories, highRisk }?: BuildOptions): Catalog;
32
+ export declare function resolveTarget(catalog: Catalog, raw: unknown, resolvers?: readonly Pick<RegisteredResolver, 'prefix' | 'resolve'>[]): CatalogNode;
33
+ /** Tools under a node (whole tree for root). */
34
+ export declare function toolsUnder(catalog: Catalog, node: CatalogNode): ToolEntry[];
35
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAY,UAAU,EAAqB,kBAAkB,EAAE,SAAS,EAAuB,UAAU,EAAE,MAAM,YAAY,CAAA;AAE3K,eAAO,MAAM,aAAa,kBAAkB,CAAA;AAC5C,eAAO,MAAM,UAAU,SAAS,CAAA;AAChC,eAAO,MAAM,iBAAiB,OAAO,CAAA;AAGrC,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAarD,CAAA;AAUD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CASvF;AAED,iFAAiF;AACjF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI9C;AAED,qEAAqE;AACrE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,SAAK,GAAG,MAAM,CAIlE;AAED,+DAA+D;AAC/D,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAMtD;AAqDD,MAAM,WAAW,YAAY;IAC3B,gFAAgF;IAChF,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;IACnC,WAAW,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;IACnC,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC7B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,EAAE,EAAE,WAAgB,EAAE,WAAgB,EAAE,UAA+B,EAAE,QAAa,EAAE,GAAE,YAAiB,GAAG,OAAO,CA+D/K;AAqBD,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,GAAE,SAAS,IAAI,CAAC,kBAAkB,EAAE,QAAQ,GAAG,SAAS,CAAC,EAAO,GAAG,WAAW,CAiDpJ;AAmBD,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,SAAS,EAAE,CAM3E"}
package/lib/catalog.js ADDED
@@ -0,0 +1,311 @@
1
+ // Builds the three-level tool directory: category -> group -> tool.
2
+ //
3
+ // The core knows no rules. Placement comes from, in order:
4
+ // 1. override classifiers (priority >= OVERRIDE_PRIORITY), e.g. user config
5
+ // 2. annotations declared by plugins (package.json `dsh.toolCatalog`, annotate())
6
+ // 3. ordinary classifiers, highest priority first
7
+ // 4. a structural fallback: group from the tool name, category `uncategorized`
8
+ //
9
+ // Grouping never decides visibility; a misplaced tool is only listed in the
10
+ // wrong place, never lost.
11
+ export const UNCATEGORIZED = 'uncategorized';
12
+ export const MISC_GROUP = 'misc';
13
+ export const OVERRIDE_PRIORITY = 1000;
14
+ // The fixed category vocabulary. Plugins may add more with defineCategory().
15
+ export const DEFAULT_CATEGORIES = {
16
+ device: 'Phones, Android, ADB and desktop control',
17
+ code: 'Source hosting, repositories and package tooling',
18
+ media: 'Video, image and audio services',
19
+ maps: 'Maps, geocoding and routing',
20
+ browser: 'Headless browser automation',
21
+ memory: 'Long-term memory and knowledge stores',
22
+ collaboration: 'Bots, group chats, teammates and other sessions',
23
+ automation: 'Schedules and automated runs',
24
+ connectors: 'MCP connector administration',
25
+ search: 'Web and social search',
26
+ system: 'Host, OS and secrets',
27
+ [UNCATEGORIZED]: 'Tools no classifier has placed yet',
28
+ };
29
+ // Leading words that describe an action rather than an owner; a shared verb
30
+ // prefix ("list_", "get_") is not a meaningful group.
31
+ const VERB_PREFIXES = new Set([
32
+ 'add', 'ask', 'attach', 'create', 'delete', 'detach', 'edit', 'exit', 'get',
33
+ 'interrupt', 'list', 'message', 'open', 'post', 'read', 'remove', 'request',
34
+ 'run', 'save', 'send', 'set', 'spawn', 'stop', 'update', 'wait', 'write',
35
+ ]);
36
+ /**
37
+ * Structural group for a tool name, used when nothing else places it:
38
+ * `mcp__server__tool` -> server, `mcp__server__sub__tool` -> server-sub,
39
+ * `prefix_rest` -> prefix when at least two tools share a non-verb prefix, else misc.
40
+ */
41
+ export function structuralGroup(name, prefixCounts) {
42
+ if (name.startsWith('mcp__')) {
43
+ const parts = name.slice(5).split('__');
44
+ if (parts.length >= 3)
45
+ return `${parts[0]}-${parts[1]}`;
46
+ return parts[0];
47
+ }
48
+ const prefix = name.split('_')[0];
49
+ if (prefix !== name && !VERB_PREFIXES.has(prefix) && (prefixCounts.get(prefix) ?? 0) >= 2)
50
+ return prefix;
51
+ return MISC_GROUP;
52
+ }
53
+ /** Short form of a tool name inside its group (drops the MCP routing prefix). */
54
+ export function shortName(name) {
55
+ if (!name.startsWith('mcp__'))
56
+ return name;
57
+ const parts = name.slice(5).split('__');
58
+ return parts[parts.length - 1] ?? name;
59
+ }
60
+ /** First sentence of a description, capped for one-line listings. */
61
+ export function summary(text, max = 80) {
62
+ const flat = String(text ?? '').replace(/\s+/g, ' ').trim();
63
+ const first = flat.split(/(?<=[.!?。!?])\s/)[0] ?? '';
64
+ return first.length > max ? `${first.slice(0, max - 1)}…` : first;
65
+ }
66
+ /** Rough token cost of one schema as the model receives it. */
67
+ export function estimateTokens(schema) {
68
+ const text = JSON.stringify(schema);
69
+ // CJK and other wide characters cost roughly one token each, not a quarter.
70
+ let wide = 0;
71
+ for (const ch of text)
72
+ if ((ch.codePointAt(0) ?? 0) > 0x2e7f)
73
+ wide += 1;
74
+ return Math.ceil((text.length - wide) / 4 + wide);
75
+ }
76
+ /** Merge every annotation that applies to `name`; later annotations win per field. */
77
+ function annotationFor(name, annotations) {
78
+ let merged;
79
+ for (const a of annotations) {
80
+ const hit = typeof a.match === 'string' ? a.match === name : a.match.test(name);
81
+ if (hit)
82
+ merged = { ...merged, ...a.meta };
83
+ }
84
+ return merged ?? {};
85
+ }
86
+ /**
87
+ * A group a classifier renamed (e.g. attribution-scan: `phone` -> `phone-control`)
88
+ * is unknown to category rules written for the old name. Ask the classifiers
89
+ * about the structural groups its tools came from instead; the category covering
90
+ * the most tools wins.
91
+ */
92
+ function inheritedCategory(group, classifiers) {
93
+ const byFallback = new Map();
94
+ for (const tool of group.tools) {
95
+ if (tool.fallbackGroup === group.name)
96
+ continue;
97
+ let list = byFallback.get(tool.fallbackGroup);
98
+ if (!list)
99
+ byFallback.set(tool.fallbackGroup, (list = []));
100
+ list.push(tool);
101
+ }
102
+ const votes = new Map();
103
+ for (const [name, tools] of byFallback) {
104
+ const probe = { name, tools: tools.map(({ name: n, description, annotation }) => ({ name: n, description, annotation })) };
105
+ const category = firstResult(classifiers, 'categorize', probe);
106
+ if (category && category !== UNCATEGORIZED)
107
+ votes.set(category, (votes.get(category) ?? 0) + tools.length);
108
+ }
109
+ let best;
110
+ for (const [category, count] of votes)
111
+ if (!best || count > best[1])
112
+ best = [category, count];
113
+ return best?.[0];
114
+ }
115
+ function firstResult(classifiers, method, arg) {
116
+ for (const c of classifiers) {
117
+ const fn = c[method];
118
+ if (typeof fn !== 'function')
119
+ continue;
120
+ try {
121
+ const value = fn.call(c, arg);
122
+ if (typeof value === 'string' && value)
123
+ return value;
124
+ }
125
+ catch {
126
+ // A failing classifier is skipped, never fatal.
127
+ }
128
+ }
129
+ return undefined;
130
+ }
131
+ /**
132
+ * Build the directory index.
133
+ * @param schemas - catalog tools (pinned already removed)
134
+ */
135
+ export function buildCatalog(schemas, { classifiers = [], annotations = [], categories = DEFAULT_CATEGORIES, highRisk = [] } = {}) {
136
+ const sorted = [...classifiers].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
137
+ const overrides = sorted.filter((c) => (c.priority ?? 0) >= OVERRIDE_PRIORITY);
138
+ const ordinary = sorted.filter((c) => (c.priority ?? 0) < OVERRIDE_PRIORITY);
139
+ const prefixCounts = new Map();
140
+ for (const { name } of schemas) {
141
+ const prefix = name.split('_')[0];
142
+ if (prefix !== name)
143
+ prefixCounts.set(prefix, (prefixCounts.get(prefix) ?? 0) + 1);
144
+ }
145
+ const risky = new Set(highRisk);
146
+ const tools = new Map();
147
+ const groups = new Map();
148
+ for (const schema of schemas) {
149
+ const meta = annotationFor(schema.name, annotations);
150
+ const probe = { name: schema.name, description: schema.description ?? '', annotation: meta };
151
+ const group = firstResult(overrides, 'group', probe)
152
+ ?? meta.group
153
+ ?? firstResult(ordinary, 'group', probe)
154
+ ?? structuralGroup(schema.name, prefixCounts);
155
+ const entry = {
156
+ name: schema.name,
157
+ short: shortName(schema.name),
158
+ group,
159
+ // Where the structural fallback alone would have put it; a renamed group
160
+ // inherits that group's category (see below).
161
+ fallbackGroup: structuralGroup(schema.name, prefixCounts),
162
+ category: UNCATEGORIZED,
163
+ summary: meta.summary ? summary(meta.summary) : summary(schema.description),
164
+ description: schema.description ?? '',
165
+ tokens: estimateTokens(schema),
166
+ highRisk: risky.has(schema.name) || meta.risk === 'high',
167
+ annotation: meta,
168
+ };
169
+ tools.set(schema.name, entry);
170
+ let bucket = groups.get(group);
171
+ if (!bucket)
172
+ groups.set(group, (bucket = { name: group, category: UNCATEGORIZED, tools: [] }));
173
+ bucket.tools.push(entry);
174
+ }
175
+ for (const group of groups.values()) {
176
+ group.tools.sort((a, b) => a.short.localeCompare(b.short));
177
+ const probe = { name: group.name, tools: group.tools.map(({ name, description, annotation }) => ({ name, description, annotation })) };
178
+ const annotated = group.tools.map((t) => t.annotation.category).find(Boolean);
179
+ group.category = firstResult(overrides, 'categorize', probe)
180
+ ?? annotated
181
+ ?? firstResult(ordinary, 'categorize', probe)
182
+ ?? inheritedCategory(group, [...overrides, ...ordinary])
183
+ ?? UNCATEGORIZED;
184
+ for (const tool of group.tools)
185
+ tool.category = group.category;
186
+ }
187
+ const categoryIndex = new Map();
188
+ for (const [name, description] of Object.entries(categories))
189
+ categoryIndex.set(name, { name, description, groups: [] });
190
+ for (const group of groups.values()) {
191
+ let category = categoryIndex.get(group.category);
192
+ if (!category)
193
+ categoryIndex.set(group.category, (category = { name: group.category, description: '', groups: [] }));
194
+ category.groups.push(group);
195
+ }
196
+ for (const category of categoryIndex.values())
197
+ category.groups.sort((a, b) => a.name.localeCompare(b.name));
198
+ return { tools, groups, categories: categoryIndex };
199
+ }
200
+ /**
201
+ * Resolve a target into catalog nodes.
202
+ * Accepts "/", "/category", "/category/group", "/category/group/tool",
203
+ * a bare category or group name, a full tool name, or a unique short tool name.
204
+ */
205
+ /**
206
+ * Resolve a target string to a node.
207
+ *
208
+ * `resolvers` lets a plugin own a prefix (`cap:`, say): each is consulted before
209
+ * the built-in rules and returns a list of target strings to resolve instead, or
210
+ * undefined to pass. A plugin can therefore add a target vocabulary without the
211
+ * core knowing anything about it.
212
+ */
213
+ // Path segments are lowercased, but names keep their original case (an MCP
214
+ // server called "GitHub"), so lookups must not depend on it. The names stay as
215
+ // they are because persisted state stores them.
216
+ const findCI = (map, key) => map.get(key) ?? [...map.values()].find((v) => v.name.toLowerCase() === key);
217
+ export function resolveTarget(catalog, raw, resolvers = []) {
218
+ const target = String(raw ?? '').trim();
219
+ for (const { prefix, resolve } of resolvers) {
220
+ if (prefix && !target.startsWith(prefix))
221
+ continue;
222
+ let expanded;
223
+ try {
224
+ expanded = resolve(target);
225
+ }
226
+ catch {
227
+ continue;
228
+ }
229
+ if (expanded === undefined || expanded === null)
230
+ continue;
231
+ const list = Array.isArray(expanded) ? expanded : [expanded];
232
+ const nodes = list.map((one) => resolveTarget(catalog, one, resolvers));
233
+ if (nodes.length === 0)
234
+ return { kind: 'missing', target };
235
+ if (nodes.length === 1)
236
+ return nodes[0];
237
+ // Several targets behind one alias: expose them as a synthetic category so
238
+ // loading, listing and unloading all work through the existing paths.
239
+ const tools = nodes.flatMap((node) => toolsUnder(catalog, node));
240
+ // `aliasTools` is the exact tool list. The node's groups are copies, so
241
+ // loading must use this list rather than subscribe to the group names —
242
+ // otherwise a shared group would drag in every sibling tool.
243
+ return {
244
+ kind: 'category',
245
+ category: { name: target, description: `Alias for ${list.join(', ')}`, groups: groupsOf(tools), alias: list, aliasTools: tools },
246
+ };
247
+ }
248
+ if (target === '' || target === '/')
249
+ return { kind: 'root' };
250
+ const exact = catalog.tools.get(target);
251
+ if (exact)
252
+ return { kind: 'tool', tool: exact };
253
+ const parts = target.replace(/^\/+|\/+$/g, '').split('/').filter(Boolean).map((p) => p.toLowerCase());
254
+ if (parts.length === 1) {
255
+ const only = parts[0];
256
+ const category = findCI(catalog.categories, only);
257
+ if (category)
258
+ return { kind: 'category', category };
259
+ const group = findCI(catalog.groups, only);
260
+ if (group)
261
+ return { kind: 'group', group };
262
+ const byShort = [...catalog.tools.values()].filter((t) => t.short.toLowerCase() === only);
263
+ if (byShort.length === 1)
264
+ return { kind: 'tool', tool: byShort[0] };
265
+ return { kind: 'missing', target };
266
+ }
267
+ const [cat = '', grp, tool] = parts;
268
+ const category = findCI(catalog.categories, cat);
269
+ if (!category)
270
+ return { kind: 'missing', target };
271
+ const group = category.groups.find((g) => g.name.toLowerCase() === grp);
272
+ if (!group)
273
+ return { kind: 'missing', target };
274
+ if (parts.length === 2)
275
+ return { kind: 'group', group };
276
+ const entry = group.tools.find((t) => t.short.toLowerCase() === tool || t.name.toLowerCase() === tool);
277
+ if (!entry || parts.length > 3)
278
+ return { kind: 'missing', target };
279
+ return { kind: 'tool', tool: entry };
280
+ }
281
+ /**
282
+ * Regroup an exact tool list by its original group, for synthetic nodes.
283
+ *
284
+ * The groups are copies holding only the given tools: reusing the catalog's own
285
+ * group objects would drag in every sibling tool, so an alias would load far
286
+ * more than it declares.
287
+ */
288
+ function groupsOf(tools) {
289
+ const byName = new Map();
290
+ for (const tool of tools) {
291
+ let group = byName.get(tool.group);
292
+ if (!group)
293
+ byName.set(tool.group, (group = { name: tool.group, category: tool.category, tools: [] }));
294
+ if (!group.tools.includes(tool))
295
+ group.tools.push(tool);
296
+ }
297
+ return [...byName.values()];
298
+ }
299
+ /** Tools under a node (whole tree for root). */
300
+ export function toolsUnder(catalog, node) {
301
+ if (node.kind === 'root')
302
+ return [...catalog.tools.values()];
303
+ if (node.kind === 'category')
304
+ return node.category.groups.flatMap((g) => g.tools);
305
+ if (node.kind === 'group')
306
+ return node.group.tools;
307
+ if (node.kind === 'tool')
308
+ return [node.tool];
309
+ return [];
310
+ }
311
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,EAAE;AACF,2DAA2D;AAC3D,8EAA8E;AAC9E,oFAAoF;AACpF,oDAAoD;AACpD,iFAAiF;AACjF,EAAE;AACF,4EAA4E;AAC5E,2BAA2B;AAI3B,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAA;AAC5C,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAA;AAChC,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAA;AAErC,6EAA6E;AAC7E,MAAM,CAAC,MAAM,kBAAkB,GAA2B;IACxD,MAAM,EAAE,0CAA0C;IAClD,IAAI,EAAE,kDAAkD;IACxD,KAAK,EAAE,iCAAiC;IACxC,IAAI,EAAE,6BAA6B;IACnC,OAAO,EAAE,6BAA6B;IACtC,MAAM,EAAE,uCAAuC;IAC/C,aAAa,EAAE,iDAAiD;IAChE,UAAU,EAAE,8BAA8B;IAC1C,UAAU,EAAE,8BAA8B;IAC1C,MAAM,EAAE,uBAAuB;IAC/B,MAAM,EAAE,sBAAsB;IAC9B,CAAC,aAAa,CAAC,EAAE,oCAAoC;CACtD,CAAA;AAED,4EAA4E;AAC5E,sDAAsD;AACtD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK;IAC3E,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS;IAC3E,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO;CACzE,CAAC,CAAA;AAEF;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,YAAiC;IAC7E,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACvC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC;YAAE,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;QACvD,OAAO,KAAK,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IACjC,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;QAAE,OAAO,MAAM,CAAA;IACxG,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACvC,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,CAAA;AACxC,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,OAAO,CAAC,IAAwB,EAAE,GAAG,GAAG,EAAE;IACxD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;IAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IACpD,OAAO,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAA;AACnE,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,cAAc,CAAC,MAAe;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACnC,4EAA4E;IAC5E,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,KAAK,MAAM,EAAE,IAAI,IAAI;QAAE,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM;YAAE,IAAI,IAAI,CAAC,CAAA;IACvE,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAA;AACnD,CAAC;AAED,sFAAsF;AACtF,SAAS,aAAa,CAAC,IAAY,EAAE,WAAkC;IACrE,IAAI,MAA4B,CAAA;IAChC,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC/E,IAAI,GAAG;YAAE,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;IAC5C,CAAC;IACD,OAAO,MAAM,IAAI,EAAE,CAAA;AACrB,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CAAC,KAAY,EAAE,WAAkC;IACzE,MAAM,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAA;IACjD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,aAAa,KAAK,KAAK,CAAC,IAAI;YAAE,SAAQ;QAC/C,IAAI,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC7C,IAAI,CAAC,IAAI;YAAE,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAA;QAC1D,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACjB,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAA;IACvC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,UAAU,EAAE,CAAC;QACvC,MAAM,KAAK,GAAe,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,CAAA;QACtI,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,EAAE,YAAY,EAAE,KAAK,CAAC,CAAA;QAC9D,IAAI,QAAQ,IAAI,QAAQ,KAAK,aAAa;YAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;IAC5G,CAAC;IACD,IAAI,IAAkC,CAAA;IACtC,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,KAAK;QAAE,IAAI,CAAC,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC;YAAE,IAAI,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;IAC7F,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;AAClB,CAAC;AAID,SAAS,WAAW,CAAC,WAAkC,EAAE,MAA8B,EAAE,GAA2B;IAClH,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,CAA2D,CAAA;QAC9E,IAAI,OAAO,EAAE,KAAK,UAAU;YAAE,SAAQ;QACtC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;YAC7B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAA;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,gDAAgD;QAClD,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAYD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,OAA8B,EAAE,EAAE,WAAW,GAAG,EAAE,EAAE,WAAW,GAAG,EAAE,EAAE,UAAU,GAAG,kBAAkB,EAAE,QAAQ,GAAG,EAAE,KAAmB,EAAE;IACpK,MAAM,MAAM,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAA;IACrF,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,iBAAiB,CAAC,CAAA;IAC9E,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAA;IAE5E,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAA;IAC9C,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QACjC,IAAI,MAAM,KAAK,IAAI;YAAE,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACpF,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC/B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqB,CAAA;IAC1C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAA;IACvC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;QACpD,MAAM,KAAK,GAAc,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;QACvG,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC;eAC/C,IAAI,CAAC,KAAK;eACV,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC;eACrC,eAAe,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;QAC/C,MAAM,KAAK,GAAc;YACvB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC;YAC7B,KAAK;YACL,yEAAyE;YACzE,8CAA8C;YAC9C,aAAa,EAAE,eAAe,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC;YACzD,QAAQ,EAAE,aAAa;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC;YAC3E,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;YACrC,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC;YAC9B,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YACxD,UAAU,EAAE,IAAI;SACjB,CAAA;QACD,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAC7B,IAAI,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAC9B,IAAI,CAAC,MAAM;YAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;QAC9F,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC1B,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QACpC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;QAC1D,MAAM,KAAK,GAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,CAAA;QAClJ,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC7E,KAAK,CAAC,QAAQ,GAAG,WAAW,CAAC,SAAS,EAAE,YAAY,EAAE,KAAK,CAAC;eACvD,SAAS;eACT,WAAW,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC;eAC1C,iBAAiB,CAAC,KAAK,EAAE,CAAC,GAAG,SAAS,EAAE,GAAG,QAAQ,CAAC,CAAC;eACrD,aAAa,CAAA;QAClB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK;YAAE,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;IAChE,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,GAAG,EAAoB,CAAA;IACjD,KAAK,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;QAAE,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;IACxH,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QACpC,IAAI,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QAChD,IAAI,CAAC,QAAQ;YAAE,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,QAAQ,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;QACpH,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC7B,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,aAAa,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IAE3G,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,CAAA;AACrD,CAAC;AAED;;;;GAIG;AACH;;;;;;;GAOG;AACH,2EAA2E;AAC3E,+EAA+E;AAC/E,gDAAgD;AAChD,MAAM,MAAM,GAAG,CAA6B,GAAmB,EAAE,GAAW,EAAiB,EAAE,CAC7F,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAA;AAE7E,MAAM,UAAU,aAAa,CAAC,OAAgB,EAAE,GAAY,EAAE,YAAuE,EAAE;IACrI,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IACvC,KAAK,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,SAAS,EAAE,CAAC;QAC5C,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,SAAQ;QAClD,IAAI,QAA8C,CAAA;QAClD,IAAI,CAAC;YACH,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,SAAQ;QACV,CAAC;QACD,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI;YAAE,SAAQ;QACzD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAA;QACvE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAA;QAC1D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC,CAAC,CAAE,CAAA;QACxC,2EAA2E;QAC3E,sEAAsE;QACtE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAA;QAChE,wEAAwE;QACxE,wEAAwE;QACxE,6DAA6D;QAC7D,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE;SACjI,CAAA;IACH,CAAC;IACD,IAAI,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;IAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACvC,IAAI,KAAK;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAA;IACrG,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAA;QACtB,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;QACjD,IAAI,QAAQ;YAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAA;QACnD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QAC1C,IAAI,KAAK;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;QAC1C,MAAM,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,CAAA;QACzF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAE,EAAE,CAAA;QACpE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAA;IACpC,CAAC;IACD,MAAM,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,KAAK,CAAA;IACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAA;IAChD,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAA;IACjD,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAA;IACvE,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAA;IAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;IACvD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,CAAA;IACtG,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAA;IAClE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;AACtC,CAAC;AAED;;;;;;GAMG;AACH,SAAS,QAAQ,CAAC,KAA2B;IAC3C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAiB,CAAA;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAClC,IAAI,CAAC,KAAK;YAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;QACtG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzD,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;AAC7B,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,UAAU,CAAC,OAAgB,EAAE,IAAiB;IAC5D,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;IAC5D,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IACjF,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAA;IAClD,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC5C,OAAO,EAAE,CAAA;AACX,CAAC"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import type { CoreConfig, HostContext } from './types.js';
2
+ export type * from './types.js';
3
+ export { buildCatalog, resolveTarget, toolsUnder, estimateTokens, summary, shortName, structuralGroup, DEFAULT_CATEGORIES, UNCATEGORIZED, MISC_GROUP, OVERRIDE_PRIORITY } from './catalog.js';
4
+ export type { BuildOptions } from './catalog.js';
5
+ export type { RegisteredClassifier, RegisteredFilter } from './service.js';
6
+ export type { VisibilityController, VisibilityOptions } from './visibility.js';
7
+ export declare const name = "tool-manager";
8
+ export declare const inject: string[];
9
+ export declare const ENTRY_TOOLS: string[];
10
+ export declare const DEFAULT_PINNED: string[];
11
+ export declare function apply(ctx: HostContext, config?: CoreConfig): void;
12
+ /** Options for toolCatalog.load / tools_load. */
13
+ export interface LoadOptions {
14
+ /** Also hand the targets to subagents started afterwards. */
15
+ forSubagents?: boolean;
16
+ }
17
+ declare const _default: {
18
+ name: string;
19
+ inject: string[];
20
+ apply: typeof apply;
21
+ };
22
+ export default _default;
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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"}