@try-works/dsh-model-as-tool 0.4.2 → 0.4.4

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/lib/bindings.d.ts CHANGED
@@ -112,4 +112,33 @@ export declare function registerContractTool(ctx: {
112
112
  toolName: string;
113
113
  dispose: () => void;
114
114
  };
115
+ /**
116
+ * Register a STANDARD contract tool served by an ACTIVE extension's
117
+ * IMPLEMENTATION (TASK-121), mirroring {@link registerContractTool} with the
118
+ * execution bound to a host-supplied dispatch instead of a catalogue adapter.
119
+ *
120
+ * The tool name, description and schemas come from the CONTRACT definition —
121
+ * never invented per extension — and the dispatch hands the CONTRACT-shaped
122
+ * input to the extension's implementation (the extension reads the standard
123
+ * shapes directly). Input/output validation, the grant authorization, the
124
+ * meta stamping and the receipt are the SAME discipline the catalogue path
125
+ * applies, so the two routes cannot diverge.
126
+ * @param ctx - the context whose tool registry receives the definition.
127
+ * @param contract - the standard contract definition.
128
+ * @param host - host identity to stamp into results.
129
+ * @param dispatch - executes through the extension implementation.
130
+ * @returns the registered tool name and the registry disposer.
131
+ */
132
+ export declare function registerContractImplementationTool(ctx: {
133
+ tools: {
134
+ register(definition: unknown): () => void;
135
+ };
136
+ }, contract: ToolContract, host: HostIdentity, dispatch: (args: Record<string, unknown>, signal: AbortSignal) => Promise<Record<string, unknown>>, implementation: {
137
+ readonly id: string;
138
+ readonly extensionId: string;
139
+ readonly modelId: string;
140
+ }): {
141
+ toolName: string;
142
+ dispose: () => void;
143
+ };
115
144
  //# sourceMappingURL=bindings.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAOL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,QAAQ,EACd,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE/D,OAAO,EAA0B,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAC7E,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACf,MAAM,gBAAgB,CAAA;AACvB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEvD,+CAA+C;AAC/C,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,gCAAgC;IAChC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;IACjC,wEAAwE;IACxE,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAA;IACrC,iEAAiE;IACjE,QAAQ,CAAC,aAAa,EAAE,MAAM,MAAM,CAAA;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;IACzB,2CAA2C;IAC3C,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC,YAAY,CAAC,CAAA;IACtD;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAA;CAC9D;AAED,+DAA+D;AAC/D,MAAM,WAAW,eAAe;IAC9B,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAA;IAC/B,gDAAgD;IAChD,QAAQ,CAAC,cAAc,EAAE,iBAAiB,CAAA;IAC1C,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;IAC9B,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;CACzC;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,iBAAiB,CAcxE;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,gBAAgB,GAAG,OAAO,CAAC,EACvE,IAAI,EAAE,YAAY,EAClB,QAAQ,GAAE,SAAS,MAAM,EAAO,GAC/B,QAAQ,CAYV;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,GAAG,gBAAgB,GAAG,OAAO,CAAC,EACvE,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,EACjC,QAAQ,GAAE,SAAS,MAAM,EAAO,GAC/B,iBAAiB,CAoBnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE;IAAE,KAAK,EAAE;QAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,IAAI,CAAA;KAAE,CAAA;CAAE,EAC7D,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,YAAY,GACjB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAoG3C"}
1
+ {"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"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"}
package/lib/bindings.js CHANGED
@@ -205,6 +205,80 @@ export function registerContractTool(ctx, binding, host) {
205
205
  void implementation;
206
206
  return { toolName: contract.toolName, dispose: ctx.tools.register(definition) };
207
207
  }
208
+ /**
209
+ * Register a STANDARD contract tool served by an ACTIVE extension's
210
+ * IMPLEMENTATION (TASK-121), mirroring {@link registerContractTool} with the
211
+ * execution bound to a host-supplied dispatch instead of a catalogue adapter.
212
+ *
213
+ * The tool name, description and schemas come from the CONTRACT definition —
214
+ * never invented per extension — and the dispatch hands the CONTRACT-shaped
215
+ * input to the extension's implementation (the extension reads the standard
216
+ * shapes directly). Input/output validation, the grant authorization, the
217
+ * meta stamping and the receipt are the SAME discipline the catalogue path
218
+ * applies, so the two routes cannot diverge.
219
+ * @param ctx - the context whose tool registry receives the definition.
220
+ * @param contract - the standard contract definition.
221
+ * @param host - host identity to stamp into results.
222
+ * @param dispatch - executes through the extension implementation.
223
+ * @returns the registered tool name and the registry disposer.
224
+ */
225
+ export function registerContractImplementationTool(ctx, contract, host, dispatch, implementation) {
226
+ assertValidContract(contract);
227
+ const rules = crossFieldRules(contract);
228
+ // The minimal binding-lite the provenance builders read: the meta names the
229
+ // extension's implementation, and the receipt records the extension package.
230
+ const bindingLite = {
231
+ contract,
232
+ implementation: {
233
+ id: implementation.id,
234
+ provider: { extension: implementation.extensionId, modelId: implementation.modelId },
235
+ },
236
+ route: 'extension',
237
+ };
238
+ const definition = defineTool({
239
+ name: contract.toolName,
240
+ description: contract.description,
241
+ parameters: toDshParameters(contract),
242
+ output: {
243
+ schema: {
244
+ type: 'object',
245
+ properties: projectSchemaToDsh(contract.outputSchema).parameters,
246
+ additionalProperties: false,
247
+ },
248
+ render: (_args, value) => {
249
+ const record = value;
250
+ return [{ type: 'text', text: renderForModel(contract, record) }];
251
+ },
252
+ },
253
+ async execute(args, exec) {
254
+ const record = args;
255
+ assertValidInput(contract, record);
256
+ for (const rule of rules) {
257
+ const violation = rule(record);
258
+ if (violation !== undefined) {
259
+ throw new Error(`${contract.toolName}: ${violation}`);
260
+ }
261
+ }
262
+ authorizeTool(host.grant, contract.toolName);
263
+ const value = await dispatch(record, exec.signal);
264
+ const meta = buildMeta(bindingLite, host);
265
+ const stamped = { ...value, meta };
266
+ assertValidOutput(contract, stamped);
267
+ host.recordReceipt?.(buildReceipt(bindingLite, host, meta));
268
+ return stamped;
269
+ },
270
+ presentCall(callArgs) {
271
+ const primary = Object.values(callArgs)[0];
272
+ return {
273
+ card: 'generic',
274
+ title: contract.toolName,
275
+ kind: 'read',
276
+ ...typeof primary === 'string' ? { rawInput: primary } : {},
277
+ };
278
+ },
279
+ });
280
+ return { toolName: contract.toolName, dispose: ctx.tools.register(definition) };
281
+ }
208
282
  /**
209
283
  * Render a contract result for the model.
210
284
  *
@@ -20,19 +20,11 @@ export declare class PayloadTranslationError extends Error {
20
20
  readonly name = "PayloadTranslationError";
21
21
  }
22
22
  /**
23
- * Translate a contract's validated arguments into an adapter's native shape.
24
- *
25
- * This is the input half of the same seam as {@link toContractPayload}. An adapter
26
- * speaks its SDK's vocabulary — `audio_path` — while the contract publishes the
27
- * caller's vocabulary — `audio.path`. Without this translation the contract layer
28
- * would be cosmetic: the model would advertise one shape and the implementation
29
- * would read another, and every call would fail on a name that no longer exists.
30
- *
31
- * The contract is the authority here too, so the mapping is explicit and total
32
- * rather than a spread that happens to overlap.
33
- * @param contractId - the contract the call was validated against.
23
+ * Translate the contract's caller-facing arguments into the implementation's
24
+ * native vocabulary.
25
+ * @param contractId - the contract the implementation was selected for.
34
26
  * @param contractArgs - the validated contract arguments.
35
- * @returns the arguments the selected adapter expects.
27
+ * @returns the native argument shape.
36
28
  */
37
29
  export declare function toNativeArgs(contractId: string, contractArgs: Readonly<Record<string, unknown>>): Record<string, unknown>;
38
30
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"contract-payload.d.ts","sourceRoot":"","sources":["../src/contract-payload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAEpD,0EAA0E;AAC1E,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,SAAkB,IAAI,6BAA4B;CACnD;AAyED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC9C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBzB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EACjC,IAAI,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM,GAC3C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAW3B"}
1
+ {"version":3,"file":"contract-payload.d.ts","sourceRoot":"","sources":["../src/contract-payload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAEpD,0EAA0E;AAC1E,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,SAAkB,IAAI,6BAA4B;CACnD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC9C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWzB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EACjC,IAAI,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM,GAC3C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAO3B"}
@@ -18,101 +18,24 @@
18
18
  export class PayloadTranslationError extends Error {
19
19
  name = 'PayloadTranslationError';
20
20
  }
21
- /** Best-effort read of a numeric field. */
22
- function numberOf(value) {
23
- return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
24
- }
25
- /**
26
- * Translate a native language-detection result into the `text.language_detect`
27
- * payload.
28
- *
29
- * The only rename is the vendor's `isTooCloseToCall` to the contract's
30
- * `tooCloseToCall`; every other field already matches, which is what makes this a
31
- * translation rather than a reshape.
32
- * @param native - the adapter's result.
33
- * @returns the contract payload, without the `meta` envelope the host stamps.
34
- */
35
- function languageDetectPayload(native) {
36
- const candidates = Array.isArray(native.candidates) ? native.candidates : [];
37
- return {
38
- // A model that found no language signal returns null rather than a guess.
39
- language: typeof native.language === 'string' ? native.language : null,
40
- reliability: typeof native.reliability === 'string' ? native.reliability : 'unknown',
41
- tooCloseToCall: native.isTooCloseToCall === true,
42
- candidates: candidates,
43
- };
44
- }
45
- /**
46
- * Translate a native transcription result into the `stt.transcribe` payload.
47
- *
48
- * `coverage` is the interesting field. Voz streams the whole file and fails loudly
49
- * on a short decode, so a returned transcript covers all the audio it read;
50
- * `transcribedSeconds` is taken from the last word's end time, which is a lower
51
- * bound on the audio actually processed. When no words are reported, coverage is
52
- * reported as zero seconds with `complete: true` only because the engine ran to
53
- * completion — an empty transcript is a valid result (TOOL-01), not a failure.
54
- * @param native - the adapter's result.
55
- * @param requestedWords - whether the caller asked for word timings.
56
- * @returns the contract payload, without the `meta` envelope the host stamps.
57
- */
58
- function transcribePayload(native, requestedWords) {
59
- const words = Array.isArray(native.words) ? native.words : null;
60
- if (requestedWords && words === null) {
61
- // TOOL-01: an unsupported timestamp request is an error, never a silent
62
- // omission the caller might read as "there were no word timings".
63
- throw new PayloadTranslationError('word timestamps were requested but the implementation returned none; '
64
- + 'this is reported as an error rather than an empty list');
65
- }
66
- let transcribedSeconds = 0;
67
- if (words !== null && words.length > 0) {
68
- const last = words[words.length - 1];
69
- transcribedSeconds = numberOf(last.end) ?? 0;
70
- }
71
- const truncated = native.wordsTruncated === true;
72
- return {
73
- text: typeof native.text === 'string' ? native.text : '',
74
- coverage: {
75
- complete: !truncated,
76
- transcribedSeconds,
77
- totalSeconds: null,
78
- reason: truncated ? 'word list truncated for transport; the transcript text is complete' : null,
79
- },
80
- words: words === null ? null : words,
81
- language: typeof native.language === 'string' ? native.language : null,
82
- };
83
- }
84
21
  /**
85
- * Translate a contract's validated arguments into an adapter's native shape.
86
- *
87
- * This is the input half of the same seam as {@link toContractPayload}. An adapter
88
- * speaks its SDK's vocabulary — `audio_path` — while the contract publishes the
89
- * caller's vocabulary — `audio.path`. Without this translation the contract layer
90
- * would be cosmetic: the model would advertise one shape and the implementation
91
- * would read another, and every call would fail on a name that no longer exists.
92
- *
93
- * The contract is the authority here too, so the mapping is explicit and total
94
- * rather than a spread that happens to overlap.
95
- * @param contractId - the contract the call was validated against.
22
+ * Translate the contract's caller-facing arguments into the implementation's
23
+ * native vocabulary.
24
+ * @param contractId - the contract the implementation was selected for.
96
25
  * @param contractArgs - the validated contract arguments.
97
- * @returns the arguments the selected adapter expects.
26
+ * @returns the native argument shape.
98
27
  */
99
28
  export function toNativeArgs(contractId, contractArgs) {
100
- switch (contractId) {
101
- case 'stt.transcribe': {
102
- const audio = contractArgs.audio;
103
- return {
104
- audio_path: audio?.path,
105
- // The contract defaults `timestamps` to none, while the adapter defaults
106
- // its own flag to true. Mapping explicitly keeps the contract's default
107
- // authoritative instead of letting the adapter's leak through.
108
- include_words: contractArgs.timestamps === 'word',
109
- ...contractArgs.language === undefined ? {} : { language: contractArgs.language },
110
- };
111
- }
112
- default:
113
- // `text.language_detect` already shares its argument names with the adapter.
114
- return { ...contractArgs };
115
- }
29
+ void contractId;
30
+ /**
31
+ * TASK-115/120/121: the extension implementations now speak the CONTRACT
32
+ * vocabulary on BOTH sides (the tongue/voz mappings published in 0.1.3 and
33
+ * 0.1.5 read {audio:{path}} and emit the contract payloads), so the host's
34
+ * argument translation is a PASS-THROUGH — the old audio_path/include_words
35
+ * native vocabulary no longer exists on the wire. A future implementation
36
+ * with a genuinely different native vocabulary re-introduces its case here.
37
+ */
38
+ return { ...contractArgs };
116
39
  }
117
40
  /**
118
41
  * Translate a native implementation result into the payload its contract declares.
@@ -123,15 +46,11 @@ export function toNativeArgs(contractId, contractArgs) {
123
46
  * @throws PayloadTranslationError when the native result cannot satisfy the contract.
124
47
  */
125
48
  export function toContractPayload(contractId, native, args = {}) {
126
- switch (contractId) {
127
- case 'text.language_detect':
128
- return languageDetectPayload(native);
129
- case 'stt.transcribe':
130
- return transcribePayload(native, args.timestamps === 'word');
131
- default:
132
- // A contract with no translator returns the native payload unchanged, which
133
- // the output schema then accepts or rejects on its own terms.
134
- return native;
135
- }
49
+ void contractId;
50
+ void args;
51
+ // TASK-115/120/121: the extension implementations emit the CONTRACT payloads
52
+ // directly, so the result translation is the identity; the output schema's
53
+ // validation is the authority that accepts or rejects the payload.
54
+ return native;
136
55
  }
137
56
  //# sourceMappingURL=contract-payload.js.map
@@ -108,6 +108,39 @@ export declare function createDispatch(environment: DispatchEnvironment, toolNam
108
108
  readonly ok: false;
109
109
  readonly failure: DispatchFailure;
110
110
  }>;
111
+ /**
112
+ * Resolve the implementation chain for a declared CONTRACT id (TASK-121).
113
+ *
114
+ * An extension whose manifest declares ONLY implementations (no `tools[]` —
115
+ * the MiniLM pair's shape) still serves a caller-facing standard tool: the
116
+ * contract id maps to the standard tool name the host knows, and this
117
+ * resolution finds the implementation by the contract id alone.
118
+ * @param manifest - the activated extension's manifest.
119
+ * @param contractId - the contract identity.
120
+ * @returns the implementation, or why the chain is incomplete.
121
+ */
122
+ export declare function resolveImplementationByContract(manifest: DispatchManifest, contractId: string): {
123
+ readonly ok: true;
124
+ readonly implementation: DeclaredImplementation;
125
+ } | {
126
+ readonly ok: false;
127
+ readonly failure: DispatchFailure;
128
+ };
129
+ /**
130
+ * Build an `execute` for a standard-named contract tool served by an
131
+ * IMPLEMENTATION-ONLY extension (TASK-121). The provider is created lazily on
132
+ * first call, exactly like the declared-tool path.
133
+ * @param environment - how to reach the extension.
134
+ * @param contractId - the contract identity to dispatch.
135
+ * @returns the execute function, or the failure that prevents one.
136
+ */
137
+ export declare function createDispatchForContract(environment: DispatchEnvironment, contractId: string): Promise<{
138
+ readonly ok: true;
139
+ readonly execute: (args: Record<string, unknown>, signal: AbortSignal) => Promise<Record<string, unknown>>;
140
+ } | {
141
+ readonly ok: false;
142
+ readonly failure: DispatchFailure;
143
+ }>;
111
144
  /**
112
145
  * Describe a dispatch failure for a caller (EXT-30).
113
146
  * @param failure - the failure.
@@ -1 +1 @@
1
- {"version":3,"file":"extension-dispatch.d.ts","sourceRoot":"","sources":["../src/extension-dispatch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"extension-dispatch.d.ts","sourceRoot":"","sources":["../src/extension-dispatch.ts"],"names":[],"mappings":"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"}
@@ -113,6 +113,60 @@ export async function createDispatch(environment, toolName) {
113
113
  },
114
114
  };
115
115
  }
116
+ /**
117
+ * Resolve the implementation chain for a declared CONTRACT id (TASK-121).
118
+ *
119
+ * An extension whose manifest declares ONLY implementations (no `tools[]` —
120
+ * the MiniLM pair's shape) still serves a caller-facing standard tool: the
121
+ * contract id maps to the standard tool name the host knows, and this
122
+ * resolution finds the implementation by the contract id alone.
123
+ * @param manifest - the activated extension's manifest.
124
+ * @param contractId - the contract identity.
125
+ * @returns the implementation, or why the chain is incomplete.
126
+ */
127
+ export function resolveImplementationByContract(manifest, contractId) {
128
+ const implementation = manifest.implementations.find(candidate => candidate.contractId === contractId);
129
+ if (implementation === undefined) {
130
+ return {
131
+ ok: false,
132
+ failure: {
133
+ code: 'no-implementation',
134
+ message: `contract ${contractId} has no implementation in this extension's manifest`,
135
+ remedy: 'The extension declares the contract but binds no model to it.',
136
+ },
137
+ };
138
+ }
139
+ return { ok: true, implementation };
140
+ }
141
+ /**
142
+ * Build an `execute` for a standard-named contract tool served by an
143
+ * IMPLEMENTATION-ONLY extension (TASK-121). The provider is created lazily on
144
+ * first call, exactly like the declared-tool path.
145
+ * @param environment - how to reach the extension.
146
+ * @param contractId - the contract identity to dispatch.
147
+ * @returns the execute function, or the failure that prevents one.
148
+ */
149
+ export async function createDispatchForContract(environment, contractId) {
150
+ const resolved = resolveImplementationByContract(environment.getManifest(), contractId);
151
+ if (!resolved.ok)
152
+ return resolved;
153
+ const { implementation } = resolved;
154
+ return {
155
+ ok: true,
156
+ async execute(args, signal) {
157
+ const provider = await environment.providerFor(implementation.modelId);
158
+ const prepared = environment.assetsFor?.();
159
+ await provider.load({ assets: prepared ?? { get: () => undefined, assetIds: [] }, signal, modelId: implementation.modelId });
160
+ const value = await provider.invoke({
161
+ implementationId: implementation.id,
162
+ input: args,
163
+ context: environment.contextFor(implementation.id, signal),
164
+ });
165
+ assertNoReservedMeta(value, implementation.id);
166
+ return value;
167
+ },
168
+ };
169
+ }
116
170
  /**
117
171
  * Describe a dispatch failure for a caller (EXT-30).
118
172
  * @param failure - the failure.
@@ -65,6 +65,22 @@ export interface HostRegistrySurface {
65
65
  readonly name: string;
66
66
  readonly contractId?: string;
67
67
  }): () => void;
68
+ /**
69
+ * Register the STANDARD-named contract tool for a MODULE implementation
70
+ * whose contract the host knows a standard name for (TASK-121).
71
+ *
72
+ * A module package that declares ONLY implementations (no `tools[]` — the
73
+ * MiniLM pair's shape) serves the standard contract directly: the host maps
74
+ * the contract id to its standard tool name (text.embed -> text_embed) and
75
+ * registers the tool with the contract's own schemas. Returns a disposer
76
+ * when it registered, or undefined when the contract is not a standard one
77
+ * (the declarative branch below then handles it).
78
+ */
79
+ registerContractImplementation?(contribution: {
80
+ readonly extensionId: string;
81
+ readonly contractId: string;
82
+ readonly implementationId: string;
83
+ }): (() => void) | undefined;
68
84
  }
69
85
  /** Raised when a contribution cannot be published. */
70
86
  export declare class ContributionError extends Error {
@@ -1 +1 @@
1
- {"version":3,"file":"extension-registrar.d.ts","sourceRoot":"","sources":["../src/extension-registrar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAE7F,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,2DAA2D;IAC3D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,wDAAwD;IACxD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,uDAAuD;AACvD,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,YAAY,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,IAAI,CAAA;IAC/C,gDAAgD;IAChD,aAAa,CAAC,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,IAAI,CAAA;IAC7F;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,CAAC,YAAY,EAAE;QACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;QAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;QACrB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAC7B,GAAG,MAAM,IAAI,CAAA;CACf;AAED,sDAAsD;AACtD,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,SAAkB,IAAI,uBAAsB;IAC5C,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,kBAAkB,GAAG,mBAAmB,CAAA;gBAC9D,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM;CAI7D;AAUD;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAA;IACtC;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACvC,yFAAyF;IACzF,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAA;CACpF;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,gBAAgB,GAAG,qBAAqB,CAkG5F"}
1
+ {"version":3,"file":"extension-registrar.d.ts","sourceRoot":"","sources":["../src/extension-registrar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAE7F,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,2DAA2D;IAC3D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,wDAAwD;IACxD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,uDAAuD;AACvD,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,YAAY,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,IAAI,CAAA;IAC/C,gDAAgD;IAChD,aAAa,CAAC,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,IAAI,CAAA;IAC7F;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,CAAC,YAAY,EAAE;QACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;QAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;QACrB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAC7B,GAAG,MAAM,IAAI,CAAA;IACd;;;;;;;;;;OAUG;IACH,8BAA8B,CAAC,CAAC,YAAY,EAAE;QAC5C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;QAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;QAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;KAClC,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAA;CAC7B;AAED,sDAAsD;AACtD,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,SAAkB,IAAI,uBAAsB;IAC5C,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,kBAAkB,GAAG,mBAAmB,CAAA;gBAC9D,IAAI,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM;CAI7D;AAUD;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAA;IACtC;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACvC,yFAAyF;IACzF,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAA;CACpF;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,gBAAgB,GAAG,qBAAqB,CA2G5F"}
@@ -89,15 +89,25 @@ export function createContributionRegistrar(options) {
89
89
  });
90
90
  }
91
91
  else if (contribution.kind === 'implementation' && options.registry.registerDeclarative !== undefined) {
92
- // An `implementation` of a MODULE package is not a caller-facing tool: the model
93
- // catalogue binds it. An implementation of a DECLARATIVE package, however, IS the
94
- // whole package: the host turns its resolved recipe into the caller-facing tool
95
- // here (RCP-01), and the returned disposer is tracked like any other handle.
96
- dispose = options.registry.registerDeclarative({
92
+ // TASK-121: a MODULE implementation whose contract has a standard tool
93
+ // name registers the standard-named contract tool; the hook returns
94
+ // undefined when the contract is not standard, and the declarative
95
+ // branch then handles it (RCP-01).
96
+ const contractRegistration = options.registry.registerContractImplementation?.({
97
97
  extensionId: contribution.extensionId,
98
- name: contribution.name,
99
- ...contribution.contractId === undefined ? {} : { contractId: contribution.contractId },
98
+ contractId: contribution.contractId ?? '',
99
+ implementationId: contribution.name,
100
100
  });
101
+ if (contractRegistration !== undefined) {
102
+ dispose = contractRegistration;
103
+ }
104
+ else {
105
+ dispose = options.registry.registerDeclarative({
106
+ extensionId: contribution.extensionId,
107
+ name: contribution.name,
108
+ ...contribution.contractId === undefined ? {} : { contractId: contribution.contractId },
109
+ });
110
+ }
101
111
  }
102
112
  else {
103
113
  dispose = () => { };
@@ -51,7 +51,15 @@
51
51
  import { stagedInstallFromDirectory, type ExtensionLifecycle, type InstallDependencyGraph } from '@try-works/tool-mode-extension-sdk';
52
52
  import type { ExtensionInstallResult, ExtensionPrepareResult, ExtensionToggleResult, ExtensionsDescribeResult, ModelToolsRemote } from './extensions-api.ts';
53
53
  import type { AcquisitionSource } from './asset-acquisition.ts';
54
- import type { PrepareAssetsSurface } from './prepared-assets.ts';
54
+ import { type PrepareAssetsSurface } from './prepared-assets.ts';
55
+ /**
56
+ * The default dependency-graph depth bound for registry installs (task-116).
57
+ *
58
+ * The SDK default (3) is too shallow for real trees; onnxruntime-node reaches
59
+ * `define-data-property` at depth 4. Preinstalled packages are leaves, so this
60
+ * only bounds registry-resolved graphs.
61
+ */
62
+ export declare const DEFAULT_REGISTRY_DEPENDENCY_DEPTH = 12;
55
63
  /** What the host can report about the shared harness model provider (declarative extensions). */
56
64
  export interface HarnessProviderStatus {
57
65
  /** Whether a provider is composed and able to serve declarative extensions. */
@@ -114,6 +122,8 @@ export type ExtensionsServiceErrorCode =
114
122
  | 'extension-requirement-unmet'
115
123
  /** The extension's optional tool runtime is not installed, so its tools cannot load. */
116
124
  | 'extension-runtime-unavailable'
125
+ /** The asset lock declares no transferable location; preparation is not possible here. */
126
+ | 'extension-asset-source-unavailable'
117
127
  /** Registry mode was selected but no registry URL is configured. */
118
128
  | 'extension-registry-unconfigured'
119
129
  /** The registry has no such package, version, or dist-tag (HTTP 404 / no matching version). */
@@ -200,6 +210,12 @@ export interface ExtensionsServiceOptions {
200
210
  * when NO bytes arrive for this long; the byte cap remains the real bound.
201
211
  */
202
212
  readonly registryTarballTimeoutMs?: number;
213
+ /**
214
+ * Dependency-graph depth bound for registry installs; defaults to
215
+ * {@link DEFAULT_REGISTRY_DEPENDENCY_DEPTH} (12). Configurable because real
216
+ * dependency trees vary; a refusal names the level and the package.
217
+ */
218
+ readonly registryDependencyDepth?: number;
203
219
  /** INTERNAL TEST SEAM: the directory installer, defaulting to the SDK's staged path. */
204
220
  readonly installDirectory?: DirectoryInstaller;
205
221
  /** INTERNAL TEST SEAM: the content digest, defaulting to the SDK's installed-content digest. */
@@ -1 +1 @@
1
- {"version":3,"file":"extensions-service.d.ts","sourceRoot":"","sources":["../src/extensions-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"extensions-service.d.ts","sourceRoot":"","sources":["../src/extensions-service.ts"],"names":[],"mappings":"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"}
@@ -54,6 +54,15 @@ import { dirname, join, resolve } from 'node:path';
54
54
  import { createTarGzipArchiveSource, digestInstalledContent, discoverExtension, ExtensionStore, installDependencyGraph, ManagementError, stagedInstall, stagedInstallFromDirectory, } from '@try-works/tool-mode-extension-sdk';
55
55
  import { createFirstPartyDependencyGraph, createRegistryDependencyGraph, createRegistrySession, DEFAULT_REGISTRY_URL, MAX_DEPENDENCY_ARCHIVE_BYTES, RegistryError, resolveFirstPartyDependency, satisfiesRegistryRange, } from "./extension-dependencies.js";
56
56
  import { createHttpSource } from "./http-acquisition.js";
57
+ import { assetSourceUnavailableReason, firstUnavailableAssetSource, } from "./prepared-assets.js";
58
+ /**
59
+ * The default dependency-graph depth bound for registry installs (task-116).
60
+ *
61
+ * The SDK default (3) is too shallow for real trees; onnxruntime-node reaches
62
+ * `define-data-property` at depth 4. Preinstalled packages are leaves, so this
63
+ * only bounds registry-resolved graphs.
64
+ */
65
+ export const DEFAULT_REGISTRY_DEPENDENCY_DEPTH = 12;
57
66
  /**
58
67
  * The readiness values that permit activation (the SDK's callable set).
59
68
  *
@@ -349,6 +358,56 @@ function replaceInstalledRecord(storeDir, updated) {
349
358
  return false;
350
359
  }
351
360
  }
361
+ /**
362
+ * Directories to search for OPERATOR-PREINSTALLED packages, deepest-nested first.
363
+ *
364
+ * A preinstalled package is a LEAF: its transitive dependencies already sit in its
365
+ * OWN `node_modules` (npm nests them when versions conflict), so root-level lookup
366
+ * alone misses e.g. `@huggingface/transformers/node_modules/onnxruntime-web`. This
367
+ * enumerates the preinstalled root, each top-level package directory, and (bounded)
368
+ * their nested package directories; the resolver tries each in order.
369
+ * @param root - the operator-configured preinstalled root (its `node_modules` is searched).
370
+ * @param depth - how many nested package levels to enumerate (bounded).
371
+ * @returns candidate package roots, root first.
372
+ */
373
+ function preinstalledSearchRoots(root, depth = 3) {
374
+ const candidates = [root];
375
+ const visit = (nodeModules, remaining) => {
376
+ if (remaining <= 0)
377
+ return;
378
+ let entries;
379
+ try {
380
+ entries = readdirSync(nodeModules);
381
+ }
382
+ catch {
383
+ return;
384
+ }
385
+ for (const entry of entries) {
386
+ if (entry.startsWith('.'))
387
+ continue;
388
+ const entryPath = join(nodeModules, entry);
389
+ if (entry.startsWith('@')) {
390
+ let scoped;
391
+ try {
392
+ scoped = readdirSync(entryPath);
393
+ }
394
+ catch {
395
+ continue;
396
+ }
397
+ for (const name of scoped) {
398
+ const packageDir = join(entryPath, name);
399
+ candidates.push(packageDir);
400
+ visit(join(packageDir, 'node_modules'), remaining - 1);
401
+ }
402
+ continue;
403
+ }
404
+ candidates.push(entryPath);
405
+ visit(join(entryPath, 'node_modules'), remaining - 1);
406
+ }
407
+ };
408
+ visit(join(root, 'node_modules'), depth);
409
+ return candidates;
410
+ }
352
411
  /**
353
412
  * Every declared deployment whose recorded readiness does not permit activation.
354
413
  *
@@ -834,7 +893,15 @@ export class ExtensionsService {
834
893
  requirements.push(requirement('assets', false, `not installed; ${input.facts.models.join(', ')} need${input.facts.models.length === 1 ? 's' : ''} model assets prepared after installation`, 'install'));
835
894
  }
836
895
  else if (blockers.length > 0) {
837
- requirements.push(requirement('assets', false, `activation blocked: ${blockers.join('; ')}`, 'prepare'));
896
+ /**
897
+ * A lock whose assets carry prose sources (no URL) cannot be prepared by this
898
+ * host. Report action `none` so the page does not offer Prepare as if it could
899
+ * succeed; the reason names the artifact and the documented export.
900
+ */
901
+ const unavailable = this.#unavailableAssetSource(input.id);
902
+ requirements.push(unavailable === undefined
903
+ ? requirement('assets', false, `activation blocked: ${blockers.join('; ')}`, 'prepare')
904
+ : requirement('assets', false, `[ASSET_SOURCE_UNAVAILABLE] ${assetSourceUnavailableReason(unavailable.assetId, unavailable.source)}`, 'none'));
838
905
  }
839
906
  else {
840
907
  requirements.push(requirement('assets', true, `every declared model deployment is prepared or callable (${input.facts.models.join(', ')})`));
@@ -950,6 +1017,27 @@ export class ExtensionsService {
950
1017
  return requirement('harness-model', false, status.reason
951
1018
  ?? 'no harness model provider is configured, so declarative extensions cannot be served; set config.harnessModel to a runnable model', status.action ?? 'config');
952
1019
  }
1020
+ /**
1021
+ * The first planned asset with neither an http(s) source nor cached bytes.
1022
+ *
1023
+ * A prose lock source (laya's "split export of the pinned checkpoint") is not a
1024
+ * download location; preparation must refuse before any transfer. A cache hit is
1025
+ * still a source because acquisition verifies the cached digest.
1026
+ * @param extensionId - the installed extension.
1027
+ * @returns the unavailable asset, or undefined when every source is reachable.
1028
+ */
1029
+ #unavailableAssetSource(extensionId) {
1030
+ const surface = this.#options.prepareSurface?.();
1031
+ if (surface === undefined)
1032
+ return undefined;
1033
+ try {
1034
+ const plan = surface.plan(extensionId);
1035
+ return firstUnavailableAssetSource(plan.assets.map(asset => ({ assetId: asset.assetId, source: asset.source, digest: asset.digest })), surface.registry.cacheDirectory);
1036
+ }
1037
+ catch {
1038
+ return undefined;
1039
+ }
1040
+ }
953
1041
  /** The executable requirement for an installed, not-yet-callable model deployment. */
954
1042
  #executableRequirement(extensionId) {
955
1043
  const surface = this.#options.prepareSurface?.();
@@ -1283,7 +1371,7 @@ export class ExtensionsService {
1283
1371
  // Registry metadata recorded AS DATA, never as trust: the bytes are
1284
1372
  // verified against the same sha512 before anything is extracted.
1285
1373
  provenance: { registryIntegrity: resolved.integrity },
1286
- dependencies: createRegistryDependencyGraph(session),
1374
+ dependencies: this.#installGraph(session),
1287
1375
  });
1288
1376
  }
1289
1377
  catch (error) {
@@ -1319,38 +1407,52 @@ export class ExtensionsService {
1319
1407
  };
1320
1408
  }
1321
1409
  /**
1322
- * The dependency graph for optional tool runtimes.
1410
+ * The dependency graph used on the REGISTRY install path (regular AND optional).
1411
+ *
1412
+ * PRECEDENCE: when the operator's preinstalled gate is ON and the host's own
1413
+ * tree holds a package satisfying the range, that operator-completed content is
1414
+ * preferred. The SDK copies it with provenance `preinstalled` and records that
1415
+ * no lifecycle script was run. Anything NOT preinstalled falls to the registry
1416
+ * arm, where EXT-10 still refuses script-declaring packages.
1323
1417
  *
1324
- * The registry arm is the default. When the operator's preinstalled gate is ON,
1325
- * a host-tree package that satisfies the range is preferred: tongue's runtime
1326
- * (@desert-ant-labs/tongue) declares a `prepare` script, which the registry arm
1327
- * must refuse under EXT-10, while content that ARRIVED from an operator-completed
1328
- * install is exactly what the gate exists for. The SDK records provenance
1329
- * `preinstalled`, so the lock states the installer ran no lifecycle script.
1418
+ * DEPTH: preinstalled packages are LEAVES for graph purposes — their transitive
1419
+ * tree travels with them — but real registry trees (onnxruntime-node) exceed the
1420
+ * SDK's default 3-level bound, so the host raises the default to
1421
+ * {@link DEFAULT_REGISTRY_DEPENDENCY_DEPTH} and makes it configurable.
1330
1422
  * @param session - the registry session.
1331
1423
  * @returns the graph.
1332
1424
  */
1333
- #optionalRuntimeGraph(session) {
1334
- const registryGraph = createRegistryDependencyGraph(session);
1425
+ #installGraph(session) {
1426
+ const depth = this.#options.registryDependencyDepth ?? DEFAULT_REGISTRY_DEPENDENCY_DEPTH;
1427
+ const registryGraph = { ...createRegistryDependencyGraph(session), maxDepth: depth };
1335
1428
  const preinstalledRoot = this.#options.preinstalledDependenciesRoot ?? '';
1336
1429
  const allowPreinstalled = this.#options.allowPreinstalledDependencies === true && preinstalledRoot !== '';
1337
1430
  if (!allowPreinstalled)
1338
1431
  return registryGraph;
1432
+ const preinstalledRoots = preinstalledSearchRoots(preinstalledRoot);
1339
1433
  return {
1340
1434
  resolver: {
1341
1435
  async resolve(name, range) {
1342
- try {
1343
- const found = resolveFirstPartyDependency({ sourcePackageDir: preinstalledRoot }, name, range);
1344
- return { name: found.name, version: found.version, dir: found.directory, provenance: 'preinstalled' };
1345
- }
1346
- catch {
1347
- return registryGraph.resolver.resolve(name, range);
1436
+ // Prefer operator-completed content, root first and then nested package
1437
+ // trees: a preinstalled package's transitive deps live in ITS OWN
1438
+ // node_modules, so root-level lookup alone would fall through to the
1439
+ // registry and refuse a script-declaring leaf under EXT-10.
1440
+ for (const candidateRoot of preinstalledRoots) {
1441
+ try {
1442
+ const found = resolveFirstPartyDependency({ sourcePackageDir: candidateRoot }, name, range);
1443
+ return { name: found.name, version: found.version, dir: found.directory, provenance: 'preinstalled' };
1444
+ }
1445
+ catch {
1446
+ continue;
1447
+ }
1348
1448
  }
1449
+ return registryGraph.resolver.resolve(name, range);
1349
1450
  },
1350
1451
  },
1351
1452
  archive: registryGraph.archive,
1352
1453
  allowPreinstalled: true,
1353
1454
  preinstalledRoot,
1455
+ maxDepth: depth,
1354
1456
  };
1355
1457
  }
1356
1458
  /**
@@ -1381,7 +1483,7 @@ export class ExtensionsService {
1381
1483
  const scratch = mkdtempSync(join(tmpdir(), 'dsh-optional-runtime-'));
1382
1484
  try {
1383
1485
  writeFileSync(join(scratch, 'package.json'), `${JSON.stringify({ name: 'dsh-optional-runtime-host', version: '0.0.0', dependencies: { [dependency.name]: dependency.range } }, null, 2)}\n`, 'utf8');
1384
- const materialized = await installDependencyGraph(scratch, this.#optionalRuntimeGraph(session));
1486
+ const materialized = await installDependencyGraph(scratch, this.#installGraph(session));
1385
1487
  const sourceNodeModules = join(scratch, 'node_modules');
1386
1488
  const targetNodeModules = join(installed.installPath, 'node_modules');
1387
1489
  if (existsSync(sourceNodeModules)) {
@@ -1683,6 +1785,14 @@ export class ExtensionsService {
1683
1785
  throw new ExtensionsServiceError('extension-preparation-failed', `the preparation plan for ${extensionId} could not be resolved: ${messageOf(error)}`, { cause: error });
1684
1786
  }
1685
1787
  const lifecycle = this.#lifecycle();
1788
+ /**
1789
+ * A prose source (no URL, no cached bytes) is refused BEFORE the lifecycle
1790
+ * probe or any transfer: a URL-parse failure after waiting is the wrong answer.
1791
+ */
1792
+ const unavailable = firstUnavailableAssetSource(plan.assets.map(asset => ({ assetId: asset.assetId, source: asset.source, digest: asset.digest })), surface.registry.cacheDirectory);
1793
+ if (unavailable !== undefined) {
1794
+ throw new ExtensionsServiceError('extension-asset-source-unavailable', `[ASSET_SOURCE_UNAVAILABLE] ${assetSourceUnavailableReason(unavailable.assetId, unavailable.source)}`);
1795
+ }
1686
1796
  if (lifecycle !== undefined && lifecycle.stateOf(extensionId) === undefined) {
1687
1797
  await this.#recordPreparationBlocker(lifecycle, extensionId, record.version);
1688
1798
  }
package/lib/index.d.ts CHANGED
@@ -158,6 +158,14 @@ export interface Config {
158
158
  * Applies only when NO bytes arrive; a slow large download is not aborted.
159
159
  */
160
160
  extensionTarballTimeoutMs?: number;
161
+ /**
162
+ * Dependency-graph depth bound for registry installs. Default 12.
163
+ *
164
+ * Preinstalled dependencies are leaves (their own tree travels with them);
165
+ * registry-resolved graphs are bounded by this, and a refusal names the level
166
+ * and the package.
167
+ */
168
+ extensionDependencyDepth?: number;
161
169
  /**
162
170
  * Operator gate: allow dependency content that arrived already materialized.
163
171
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/lib/index.js CHANGED
@@ -18,7 +18,7 @@ import { loadCatalog } from "./catalog.js";
18
18
  import { resolveCapability } from "./capability.js";
19
19
  import { createAdapter } from "./adapters/index.js";
20
20
  import { registerModelTool } from "./registrar.js";
21
- import { registerContractTool } from "./bindings.js";
21
+ import { registerContractTool, registerContractImplementationTool } from "./bindings.js";
22
22
  import { mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
23
23
  import { dirname, join, resolve } from 'node:path';
24
24
  import { createContributionRegistrar } from "./extension-registrar.js";
@@ -30,7 +30,7 @@ import { createFileCredentialStore, defaultCredentialStoreFile } from "./mcp/cre
30
30
  import { buildHarnessLlmProvider, discoverDefaultHarnessModel, resolveRunnableHarnessModel } from "./harness-llm.js";
31
31
  import { parseRecipe } from '@try-works/tool-mode-recipes';
32
32
  import { createManagedWorkerRegistry } from "./managed-workers.js";
33
- import { createDispatch, describeDispatchFailure, resolveImplementation } from "./extension-dispatch.js";
33
+ import { createDispatch, createDispatchForContract, describeDispatchFailure, resolveImplementation } from "./extension-dispatch.js";
34
34
  import { captureToolSchemaSnapshot, describePlanningRejections, hasPlanningInputShape, offerToolsFromSnapshot, PLANNING_EXCLUDED_TOOLS, PLANNING_TOOL_INPUT_SCHEMA, PLANNING_TOOL_NAME, recheckProposals, } from "./planning.js";
35
35
  import { discoverExtension, loadExtensionModule, resolveDeclarativeImplementations, resolveExtensionEntry } from '@try-works/tool-mode-extension-sdk';
36
36
  import { ExtensionStore, ExtensionLifecycle } from '@try-works/tool-mode-extension-sdk';
@@ -109,6 +109,8 @@ export const Config = z.object({
109
109
  * slowly is not aborted by the short package-metadata timeout.
110
110
  */
111
111
  extensionTarballTimeoutMs: z.number().min(1000).default(10 * 60_000),
112
+ /** Depth bound for registry dependency graphs. Default 12 (SDK default is 3). */
113
+ extensionDependencyDepth: z.number().min(1).max(64).default(12),
112
114
  allowPreinstalledDependencies: z.boolean().default(false),
113
115
  preinstalledDependenciesRoot: z.string().default(''),
114
116
  /**
@@ -343,6 +345,52 @@ export async function apply(ctx, config = {}) {
343
345
  * install loop; the extension-store block assigns it.
344
346
  */
345
347
  let extensionLifecycle;
348
+ /**
349
+ * TASK-117: the catalogue-vs-extension tool-name reconciliation.
350
+ *
351
+ * OWNERSHIP RULE: an INSTALLED extension that declares a tool with a given
352
+ * name OWNS that name — its activation registers the tool, so the catalogue
353
+ * must SKIP its own registration for a contract-backed entry with the same
354
+ * tool name (the live EXTENSION_FAULT was the catalogue winning the race at
355
+ * boot). The skip is recorded; when the owning extension deactivates, the
356
+ * catalogue registration is RESTORED. Deterministic in both orders: the
357
+ * probe reads the durable store, not an in-flight registry.
358
+ */
359
+ const extensionStore = config.extensionStore !== undefined && config.extensionStore.length > 0
360
+ ? new ExtensionStore(config.extensionStore)
361
+ : undefined;
362
+ const catalogueDeferred = new Set();
363
+ const extensionOwnsToolName = (toolName) => {
364
+ if (extensionStore === undefined)
365
+ return false;
366
+ try {
367
+ // Only an ACTIVE extension owns a name at runtime: a disabled (or
368
+ // failed) installation must not keep the catalogue from serving it.
369
+ const active = new Set(extensionStore.readProfileState('default').value
370
+ .filter(entry => entry.desiredActivation === 'active' && entry.observedActivation === 'active')
371
+ .map(entry => entry.extensionId));
372
+ for (const record of extensionStore.listInstalled().value) {
373
+ if (!active.has(record.extensionId))
374
+ continue;
375
+ const discovery = discoverExtension(record.installPath);
376
+ if (discovery.manifest.tools.some(tool => tool.name === toolName))
377
+ return true;
378
+ // TASK-121: an implementation-only extension owns the STANDARD tool
379
+ // name of each implementation's contract (text.embed -> text_embed),
380
+ // exactly as the registrar registers it.
381
+ const implementationNames = (discovery.manifest.implementations ?? [])
382
+ .map(implementation => STANDARD_CONTRACTS.find(contract => contract.contract === implementation.contractId)?.toolName)
383
+ .filter((name) => name !== undefined);
384
+ if (implementationNames.includes(toolName))
385
+ return true;
386
+ }
387
+ }
388
+ catch {
389
+ // A broken package cannot own a tool name; the catalogue keeps it.
390
+ return false;
391
+ }
392
+ return false;
393
+ };
346
394
  /**
347
395
  * The extensions the contribution registrar currently admits.
348
396
  *
@@ -380,6 +428,7 @@ export async function apply(ctx, config = {}) {
380
428
  registryUrl: config.extensionRegistry ?? 'https://registry.npmjs.org/',
381
429
  registryTarballMaxBytes: config.extensionTarballMaxBytes ?? 256 * 1024 * 1024,
382
430
  registryTarballTimeoutMs: config.extensionTarballTimeoutMs ?? 10 * 60_000,
431
+ registryDependencyDepth: config.extensionDependencyDepth ?? 12,
383
432
  /**
384
433
  * The operator gate for already-materialized dependencies. OFF by default:
385
434
  * a dependency whose package.json declares install-time scripts still
@@ -418,11 +467,28 @@ export async function apply(ctx, config = {}) {
418
467
  onActivationChange: (extensionId, active) => {
419
468
  if (active) {
420
469
  activatedExtensions.add(extensionId);
470
+ // TASK-117: the extension now owns its tool names — withdraw the
471
+ // catalogue registrations for those names BEFORE the lifecycle
472
+ // publishes (the hook runs before activate), so the activation cannot
473
+ // collide with a catalogue tool. The names are deferred, not lost.
474
+ for (const item of resolved.filter(candidate => candidate.entry.contract !== null)) {
475
+ if (!extensionOwnsToolName(item.entry.tool.name))
476
+ continue;
477
+ if (!installed.has(item.entry.id))
478
+ continue;
479
+ uninstall(item.entry.id);
480
+ catalogueDeferred.add(item.entry.id);
481
+ ctx.logger.info(`model-tools: ${item.entry.name}'s tool ${item.entry.tool.name} is taken over by ${extensionId}; `
482
+ + 'the catalogue registration is withdrawn and deferred');
483
+ }
421
484
  return;
422
485
  }
423
486
  if (extensionLifecycle?.stateOf(extensionId)?.observedActivation !== 'active') {
424
487
  activatedExtensions.delete(extensionId);
425
488
  }
489
+ // TASK-117: the extension released its tool names — restore every
490
+ // deferred catalogue registration the release freed.
491
+ void restoreDeferredCatalogue();
426
492
  },
427
493
  /**
428
494
  * The harness-model provider status seam (task-93): the thunk evaluates the
@@ -1117,6 +1183,18 @@ export async function apply(ctx, config = {}) {
1117
1183
  toolName = existing.toolName;
1118
1184
  dispose = () => { };
1119
1185
  }
1186
+ else if (extensionOwnsToolName(entry.tool.name)) {
1187
+ /**
1188
+ * TASK-117: an installed extension OWNS this tool name — its
1189
+ * activation registers it, so the catalogue registration is SKIPPED
1190
+ * rather than racing it (the live EXTENSION_FAULT). The deferral is
1191
+ * recorded; the extension's deactivation restores the catalogue tool.
1192
+ */
1193
+ catalogueDeferred.add(entry.id);
1194
+ ctx.logger.info(`model-tools: ${entry.name}'s tool ${entry.tool.name} is owned by an installed extension; `
1195
+ + 'the catalogue registration is deferred until the extension releases the name');
1196
+ return false;
1197
+ }
1120
1198
  else {
1121
1199
  const registered = registerContractTool(ctx, binding, host);
1122
1200
  registeredContracts.set(entry.contract, registered);
@@ -1218,6 +1296,33 @@ export async function apply(ctx, config = {}) {
1218
1296
  const configuredIds = resolved
1219
1297
  .filter(item => (wanted === undefined || wanted.has(item.entry.id)) && !excluded.has(item.entry.id))
1220
1298
  .map(item => item.entry.id);
1299
+ /**
1300
+ * TASK-117: the deferred catalogue registrations, restored when the owning
1301
+ * extension releases a tool name (deactivation). Runs after `install` and
1302
+ * `resolved` exist; the onActivationChange hook fires it asynchronously.
1303
+ */
1304
+ const restoreDeferredCatalogue = async () => {
1305
+ for (const modelId of [...catalogueDeferred]) {
1306
+ const item = resolved.find(candidate => candidate.entry.id === modelId);
1307
+ if (item === undefined) {
1308
+ catalogueDeferred.delete(modelId);
1309
+ continue;
1310
+ }
1311
+ if (extensionOwnsToolName(item.entry.tool.name))
1312
+ continue;
1313
+ catalogueDeferred.delete(modelId);
1314
+ ctx.logger.info(`model-tools: ${item.entry.name}'s tool ${item.entry.tool.name} is released; restoring the catalogue registration`);
1315
+ try {
1316
+ await install(item);
1317
+ }
1318
+ catch (error) {
1319
+ // A failed restore is reported, never swallowed silently: the operator
1320
+ // must see why the catalogue tool did not come back.
1321
+ ctx.logger.warn(`model-tools: could not restore the catalogue registration for ${item.entry.name}: `
1322
+ + `${error instanceof Error ? error.message : String(error)}`);
1323
+ }
1324
+ }
1325
+ };
1221
1326
  for (const item of resolved) {
1222
1327
  const { install: selection, disabled } = resolveSelection(configuredIds, persisted);
1223
1328
  if (!selection.has(item.entry.id)) {
@@ -2360,7 +2465,9 @@ export async function apply(ctx, config = {}) {
2360
2465
  */
2361
2466
  const extensionStoreDir = config.extensionStore ?? '';
2362
2467
  if (extensionStoreDir.length > 0) {
2363
- const store = new ExtensionStore(extensionStoreDir);
2468
+ // TASK-117: the store is the HOISTED instance (constructed at the apply
2469
+ // top so the catalogue-install loop can probe extension tool ownership).
2470
+ const store = extensionStore;
2364
2471
  /**
2365
2472
  * How dispatch reaches an ACTIVATED extension.
2366
2473
  *
@@ -2966,6 +3073,50 @@ export async function apply(ctx, config = {}) {
2966
3073
  * deployment with no harness composition fails loudly (the narrow rollback
2967
3074
  * quarantines it) instead of silently registering nothing.
2968
3075
  */
3076
+ /**
3077
+ * TASK-121: the STANDARD contract tool for an implementation-only
3078
+ * MODULE extension. The contract id maps to the standard tool name
3079
+ * (text.embed -> text_embed — never invented per extension), and the
3080
+ * tool's schemas come from the contract definition itself. The
3081
+ * extension owns the name while active (task-117's probe reads the
3082
+ * implementations' standard names too); the deactivation withdraws it.
3083
+ */
3084
+ registerContractImplementation: (contribution) => {
3085
+ const record = store.listInstalled().value.find(candidate => candidate.extensionId === contribution.extensionId);
3086
+ if (record === undefined)
3087
+ return undefined;
3088
+ const discovery = discoverExtension(record.installPath);
3089
+ // DECLARATIVE packages are served by the recipe path below, never by
3090
+ // this standard-contract path (their contracts may share standard
3091
+ // names, e.g. text.title, but their execution is the recipe broker).
3092
+ if (discovery.manifest.execution?.kind === 'declarative')
3093
+ return undefined;
3094
+ const contract = STANDARD_CONTRACTS.find(candidate => candidate.contract === contribution.contractId);
3095
+ if (contract === undefined)
3096
+ return undefined;
3097
+ const toolName = contract.toolName;
3098
+ // No duplicate: the extension's own manifest tool (when it declares
3099
+ // one) already serves the contract under the standard name.
3100
+ if (extensionToolOwners.get(toolName) === contribution.extensionId)
3101
+ return () => { };
3102
+ const environment = environmentFor(contribution.extensionId);
3103
+ const manifestImplementation = environment.getManifest().implementations.find(candidate => candidate.contractId === contribution.contractId);
3104
+ const registered = registerContractImplementationTool(ctx, contract, host, async (args, signal) => {
3105
+ const dispatch = await createDispatchForContract(environment, contribution.contractId);
3106
+ if (!dispatch.ok)
3107
+ throw new Error(describeDispatchFailure(dispatch.failure));
3108
+ return dispatch.execute(args, signal);
3109
+ }, {
3110
+ id: contribution.implementationId,
3111
+ extensionId: contribution.extensionId,
3112
+ modelId: manifestImplementation?.modelId ?? contribution.implementationId,
3113
+ });
3114
+ extensionToolOwners.set(toolName, contribution.extensionId);
3115
+ return () => {
3116
+ extensionToolOwners.delete(toolName);
3117
+ registered.dispose();
3118
+ };
3119
+ },
2969
3120
  registerDeclarative: (contribution) => {
2970
3121
  const record = store.listInstalled().value.find(candidate => candidate.extensionId === contribution.extensionId);
2971
3122
  if (record === undefined)
@@ -110,8 +110,44 @@ export declare function identityFor(extensionId: string, modelId: string, lock:
110
110
  export declare function plannedAssets(lock: ParsedAssetLock, assetSetId: string): readonly PlannedAsset[];
111
111
  /** The group map for one asset set, keyed by group id. */
112
112
  export declare function lockGroups(lock: ParsedAssetLock, assetSetId: string): readonly LockGroup[];
113
+ /**
114
+ * Whether one lock `source` is a resolvable http(s) download URL.
115
+ * @param source - the lock's source string.
116
+ * @returns whether a transfer can be planned for it.
117
+ */
118
+ export declare function isFetchableAssetSource(source: string): boolean;
119
+ /** The minimum an asset needs for a source check. */
120
+ export interface AssetSourceProbe {
121
+ readonly assetId: string;
122
+ readonly source: string;
123
+ readonly digest: string;
124
+ }
125
+ /**
126
+ * The operator-facing reason an asset has no transferable location.
127
+ *
128
+ * A prose `source` (e.g. "the split export of the pinned checkpoint") is not a
129
+ * download URL; the bytes must be produced by the documented export and placed in
130
+ * the prepared-assets cache (file name = the pinned digest) before a transfer-free
131
+ * preparation can succeed.
132
+ * @param assetId - the lock asset id.
133
+ * @param source - the prose/non-URL source.
134
+ * @returns the exact refusal reason.
135
+ */
136
+ export declare function assetSourceUnavailableReason(assetId: string, source: string): string;
137
+ /**
138
+ * The first planned asset with neither an http(s) URL nor bytes already in the cache.
139
+ *
140
+ * A cache hit is a legitimate source: a later acquisition still verifies the blob
141
+ * against the pinned digest, so pre-seeded artifacts are verified rather than trusted.
142
+ * @param assets - the planned assets to check.
143
+ * @param cacheRoot - the content-addressed cache root (blob filename = digest).
144
+ * @returns the first unavailable asset, or undefined when every asset is reachable.
145
+ */
146
+ export declare function firstUnavailableAssetSource(assets: readonly AssetSourceProbe[], cacheRoot: string): AssetSourceProbe | undefined;
113
147
  /** The host-side prepared-assets registry (session-scoped). */
114
148
  export interface PreparedAssetRegistry {
149
+ /** The content-addressed cache root (blob filename = the pinned digest). */
150
+ readonly cacheDirectory: string;
115
151
  /** The plan the last extensions-prepare-plan built, per extension id. */
116
152
  plans(): ReadonlyMap<string, PreparationPlan>;
117
153
  /** The acquired group map per extension id (PreparedAssetMapV1 shapes). */
@@ -1 +1 @@
1
- {"version":3,"file":"prepared-assets.d.ts","sourceRoot":"","sources":["../src/prepared-assets.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prepared-assets.d.ts","sourceRoot":"","sources":["../src/prepared-assets.ts"],"names":[],"mappings":"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"}
@@ -127,6 +127,47 @@ export function lockGroups(lock, assetSetId) {
127
127
  throw new Error(`the lock declares no asset set "${assetSetId}"`);
128
128
  return set.groups;
129
129
  }
130
+ /**
131
+ * Whether one lock `source` is a resolvable http(s) download URL.
132
+ * @param source - the lock's source string.
133
+ * @returns whether a transfer can be planned for it.
134
+ */
135
+ export function isFetchableAssetSource(source) {
136
+ /**
137
+ * A source is fetchable when it has a URI SCHEME at all: https/http, a `file:`
138
+ * deployment lock, or the injected-source test scheme (`fixture:`). A PROSE
139
+ * description ("the split export of the pinned checkpoint") has no scheme and
140
+ * cannot plan a transfer.
141
+ */
142
+ return /^[a-z][a-z0-9+.-]*:/i.test(source.trim());
143
+ }
144
+ /**
145
+ * The operator-facing reason an asset has no transferable location.
146
+ *
147
+ * A prose `source` (e.g. "the split export of the pinned checkpoint") is not a
148
+ * download URL; the bytes must be produced by the documented export and placed in
149
+ * the prepared-assets cache (file name = the pinned digest) before a transfer-free
150
+ * preparation can succeed.
151
+ * @param assetId - the lock asset id.
152
+ * @param source - the prose/non-URL source.
153
+ * @returns the exact refusal reason.
154
+ */
155
+ export function assetSourceUnavailableReason(assetId, source) {
156
+ return `the asset lock declares no download URL for ${assetId}: its source is ${JSON.stringify(source)}; `
157
+ + 'the artifacts must be produced by the documented export and placed in the prepared-assets cache';
158
+ }
159
+ /**
160
+ * The first planned asset with neither an http(s) URL nor bytes already in the cache.
161
+ *
162
+ * A cache hit is a legitimate source: a later acquisition still verifies the blob
163
+ * against the pinned digest, so pre-seeded artifacts are verified rather than trusted.
164
+ * @param assets - the planned assets to check.
165
+ * @param cacheRoot - the content-addressed cache root (blob filename = digest).
166
+ * @returns the first unavailable asset, or undefined when every asset is reachable.
167
+ */
168
+ export function firstUnavailableAssetSource(assets, cacheRoot) {
169
+ return assets.find(asset => !isFetchableAssetSource(asset.source) && !existsSync(join(cacheRoot, asset.digest)));
170
+ }
130
171
  /** The filesystem store acquisition needs, over node:fs. */
131
172
  function fsStore() {
132
173
  return {
@@ -175,6 +216,7 @@ export function createPreparedAssetRegistry(options) {
175
216
  // The content-addressed blob pool, shared across extensions (RES-03: two
176
217
  // owners share one set of bytes).
177
218
  return {
219
+ cacheDirectory: cacheRoot,
178
220
  plans() {
179
221
  return new Map([...held.entries()].map(([extensionId, preparation]) => [extensionId, preparation.plan]));
180
222
  },
@@ -215,6 +257,17 @@ export function createPreparedAssetRegistry(options) {
215
257
  return held.get(extensionId)?.groups ?? [];
216
258
  },
217
259
  async prepare(extensionId, plan, groups, options) {
260
+ /**
261
+ * A lock whose assets carry PROSE sources (no URL) has no transferable
262
+ * location; refuse BEFORE any acquisition, naming the asset, instead of
263
+ * surfacing a URL-parse error from deep inside the transport. Artifacts
264
+ * already materialized in the content-addressed cache are a legitimate
265
+ * source (a later acquisition still verifies their digest).
266
+ */
267
+ const unavailable = firstUnavailableAssetSource(groups.flatMap(group => group.assets.map(asset => ({ assetId: `${group.id}/${asset.id}`, source: asset.source, digest: asset.digest }))), cacheRoot);
268
+ if (unavailable !== undefined) {
269
+ return { ok: false, reason: assetSourceUnavailableReason(unavailable.assetId, unavailable.source) };
270
+ }
218
271
  if (!options.allowExecutable && plan.requiresExecutableApproval) {
219
272
  return {
220
273
  ok: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@try-works/dsh-model-as-tool",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
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",