@try-works/dsh-model-as-tool 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +245 -2
  2. package/catalog/desert-ant-models.json +629 -0
  3. package/catalog/playbooks.json +531 -0
  4. package/cordis.patch.yml +39 -0
  5. package/lib/adapters/index.d.ts +48 -0
  6. package/lib/adapters/index.d.ts.map +1 -0
  7. package/lib/adapters/index.js +67 -0
  8. package/lib/adapters/tongue.d.ts +23 -0
  9. package/lib/adapters/tongue.d.ts.map +1 -0
  10. package/lib/adapters/tongue.js +85 -0
  11. package/lib/adapters/types.d.ts +95 -0
  12. package/lib/adapters/types.d.ts.map +1 -0
  13. package/lib/adapters/types.js +85 -0
  14. package/lib/adapters/voz.d.ts +22 -0
  15. package/lib/adapters/voz.d.ts.map +1 -0
  16. package/lib/adapters/voz.js +90 -0
  17. package/lib/capability.d.ts +58 -0
  18. package/lib/capability.d.ts.map +1 -0
  19. package/lib/capability.js +175 -0
  20. package/lib/catalog.d.ts +37 -0
  21. package/lib/catalog.d.ts.map +1 -0
  22. package/lib/catalog.js +217 -0
  23. package/lib/index.d.ts +120 -0
  24. package/lib/index.d.ts.map +1 -0
  25. package/lib/index.js +391 -0
  26. package/lib/playbook.d.ts +42 -0
  27. package/lib/playbook.d.ts.map +1 -0
  28. package/lib/playbook.js +65 -0
  29. package/lib/registrar.d.ts +59 -0
  30. package/lib/registrar.d.ts.map +1 -0
  31. package/lib/registrar.js +136 -0
  32. package/lib/skills.d.ts +25 -0
  33. package/lib/skills.d.ts.map +1 -0
  34. package/lib/skills.js +102 -0
  35. package/lib/state.d.ts +100 -0
  36. package/lib/state.d.ts.map +1 -0
  37. package/lib/state.js +160 -0
  38. package/lib/transport.d.ts +158 -0
  39. package/lib/transport.d.ts.map +1 -0
  40. package/lib/transport.js +332 -0
  41. package/lib/types.d.ts +111 -0
  42. package/lib/types.d.ts.map +1 -0
  43. package/lib/types.js +8 -0
  44. package/package.json +83 -4
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Capability resolution: decide whether a catalog model can actually run in
3
+ * this DSH process, and by which route.
4
+ *
5
+ * The rule this module enforces is that a model becomes a tool only when an
6
+ * adapter can really invoke it. Every other model stays catalogued and
7
+ * reportable, so `model_tools` can explain what is missing instead of the agent
8
+ * discovering a broken tool at call time.
9
+ *
10
+ * @module @try-works/dsh-model-as-tool/capability
11
+ */
12
+ import { createRequire } from 'node:module';
13
+ import { DEFAULT_CLI_COMMAND } from "./transport.js";
14
+ /**
15
+ * Node resolution context for this plugin.
16
+ *
17
+ * The plugin must resolve model packages from the DSH installation that is
18
+ * hosting it, not from its own nested `node_modules`, so that an operator who
19
+ * installs `@desert-ant-labs/tongue` into the profile gets a working tool.
20
+ */
21
+ const requireFromHere = createRequire(import.meta.url);
22
+ /**
23
+ * Whether a package specifier resolves from this plugin's installation.
24
+ *
25
+ * Resolution deliberately does not load the module: importing a model package
26
+ * pulls in a WASM or native runtime, and capability probing must stay cheap
27
+ * enough to run at plugin load.
28
+ * @param specifier - package name, optionally with a subpath.
29
+ * @returns whether Node can resolve the specifier.
30
+ */
31
+ export function canResolve(specifier) {
32
+ try {
33
+ requireFromHere.resolve(specifier);
34
+ return true;
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ }
40
+ /** Join a package and its documented subpath into one specifier. */
41
+ export function packageSpecifier(pkg, subpath) {
42
+ return subpath === null ? pkg : `${pkg}${subpath}`;
43
+ }
44
+ /** Reason text for a model that has no runnable route on any platform. */
45
+ function unavailableReason(entry) {
46
+ if (entry.closedBeta) {
47
+ return `${entry.name} is in closed beta: the weights are published at ${entry.hfRepo} but no SDK ships them yet, so it cannot be installed as a tool.`;
48
+ }
49
+ if (entry.appleOnly) {
50
+ return `${entry.name} is Apple-only (Core ML/MLX through the Swift package); there is no JavaScript SDK, so it cannot run in a Node process. Point \`remote.endpoint\` at a bridge on an Apple machine to reach it.`;
51
+ }
52
+ if (entry.npmPackage === null && entry.cliVerb === null) {
53
+ return `${entry.name} has no npm package and no CLI verb, so no transport can reach it.`;
54
+ }
55
+ if (entry.npmPackage === null) {
56
+ return `${entry.name} has no npm package; run it through the Desert Ant CLI (macOS/Linux) with \`cli.enabled\`, or through a bridge with \`remote.endpoint\`.`;
57
+ }
58
+ return `${entry.name} has no runtime available to this process.`;
59
+ }
60
+ /** Whether the CLI can carry this model at all. */
61
+ function cliCapable(entry) {
62
+ return entry.cliVerb !== null && !entry.closedBeta;
63
+ }
64
+ /**
65
+ * Resolve how (and whether) one model can run here.
66
+ *
67
+ * Transport preference is deliberate: an in-process package is fastest and
68
+ * needs no external service, so it wins; the CLI is local but out-of-process;
69
+ * the bridge is last because it depends on another machine. A user who would
70
+ * rather route everything through a bridge can disable the other two.
71
+ * @param entry - the catalog entry to resolve.
72
+ * @param options - overrides for testing; `resolve`, `platform` and the transport switches replace the process facts.
73
+ * @returns the verdict, including the reason for every negative one.
74
+ */
75
+ export function resolveCapability(entry, options = {}) {
76
+ const resolve = options.resolve ?? canResolve;
77
+ const platform = options.platform ?? process.platform;
78
+ const allowNpm = options.allowNpm ?? true;
79
+ const remoteEndpoint = options.remoteEndpoint;
80
+ // A bridge is checked first among the fallbacks because it is the only route
81
+ // for Apple-only models, which have neither a package nor (for some) a verb.
82
+ const bridgeUsable = remoteEndpoint !== undefined && remoteEndpoint.length > 0 && !entry.closedBeta;
83
+ const pkg = entry.npmPackage;
84
+ // Why the in-process route did not pan out. Kept so the final verdict can name
85
+ // the exact missing piece ("install onnxruntime-node") instead of falling back
86
+ // to a generic sentence once the CLI and bridge have also been ruled out.
87
+ let npmMiss;
88
+ if (pkg !== null && allowNpm) {
89
+ const missingRuntimes = entry.requiresRuntime.filter(name => !resolve(name));
90
+ if (missingRuntimes.length > 0) {
91
+ npmMiss = {
92
+ reason: `${entry.name} needs ${missingRuntimes.join(', ')} to run here; install it beside the plugin (npm i ${missingRuntimes.join(' ')}).`,
93
+ missing: missingRuntimes,
94
+ };
95
+ }
96
+ else {
97
+ const native = packageSpecifier(pkg, entry.npmSubpath);
98
+ const onnx = entry.requiresRuntime.length > 0;
99
+ // A declared ONNX runtime wins over the package's own default entry: for
100
+ // these packages the default import is the browser build, which refuses
101
+ // to initialize in Node.
102
+ if (onnx) {
103
+ if (resolve(pkg)) {
104
+ return {
105
+ runnable: true,
106
+ route: 'npm-onnxruntime',
107
+ reason: `${entry.name} runs through ${entry.requiresRuntime.join(', ')}.`,
108
+ resolved: [...entry.requiresRuntime, pkg],
109
+ };
110
+ }
111
+ npmMiss = {
112
+ reason: `${entry.name} requires the ${pkg} package, which is not installed.`,
113
+ missing: [pkg],
114
+ };
115
+ }
116
+ else if (platform === 'win32' && entry.windowsSupport === 'browser-only') {
117
+ npmMiss = {
118
+ reason: `${entry.name} has no prebuilt native build for win32-${process.arch}: ${native} supports linux-x64, linux-arm64 and darwin-arm64 only.`,
119
+ missing: [native],
120
+ };
121
+ }
122
+ else if (resolve(native)) {
123
+ return {
124
+ runnable: true,
125
+ route: 'npm-native',
126
+ reason: `${entry.name} resolves ${native} for this platform.`,
127
+ resolved: [native],
128
+ };
129
+ }
130
+ else {
131
+ npmMiss = {
132
+ reason: `${entry.name} requires the ${native} package, which is not installed.`,
133
+ missing: [native],
134
+ };
135
+ }
136
+ }
137
+ }
138
+ // The CLI runs every shipping model on macOS and Linux, so it is checked
139
+ // before giving up — including for models whose npm prebuild is missing here.
140
+ if (cliCapable(entry) && (options.cliAvailable ?? false)) {
141
+ return {
142
+ runnable: true,
143
+ route: 'cli',
144
+ reason: `${entry.name} runs through the Desert Ant CLI (\`${DEFAULT_CLI_COMMAND} ${entry.cliVerb}\`).`,
145
+ resolved: [DEFAULT_CLI_COMMAND],
146
+ };
147
+ }
148
+ if (bridgeUsable) {
149
+ return {
150
+ runnable: true,
151
+ route: 'remote',
152
+ reason: `${entry.name} is reached through the bridge at ${remoteEndpoint}.`,
153
+ resolved: [remoteEndpoint],
154
+ };
155
+ }
156
+ if (npmMiss !== undefined && !entry.closedBeta && !entry.appleOnly) {
157
+ return {
158
+ runnable: false,
159
+ route: 'unavailable',
160
+ reason: npmMiss.reason,
161
+ missing: npmMiss.missing,
162
+ };
163
+ }
164
+ return { runnable: false, route: 'unavailable', reason: unavailableReason(entry) };
165
+ }
166
+ /**
167
+ * Resolve every catalog entry.
168
+ * @param entries - validated catalog entries.
169
+ * @param options - resolution overrides, forwarded to {@link resolveCapability}.
170
+ * @returns one record per entry, in catalog order.
171
+ */
172
+ export function resolveCatalog(entries, options = {}) {
173
+ return entries.map(entry => ({ entry, verdict: resolveCapability(entry, options) }));
174
+ }
175
+ //# sourceMappingURL=capability.js.map
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Loads and validates the Desert Ant Labs model catalog.
3
+ *
4
+ * The catalog is plain JSON shipped beside the plugin so that a deployment can
5
+ * inspect or override it without rebuilding: `catalogFile` points at another
6
+ * document with the same shape.
7
+ *
8
+ * @module @try-works/dsh-model-as-tool/catalog
9
+ */
10
+ import type { ModelCatalogEntry } from './types.ts';
11
+ /** Absolute path of the catalog document shipped with this package. */
12
+ export declare const DEFAULT_CATALOG_FILE: string;
13
+ /** Raised when the catalog document is missing, unparseable, or malformed. */
14
+ export declare class CatalogError extends Error {
15
+ readonly name = "CatalogError";
16
+ }
17
+ /**
18
+ * Parse and validate one catalog entry. Validation is strict on purpose: every
19
+ * downstream decision (which tool to register, whether it can run, what the
20
+ * model sees) reads these fields, so a malformed entry must fail at load rather
21
+ * than become a silently missing tool.
22
+ * @param raw - one decoded JSON object.
23
+ * @param source - description of where the document came from, for messages.
24
+ * @param index - position in the array, for entries with no usable id.
25
+ * @returns the validated entry.
26
+ */
27
+ export declare function parseCatalogEntry(raw: unknown, source: string, index: number): ModelCatalogEntry;
28
+ /**
29
+ * Load the catalog from a JSON document.
30
+ * @param file - absolute path of the catalog document.
31
+ * @returns every validated entry, in document order.
32
+ * @throws CatalogError when the file cannot be read, is not valid JSON, is not an array, or holds a malformed entry.
33
+ */
34
+ export declare function loadCatalog(file?: string): ModelCatalogEntry[];
35
+ /** Index a catalog by model id. */
36
+ export declare function indexCatalog(entries: readonly ModelCatalogEntry[]): Map<string, ModelCatalogEntry>;
37
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAA0D,MAAM,YAAY,CAAA;AAE3G,uEAAuE;AACvE,eAAO,MAAM,oBAAoB,QAEhC,CAAA;AAWD,8EAA8E;AAC9E,qBAAa,YAAa,SAAQ,KAAK;IACrC,SAAkB,IAAI,kBAAiB;CACxC;AA8CD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAqGhG;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAA6B,GAAG,iBAAiB,EAAE,CA6BpF;AAED,mCAAmC;AACnC,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAElG"}
package/lib/catalog.js ADDED
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Loads and validates the Desert Ant Labs model catalog.
3
+ *
4
+ * The catalog is plain JSON shipped beside the plugin so that a deployment can
5
+ * inspect or override it without rebuilding: `catalogFile` points at another
6
+ * document with the same shape.
7
+ *
8
+ * @module @try-works/dsh-model-as-tool/catalog
9
+ */
10
+ import { readFileSync } from 'node:fs';
11
+ import { fileURLToPath } from 'node:url';
12
+ /** Absolute path of the catalog document shipped with this package. */
13
+ export const DEFAULT_CATALOG_FILE = fileURLToPath(new URL('../catalog/desert-ant-models.json', import.meta.url));
14
+ const INPUTS = ['text', 'audio', 'image', 'video', 'stroke', 'transcript'];
15
+ const WINDOWS_SUPPORT = [
16
+ 'native-node',
17
+ 'onnxruntime-node',
18
+ 'apple-only',
19
+ 'browser-only',
20
+ 'no-sdk',
21
+ ];
22
+ /** Raised when the catalog document is missing, unparseable, or malformed. */
23
+ export class CatalogError extends Error {
24
+ name = 'CatalogError';
25
+ }
26
+ function fail(source, message) {
27
+ throw new CatalogError(`${source}: ${message}`);
28
+ }
29
+ function requireString(entry, key, source) {
30
+ const value = entry[key];
31
+ if (typeof value !== 'string' || value.length === 0) {
32
+ fail(source, `entry "${String(entry.id ?? '?')}" field "${key}" must be a non-empty string`);
33
+ }
34
+ return value;
35
+ }
36
+ const PARAM_TYPES = ['string', 'number', 'integer', 'boolean', 'string[]'];
37
+ /**
38
+ * Normalize one parameter declaration.
39
+ *
40
+ * The string shorthand exists because most parameters are prose descriptions of
41
+ * a string argument; accepting it here keeps the catalog readable while the
42
+ * registrar still receives one resolved shape.
43
+ * @param raw - the declaration as written in the document.
44
+ * @param scope - entry description for error messages.
45
+ * @param key - parameter name.
46
+ * @returns the normalized parameter.
47
+ */
48
+ function parseParam(raw, scope, key) {
49
+ if (typeof raw === 'string' && raw.length > 0)
50
+ return { description: raw, type: 'string' };
51
+ if (typeof raw === 'object' && raw !== null && !Array.isArray(raw)) {
52
+ const spec = raw;
53
+ const description = spec.description;
54
+ if (typeof description !== 'string' || description.length === 0) {
55
+ throw new CatalogError(`${scope} tool.params.${key}.description must be a non-empty string`);
56
+ }
57
+ const type = spec.type;
58
+ if (type !== undefined && !PARAM_TYPES.includes(type)) {
59
+ throw new CatalogError(`${scope} tool.params.${key}.type must be one of ${PARAM_TYPES.join(', ')}`);
60
+ }
61
+ return { description, type: type ?? 'string' };
62
+ }
63
+ throw new CatalogError(`${scope} tool.params.${key} must be a description string or a parameter object`);
64
+ }
65
+ /**
66
+ * Parse and validate one catalog entry. Validation is strict on purpose: every
67
+ * downstream decision (which tool to register, whether it can run, what the
68
+ * model sees) reads these fields, so a malformed entry must fail at load rather
69
+ * than become a silently missing tool.
70
+ * @param raw - one decoded JSON object.
71
+ * @param source - description of where the document came from, for messages.
72
+ * @param index - position in the array, for entries with no usable id.
73
+ * @returns the validated entry.
74
+ */
75
+ export function parseCatalogEntry(raw, source, index) {
76
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
77
+ fail(source, `entry ${String(index)} must be an object`);
78
+ }
79
+ const entry = raw;
80
+ const id = requireString(entry, 'id', source);
81
+ const scope = `entry "${id}"`;
82
+ const input = requireString(entry, 'input', source);
83
+ if (!INPUTS.includes(input)) {
84
+ fail(source, `${scope} has unsupported input ${JSON.stringify(input)} (expected one of ${INPUTS.join(', ')})`);
85
+ }
86
+ const windowsSupport = requireString(entry, 'windowsSupport', source);
87
+ if (!WINDOWS_SUPPORT.includes(windowsSupport)) {
88
+ fail(source, `${scope} has unsupported windowsSupport ${JSON.stringify(windowsSupport)} (expected one of ${WINDOWS_SUPPORT.join(', ')})`);
89
+ }
90
+ const tool = entry.tool;
91
+ if (typeof tool !== 'object' || tool === null)
92
+ fail(source, `${scope} is missing its "tool" object`);
93
+ const skill = entry.skill;
94
+ if (typeof skill !== 'object' || skill === null)
95
+ fail(source, `${scope} is missing its "skill" object`);
96
+ const toolSpec = tool;
97
+ const skillSpec = skill;
98
+ const params = toolSpec.params;
99
+ if (typeof params !== 'object' || params === null || Array.isArray(params)) {
100
+ fail(source, `${scope} tool.params must be an object`);
101
+ }
102
+ const bool = (key) => {
103
+ const value = entry[key];
104
+ if (typeof value !== 'boolean')
105
+ fail(source, `${scope} field "${key}" must be a boolean`);
106
+ return value;
107
+ };
108
+ const nullableNumber = (key) => {
109
+ const value = entry[key];
110
+ if (value !== null && (typeof value !== 'number' || !Number.isFinite(value))) {
111
+ fail(source, `${scope} field "${key}" must be a finite number or null`);
112
+ }
113
+ return value;
114
+ };
115
+ const nullableString = (key) => {
116
+ const value = entry[key];
117
+ if (value !== null && typeof value !== 'string') {
118
+ fail(source, `${scope} field "${key}" must be a string or null`);
119
+ }
120
+ return value;
121
+ };
122
+ const strings = (key) => {
123
+ const value = entry[key];
124
+ if (!Array.isArray(value) || value.some(item => typeof item !== 'string')) {
125
+ fail(source, `${scope} field "${key}" must be an array of strings`);
126
+ }
127
+ return value;
128
+ };
129
+ const toolName = requireString(toolSpec, 'name', source);
130
+ if (!/^[a-z][a-z0-9_]*$/.test(toolName)) {
131
+ fail(source, `${scope} tool.name ${JSON.stringify(toolName)} must be lower snake_case starting with a letter`);
132
+ }
133
+ const skillName = requireString(skillSpec, 'name', source);
134
+ if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(skillName)) {
135
+ fail(source, `${scope} skill.name ${JSON.stringify(skillName)} must be kebab-case`);
136
+ }
137
+ return {
138
+ id,
139
+ name: requireString(entry, 'name', source),
140
+ summary: requireString(entry, 'summary', source),
141
+ capability: requireString(entry, 'capability', source),
142
+ input: input,
143
+ output: requireString(entry, 'output', source),
144
+ languages: nullableNumber('languages'),
145
+ modelSizeMB: nullableNumber('modelSizeMB'),
146
+ appleOnly: bool('appleOnly'),
147
+ closedBeta: bool('closedBeta'),
148
+ verifiedRunnableOnWindows: bool('verifiedRunnableOnWindows'),
149
+ windowsSupport: windowsSupport,
150
+ npmPackage: nullableString('npmPackage'),
151
+ npmSubpath: nullableString('npmSubpath'),
152
+ requiresRuntime: strings('requiresRuntime'),
153
+ cliVerb: nullableString('cliVerb'),
154
+ license: requireString(entry, 'license', source),
155
+ docsUrl: requireString(entry, 'docsUrl', source),
156
+ hfRepo: requireString(entry, 'hfRepo', source),
157
+ tool: {
158
+ name: toolName,
159
+ description: requireString(toolSpec, 'description', source),
160
+ params: Object.fromEntries(Object.entries(params).map(([key, value]) => [
161
+ key,
162
+ parseParam(value, scope, key),
163
+ ])),
164
+ returns: requireString(toolSpec, 'returns', source),
165
+ },
166
+ skill: {
167
+ name: skillName,
168
+ description: requireString(skillSpec, 'description', source),
169
+ ...typeof skillSpec.whenToUse === 'string' ? { whenToUse: skillSpec.whenToUse } : {},
170
+ },
171
+ };
172
+ }
173
+ /**
174
+ * Load the catalog from a JSON document.
175
+ * @param file - absolute path of the catalog document.
176
+ * @returns every validated entry, in document order.
177
+ * @throws CatalogError when the file cannot be read, is not valid JSON, is not an array, or holds a malformed entry.
178
+ */
179
+ export function loadCatalog(file = DEFAULT_CATALOG_FILE) {
180
+ let text;
181
+ try {
182
+ text = readFileSync(file, 'utf8');
183
+ }
184
+ catch (error) {
185
+ // Node errors are not stable enough to switch on; the message is the point.
186
+ throw new CatalogError(`cannot read model catalog ${file}: ${error instanceof Error ? error.message : String(error)}`);
187
+ }
188
+ let parsed;
189
+ try {
190
+ parsed = JSON.parse(text);
191
+ }
192
+ catch (error) {
193
+ throw new CatalogError(`${file} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
194
+ }
195
+ if (!Array.isArray(parsed))
196
+ throw new CatalogError(`${file} must contain a JSON array of model entries`);
197
+ const entries = parsed.map((raw, index) => parseCatalogEntry(raw, file, index));
198
+ const seen = new Set();
199
+ for (const entry of entries) {
200
+ if (seen.has(entry.id))
201
+ throw new CatalogError(`${file} declares model id "${entry.id}" more than once`);
202
+ seen.add(entry.id);
203
+ }
204
+ const toolNames = new Set();
205
+ for (const entry of entries) {
206
+ if (toolNames.has(entry.tool.name)) {
207
+ throw new CatalogError(`${file} maps tool name "${entry.tool.name}" to more than one model`);
208
+ }
209
+ toolNames.add(entry.tool.name);
210
+ }
211
+ return entries;
212
+ }
213
+ /** Index a catalog by model id. */
214
+ export function indexCatalog(entries) {
215
+ return new Map(entries.map(entry => [entry.id, entry]));
216
+ }
217
+ //# sourceMappingURL=catalog.js.map
package/lib/index.d.ts ADDED
@@ -0,0 +1,120 @@
1
+ /**
2
+ * dsh-model-as-tool — install on-device models as DSH tools and skills.
3
+ *
4
+ * The plugin composes five layers: a JSON catalog describing every model, a
5
+ * capability resolver that decides which of them can run in this process, an
6
+ * adapter per runnable model, a registrar that turns each one into a DSH tool,
7
+ * and a skill per tool that teaches the agent when to reach for it.
8
+ *
9
+ * Nothing is imported from a model package at plugin load, so a deployment that
10
+ * installs none of them still starts cleanly and reports exactly what is
11
+ * missing. A model only becomes a tool when its adapter can really invoke it.
12
+ *
13
+ * @module @try-works/dsh-model-as-tool
14
+ */
15
+ import type { Context } from '@deepseek-ai/cordis';
16
+ import z from '@deepseek-ai/schemastery';
17
+ export declare const name = "model-tools";
18
+ export declare const inject: string[];
19
+ /** Plugin configuration. */
20
+ export interface Config {
21
+ /** Catalog document to load; defaults to the bundled Desert Ant catalog. */
22
+ catalogFile?: string;
23
+ /** Playbook document to load; defaults to the bundled playbooks. */
24
+ playbookFile?: string;
25
+ /**
26
+ * Model ids to expose. An empty list (the default) means every model that can
27
+ * run here; a non-empty list is intersected with what can run, so naming an
28
+ * unsupported model never registers a tool that would fail at call time.
29
+ *
30
+ * The field is an empty array rather than `undefined` when unset: the config
31
+ * schema materializes a declared array, so the code treats empty as "no
32
+ * explicit allowlist" instead of "expose nothing".
33
+ */
34
+ models?: string[];
35
+ /** Model ids to exclude, applied after `models`. */
36
+ exclude?: string[];
37
+ /**
38
+ * Register a tool for a model whose runtime is missing, so the failure is
39
+ * reported at call time instead of the tool being absent. Off by default:
40
+ * exposing a tool that cannot work wastes a model turn.
41
+ */
42
+ exposeUnavailable?: boolean;
43
+ /** Publish one skill per registered tool. Default true. */
44
+ registerSkills?: boolean;
45
+ /** Register the `model_tools` inspection tool. Default true. */
46
+ registerControlTool?: boolean;
47
+ /**
48
+ * The Desert Ant CLI transport, which runs on macOS and Linux and can reach
49
+ * every shipping model — including the Apple-only ones that have no npm
50
+ * package.
51
+ */
52
+ cli?: {
53
+ /** Whether the CLI may be used when it is found on PATH. Default true. */
54
+ enabled?: boolean;
55
+ /** Command name or absolute path. Default `desertant`. */
56
+ command?: string;
57
+ };
58
+ /**
59
+ * A user-hosted bridge, reached over HTTP, for models this machine cannot run
60
+ * itself — most importantly the Apple-only models.
61
+ *
62
+ * The plugin does not run this service; the user does, on a machine that can
63
+ * execute the model. The licence forbids re-hosting the models as a service,
64
+ * so point this at your own machine.
65
+ */
66
+ remote?: {
67
+ /** Bridge base URL, for example `http://mac-studio.local:8787`. */
68
+ endpoint?: string;
69
+ /** Optional bearer token sent to the bridge. */
70
+ token?: string;
71
+ };
72
+ /**
73
+ * Whether in-process npm packages may be used. Set false to force every call
74
+ * through the CLI or the bridge. Default true.
75
+ */
76
+ allowNpm?: boolean;
77
+ /**
78
+ * Where the user's enable/disable choices are persisted. Defaults to
79
+ * `<DSH_HOME>/model-as-tool/state.json`.
80
+ */
81
+ stateFile?: string;
82
+ /**
83
+ * Whether `enable`/`disable` persist across restarts. Default true; false
84
+ * restores the earlier session-scoped behaviour.
85
+ */
86
+ persist?: boolean;
87
+ }
88
+ /** Validate and default the plugin configuration. */
89
+ export declare const Config: z<Config>;
90
+ /** One model as the `model_tools` control tool reports it. */
91
+ export interface ModelDescriptor {
92
+ readonly id: string;
93
+ readonly name: string;
94
+ readonly summary: string;
95
+ readonly capability: string;
96
+ readonly input: string;
97
+ readonly tool: string;
98
+ readonly skill: string;
99
+ readonly runnable: boolean;
100
+ readonly route: string;
101
+ readonly reason: string;
102
+ readonly languages: number | null;
103
+ readonly license: string;
104
+ readonly docs: string;
105
+ }
106
+ /**
107
+ * Register the Desert Ant model tools and skills.
108
+ * @param ctx - the plugin context whose tool registry receives the definitions.
109
+ * @param config - deployment configuration for which models to expose.
110
+ */
111
+ export declare function apply(ctx: Context, config?: Config): void;
112
+ export { loadCatalog, CatalogError, DEFAULT_CATALOG_FILE } from './catalog.ts';
113
+ export { resolveCapability, resolveCatalog, canResolve, packageSpecifier, type ResolvedModel } from './capability.ts';
114
+ export { createAdapter, ADAPTER_FACTORIES } from './adapters/index.ts';
115
+ export { buildArgv, commandExists, createCliTransport, createRemoteTransport, parseBridgeResponse, parseCliOutcome, splitArguments, BRIDGE_PATH, DEFAULT_CLI_COMMAND, type CommandRunner, type CommandTransport, type HttpPost, type TransportOptions, } from './transport.ts';
116
+ export { renderSkillBody } from './skills.ts';
117
+ export { loadPlaybooks, DEFAULT_PLAYBOOK_FILE, type ModelPlaybook } from './playbook.ts';
118
+ export { createFileStateStore, createMemoryStateStore, defaultStateFile, parseState, resolveSelection, withChoice, EMPTY_STATE, StateError, type PersistedState, type StateStore, } from './state.ts';
119
+ export type { CapabilityVerdict, ModelCatalogEntry, ModelInput, ModelParam, ModelParamType, ModelRoute, ModelToolSpec, ModelSkillSpec, WindowsSupport, } from './types.ts';
120
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}