@try-works/dsh-model-as-tool 0.1.1 → 0.1.3
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 +51 -0
- package/bin/dsh-tool-mode-mcp-stdio.mjs +80 -0
- package/catalog/desert-ant-models.json +77 -13
- package/lib/adapters/index.d.ts +19 -6
- package/lib/adapters/index.d.ts.map +1 -1
- package/lib/adapters/index.js +28 -13
- package/lib/adapters/tongue.d.ts +11 -3
- package/lib/adapters/tongue.d.ts.map +1 -1
- package/lib/adapters/tongue.js +12 -4
- package/lib/adapters/types.d.ts +11 -0
- package/lib/adapters/types.d.ts.map +1 -1
- package/lib/adapters/voz.d.ts +7 -1
- package/lib/adapters/voz.d.ts.map +1 -1
- package/lib/adapters/voz.js +16 -4
- package/lib/asset-acquisition.d.ts +137 -0
- package/lib/asset-acquisition.d.ts.map +1 -0
- package/lib/asset-acquisition.js +161 -0
- package/lib/authority.d.ts +153 -0
- package/lib/authority.d.ts.map +1 -0
- package/lib/authority.js +194 -0
- package/lib/bindings.d.ts +115 -0
- package/lib/bindings.d.ts.map +1 -0
- package/lib/bindings.js +239 -0
- package/lib/catalog.d.ts.map +1 -1
- package/lib/catalog.js +57 -0
- package/lib/contract-payload.d.ts +47 -0
- package/lib/contract-payload.d.ts.map +1 -0
- package/lib/contract-payload.js +137 -0
- package/lib/deployment-coordinator.d.ts +213 -0
- package/lib/deployment-coordinator.d.ts.map +1 -0
- package/lib/deployment-coordinator.js +274 -0
- package/lib/harness-budgets.d.ts +158 -0
- package/lib/harness-budgets.d.ts.map +1 -0
- package/lib/harness-budgets.js +152 -0
- package/lib/index.d.ts +41 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +424 -16
- package/lib/licensing.d.ts +221 -0
- package/lib/licensing.d.ts.map +1 -0
- package/lib/licensing.js +188 -0
- package/lib/mcp/host-binding.d.ts +91 -0
- package/lib/mcp/host-binding.d.ts.map +1 -0
- package/lib/mcp/host-binding.js +133 -0
- package/lib/mcp/http.d.ts +130 -0
- package/lib/mcp/http.d.ts.map +1 -0
- package/lib/mcp/http.js +274 -0
- package/lib/mcp/protocol.d.ts +261 -0
- package/lib/mcp/protocol.d.ts.map +1 -0
- package/lib/mcp/protocol.js +387 -0
- package/lib/mcp/server.d.ts +115 -0
- package/lib/mcp/server.d.ts.map +1 -0
- package/lib/mcp/server.js +200 -0
- package/lib/mcp/stdio.d.ts +80 -0
- package/lib/mcp/stdio.d.ts.map +1 -0
- package/lib/mcp/stdio.js +176 -0
- package/lib/mcp/subscriptions.d.ts +135 -0
- package/lib/mcp/subscriptions.d.ts.map +1 -0
- package/lib/mcp/subscriptions.js +207 -0
- package/lib/provider-bridge.d.ts +69 -0
- package/lib/provider-bridge.d.ts.map +1 -0
- package/lib/provider-bridge.js +218 -0
- package/lib/publication.d.ts +160 -0
- package/lib/publication.d.ts.map +1 -0
- package/lib/publication.js +173 -0
- package/lib/receipt.d.ts +208 -0
- package/lib/receipt.d.ts.map +1 -0
- package/lib/receipt.js +150 -0
- package/lib/registrar.d.ts +13 -0
- package/lib/registrar.d.ts.map +1 -1
- package/lib/registrar.js +20 -3
- package/lib/resource-governance.d.ts +204 -0
- package/lib/resource-governance.d.ts.map +1 -0
- package/lib/resource-governance.js +213 -0
- package/lib/server-lifecycle.d.ts +175 -0
- package/lib/server-lifecycle.d.ts.map +1 -0
- package/lib/server-lifecycle.js +269 -0
- package/lib/types.d.ts +21 -0
- package/lib/types.d.ts.map +1 -1
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.d.ts +16 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/lang-detect.js +85 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.d.ts +20 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/stt-transcribe.js +112 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts +82 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/dsh.js +260 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts +23 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/index.js +24 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/meta.d.ts +104 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/meta.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/meta.js +55 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts +81 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/registry.js +163 -0
- package/node_modules/@try-works/tool-mode-contracts/package.json +35 -0
- package/package.json +17 -5
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract definitions and their runtime validation.
|
|
3
|
+
*
|
|
4
|
+
* A contract is the tool's public identity: stable name, version, input and
|
|
5
|
+
* output schema, semantics, limits and policy metadata (DECL-01). It is
|
|
6
|
+
* deliberately model-free — implementations bind to it, it does not know about
|
|
7
|
+
* them — which is what lets two models serve one `stt_transcribe` instead of
|
|
8
|
+
* producing a duplicate tool each (BASE-02).
|
|
9
|
+
*
|
|
10
|
+
* Milestone A is explicit that "a copied schema with no runtime validation is not
|
|
11
|
+
* completion", so this module validates both directions: the contract DEFINITION
|
|
12
|
+
* is checked when registered, and every RESULT is checked against the declared
|
|
13
|
+
* output schema before it reaches a caller.
|
|
14
|
+
*
|
|
15
|
+
* @module @try-works/tool-mode-contracts/registry
|
|
16
|
+
*/
|
|
17
|
+
import { Ajv } from 'ajv';
|
|
18
|
+
import { TOOL_META_SCHEMA } from "./meta.js";
|
|
19
|
+
/** A contract that failed validation, with every reason. */
|
|
20
|
+
export class ContractError extends Error {
|
|
21
|
+
name = 'ContractError';
|
|
22
|
+
/** The individual violations, in declaration order. */
|
|
23
|
+
violations;
|
|
24
|
+
constructor(subject, violations) {
|
|
25
|
+
super(`${subject} is not a valid contract: ${violations.join('; ')}`);
|
|
26
|
+
this.violations = violations;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** A result that did not satisfy its contract's output schema. */
|
|
30
|
+
export class ContractViolationError extends Error {
|
|
31
|
+
name = 'ContractViolationError';
|
|
32
|
+
violations;
|
|
33
|
+
constructor(contract, violations) {
|
|
34
|
+
super(`result violates the ${contract} contract: ${violations.join('; ')}`);
|
|
35
|
+
this.violations = violations;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The validator. `strict: false` because contract schemas use JSON Schema
|
|
40
|
+
* keywords that Ajv's strict mode rejects when they are merely annotated, and
|
|
41
|
+
* `allErrors` so a violation report lists every problem rather than the first.
|
|
42
|
+
*/
|
|
43
|
+
function createAjv() {
|
|
44
|
+
return new Ajv({ allErrors: true, strict: false, allowUnionTypes: true });
|
|
45
|
+
}
|
|
46
|
+
const ajv = createAjv();
|
|
47
|
+
const outputValidators = new Map();
|
|
48
|
+
const inputValidators = new Map();
|
|
49
|
+
/** Render Ajv errors as stable, deduplicated strings. */
|
|
50
|
+
function renderErrors(errors) {
|
|
51
|
+
const seen = new Set();
|
|
52
|
+
const out = [];
|
|
53
|
+
for (const error of errors ?? []) {
|
|
54
|
+
const path = error.instancePath === '' ? '(root)' : error.instancePath;
|
|
55
|
+
const line = `${path} ${error.message ?? 'is invalid'}`;
|
|
56
|
+
if (!seen.has(line)) {
|
|
57
|
+
seen.add(line);
|
|
58
|
+
out.push(line);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Validate a contract definition.
|
|
65
|
+
*
|
|
66
|
+
* This is deliberately strict about the identity fields: a contract whose
|
|
67
|
+
* `toolName` is not a legal tool name, or whose version is not semver, would
|
|
68
|
+
* register a tool that callers cannot address consistently.
|
|
69
|
+
* @param contract - the definition to check.
|
|
70
|
+
* @throws ContractError listing every violation.
|
|
71
|
+
*/
|
|
72
|
+
export function assertValidContract(contract) {
|
|
73
|
+
const violations = [];
|
|
74
|
+
if (!/^[a-z][a-z0-9_]*$/.test(contract.toolName)) {
|
|
75
|
+
violations.push(`toolName ${JSON.stringify(contract.toolName)} must be lower snake_case`);
|
|
76
|
+
}
|
|
77
|
+
if (!/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/.test(contract.contract)) {
|
|
78
|
+
violations.push(`contract ${JSON.stringify(contract.contract)} must be a dotted lower-case identity `
|
|
79
|
+
+ '(for example "stt.transcribe" or "text.language_detect")');
|
|
80
|
+
}
|
|
81
|
+
if (!/^\d+\.\d+\.\d+$/.test(contract.version)) {
|
|
82
|
+
violations.push(`version ${JSON.stringify(contract.version)} must be semantic (x.y.z)`);
|
|
83
|
+
}
|
|
84
|
+
if (contract.description.trim().length < 10) {
|
|
85
|
+
violations.push('description must be a real sentence, not a placeholder');
|
|
86
|
+
}
|
|
87
|
+
const input = contract.inputSchema;
|
|
88
|
+
if (input.type !== 'object') {
|
|
89
|
+
violations.push('inputSchema root must be an object (clients require an object argument)');
|
|
90
|
+
}
|
|
91
|
+
const output = contract.outputSchema;
|
|
92
|
+
if (output.type !== 'object') {
|
|
93
|
+
violations.push('outputSchema root must be an object for broad client compatibility (DECL-02)');
|
|
94
|
+
}
|
|
95
|
+
else if (output.properties?.meta === undefined) {
|
|
96
|
+
violations.push('outputSchema must include the shared `meta` envelope (DECL-03)');
|
|
97
|
+
}
|
|
98
|
+
// DECL-02: an unconstrained open object is not an adequate leaf-tool contract.
|
|
99
|
+
if (output.additionalProperties !== false) {
|
|
100
|
+
violations.push('outputSchema must be closed (additionalProperties: false), not a generic open object (DECL-02)');
|
|
101
|
+
}
|
|
102
|
+
if (contract.unsupported.length === 0) {
|
|
103
|
+
violations.push('unsupported must name at least one case; an empty list claims universal support');
|
|
104
|
+
}
|
|
105
|
+
if (violations.length > 0)
|
|
106
|
+
throw new ContractError(contract.contract, violations);
|
|
107
|
+
// Schemas must be compilable, or the contract is unenforceable.
|
|
108
|
+
try {
|
|
109
|
+
inputValidators.set(contract.contract, ajv.compile(contract.inputSchema));
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
throw new ContractError(contract.contract, [`inputSchema does not compile: ${message(error)}`]);
|
|
113
|
+
}
|
|
114
|
+
try {
|
|
115
|
+
outputValidators.set(contract.contract, ajv.compile(contract.outputSchema));
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
throw new ContractError(contract.contract, [`outputSchema does not compile: ${message(error)}`]);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Validate caller arguments against the contract's input schema.
|
|
123
|
+
* @param contract - the contract to check against.
|
|
124
|
+
* @param args - the candidate arguments.
|
|
125
|
+
* @throws ContractViolationError listing every violation.
|
|
126
|
+
*/
|
|
127
|
+
export function assertValidInput(contract, args) {
|
|
128
|
+
const validate = inputValidators.get(contract.contract);
|
|
129
|
+
if (validate === undefined) {
|
|
130
|
+
throw new ContractError(contract.contract, ['input was validated before the contract was registered']);
|
|
131
|
+
}
|
|
132
|
+
if (!validate(args))
|
|
133
|
+
throw new ContractViolationError(contract.contract, renderErrors(validate.errors));
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Validate a result against the contract's output schema.
|
|
137
|
+
*
|
|
138
|
+
* This runs before the value reaches a caller, so a violation surfaces as a
|
|
139
|
+
* tool failure rather than as malformed data downstream (AT-11).
|
|
140
|
+
* @param contract - the contract to check against.
|
|
141
|
+
* @param value - the candidate result.
|
|
142
|
+
* @throws ContractViolationError listing every violation.
|
|
143
|
+
*/
|
|
144
|
+
export function assertValidOutput(contract, value) {
|
|
145
|
+
const validate = outputValidators.get(contract.contract);
|
|
146
|
+
if (validate === undefined) {
|
|
147
|
+
throw new ContractError(contract.contract, ['result was validated before the contract was registered']);
|
|
148
|
+
}
|
|
149
|
+
if (!validate(value))
|
|
150
|
+
throw new ContractViolationError(contract.contract, renderErrors(validate.errors));
|
|
151
|
+
}
|
|
152
|
+
/** The meta envelope's own schema, exported for contract authors. */
|
|
153
|
+
export { TOOL_META_SCHEMA };
|
|
154
|
+
/** Best-effort message from an arbitrary thrown value. */
|
|
155
|
+
function message(error) {
|
|
156
|
+
try {
|
|
157
|
+
return error instanceof Error ? error.message : String(error);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return '<unrenderable>';
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@try-works/tool-mode-contracts",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Model-free standard tool contracts for Tool Mode: identities, schemas, semantics and runtime validation",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/try-works/dsh-model-as-tool.git",
|
|
10
|
+
"directory": "packages/tool-mode-contracts"
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "lib/index.js",
|
|
14
|
+
"types": "lib/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": { "types": "./lib/index.d.ts", "default": "./lib/index.js" },
|
|
17
|
+
"./src/*": "./src/*",
|
|
18
|
+
"./package.json": "./package.json"
|
|
19
|
+
},
|
|
20
|
+
"files": ["lib/**/*.js", "lib/**/*.d.ts", "lib/**/*.d.ts.map", "README.md"],
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"ajv": "^8.20.0"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc -p tsconfig.build.json",
|
|
26
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
27
|
+
"test": "tsx --test tests/*.test.ts",
|
|
28
|
+
"prepack": "tsc -p tsconfig.build.json",
|
|
29
|
+
"prepare": "tsc -p tsconfig.build.json"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^24.0.0",
|
|
33
|
+
"typescript": "^5.9.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@try-works/dsh-model-as-tool",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Install Desert Ant Labs on-device models as DSH tools and skills, with per-platform capability gating",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
"catalog/desert-ant-models.json",
|
|
49
49
|
"catalog/playbooks.json",
|
|
50
50
|
"cordis.patch.yml",
|
|
51
|
-
"README.md"
|
|
51
|
+
"README.md",
|
|
52
|
+
"bin"
|
|
52
53
|
],
|
|
53
54
|
"dsh": {
|
|
54
55
|
"bundle": {
|
|
@@ -75,11 +76,22 @@
|
|
|
75
76
|
"build": "tsc -p tsconfig.build.json",
|
|
76
77
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
77
78
|
"test": "tsx --test tests/*.test.ts",
|
|
78
|
-
"prepack": "
|
|
79
|
-
"prepare": "tsc -p tsconfig.build.json"
|
|
79
|
+
"prepack": "node scripts/stage-bundle.mjs && npm run build",
|
|
80
|
+
"prepare": "tsc -p tsconfig.build.json",
|
|
81
|
+
"postpack": "node scripts/stage-bundle.mjs --clean"
|
|
80
82
|
},
|
|
81
83
|
"devDependencies": {
|
|
82
84
|
"@types/node": "^24.0.0",
|
|
83
85
|
"typescript": "^5.9.0"
|
|
84
|
-
}
|
|
86
|
+
},
|
|
87
|
+
"dependencies": {
|
|
88
|
+
"@try-works/tool-mode-contracts": "^0.1.0",
|
|
89
|
+
"ajv": "^8.20.0"
|
|
90
|
+
},
|
|
91
|
+
"bin": {
|
|
92
|
+
"dsh-tool-mode-mcp-stdio": "./bin/dsh-tool-mode-mcp-stdio.mjs"
|
|
93
|
+
},
|
|
94
|
+
"bundledDependencies": [
|
|
95
|
+
"@try-works/tool-mode-contracts"
|
|
96
|
+
]
|
|
85
97
|
}
|