@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.
- package/README.md +245 -2
- package/catalog/desert-ant-models.json +629 -0
- package/catalog/playbooks.json +531 -0
- package/cordis.patch.yml +39 -0
- package/lib/adapters/index.d.ts +48 -0
- package/lib/adapters/index.d.ts.map +1 -0
- package/lib/adapters/index.js +67 -0
- package/lib/adapters/tongue.d.ts +23 -0
- package/lib/adapters/tongue.d.ts.map +1 -0
- package/lib/adapters/tongue.js +85 -0
- package/lib/adapters/types.d.ts +95 -0
- package/lib/adapters/types.d.ts.map +1 -0
- package/lib/adapters/types.js +85 -0
- package/lib/adapters/voz.d.ts +22 -0
- package/lib/adapters/voz.d.ts.map +1 -0
- package/lib/adapters/voz.js +90 -0
- package/lib/capability.d.ts +58 -0
- package/lib/capability.d.ts.map +1 -0
- package/lib/capability.js +175 -0
- package/lib/catalog.d.ts +37 -0
- package/lib/catalog.d.ts.map +1 -0
- package/lib/catalog.js +217 -0
- package/lib/index.d.ts +120 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +391 -0
- package/lib/playbook.d.ts +42 -0
- package/lib/playbook.d.ts.map +1 -0
- package/lib/playbook.js +65 -0
- package/lib/registrar.d.ts +59 -0
- package/lib/registrar.d.ts.map +1 -0
- package/lib/registrar.js +136 -0
- package/lib/skills.d.ts +25 -0
- package/lib/skills.d.ts.map +1 -0
- package/lib/skills.js +102 -0
- package/lib/state.d.ts +100 -0
- package/lib/state.d.ts.map +1 -0
- package/lib/state.js +160 -0
- package/lib/transport.d.ts +158 -0
- package/lib/transport.d.ts.map +1 -0
- package/lib/transport.js +332 -0
- package/lib/types.d.ts +111 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +8 -0
- package/package.json +83 -4
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command transports: reaching a model that is not an in-process npm package.
|
|
3
|
+
*
|
|
4
|
+
* Two transports share one shape:
|
|
5
|
+
*
|
|
6
|
+
* - **cli** — runs the Desert Ant CLI (`desertant`/`da`), which exposes every
|
|
7
|
+
* shipping model as `desertant <verb> … --json` and runs on macOS and Linux.
|
|
8
|
+
* - **remote** — POSTs to a bridge the user runs on a machine that can execute
|
|
9
|
+
* the model. This is what makes an Apple-only model such as Title reachable
|
|
10
|
+
* from a Windows host.
|
|
11
|
+
*
|
|
12
|
+
* Both are injected with their side-effecting primitive (`CommandRunner`,
|
|
13
|
+
* `HttpPost`) so behaviour is testable without spawning a process or opening a
|
|
14
|
+
* socket, and so a deployment can substitute its own runner.
|
|
15
|
+
*
|
|
16
|
+
* @module @try-works/dsh-model-as-tool/transport
|
|
17
|
+
*/
|
|
18
|
+
import type { ModelCatalogEntry } from './types.ts';
|
|
19
|
+
import { type JsonValue } from './adapters/types.ts';
|
|
20
|
+
/** One invocation to route through a transport. */
|
|
21
|
+
export interface TransportRequest {
|
|
22
|
+
/** The catalog entry being invoked. */
|
|
23
|
+
readonly entry: ModelCatalogEntry;
|
|
24
|
+
/** Validated tool arguments; the first declared parameter is the primary input. */
|
|
25
|
+
readonly args: Readonly<Record<string, unknown>>;
|
|
26
|
+
/** Caller cancellation. */
|
|
27
|
+
readonly signal: AbortSignal;
|
|
28
|
+
}
|
|
29
|
+
/** Outcome of running one command. */
|
|
30
|
+
export interface CommandOutcome {
|
|
31
|
+
readonly code: number;
|
|
32
|
+
readonly stdout: string;
|
|
33
|
+
readonly stderr: string;
|
|
34
|
+
}
|
|
35
|
+
/** Run a command to completion. Injectable so tests need no real process. */
|
|
36
|
+
export type CommandRunner = (command: string, argv: readonly string[], signal: AbortSignal) => Promise<CommandOutcome>;
|
|
37
|
+
/** Post a JSON body and read the response. Injectable for the same reason. */
|
|
38
|
+
export type HttpPost = (url: string, body: unknown, headers: Readonly<Record<string, string>>, signal: AbortSignal) => Promise<{
|
|
39
|
+
readonly status: number;
|
|
40
|
+
readonly body: string;
|
|
41
|
+
}>;
|
|
42
|
+
/** A model invoked out-of-process. */
|
|
43
|
+
export interface CommandTransport {
|
|
44
|
+
readonly kind: 'cli' | 'remote';
|
|
45
|
+
invoke(request: TransportRequest): Promise<Record<string, JsonValue>>;
|
|
46
|
+
}
|
|
47
|
+
/** The Desert Ant CLI's exit codes, as documented for agents. */
|
|
48
|
+
export declare const CLI_EXIT_RUNTIME_ERROR = 1;
|
|
49
|
+
export declare const CLI_EXIT_USAGE_ERROR = 64;
|
|
50
|
+
/**
|
|
51
|
+
* Default command name. `da` is the short alias the CLI installs.
|
|
52
|
+
*/
|
|
53
|
+
export declare const DEFAULT_CLI_COMMAND = "desertant";
|
|
54
|
+
/** The path every bridge must serve. */
|
|
55
|
+
export declare const BRIDGE_PATH = "/invoke";
|
|
56
|
+
/**
|
|
57
|
+
* Whether a command is on PATH.
|
|
58
|
+
*
|
|
59
|
+
* Probed by scanning PATH rather than by running the command, because this runs
|
|
60
|
+
* at plugin load and a capability probe must not start a process (or pay a
|
|
61
|
+
* CLI's startup cost) just to decide what to advertise.
|
|
62
|
+
* @param command - command name or an absolute path.
|
|
63
|
+
* @param pathValue - the PATH to search; defaults to the process environment.
|
|
64
|
+
* @returns whether an executable file of that name exists.
|
|
65
|
+
*/
|
|
66
|
+
export declare function commandExists(command: string, pathValue?: string): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Split the tool arguments into the CLI's positional inputs and its
|
|
69
|
+
* `--option key=value` flags.
|
|
70
|
+
*
|
|
71
|
+
* The first declared catalog parameter is the primary input, matching how the
|
|
72
|
+
* registrar marks it required. A file model accepts several paths positionally
|
|
73
|
+
* (the CLI loads the model once for all of them), so a primary declared as a
|
|
74
|
+
* string list becomes several positionals. Everything else becomes an option,
|
|
75
|
+
* with lists comma-joined because the CLI's option syntax is `key=value`.
|
|
76
|
+
* @param entry - the catalog entry being invoked.
|
|
77
|
+
* @param args - validated tool arguments.
|
|
78
|
+
* @returns the positional inputs and the option list.
|
|
79
|
+
*/
|
|
80
|
+
export declare function splitArguments(entry: ModelCatalogEntry, args: Readonly<Record<string, unknown>>): {
|
|
81
|
+
positionals: string[];
|
|
82
|
+
options: [string, string][];
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Build the CLI argv for one invocation.
|
|
86
|
+
*
|
|
87
|
+
* `--json` is what makes stdout a single JSON value, and it also implies
|
|
88
|
+
* `--no-color`, so no escape sequences have to be stripped.
|
|
89
|
+
* @param entry - the catalog entry being invoked.
|
|
90
|
+
* @param args - validated tool arguments.
|
|
91
|
+
* @returns the argv to run, after the command itself.
|
|
92
|
+
*/
|
|
93
|
+
export declare function buildArgv(entry: ModelCatalogEntry, args: Readonly<Record<string, unknown>>): string[];
|
|
94
|
+
/**
|
|
95
|
+
* Parse the CLI's stdout into a canonical value.
|
|
96
|
+
*
|
|
97
|
+
* The CLI writes exactly one JSON value to stdout under `--json` and keeps every
|
|
98
|
+
* diagnostic on stderr, so a parse failure means the command did not behave as
|
|
99
|
+
* documented rather than that output needs cleaning.
|
|
100
|
+
* @param entry - the model, for error messages.
|
|
101
|
+
* @param outcome - the completed command.
|
|
102
|
+
* @returns the parsed value.
|
|
103
|
+
* @throws when the exit code is non-zero or stdout is not a single JSON value.
|
|
104
|
+
*/
|
|
105
|
+
export declare function parseCliOutcome(entry: ModelCatalogEntry, outcome: CommandOutcome): Record<string, JsonValue>;
|
|
106
|
+
/** Spawn a command and capture its output. */
|
|
107
|
+
export declare const spawnRunner: CommandRunner;
|
|
108
|
+
/** POST JSON with the global fetch and read the response as text. */
|
|
109
|
+
export declare const fetchPost: HttpPost;
|
|
110
|
+
/** Options shared by both out-of-process transports. */
|
|
111
|
+
export interface TransportOptions {
|
|
112
|
+
/** Command name or path for the CLI transport. */
|
|
113
|
+
readonly cliCommand?: string;
|
|
114
|
+
/** Bridge base URL for the remote transport. */
|
|
115
|
+
readonly endpoint?: string;
|
|
116
|
+
/** Optional bearer token sent to the bridge. */
|
|
117
|
+
readonly token?: string;
|
|
118
|
+
/** Injected command runner. */
|
|
119
|
+
readonly run?: CommandRunner;
|
|
120
|
+
/** Injected HTTP poster. */
|
|
121
|
+
readonly post?: HttpPost;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Build the CLI transport for one model.
|
|
125
|
+
* @param entry - the catalog entry, which must declare a CLI verb.
|
|
126
|
+
* @param options - command name and injected runner.
|
|
127
|
+
* @returns the transport.
|
|
128
|
+
*/
|
|
129
|
+
export declare function createCliTransport(entry: ModelCatalogEntry, options?: TransportOptions): CommandTransport;
|
|
130
|
+
/**
|
|
131
|
+
* Build the remote transport for one model.
|
|
132
|
+
*
|
|
133
|
+
* The bridge contract is deliberately small so a user can implement it in a few
|
|
134
|
+
* lines on a machine that can run the model:
|
|
135
|
+
*
|
|
136
|
+
* ```
|
|
137
|
+
* POST <endpoint>/invoke
|
|
138
|
+
* { "model": "title", "verb": "title", "input": "<primary>", "options": { "max-tokens": "96" } }
|
|
139
|
+
* → 200 { "ok": true, "result": <the model's JSON> }
|
|
140
|
+
* → 4xx { "ok": false, "error": "<message>" }
|
|
141
|
+
* ```
|
|
142
|
+
* @param entry - the catalog entry to reach.
|
|
143
|
+
* @param options - endpoint, optional token, injected poster.
|
|
144
|
+
* @returns the transport.
|
|
145
|
+
*/
|
|
146
|
+
export declare function createRemoteTransport(entry: ModelCatalogEntry, options?: TransportOptions): CommandTransport;
|
|
147
|
+
/**
|
|
148
|
+
* Interpret one bridge response.
|
|
149
|
+
* @param entry - the model, for error messages.
|
|
150
|
+
* @param response - the HTTP status and body.
|
|
151
|
+
* @returns the model's result as a canonical value.
|
|
152
|
+
* @throws when the bridge reports a failure or an unreadable body.
|
|
153
|
+
*/
|
|
154
|
+
export declare function parseBridgeResponse(entry: ModelCatalogEntry, response: {
|
|
155
|
+
readonly status: number;
|
|
156
|
+
readonly body: string;
|
|
157
|
+
}): Record<string, JsonValue>;
|
|
158
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AACnD,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAEpE,mDAAmD;AACnD,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAA;IACjC,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAChD,2BAA2B;IAC3B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAC7B;AAED,sCAAsC;AACtC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,6EAA6E;AAC7E,MAAM,MAAM,aAAa,GAAG,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,MAAM,EAAE,WAAW,KAChB,OAAO,CAAC,cAAc,CAAC,CAAA;AAE5B,8EAA8E;AAC9E,MAAM,MAAM,QAAQ,GAAG,CACrB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACzC,MAAM,EAAE,WAAW,KAChB,OAAO,CAAC;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAEhE,sCAAsC;AACtC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,QAAQ,CAAA;IAC/B,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAA;CACtE;AAED,iEAAiE;AACjE,eAAO,MAAM,sBAAsB,IAAI,CAAA;AACvC,eAAO,MAAM,oBAAoB,KAAK,CAAA;AAEtC;;GAEG;AACH,eAAO,MAAM,mBAAmB,cAAc,CAAA;AAE9C,wCAAwC;AACxC,eAAO,MAAM,WAAW,YAAY,CAAA;AAEpC;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAgB1E;AAYD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,iBAAiB,EACxB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACtC;IAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;CAAE,CAgCxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,iBAAiB,EACxB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACtC,MAAM,EAAE,CAOV;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,cAAc,GACtB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CA6B3B;AAmBD,8CAA8C;AAC9C,eAAO,MAAM,WAAW,EAAE,aAmCtB,CAAA;AAEJ,qEAAqE;AACrE,eAAO,MAAM,SAAS,EAAE,QAQvB,CAAA;AAED,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,gDAAgD;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,+BAA+B;IAC/B,QAAQ,CAAC,GAAG,CAAC,EAAE,aAAa,CAAA;IAC5B,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAA;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,iBAAiB,EACxB,OAAO,GAAE,gBAAqB,GAC7B,gBAAgB,CAalB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,iBAAiB,EACxB,OAAO,GAAE,gBAAqB,GAC7B,gBAAgB,CAmClB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,iBAAiB,EACxB,QAAQ,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC3D,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAkB3B"}
|
package/lib/transport.js
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command transports: reaching a model that is not an in-process npm package.
|
|
3
|
+
*
|
|
4
|
+
* Two transports share one shape:
|
|
5
|
+
*
|
|
6
|
+
* - **cli** — runs the Desert Ant CLI (`desertant`/`da`), which exposes every
|
|
7
|
+
* shipping model as `desertant <verb> … --json` and runs on macOS and Linux.
|
|
8
|
+
* - **remote** — POSTs to a bridge the user runs on a machine that can execute
|
|
9
|
+
* the model. This is what makes an Apple-only model such as Title reachable
|
|
10
|
+
* from a Windows host.
|
|
11
|
+
*
|
|
12
|
+
* Both are injected with their side-effecting primitive (`CommandRunner`,
|
|
13
|
+
* `HttpPost`) so behaviour is testable without spawning a process or opening a
|
|
14
|
+
* socket, and so a deployment can substitute its own runner.
|
|
15
|
+
*
|
|
16
|
+
* @module @try-works/dsh-model-as-tool/transport
|
|
17
|
+
*/
|
|
18
|
+
import { spawn } from 'node:child_process';
|
|
19
|
+
import { accessSync, constants } from 'node:fs';
|
|
20
|
+
import { delimiter, join } from 'node:path';
|
|
21
|
+
import { throwIfAborted } from "./adapters/types.js";
|
|
22
|
+
/** The Desert Ant CLI's exit codes, as documented for agents. */
|
|
23
|
+
export const CLI_EXIT_RUNTIME_ERROR = 1;
|
|
24
|
+
export const CLI_EXIT_USAGE_ERROR = 64;
|
|
25
|
+
/**
|
|
26
|
+
* Default command name. `da` is the short alias the CLI installs.
|
|
27
|
+
*/
|
|
28
|
+
export const DEFAULT_CLI_COMMAND = 'desertant';
|
|
29
|
+
/** The path every bridge must serve. */
|
|
30
|
+
export const BRIDGE_PATH = '/invoke';
|
|
31
|
+
/**
|
|
32
|
+
* Whether a command is on PATH.
|
|
33
|
+
*
|
|
34
|
+
* Probed by scanning PATH rather than by running the command, because this runs
|
|
35
|
+
* at plugin load and a capability probe must not start a process (or pay a
|
|
36
|
+
* CLI's startup cost) just to decide what to advertise.
|
|
37
|
+
* @param command - command name or an absolute path.
|
|
38
|
+
* @param pathValue - the PATH to search; defaults to the process environment.
|
|
39
|
+
* @returns whether an executable file of that name exists.
|
|
40
|
+
*/
|
|
41
|
+
export function commandExists(command, pathValue) {
|
|
42
|
+
// An explicit path is checked directly; a bare name is searched on PATH.
|
|
43
|
+
if (command.includes('/') || command.includes('\\')) {
|
|
44
|
+
return isExecutable(command);
|
|
45
|
+
}
|
|
46
|
+
const searchPath = pathValue ?? process.env.PATH ?? '';
|
|
47
|
+
const extensions = process.platform === 'win32'
|
|
48
|
+
? (process.env.PATHEXT ?? '.COM;.EXE;.BAT;.CMD').split(';')
|
|
49
|
+
: [''];
|
|
50
|
+
for (const directory of searchPath.split(delimiter)) {
|
|
51
|
+
if (directory.length === 0)
|
|
52
|
+
continue;
|
|
53
|
+
for (const extension of extensions) {
|
|
54
|
+
if (isExecutable(join(directory, command + extension)))
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
/** Whether a path is an existing executable file. */
|
|
61
|
+
function isExecutable(candidate) {
|
|
62
|
+
try {
|
|
63
|
+
accessSync(candidate, constants.X_OK);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Split the tool arguments into the CLI's positional inputs and its
|
|
72
|
+
* `--option key=value` flags.
|
|
73
|
+
*
|
|
74
|
+
* The first declared catalog parameter is the primary input, matching how the
|
|
75
|
+
* registrar marks it required. A file model accepts several paths positionally
|
|
76
|
+
* (the CLI loads the model once for all of them), so a primary declared as a
|
|
77
|
+
* string list becomes several positionals. Everything else becomes an option,
|
|
78
|
+
* with lists comma-joined because the CLI's option syntax is `key=value`.
|
|
79
|
+
* @param entry - the catalog entry being invoked.
|
|
80
|
+
* @param args - validated tool arguments.
|
|
81
|
+
* @returns the positional inputs and the option list.
|
|
82
|
+
*/
|
|
83
|
+
export function splitArguments(entry, args) {
|
|
84
|
+
const names = Object.keys(entry.tool.params);
|
|
85
|
+
const primaryName = names[0];
|
|
86
|
+
if (primaryName === undefined) {
|
|
87
|
+
throw new Error(`${entry.name} declares no parameters, so its input cannot be addressed`);
|
|
88
|
+
}
|
|
89
|
+
const primaryValue = args[primaryName];
|
|
90
|
+
let positionals;
|
|
91
|
+
if (typeof primaryValue === 'string' && primaryValue.length > 0) {
|
|
92
|
+
positionals = [primaryValue];
|
|
93
|
+
}
|
|
94
|
+
else if (Array.isArray(primaryValue) && primaryValue.length > 0
|
|
95
|
+
&& primaryValue.every(item => typeof item === 'string' && item.length > 0)) {
|
|
96
|
+
positionals = primaryValue;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
throw new Error(`argument "${primaryName}" must be a non-empty string or list of paths`);
|
|
100
|
+
}
|
|
101
|
+
const options = [];
|
|
102
|
+
for (const name of names.slice(1)) {
|
|
103
|
+
const value = args[name];
|
|
104
|
+
if (value === undefined)
|
|
105
|
+
continue;
|
|
106
|
+
if (Array.isArray(value)) {
|
|
107
|
+
options.push([name.replaceAll('_', '-'), value.map(String).join(',')]);
|
|
108
|
+
}
|
|
109
|
+
else if (typeof value === 'boolean' || typeof value === 'number') {
|
|
110
|
+
options.push([name.replaceAll('_', '-'), String(value)]);
|
|
111
|
+
}
|
|
112
|
+
else if (typeof value === 'string') {
|
|
113
|
+
options.push([name.replaceAll('_', '-'), value]);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
throw new Error(`argument "${name}" must be a string, number, boolean or string list`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return { positionals, options };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Build the CLI argv for one invocation.
|
|
123
|
+
*
|
|
124
|
+
* `--json` is what makes stdout a single JSON value, and it also implies
|
|
125
|
+
* `--no-color`, so no escape sequences have to be stripped.
|
|
126
|
+
* @param entry - the catalog entry being invoked.
|
|
127
|
+
* @param args - validated tool arguments.
|
|
128
|
+
* @returns the argv to run, after the command itself.
|
|
129
|
+
*/
|
|
130
|
+
export function buildArgv(entry, args) {
|
|
131
|
+
const verb = entry.cliVerb;
|
|
132
|
+
if (verb === null)
|
|
133
|
+
throw new Error(`${entry.name} has no CLI verb, so the CLI cannot run it`);
|
|
134
|
+
const { positionals, options } = splitArguments(entry, args);
|
|
135
|
+
const argv = [verb, ...positionals, '--json'];
|
|
136
|
+
for (const [key, value] of options)
|
|
137
|
+
argv.push('--option', `${key}=${value}`);
|
|
138
|
+
return argv;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Parse the CLI's stdout into a canonical value.
|
|
142
|
+
*
|
|
143
|
+
* The CLI writes exactly one JSON value to stdout under `--json` and keeps every
|
|
144
|
+
* diagnostic on stderr, so a parse failure means the command did not behave as
|
|
145
|
+
* documented rather than that output needs cleaning.
|
|
146
|
+
* @param entry - the model, for error messages.
|
|
147
|
+
* @param outcome - the completed command.
|
|
148
|
+
* @returns the parsed value.
|
|
149
|
+
* @throws when the exit code is non-zero or stdout is not a single JSON value.
|
|
150
|
+
*/
|
|
151
|
+
export function parseCliOutcome(entry, outcome) {
|
|
152
|
+
if (outcome.code === CLI_EXIT_USAGE_ERROR) {
|
|
153
|
+
throw new Error(`${entry.name}: the CLI rejected the call (exit 64). ${outcome.stderr.trim() || 'usage error'}`);
|
|
154
|
+
}
|
|
155
|
+
if (outcome.code === CLI_EXIT_RUNTIME_ERROR) {
|
|
156
|
+
throw new Error(`${entry.name} failed (exit 1). ${outcome.stderr.trim() || 'runtime error'}`);
|
|
157
|
+
}
|
|
158
|
+
if (outcome.code !== 0) {
|
|
159
|
+
throw new Error(`${entry.name}: the CLI exited ${outcome.code}. ${outcome.stderr.trim() || 'unknown failure'}`);
|
|
160
|
+
}
|
|
161
|
+
const text = outcome.stdout.trim();
|
|
162
|
+
if (text.length === 0) {
|
|
163
|
+
throw new Error(`${entry.name}: the CLI produced no JSON on stdout`);
|
|
164
|
+
}
|
|
165
|
+
let parsed;
|
|
166
|
+
try {
|
|
167
|
+
parsed = JSON.parse(text);
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
throw new Error(`${entry.name}: the CLI stdout was not JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
171
|
+
}
|
|
172
|
+
return asRecord(entry, parsed);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Wrap a JSON value as the object a tool output schema requires.
|
|
176
|
+
* @param entry - the model, for error messages.
|
|
177
|
+
* @param value - the parsed value.
|
|
178
|
+
* @returns the value as a record; a non-object is wrapped under `result`.
|
|
179
|
+
*/
|
|
180
|
+
function asRecord(entry, value) {
|
|
181
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
182
|
+
return value;
|
|
183
|
+
}
|
|
184
|
+
if (Array.isArray(value))
|
|
185
|
+
return { result: value };
|
|
186
|
+
// A scalar result is still a result; naming it keeps the output contract
|
|
187
|
+
// stable instead of failing a call that actually succeeded.
|
|
188
|
+
void entry;
|
|
189
|
+
return { result: value };
|
|
190
|
+
}
|
|
191
|
+
/** Spawn a command and capture its output. */
|
|
192
|
+
export const spawnRunner = (command, argv, signal) => new Promise((resolve, reject) => {
|
|
193
|
+
// `shell: false` keeps argv elements from being re-interpreted by a shell,
|
|
194
|
+
// so a model input containing quotes or `&` cannot become a second command.
|
|
195
|
+
const child = spawn(command, [...argv], { shell: false, windowsHide: true });
|
|
196
|
+
let stdout = '';
|
|
197
|
+
let stderr = '';
|
|
198
|
+
let settled = false;
|
|
199
|
+
const onAbort = () => {
|
|
200
|
+
if (settled)
|
|
201
|
+
return;
|
|
202
|
+
settled = true;
|
|
203
|
+
child.kill();
|
|
204
|
+
reject(signal.reason instanceof Error ? signal.reason : new Error('aborted'));
|
|
205
|
+
};
|
|
206
|
+
if (signal.aborted) {
|
|
207
|
+
onAbort();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
211
|
+
child.stdout.setEncoding('utf8');
|
|
212
|
+
child.stderr.setEncoding('utf8');
|
|
213
|
+
child.stdout.on('data', (chunk) => { stdout += chunk; });
|
|
214
|
+
child.stderr.on('data', (chunk) => { stderr += chunk; });
|
|
215
|
+
child.on('error', (error) => {
|
|
216
|
+
if (settled)
|
|
217
|
+
return;
|
|
218
|
+
settled = true;
|
|
219
|
+
signal.removeEventListener('abort', onAbort);
|
|
220
|
+
reject(new Error(`cannot run "${command}": ${error.message}`));
|
|
221
|
+
});
|
|
222
|
+
child.on('close', (code) => {
|
|
223
|
+
if (settled)
|
|
224
|
+
return;
|
|
225
|
+
settled = true;
|
|
226
|
+
signal.removeEventListener('abort', onAbort);
|
|
227
|
+
resolve({ code: code ?? -1, stdout, stderr });
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
/** POST JSON with the global fetch and read the response as text. */
|
|
231
|
+
export const fetchPost = async (url, body, headers, signal) => {
|
|
232
|
+
const response = await fetch(url, {
|
|
233
|
+
method: 'POST',
|
|
234
|
+
headers: { 'content-type': 'application/json', ...headers },
|
|
235
|
+
body: JSON.stringify(body),
|
|
236
|
+
signal,
|
|
237
|
+
});
|
|
238
|
+
return { status: response.status, body: await response.text() };
|
|
239
|
+
};
|
|
240
|
+
/**
|
|
241
|
+
* Build the CLI transport for one model.
|
|
242
|
+
* @param entry - the catalog entry, which must declare a CLI verb.
|
|
243
|
+
* @param options - command name and injected runner.
|
|
244
|
+
* @returns the transport.
|
|
245
|
+
*/
|
|
246
|
+
export function createCliTransport(entry, options = {}) {
|
|
247
|
+
const command = options.cliCommand ?? DEFAULT_CLI_COMMAND;
|
|
248
|
+
const run = options.run ?? spawnRunner;
|
|
249
|
+
return {
|
|
250
|
+
kind: 'cli',
|
|
251
|
+
async invoke({ args, signal }) {
|
|
252
|
+
throwIfAborted(signal);
|
|
253
|
+
const argv = buildArgv(entry, args);
|
|
254
|
+
const outcome = await run(command, argv, signal);
|
|
255
|
+
throwIfAborted(signal);
|
|
256
|
+
return parseCliOutcome(entry, outcome);
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Build the remote transport for one model.
|
|
262
|
+
*
|
|
263
|
+
* The bridge contract is deliberately small so a user can implement it in a few
|
|
264
|
+
* lines on a machine that can run the model:
|
|
265
|
+
*
|
|
266
|
+
* ```
|
|
267
|
+
* POST <endpoint>/invoke
|
|
268
|
+
* { "model": "title", "verb": "title", "input": "<primary>", "options": { "max-tokens": "96" } }
|
|
269
|
+
* → 200 { "ok": true, "result": <the model's JSON> }
|
|
270
|
+
* → 4xx { "ok": false, "error": "<message>" }
|
|
271
|
+
* ```
|
|
272
|
+
* @param entry - the catalog entry to reach.
|
|
273
|
+
* @param options - endpoint, optional token, injected poster.
|
|
274
|
+
* @returns the transport.
|
|
275
|
+
*/
|
|
276
|
+
export function createRemoteTransport(entry, options = {}) {
|
|
277
|
+
const endpoint = options.endpoint;
|
|
278
|
+
if (endpoint === undefined || endpoint.length === 0) {
|
|
279
|
+
throw new Error('the remote transport requires an endpoint');
|
|
280
|
+
}
|
|
281
|
+
const post = options.post ?? fetchPost;
|
|
282
|
+
const url = `${endpoint.replace(/\/+$/, '')}${BRIDGE_PATH}`;
|
|
283
|
+
const headers = options.token === undefined
|
|
284
|
+
? {}
|
|
285
|
+
: { authorization: `Bearer ${options.token}` };
|
|
286
|
+
return {
|
|
287
|
+
kind: 'remote',
|
|
288
|
+
async invoke({ args, signal }) {
|
|
289
|
+
throwIfAborted(signal);
|
|
290
|
+
const verb = entry.cliVerb;
|
|
291
|
+
if (verb === null)
|
|
292
|
+
throw new Error(`${entry.name} declares no verb for the bridge to run`);
|
|
293
|
+
const { positionals, options: flags } = splitArguments(entry, args);
|
|
294
|
+
const response = await post(url, {
|
|
295
|
+
model: entry.id,
|
|
296
|
+
verb,
|
|
297
|
+
// A file model may pass several paths; `input` carries them all so the
|
|
298
|
+
// bridge does not have to know which models take more than one.
|
|
299
|
+
input: positionals.length === 1 ? positionals[0] : positionals,
|
|
300
|
+
options: Object.fromEntries(flags),
|
|
301
|
+
}, headers, signal);
|
|
302
|
+
throwIfAborted(signal);
|
|
303
|
+
return parseBridgeResponse(entry, response);
|
|
304
|
+
},
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Interpret one bridge response.
|
|
309
|
+
* @param entry - the model, for error messages.
|
|
310
|
+
* @param response - the HTTP status and body.
|
|
311
|
+
* @returns the model's result as a canonical value.
|
|
312
|
+
* @throws when the bridge reports a failure or an unreadable body.
|
|
313
|
+
*/
|
|
314
|
+
export function parseBridgeResponse(entry, response) {
|
|
315
|
+
let parsed;
|
|
316
|
+
try {
|
|
317
|
+
parsed = JSON.parse(response.body);
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
throw new Error(`${entry.name}: the bridge returned a non-JSON body (HTTP ${response.status})`);
|
|
321
|
+
}
|
|
322
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
323
|
+
throw new Error(`${entry.name}: the bridge returned an unexpected body shape`);
|
|
324
|
+
}
|
|
325
|
+
const envelope = parsed;
|
|
326
|
+
if (envelope.ok !== true) {
|
|
327
|
+
const detail = typeof envelope.error === 'string' ? envelope.error : `HTTP ${response.status}`;
|
|
328
|
+
throw new Error(`${entry.name}: the bridge could not run the model. ${detail}`);
|
|
329
|
+
}
|
|
330
|
+
return asRecord(entry, envelope.result);
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=transport.js.map
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data model for the Desert Ant Labs model catalog and the capability layer
|
|
3
|
+
* that decides whether a model can actually run in the current DSH process.
|
|
4
|
+
*
|
|
5
|
+
* @module @try-works/dsh-model-as-tool/types
|
|
6
|
+
*/
|
|
7
|
+
/** The kind of value a model consumes. */
|
|
8
|
+
export type ModelInput = 'text' | 'audio' | 'image' | 'video' | 'stroke' | 'transcript';
|
|
9
|
+
/**
|
|
10
|
+
* How the model's weights are reachable from a Node process on each platform.
|
|
11
|
+
* This is the field the capability resolver keys off, because it encodes the
|
|
12
|
+
* upstream packaging reality rather than an aspiration.
|
|
13
|
+
*/
|
|
14
|
+
export type WindowsSupport =
|
|
15
|
+
/** Ships a prebuilt native core for this platform and works in plain Node. */
|
|
16
|
+
'native-node'
|
|
17
|
+
/** Needs a caller-supplied ONNX Runtime module (e.g. `onnxruntime-node`). */
|
|
18
|
+
| 'onnxruntime-node'
|
|
19
|
+
/** No Node runtime anywhere: Apple platforms only, through the Swift SDK. */
|
|
20
|
+
| 'apple-only'
|
|
21
|
+
/** Prebuilt native core exists, but not for this platform/arch. */
|
|
22
|
+
| 'browser-only'
|
|
23
|
+
/** Weights exist but no SDK ships them at all. */
|
|
24
|
+
| 'no-sdk';
|
|
25
|
+
/** The JSON-level type of one tool parameter. */
|
|
26
|
+
export type ModelParamType = 'string' | 'number' | 'integer' | 'boolean' | 'string[]';
|
|
27
|
+
/**
|
|
28
|
+
* One declared tool parameter.
|
|
29
|
+
*
|
|
30
|
+
* A bare string is shorthand for `{ type: 'string', description }`, which is
|
|
31
|
+
* what most of the catalog's parameters are; the object form exists for the
|
|
32
|
+
* parameters that are genuinely numbers, booleans or string lists.
|
|
33
|
+
*/
|
|
34
|
+
export interface ModelParam {
|
|
35
|
+
/** Model-facing description of the parameter. */
|
|
36
|
+
readonly description: string;
|
|
37
|
+
/** Declared type; defaults to `string`. */
|
|
38
|
+
readonly type?: ModelParamType;
|
|
39
|
+
}
|
|
40
|
+
/** One parameter as written in the catalog document. */
|
|
41
|
+
export type ModelParamSpec = string | ModelParam;
|
|
42
|
+
/** The model-facing tool a catalog entry installs. */
|
|
43
|
+
export interface ModelToolSpec {
|
|
44
|
+
/** DSH tool name (lower snake_case). */
|
|
45
|
+
readonly name: string;
|
|
46
|
+
/** Model-facing description of the tool. */
|
|
47
|
+
readonly description: string;
|
|
48
|
+
/** Parameter name -> declaration, in documentation order; the first is the primary input. */
|
|
49
|
+
readonly params: Readonly<Record<string, ModelParam>>;
|
|
50
|
+
/** What the tool returns. */
|
|
51
|
+
readonly returns: string;
|
|
52
|
+
}
|
|
53
|
+
/** The skill a catalog entry publishes alongside its tool. */
|
|
54
|
+
export interface ModelSkillSpec {
|
|
55
|
+
/** Kebab-case skill name. */
|
|
56
|
+
readonly name: string;
|
|
57
|
+
/** Short routing description for the skill catalog. */
|
|
58
|
+
readonly description: string;
|
|
59
|
+
/** Optional extra routing guidance. */
|
|
60
|
+
readonly whenToUse?: string;
|
|
61
|
+
}
|
|
62
|
+
/** One model in the Desert Ant Labs catalog. */
|
|
63
|
+
export interface ModelCatalogEntry {
|
|
64
|
+
readonly id: string;
|
|
65
|
+
readonly name: string;
|
|
66
|
+
readonly summary: string;
|
|
67
|
+
readonly capability: string;
|
|
68
|
+
readonly input: ModelInput;
|
|
69
|
+
readonly output: string;
|
|
70
|
+
readonly languages: number | null;
|
|
71
|
+
readonly modelSizeMB: number | null;
|
|
72
|
+
readonly appleOnly: boolean;
|
|
73
|
+
readonly closedBeta: boolean;
|
|
74
|
+
/** True only where this repository verified a real inference on Windows x64. */
|
|
75
|
+
readonly verifiedRunnableOnWindows: boolean;
|
|
76
|
+
readonly windowsSupport: WindowsSupport;
|
|
77
|
+
readonly npmPackage: string | null;
|
|
78
|
+
readonly npmSubpath: string | null;
|
|
79
|
+
readonly requiresRuntime: readonly string[];
|
|
80
|
+
readonly cliVerb: string | null;
|
|
81
|
+
readonly license: string;
|
|
82
|
+
readonly docsUrl: string;
|
|
83
|
+
readonly hfRepo: string;
|
|
84
|
+
readonly tool: ModelToolSpec;
|
|
85
|
+
readonly skill: ModelSkillSpec;
|
|
86
|
+
}
|
|
87
|
+
/** How an adapter reaches a model at run time. */
|
|
88
|
+
export type ModelRoute =
|
|
89
|
+
/** An npm package loaded in this process. */
|
|
90
|
+
'npm-native'
|
|
91
|
+
/** An npm package plus a caller-supplied ONNX Runtime module. */
|
|
92
|
+
| 'npm-onnxruntime'
|
|
93
|
+
/** The Desert Ant CLI, run as a child process (macOS and Linux). */
|
|
94
|
+
| 'cli'
|
|
95
|
+
/** A user-hosted bridge, reached over HTTP. */
|
|
96
|
+
| 'remote'
|
|
97
|
+
/** No route available in this process. */
|
|
98
|
+
| 'unavailable';
|
|
99
|
+
/** The capability resolver's verdict for one model in the current process. */
|
|
100
|
+
export interface CapabilityVerdict {
|
|
101
|
+
/** Whether an adapter can actually produce a working tool for this model. */
|
|
102
|
+
readonly runnable: boolean;
|
|
103
|
+
readonly route: ModelRoute;
|
|
104
|
+
/** Why the model is or is not runnable, always populated for a negative verdict. */
|
|
105
|
+
readonly reason: string;
|
|
106
|
+
/** Resolved package specifiers this verdict depended on, for diagnostics. */
|
|
107
|
+
readonly resolved?: readonly string[];
|
|
108
|
+
/** Resolved package specifiers that were required but missing. */
|
|
109
|
+
readonly missing?: readonly string[];
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,0CAA0C;AAC1C,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,YAAY,CAAA;AAEvF;;;;GAIG;AACH,MAAM,MAAM,cAAc;AACxB,8EAA8E;AAC5E,aAAa;AACf,6EAA6E;GAC3E,kBAAkB;AACpB,6EAA6E;GAC3E,YAAY;AACd,mEAAmE;GACjE,cAAc;AAChB,kDAAkD;GAChD,QAAQ,CAAA;AAEZ,iDAAiD;AACjD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAA;AAErF;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,iDAAiD;IACjD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,2CAA2C;IAC3C,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,CAAA;CAC/B;AAED,wDAAwD;AACxD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,UAAU,CAAA;AAEhD,sDAAsD;AACtD,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,4CAA4C;IAC5C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,6FAA6F;IAC7F,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAA;IACrD,6BAA6B;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,8DAA8D;AAC9D,MAAM,WAAW,cAAc;IAC7B,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,uDAAuD;IACvD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,uCAAuC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,gDAAgD;AAChD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IACnC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,yBAAyB,EAAE,OAAO,CAAA;IAC3C,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAA;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAA;CAC/B;AAED,kDAAkD;AAClD,MAAM,MAAM,UAAU;AACpB,6CAA6C;AAC3C,YAAY;AACd,iEAAiE;GAC/D,iBAAiB;AACnB,oEAAoE;GAClE,KAAK;AACP,+CAA+C;GAC7C,QAAQ;AACV,0CAA0C;GACxC,aAAa,CAAA;AAEjB,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,kEAAkE;IAClE,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC"}
|
package/lib/types.js
ADDED