@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 +29 -0
- package/lib/bindings.d.ts.map +1 -1
- package/lib/bindings.js +74 -0
- package/lib/contract-payload.d.ts +4 -12
- package/lib/contract-payload.d.ts.map +1 -1
- package/lib/contract-payload.js +20 -101
- package/lib/extension-dispatch.d.ts +33 -0
- package/lib/extension-dispatch.d.ts.map +1 -1
- package/lib/extension-dispatch.js +54 -0
- package/lib/extension-registrar.d.ts +16 -0
- package/lib/extension-registrar.d.ts.map +1 -1
- package/lib/extension-registrar.js +17 -7
- package/lib/extensions-service.d.ts +17 -1
- package/lib/extensions-service.d.ts.map +1 -1
- package/lib/extensions-service.js +128 -18
- package/lib/index.d.ts +8 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +154 -3
- package/lib/prepared-assets.d.ts +36 -0
- package/lib/prepared-assets.d.ts.map +1 -1
- package/lib/prepared-assets.js +53 -0
- package/package.json +1 -1
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
|
package/lib/bindings.d.ts.map
CHANGED
|
@@ -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
|
|
24
|
-
*
|
|
25
|
-
*
|
|
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
|
|
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;
|
|
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"}
|
package/lib/contract-payload.js
CHANGED
|
@@ -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
|
|
86
|
-
*
|
|
87
|
-
*
|
|
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
|
|
26
|
+
* @returns the native argument shape.
|
|
98
27
|
*/
|
|
99
28
|
export function toNativeArgs(contractId, contractArgs) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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;
|
|
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
|
-
//
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
|
|
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
|
-
|
|
99
|
-
|
|
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
|
|
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":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAKH,OAAO,EAQL,0BAA0B,EAC1B,KAAK,kBAAkB,EAEvB,KAAK,sBAAsB,EAG5B,MAAM,oCAAoC,CAAA;AAC3C,OAAO,KAAK,EACV,sBAAsB,EAGtB,sBAAsB,EAMtB,qBAAqB,EACrB,wBAAwB,EACxB,gBAAgB,EACjB,MAAM,qBAAqB,CAAA;AAY5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAE/D,OAAO,KAAK,
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
-
*
|
|
1325
|
-
*
|
|
1326
|
-
*
|
|
1327
|
-
*
|
|
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
|
-
#
|
|
1334
|
-
const
|
|
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
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
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.#
|
|
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
|
*
|
package/lib/index.d.ts.map
CHANGED
|
@@ -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
|
-
|
|
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)
|
package/lib/prepared-assets.d.ts
CHANGED
|
@@ -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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"}
|
package/lib/prepared-assets.js
CHANGED
|
@@ -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,
|