@try-works/dsh-model-as-tool 0.1.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/dsh-tool-mode-credentials.mjs +20 -0
- package/bin/dsh-tool-mode.mjs +202 -0
- package/catalog/desert-ant-models.json +693 -693
- package/client/client.model-tools.js +614 -0
- package/client/index.js +1717 -0
- package/lib/adapters/index.d.ts.map +1 -1
- package/lib/adapters/index.js +4 -4
- package/lib/bindings.d.ts.map +1 -1
- package/lib/bindings.js +26 -25
- package/lib/capability.d.ts.map +1 -1
- package/lib/capability.js +17 -0
- package/lib/capture-path.d.ts +97 -0
- package/lib/capture-path.d.ts.map +1 -0
- package/lib/capture-path.js +152 -0
- package/lib/diagnostics.d.ts +166 -0
- package/lib/diagnostics.d.ts.map +1 -0
- package/lib/diagnostics.js +135 -0
- package/lib/extension-dependencies.d.ts +325 -0
- package/lib/extension-dependencies.d.ts.map +1 -0
- package/lib/extension-dependencies.js +858 -0
- package/lib/extension-dispatch.d.ts +117 -0
- package/lib/extension-dispatch.d.ts.map +1 -0
- package/lib/extension-dispatch.js +124 -0
- package/lib/extension-registrar.d.ts +100 -0
- package/lib/extension-registrar.d.ts.map +1 -0
- package/lib/extension-registrar.js +134 -0
- package/lib/extensions-api.d.ts +221 -0
- package/lib/extensions-api.d.ts.map +1 -0
- package/lib/extensions-api.js +17 -0
- package/lib/extensions-remote.d.ts +54 -0
- package/lib/extensions-remote.d.ts.map +1 -0
- package/lib/extensions-remote.js +66 -0
- package/lib/extensions-service.d.ts +367 -0
- package/lib/extensions-service.d.ts.map +1 -0
- package/lib/extensions-service.js +1527 -0
- package/lib/harness-llm.d.ts +138 -0
- package/lib/harness-llm.d.ts.map +1 -0
- package/lib/harness-llm.js +218 -0
- package/lib/harness-serving.d.ts +95 -0
- package/lib/harness-serving.d.ts.map +1 -0
- package/lib/harness-serving.js +157 -0
- package/lib/headless.d.ts +97 -0
- package/lib/headless.d.ts.map +1 -0
- package/lib/headless.js +349 -0
- package/lib/http-acquisition.d.ts +27 -0
- package/lib/http-acquisition.d.ts.map +1 -0
- package/lib/http-acquisition.js +136 -0
- package/lib/index.d.ts +271 -7
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2644 -70
- package/lib/invocation-accounting.d.ts +169 -0
- package/lib/invocation-accounting.d.ts.map +1 -0
- package/lib/invocation-accounting.js +148 -0
- package/lib/legacy-migration.d.ts +95 -0
- package/lib/legacy-migration.d.ts.map +1 -0
- package/lib/legacy-migration.js +429 -0
- package/lib/managed-workers.d.ts +151 -0
- package/lib/managed-workers.d.ts.map +1 -0
- package/lib/managed-workers.js +249 -0
- package/lib/mcp/client-grant.d.ts +74 -0
- package/lib/mcp/client-grant.d.ts.map +1 -0
- package/lib/mcp/client-grant.js +60 -0
- package/lib/mcp/credential-cli.d.ts +38 -0
- package/lib/mcp/credential-cli.d.ts.map +1 -0
- package/lib/mcp/credential-cli.js +148 -0
- package/lib/mcp/credential-store.d.ts +143 -0
- package/lib/mcp/credential-store.d.ts.map +1 -0
- package/lib/mcp/credential-store.js +454 -0
- package/lib/mcp/host-binding.d.ts +25 -0
- package/lib/mcp/host-binding.d.ts.map +1 -1
- package/lib/mcp/host-binding.js +107 -14
- package/lib/mcp/http.d.ts +68 -18
- package/lib/mcp/http.d.ts.map +1 -1
- package/lib/mcp/http.js +390 -62
- package/lib/mcp/oauth.d.ts +149 -0
- package/lib/mcp/oauth.d.ts.map +1 -0
- package/lib/mcp/oauth.js +396 -0
- package/lib/mcp/protocol.d.ts +46 -7
- package/lib/mcp/protocol.d.ts.map +1 -1
- package/lib/mcp/protocol.js +63 -16
- package/lib/mcp/rate-limit.d.ts +68 -0
- package/lib/mcp/rate-limit.d.ts.map +1 -0
- package/lib/mcp/rate-limit.js +114 -0
- package/lib/mcp/sdk-v2.d.ts +17 -0
- package/lib/mcp/sdk-v2.d.ts.map +1 -0
- package/lib/mcp/sdk-v2.js +181 -0
- package/lib/mcp/server.d.ts +11 -1
- package/lib/mcp/server.d.ts.map +1 -1
- package/lib/mcp/server.js +80 -13
- package/lib/mcp/stdio.d.ts.map +1 -1
- package/lib/mcp/stdio.js +9 -1
- package/lib/mcp/subscriptions.d.ts +43 -1
- package/lib/mcp/subscriptions.d.ts.map +1 -1
- package/lib/mcp/subscriptions.js +90 -9
- package/lib/model-qualification.d.ts +192 -0
- package/lib/model-qualification.d.ts.map +1 -0
- package/lib/model-qualification.js +178 -0
- package/lib/planning.d.ts +246 -0
- package/lib/planning.d.ts.map +1 -0
- package/lib/planning.js +457 -0
- package/lib/prepared-assets.d.ts +178 -0
- package/lib/prepared-assets.d.ts.map +1 -0
- package/lib/prepared-assets.js +286 -0
- package/lib/provider-bridge.d.ts +37 -0
- package/lib/provider-bridge.d.ts.map +1 -1
- package/lib/provider-bridge.js +189 -12
- package/lib/ptc-authority.d.ts +140 -0
- package/lib/ptc-authority.d.ts.map +1 -0
- package/lib/ptc-authority.js +216 -0
- package/lib/ptc-runtime.d.ts +156 -0
- package/lib/ptc-runtime.d.ts.map +1 -0
- package/lib/ptc-runtime.js +191 -0
- package/lib/publication.d.ts +2 -1
- package/lib/publication.d.ts.map +1 -1
- package/lib/publication.js +13 -5
- package/lib/receipt.d.ts.map +1 -1
- package/lib/receipt.js +8 -0
- package/lib/title-proposal.d.ts +194 -0
- package/lib/title-proposal.d.ts.map +1 -0
- package/lib/title-proposal.js +244 -0
- package/lib/tool-mode-run.d.ts +235 -0
- package/lib/tool-mode-run.d.ts.map +1 -0
- package/lib/tool-mode-run.js +283 -0
- package/lib/types.d.ts +3 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/update-surface.d.ts +79 -0
- package/lib/update-surface.d.ts.map +1 -0
- package/lib/update-surface.js +224 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts +38 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/standard.js +445 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts +14 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-embed.js +63 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts +14 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/contracts/text-rerank.js +76 -0
- package/node_modules/@try-works/tool-mode-contracts/lib/dsh.d.ts.map +1 -1
- package/node_modules/@try-works/tool-mode-contracts/lib/dsh.js +69 -55
- package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts +4 -1
- package/node_modules/@try-works/tool-mode-contracts/lib/index.d.ts.map +1 -1
- package/node_modules/@try-works/tool-mode-contracts/lib/index.js +26 -2
- package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts +28 -2
- package/node_modules/@try-works/tool-mode-contracts/lib/registry.d.ts.map +1 -1
- package/node_modules/@try-works/tool-mode-contracts/lib/registry.js +93 -10
- package/node_modules/@try-works/tool-mode-contracts/package.json +0 -1
- package/node_modules/@try-works/tool-mode-extension-sdk/bin/dsh-tool-mode.mjs +20 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts +80 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/cli.js +533 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts +83 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/declarative-recipes.js +125 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts +70 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/discovery.js +201 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts +57 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/errors.js +83 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts +32 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/index.js +32 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts +86 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/archive.js +191 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts +126 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/dependencies.js +297 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts +216 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/lifecycle.js +800 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts +210 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/migration.js +368 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts +63 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/runtime-link.js +149 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts +35 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/source-directory.js +179 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts +179 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/staged.js +235 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts +367 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/store.js +807 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.d.ts +44 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/tar-gzip-source.js +243 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts +185 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/update-flow.js +504 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts +17 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/install/zip-source.js +80 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts +52 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/load.js +102 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts +171 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/manifest.js +271 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts +242 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/runtime.js +58 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts +118 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/state.js +113 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts +2 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker/worker-child.js +351 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts +150 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/lib/worker.js +670 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/package.json +53 -0
- package/node_modules/@try-works/tool-mode-extension-sdk/schema/extension-manifest-1.1.0.schema.json +253 -0
- package/node_modules/@try-works/tool-mode-recipes/bin/tool-mode-recipe.mjs +15 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts +427 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/broker.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/broker.js +592 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts +60 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/cli.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/cli.js +936 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts +237 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/dsh-adapter.js +200 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts +85 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/fixture-provider.js +176 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts +105 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/images.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/images.js +129 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts +25 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/index.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/index.js +25 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts +325 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/recipe-format.js +1310 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts +51 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/templates.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/templates.js +310 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts +227 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/titles.d.ts.map +1 -0
- package/node_modules/@try-works/tool-mode-recipes/lib/titles.js +407 -0
- package/node_modules/@try-works/tool-mode-recipes/package.json +56 -0
- package/node_modules/@try-works/tool-mode-recipes/recipes/describe-image.json +38 -0
- package/node_modules/@try-works/tool-mode-recipes/recipes/text-title.json +45 -0
- package/node_modules/@try-works/tool-mode-recipes/schema/harness-model-recipe.schema.json +273 -0
- package/package.json +43 -15
- package/remote/spec.mjs +462 -0
- package/remote/typert.host.mjs +14 -0
- package/remote/typert.remote-client.mjs +16 -0
- package/lib/adapters/tongue.d.ts +0 -31
- package/lib/adapters/tongue.d.ts.map +0 -1
- package/lib/adapters/tongue.js +0 -93
- package/lib/adapters/voz.d.ts +0 -28
- package/lib/adapters/voz.d.ts.map +0 -1
- package/lib/adapters/voz.js +0 -102
- /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.d.ts +0 -0
- /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.d.ts.map +0 -0
- /package/{lib → node_modules/@try-works/tool-mode-extension-sdk/lib}/licensing.js +0 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The HOST-side injection seam for the DSH-backed harness provider (HLM-01/02/03).
|
|
3
|
+
*
|
|
4
|
+
* The recipes package ships {@link DshLlmProvider} — a REAL `LlmProvider` over the DSH
|
|
5
|
+
* harness's own LLM surface (`ctx.llm`), with capabilities read from the model's own
|
|
6
|
+
* descriptor and images transported through a deployment-supplied hook. What the host
|
|
7
|
+
* adds here is the COMPOSITION, and it is deliberately narrow:
|
|
8
|
+
*
|
|
9
|
+
* - the surface is reached STRUCTURALLY, so the host never imports the DSH packages at
|
|
10
|
+
* this boundary (they are the deployment's peers, and this module reads exactly the
|
|
11
|
+
* two members the adapter consumes);
|
|
12
|
+
* - the image transport is minted ONLY when the deployment can actually reach the DSH
|
|
13
|
+
* attachment service (`ctx.attachments.saveImage`): without it the provider is built
|
|
14
|
+
* WITHOUT the hook, so an image-capable model honestly reports `images: 'unknown'`
|
|
15
|
+
* and the broker refuses image recipes with EXECUTOR_CAPABILITY_UNKNOWN — never a
|
|
16
|
+
* silent drop (HLM-11);
|
|
17
|
+
* - every failure fails CLOSED: an unreachable surface, a descriptor that cannot be
|
|
18
|
+
* resolved, or a descriptor naming another route yields `undefined` plus a diagnostic,
|
|
19
|
+
* so the deployment runs as if the option were absent rather than half-wired.
|
|
20
|
+
*
|
|
21
|
+
* @module @try-works/dsh-model-as-tool/harness-llm
|
|
22
|
+
*/
|
|
23
|
+
import { type LlmProvider } from '@try-works/tool-mode-recipes';
|
|
24
|
+
/** The opt-in configuration naming one DSH provider route and model. */
|
|
25
|
+
export interface HarnessModelConfig {
|
|
26
|
+
/** The registered adapter route, e.g. `deepseek`. */
|
|
27
|
+
readonly provider: string;
|
|
28
|
+
/** The exact model id, e.g. `deepseek-chat`. */
|
|
29
|
+
readonly model: string;
|
|
30
|
+
}
|
|
31
|
+
/** One discovered default route/model (the AUTO step's product). */
|
|
32
|
+
export interface HarnessModelDiscovery {
|
|
33
|
+
readonly provider: string;
|
|
34
|
+
readonly model: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Discover the deployment's default/selected model for the AUTO composition
|
|
38
|
+
* (task-93 + task-97). DEFAULT-SAFE: any ambiguity or malformed entry yields
|
|
39
|
+
* `undefined` — never a guessed route.
|
|
40
|
+
*
|
|
41
|
+
* Probes, in order:
|
|
42
|
+
* 1. the settings service's `describe()` descriptor list: the descriptor whose
|
|
43
|
+
* `ns` is `agent-default-model` (the live web profile's settings namespace),
|
|
44
|
+
* with the resolved `{provider, model}` read from its `value` — the actual
|
|
45
|
+
* SettingsForms API (there is no synchronous `get(ns)`, which was live bug
|
|
46
|
+
* #2);
|
|
47
|
+
* 2. the root config's `model.default` as the `provider/model` string.
|
|
48
|
+
* @param ctx - the surfaces to probe, read structurally.
|
|
49
|
+
* @returns the discovered route/model, or undefined when none is unambiguous.
|
|
50
|
+
*/
|
|
51
|
+
export declare function discoverDefaultHarnessModel(ctx: {
|
|
52
|
+
readonly settings?: unknown;
|
|
53
|
+
readonly config?: {
|
|
54
|
+
readonly model?: {
|
|
55
|
+
readonly default?: unknown;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
}): HarnessModelDiscovery | undefined;
|
|
59
|
+
/** The attachment-minting surface `ctx.attachments` satisfies structurally. */
|
|
60
|
+
interface DshAttachmentsSurface {
|
|
61
|
+
saveImage(input: {
|
|
62
|
+
readonly data: Uint8Array;
|
|
63
|
+
readonly mediaType: string;
|
|
64
|
+
}): Promise<unknown>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The LlmRuntime contract the AUTO composition resolves through (read from
|
|
68
|
+
* D:\deepseek-harness\packages\llm\llm\lib\types\index.d.ts):
|
|
69
|
+
* - `resolveModelInfo(provider, model)` keys on the REGISTERED ROUTE id
|
|
70
|
+
* (LlmRuntime.resolveModelInfo → registration(provider) → the adapter),
|
|
71
|
+
* - `listProviders(): LlmProviderInfo[]` (sync) — the registered routes,
|
|
72
|
+
* - `listConfigurableProviders(): LlmConfigurableProvider[]` (sync) — the
|
|
73
|
+
* directory mapping a settings namespace to the route it activates
|
|
74
|
+
* (`{provider, displayName, settingsNs, settingsPath}`),
|
|
75
|
+
* - `listModels(provider): Promise<LlmModelInfo[]>` — the per-route catalog.
|
|
76
|
+
*/
|
|
77
|
+
export interface HarnessLlmRuntimeSurface {
|
|
78
|
+
resolveModelInfo(provider: string, model: string, signal?: AbortSignal): Promise<unknown>;
|
|
79
|
+
listProviders?(): readonly {
|
|
80
|
+
id: string;
|
|
81
|
+
name: string;
|
|
82
|
+
}[];
|
|
83
|
+
listConfigurableProviders?(): readonly {
|
|
84
|
+
provider: string;
|
|
85
|
+
displayName: string;
|
|
86
|
+
settingsNs?: string;
|
|
87
|
+
settingsPath?: readonly string[];
|
|
88
|
+
}[];
|
|
89
|
+
listModels?(provider: string): Promise<readonly {
|
|
90
|
+
provider?: string;
|
|
91
|
+
id: string;
|
|
92
|
+
name: string;
|
|
93
|
+
}[]>;
|
|
94
|
+
}
|
|
95
|
+
/** One resolution outcome (task-98): the runnable pair, or the exact refusal. */
|
|
96
|
+
export type HarnessModelResolution = {
|
|
97
|
+
readonly ok: true;
|
|
98
|
+
readonly route: string;
|
|
99
|
+
readonly model: string;
|
|
100
|
+
} | {
|
|
101
|
+
readonly ok: false;
|
|
102
|
+
readonly kind: 'not-ready-yet' | 'not-configured';
|
|
103
|
+
readonly reason: string;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Resolve a RUNNABLE (route, model) pair the way the runtime does (task-98):
|
|
107
|
+
* the configured provider may be a settings namespace or display name rather
|
|
108
|
+
* than the registered ROUTE id, so a direct resolveModelInfo failure is not
|
|
109
|
+
* 'not configured' — the runtime's own listings map the configured provider to
|
|
110
|
+
* its route and confirm the model through the route's catalog. An EMPTY route
|
|
111
|
+
* registry is 'not ready yet' (the adapter plugins register after this plugin
|
|
112
|
+
* in the composition order), which is retryable — never locked in as 'none'.
|
|
113
|
+
* @param llm - the LLM surface, read structurally (the listings are optional).
|
|
114
|
+
* @param desired - the configured provider/model (the agent-default-model pair).
|
|
115
|
+
* @param log - the diagnostic sink.
|
|
116
|
+
* @returns the runnable pair, or the exact not-ready-yet/not-configured reason.
|
|
117
|
+
*/
|
|
118
|
+
export declare function resolveRunnableHarnessModel(llm: HarnessLlmRuntimeSurface, desired: {
|
|
119
|
+
readonly provider: string;
|
|
120
|
+
readonly model: string;
|
|
121
|
+
}, log?: (message: string) => void): Promise<HarnessModelResolution>;
|
|
122
|
+
/**
|
|
123
|
+
* Build the DSH-backed harness provider for one opt-in route/model.
|
|
124
|
+
*
|
|
125
|
+
* DEFAULT OFF: this runs only when the operator set {@link HarnessModelConfig}, and it
|
|
126
|
+
* returns `undefined` (with a diagnostic) whenever the DSH surface cannot actually
|
|
127
|
+
* serve the named model.
|
|
128
|
+
* @param ctx - the host context, read structurally.
|
|
129
|
+
* @param config - the operator's provider/model selection.
|
|
130
|
+
* @param log - a diagnostic sink for the fail-closed reasons.
|
|
131
|
+
* @returns the provider, or undefined when the deployment cannot build one.
|
|
132
|
+
*/
|
|
133
|
+
export declare function buildHarnessLlmProvider(ctx: {
|
|
134
|
+
readonly llm?: unknown;
|
|
135
|
+
readonly attachments?: DshAttachmentsSurface;
|
|
136
|
+
}, config: HarnessModelConfig, log?: (message: string) => void): Promise<LlmProvider | undefined>;
|
|
137
|
+
export {};
|
|
138
|
+
//# sourceMappingURL=harness-llm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-llm.d.ts","sourceRoot":"","sources":["../src/harness-llm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAA8D,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAE3H,wEAAwE;AACxE,MAAM,WAAW,kBAAkB;IACjC,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,gDAAgD;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,oEAAoE;AACpE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE;IAC/C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE;YAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE,CAAA;CACtE,GAAG,qBAAqB,GAAG,SAAS,CAiCpC;AAED,+EAA+E;AAC/E,UAAU,qBAAqB;IAC7B,SAAS,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC9F;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,wBAAwB;IACvC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACzF,aAAa,CAAC,IAAI,SAAS;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzD,yBAAyB,CAAC,IAAI,SAAS;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,EAAE,CAAA;IACzI,UAAU,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAAA;CACnG;AAED,iFAAiF;AACjF,MAAM,MAAM,sBAAsB,GAC9B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,gBAAgB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtG;;;;;;;;;;;;GAYG;AACH,wBAAsB,2BAA2B,CAC/C,GAAG,EAAE,wBAAwB,EAC7B,OAAO,EAAE;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAC9D,GAAG,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,GACxC,OAAO,CAAC,sBAAsB,CAAC,CAwFjC;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,qBAAqB,CAAA;CAC7C,EACD,MAAM,EAAE,kBAAkB,EAC1B,GAAG,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,GACxC,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAiClC"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The HOST-side injection seam for the DSH-backed harness provider (HLM-01/02/03).
|
|
3
|
+
*
|
|
4
|
+
* The recipes package ships {@link DshLlmProvider} — a REAL `LlmProvider` over the DSH
|
|
5
|
+
* harness's own LLM surface (`ctx.llm`), with capabilities read from the model's own
|
|
6
|
+
* descriptor and images transported through a deployment-supplied hook. What the host
|
|
7
|
+
* adds here is the COMPOSITION, and it is deliberately narrow:
|
|
8
|
+
*
|
|
9
|
+
* - the surface is reached STRUCTURALLY, so the host never imports the DSH packages at
|
|
10
|
+
* this boundary (they are the deployment's peers, and this module reads exactly the
|
|
11
|
+
* two members the adapter consumes);
|
|
12
|
+
* - the image transport is minted ONLY when the deployment can actually reach the DSH
|
|
13
|
+
* attachment service (`ctx.attachments.saveImage`): without it the provider is built
|
|
14
|
+
* WITHOUT the hook, so an image-capable model honestly reports `images: 'unknown'`
|
|
15
|
+
* and the broker refuses image recipes with EXECUTOR_CAPABILITY_UNKNOWN — never a
|
|
16
|
+
* silent drop (HLM-11);
|
|
17
|
+
* - every failure fails CLOSED: an unreachable surface, a descriptor that cannot be
|
|
18
|
+
* resolved, or a descriptor naming another route yields `undefined` plus a diagnostic,
|
|
19
|
+
* so the deployment runs as if the option were absent rather than half-wired.
|
|
20
|
+
*
|
|
21
|
+
* @module @try-works/dsh-model-as-tool/harness-llm
|
|
22
|
+
*/
|
|
23
|
+
import { DshLlmProvider } from '@try-works/tool-mode-recipes';
|
|
24
|
+
/**
|
|
25
|
+
* Discover the deployment's default/selected model for the AUTO composition
|
|
26
|
+
* (task-93 + task-97). DEFAULT-SAFE: any ambiguity or malformed entry yields
|
|
27
|
+
* `undefined` — never a guessed route.
|
|
28
|
+
*
|
|
29
|
+
* Probes, in order:
|
|
30
|
+
* 1. the settings service's `describe()` descriptor list: the descriptor whose
|
|
31
|
+
* `ns` is `agent-default-model` (the live web profile's settings namespace),
|
|
32
|
+
* with the resolved `{provider, model}` read from its `value` — the actual
|
|
33
|
+
* SettingsForms API (there is no synchronous `get(ns)`, which was live bug
|
|
34
|
+
* #2);
|
|
35
|
+
* 2. the root config's `model.default` as the `provider/model` string.
|
|
36
|
+
* @param ctx - the surfaces to probe, read structurally.
|
|
37
|
+
* @returns the discovered route/model, or undefined when none is unambiguous.
|
|
38
|
+
*/
|
|
39
|
+
export function discoverDefaultHarnessModel(ctx) {
|
|
40
|
+
// 1. The agent-default-model settings descriptor (what the Web composer
|
|
41
|
+
// writes into the profile patch; its ns is 'agent-default-model').
|
|
42
|
+
const settings = ctx.settings;
|
|
43
|
+
const described = settings?.describe?.();
|
|
44
|
+
if (Array.isArray(described)) {
|
|
45
|
+
for (const descriptor of described) {
|
|
46
|
+
if (descriptor === null || typeof descriptor !== 'object')
|
|
47
|
+
continue;
|
|
48
|
+
const entry = descriptor;
|
|
49
|
+
if (entry.ns !== 'agent-default-model')
|
|
50
|
+
continue;
|
|
51
|
+
const value = entry.value;
|
|
52
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
53
|
+
const resolved = value;
|
|
54
|
+
const provider = resolved['provider'];
|
|
55
|
+
const model = resolved['model'];
|
|
56
|
+
if (typeof provider === 'string' && provider.length > 0 && typeof model === 'string' && model.length > 0) {
|
|
57
|
+
return { provider, model };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// The matching descriptor carries no unambiguous pair: refuse rather
|
|
61
|
+
// than continue probing a malformed entry.
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// 2. The root config's model.default, the `provider/model` string.
|
|
66
|
+
const declared = ctx.config?.model?.default;
|
|
67
|
+
if (typeof declared === 'string') {
|
|
68
|
+
const slash = declared.indexOf('/');
|
|
69
|
+
if (slash > 0 && slash < declared.length - 1) {
|
|
70
|
+
return { provider: declared.slice(0, slash), model: declared.slice(slash + 1) };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Resolve a RUNNABLE (route, model) pair the way the runtime does (task-98):
|
|
77
|
+
* the configured provider may be a settings namespace or display name rather
|
|
78
|
+
* than the registered ROUTE id, so a direct resolveModelInfo failure is not
|
|
79
|
+
* 'not configured' — the runtime's own listings map the configured provider to
|
|
80
|
+
* its route and confirm the model through the route's catalog. An EMPTY route
|
|
81
|
+
* registry is 'not ready yet' (the adapter plugins register after this plugin
|
|
82
|
+
* in the composition order), which is retryable — never locked in as 'none'.
|
|
83
|
+
* @param llm - the LLM surface, read structurally (the listings are optional).
|
|
84
|
+
* @param desired - the configured provider/model (the agent-default-model pair).
|
|
85
|
+
* @param log - the diagnostic sink.
|
|
86
|
+
* @returns the runnable pair, or the exact not-ready-yet/not-configured reason.
|
|
87
|
+
*/
|
|
88
|
+
export async function resolveRunnableHarnessModel(llm, desired, log = () => { }) {
|
|
89
|
+
// 1. The direct pair: the config's provider IS the route.
|
|
90
|
+
try {
|
|
91
|
+
await llm.resolveModelInfo(desired.provider, desired.model);
|
|
92
|
+
return { ok: true, route: desired.provider, model: desired.model };
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
log(`direct ${desired.provider}/${desired.model} does not resolve: ${error instanceof Error ? error.message : String(error)}`);
|
|
96
|
+
}
|
|
97
|
+
// 2. Map the configured provider to a registered route.
|
|
98
|
+
const providers = llm.listProviders?.() ?? [];
|
|
99
|
+
if (providers.length === 0) {
|
|
100
|
+
return {
|
|
101
|
+
ok: false,
|
|
102
|
+
kind: 'not-ready-yet',
|
|
103
|
+
reason: 'the deployment\'s LLM surface has not registered its provider routes yet; retry once the deployment '
|
|
104
|
+
+ 'finishes starting (this is not a configuration error)',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const byId = providers.find(entry => entry.id === desired.provider);
|
|
108
|
+
const byName = providers.find(entry => entry.name === desired.provider);
|
|
109
|
+
let route = byId?.id ?? byName?.id;
|
|
110
|
+
const directory = llm.listConfigurableProviders?.() ?? [];
|
|
111
|
+
if (route === undefined) {
|
|
112
|
+
const entry = directory.find(candidate => (candidate.provider === desired.provider
|
|
113
|
+
|| candidate.settingsNs === desired.provider
|
|
114
|
+
|| candidate.displayName === desired.provider));
|
|
115
|
+
route = entry?.provider;
|
|
116
|
+
}
|
|
117
|
+
if (route === undefined) {
|
|
118
|
+
/**
|
|
119
|
+
* TASK-100: an EMPTY configurable-provider directory means the runtime is
|
|
120
|
+
* still registering — the adapter routes appear FIRST and the directory
|
|
121
|
+
* entries land after, so a provider the directory cannot map yet is
|
|
122
|
+
* not-ready-yet, never a terminal not-configured (the live 0.3.4
|
|
123
|
+
* regression finalized exactly this too early). The retry keeps polling.
|
|
124
|
+
*/
|
|
125
|
+
if (directory.length === 0) {
|
|
126
|
+
return {
|
|
127
|
+
ok: false,
|
|
128
|
+
kind: 'not-ready-yet',
|
|
129
|
+
reason: 'the deployment\'s LLM surface has not registered its provider routes yet; retry once the deployment '
|
|
130
|
+
+ 'finishes starting (this is not a configuration error)',
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
kind: 'not-configured',
|
|
136
|
+
reason: `the configured provider ${JSON.stringify(desired.provider)} is not a registered LLM route in this `
|
|
137
|
+
+ 'deployment; set config.harnessModel to a runnable route',
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// 3. Confirm the model through the route's own catalog, then a direct probe.
|
|
141
|
+
if (llm.listModels !== undefined) {
|
|
142
|
+
try {
|
|
143
|
+
const catalog = await llm.listModels(route);
|
|
144
|
+
if (catalog.some(entry => entry.id === desired.model)) {
|
|
145
|
+
return { ok: true, route, model: desired.model };
|
|
146
|
+
}
|
|
147
|
+
if (catalog.length > 0) {
|
|
148
|
+
return {
|
|
149
|
+
ok: false,
|
|
150
|
+
kind: 'not-configured',
|
|
151
|
+
reason: `the model ${JSON.stringify(desired.model)} is not served by the ${route} route (its catalog lists `
|
|
152
|
+
+ `${catalog.map(entry => entry.id).join(', ')}); set config.harnessModel to a served model`,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
log(`the ${route} catalog could not be listed: ${error instanceof Error ? error.message : String(error)}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
await llm.resolveModelInfo(route, desired.model);
|
|
162
|
+
return { ok: true, route, model: desired.model };
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return {
|
|
166
|
+
ok: false,
|
|
167
|
+
kind: 'not-configured',
|
|
168
|
+
reason: `the ${route} route does not serve the model ${JSON.stringify(desired.model)}; set config.harnessModel `
|
|
169
|
+
+ 'to a served model',
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Build the DSH-backed harness provider for one opt-in route/model.
|
|
175
|
+
*
|
|
176
|
+
* DEFAULT OFF: this runs only when the operator set {@link HarnessModelConfig}, and it
|
|
177
|
+
* returns `undefined` (with a diagnostic) whenever the DSH surface cannot actually
|
|
178
|
+
* serve the named model.
|
|
179
|
+
* @param ctx - the host context, read structurally.
|
|
180
|
+
* @param config - the operator's provider/model selection.
|
|
181
|
+
* @param log - a diagnostic sink for the fail-closed reasons.
|
|
182
|
+
* @returns the provider, or undefined when the deployment cannot build one.
|
|
183
|
+
*/
|
|
184
|
+
export async function buildHarnessLlmProvider(ctx, config, log = () => { }) {
|
|
185
|
+
if (ctx.llm === undefined) {
|
|
186
|
+
log('the DSH LLM surface is not mounted in this deployment, so the harness provider is not wired');
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
// HLM-11: the image transport exists only when the attachment service does. Without
|
|
190
|
+
// it the adapter reports images 'unknown' and the broker refuses rather than drops.
|
|
191
|
+
const attachments = ctx.attachments;
|
|
192
|
+
let images;
|
|
193
|
+
if (attachments !== undefined) {
|
|
194
|
+
images = async (image) => ({
|
|
195
|
+
type: 'image',
|
|
196
|
+
attachment: await attachments.saveImage({ data: image.bytes, mediaType: image.mediaType }),
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
log('the DSH attachment service is not mounted, so image recipes will refuse with EXECUTOR_CAPABILITY_UNKNOWN');
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
return await DshLlmProvider.create({
|
|
204
|
+
llm: ctx.llm,
|
|
205
|
+
provider: config.provider,
|
|
206
|
+
model: config.model,
|
|
207
|
+
...images === undefined ? {} : { images },
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
// Fail closed: a descriptor that cannot be resolved (route not registered) or one
|
|
212
|
+
// naming another model leaves the deployment as if the option were absent.
|
|
213
|
+
log(`could not build the harness provider for ${config.provider}/${config.model}: `
|
|
214
|
+
+ `${error instanceof Error ? error.message : String(error)}`);
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=harness-llm.js.map
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serving a declarative package's recipes through a deployment-supplied harness provider.
|
|
3
|
+
*
|
|
4
|
+
* THE LAST LINK OF SLICE 3, and the reason it is a module rather than a few lines in the host:
|
|
5
|
+
* this is where a resolved RECIPE becomes a callable TOOL, and the pieces have to be joined in a
|
|
6
|
+
* specific order for the authorization to mean anything.
|
|
7
|
+
*
|
|
8
|
+
* WHAT THIS DELIBERATELY IS NOT. It does not construct an `LlmProvider`. Which model answers a
|
|
9
|
+
* harness call is a deployment's business, and this plugin holds no model-specific code — that
|
|
10
|
+
* is an architectural rule the repository enforces with a gate. Instead a deployment SUPPLIES a
|
|
11
|
+
* provider and this module does the joining: authorize the recipe's tool name, run through the
|
|
12
|
+
* broker, and refuse honestly when no provider was supplied.
|
|
13
|
+
*
|
|
14
|
+
* WHY THE REFUSAL IS STILL THE DEFAULT. A declarative package resolves and its recipes parse,
|
|
15
|
+
* and without a provider nothing can call a model. Serving the tool anyway would present a tool
|
|
16
|
+
* that fails at invocation, so the refusal happens at RESOLUTION — where a reader can see why —
|
|
17
|
+
* rather than at the first call.
|
|
18
|
+
*
|
|
19
|
+
* @module @try-works/dsh-model-as-tool/harness-serving
|
|
20
|
+
*/
|
|
21
|
+
import { type BrokerRecord, type LlmProvider } from '@try-works/tool-mode-recipes';
|
|
22
|
+
/** A deployment's harness composition. */
|
|
23
|
+
export interface HarnessComposition {
|
|
24
|
+
/**
|
|
25
|
+
* The provider that answers harness calls, supplied by the DEPLOYMENT.
|
|
26
|
+
*
|
|
27
|
+
* Absent when a deployment composes none — which is the state this plugin ships in, and the
|
|
28
|
+
* state the refusal exists for.
|
|
29
|
+
*/
|
|
30
|
+
readonly provider?: LlmProvider;
|
|
31
|
+
/**
|
|
32
|
+
* Where invocation records go.
|
|
33
|
+
*
|
|
34
|
+
* The broker REFUSES TO CONSTRUCT without one, because a broker that records nothing cannot be
|
|
35
|
+
* audited. Making it required here means a caller cannot compose a harness path that silently
|
|
36
|
+
* reports nothing — the failure is at construction rather than at audit time.
|
|
37
|
+
*/
|
|
38
|
+
readonly journal: (record: BrokerRecord) => void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A harness call the caller CANCELLED.
|
|
42
|
+
*
|
|
43
|
+
* Distinct from `HarnessFailedError` on purpose: a caller who walked away is not a malfunction,
|
|
44
|
+
* and conflating the two makes every cancellation look like a fault. The same discipline the
|
|
45
|
+
* invocation accounting applies to `cancelled`.
|
|
46
|
+
*/
|
|
47
|
+
export declare class HarnessCancelledError extends Error {
|
|
48
|
+
readonly toolName: string;
|
|
49
|
+
readonly reason: string;
|
|
50
|
+
readonly name = "HarnessCancelledError";
|
|
51
|
+
constructor(toolName: string, reason: string);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A harness call that FAILED, carrying the broker's machine-readable code.
|
|
55
|
+
*
|
|
56
|
+
* The code is preserved rather than flattened into a message, so a caller branches on the CAUSE
|
|
57
|
+
* instead of matching prose.
|
|
58
|
+
*/
|
|
59
|
+
export declare class HarnessFailedError extends Error {
|
|
60
|
+
readonly toolName: string;
|
|
61
|
+
readonly code: string;
|
|
62
|
+
readonly reason: string;
|
|
63
|
+
readonly name = "HarnessFailedError";
|
|
64
|
+
constructor(toolName: string, code: string, reason: string);
|
|
65
|
+
}
|
|
66
|
+
/** A recipe made callable. */
|
|
67
|
+
export interface ServedRecipe {
|
|
68
|
+
readonly implementationId: string;
|
|
69
|
+
readonly contractId: string;
|
|
70
|
+
readonly toolName: string;
|
|
71
|
+
/** Run the recipe. Throws with the broker's own reason when it cannot. */
|
|
72
|
+
readonly invoke: (args: Record<string, unknown>, signal?: AbortSignal) => Promise<unknown>;
|
|
73
|
+
}
|
|
74
|
+
/** The outcome of preparing a declarative package's recipes. */
|
|
75
|
+
export type ServeOutcome = {
|
|
76
|
+
readonly ok: true;
|
|
77
|
+
readonly served: readonly ServedRecipe[];
|
|
78
|
+
} | {
|
|
79
|
+
readonly ok: false;
|
|
80
|
+
readonly code: 'no-provider' | 'recipe-rejected';
|
|
81
|
+
readonly detail: string;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Prepare a declarative package's resolved recipes for serving.
|
|
85
|
+
*
|
|
86
|
+
* @param composition - the deployment's harness composition.
|
|
87
|
+
* @param resolved - the recipes resolved through the convention.
|
|
88
|
+
* @returns the served recipes, or the reason none can be served.
|
|
89
|
+
*/
|
|
90
|
+
export declare function prepareDeclarative(composition: HarnessComposition, resolved: readonly {
|
|
91
|
+
readonly id: string;
|
|
92
|
+
readonly contractId: string;
|
|
93
|
+
readonly recipe: unknown;
|
|
94
|
+
}[]): ServeOutcome;
|
|
95
|
+
//# sourceMappingURL=harness-serving.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-serving.d.ts","sourceRoot":"","sources":["../src/harness-serving.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,WAAW,EAEjB,MAAM,8BAA8B,CAAA;AAErC,0CAA0C;AAC1C,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAA;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAA;CACjD;AAED;;;;;;GAMG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAElC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM;IAD9D,SAAkB,IAAI,2BAA0B;gBAC3B,QAAQ,EAAE,MAAM,EAAW,MAAM,EAAE,MAAM;CAG/D;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAE/B,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM;IADrF,SAAkB,IAAI,wBAAuB;gBACxB,QAAQ,EAAE,MAAM,EAAW,IAAI,EAAE,MAAM,EAAW,MAAM,EAAE,MAAM;CAGtF;AAED,8BAA8B;AAC9B,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAC3F;AAED,gEAAgE;AAChE,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,iBAAiB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAErG;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,kBAAkB,EAC/B,QAAQ,EAAE,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAE,EAAE,GAClG,YAAY,CA+Fd"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serving a declarative package's recipes through a deployment-supplied harness provider.
|
|
3
|
+
*
|
|
4
|
+
* THE LAST LINK OF SLICE 3, and the reason it is a module rather than a few lines in the host:
|
|
5
|
+
* this is where a resolved RECIPE becomes a callable TOOL, and the pieces have to be joined in a
|
|
6
|
+
* specific order for the authorization to mean anything.
|
|
7
|
+
*
|
|
8
|
+
* WHAT THIS DELIBERATELY IS NOT. It does not construct an `LlmProvider`. Which model answers a
|
|
9
|
+
* harness call is a deployment's business, and this plugin holds no model-specific code — that
|
|
10
|
+
* is an architectural rule the repository enforces with a gate. Instead a deployment SUPPLIES a
|
|
11
|
+
* provider and this module does the joining: authorize the recipe's tool name, run through the
|
|
12
|
+
* broker, and refuse honestly when no provider was supplied.
|
|
13
|
+
*
|
|
14
|
+
* WHY THE REFUSAL IS STILL THE DEFAULT. A declarative package resolves and its recipes parse,
|
|
15
|
+
* and without a provider nothing can call a model. Serving the tool anyway would present a tool
|
|
16
|
+
* that fails at invocation, so the refusal happens at RESOLUTION — where a reader can see why —
|
|
17
|
+
* rather than at the first call.
|
|
18
|
+
*
|
|
19
|
+
* @module @try-works/dsh-model-as-tool/harness-serving
|
|
20
|
+
*/
|
|
21
|
+
import { HarnessBroker, parseRecipe, } from '@try-works/tool-mode-recipes';
|
|
22
|
+
/**
|
|
23
|
+
* A harness call the caller CANCELLED.
|
|
24
|
+
*
|
|
25
|
+
* Distinct from `HarnessFailedError` on purpose: a caller who walked away is not a malfunction,
|
|
26
|
+
* and conflating the two makes every cancellation look like a fault. The same discipline the
|
|
27
|
+
* invocation accounting applies to `cancelled`.
|
|
28
|
+
*/
|
|
29
|
+
export class HarnessCancelledError extends Error {
|
|
30
|
+
toolName;
|
|
31
|
+
reason;
|
|
32
|
+
name = 'HarnessCancelledError';
|
|
33
|
+
constructor(toolName, reason) {
|
|
34
|
+
super(`the harness recipe ${toolName} was cancelled: ${reason}`);
|
|
35
|
+
this.toolName = toolName;
|
|
36
|
+
this.reason = reason;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A harness call that FAILED, carrying the broker's machine-readable code.
|
|
41
|
+
*
|
|
42
|
+
* The code is preserved rather than flattened into a message, so a caller branches on the CAUSE
|
|
43
|
+
* instead of matching prose.
|
|
44
|
+
*/
|
|
45
|
+
export class HarnessFailedError extends Error {
|
|
46
|
+
toolName;
|
|
47
|
+
code;
|
|
48
|
+
reason;
|
|
49
|
+
name = 'HarnessFailedError';
|
|
50
|
+
constructor(toolName, code, reason) {
|
|
51
|
+
super(`the harness recipe ${toolName} failed (${code}): ${reason}`);
|
|
52
|
+
this.toolName = toolName;
|
|
53
|
+
this.code = code;
|
|
54
|
+
this.reason = reason;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Prepare a declarative package's resolved recipes for serving.
|
|
59
|
+
*
|
|
60
|
+
* @param composition - the deployment's harness composition.
|
|
61
|
+
* @param resolved - the recipes resolved through the convention.
|
|
62
|
+
* @returns the served recipes, or the reason none can be served.
|
|
63
|
+
*/
|
|
64
|
+
export function prepareDeclarative(composition, resolved) {
|
|
65
|
+
/**
|
|
66
|
+
* NO PROVIDER MEANS NO SERVING, and the refusal names the composition rather than the package.
|
|
67
|
+
* A reader who is told "the package is declarative" would look in the wrong place: the package
|
|
68
|
+
* is complete and its recipes resolve.
|
|
69
|
+
*/
|
|
70
|
+
if (composition.provider === undefined) {
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
code: 'no-provider',
|
|
74
|
+
detail: 'this deployment composes no harness LlmProvider, so a declarative package\'s recipes '
|
|
75
|
+
+ 'cannot be executed. The recipes resolved and the broker is available; what is absent '
|
|
76
|
+
+ 'is the provider that would answer a model call.',
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const broker = new HarnessBroker({ record: composition.journal });
|
|
80
|
+
const served = [];
|
|
81
|
+
for (const entry of resolved) {
|
|
82
|
+
/**
|
|
83
|
+
* THE RECIPE IS VALIDATED HERE, and it previously was not — a HIGH-severity gap found by
|
|
84
|
+
* adversarial review.
|
|
85
|
+
*
|
|
86
|
+
* This line used to be a bare cast: `entry.recipe as RecipeManifest`. The production resolver
|
|
87
|
+
* hands over raw `JSON.parse` output, so NOTHING validated the file between disk and
|
|
88
|
+
* execution. The review took `text-title.json` and applied one mutation at a time — an
|
|
89
|
+
* unexpected `tools` array, a `systemPrompt`, a `${process.env.SECRET_KEY}` interpolation, an
|
|
90
|
+
* uppercase or path-like tool name, `__proto__`, an absurd `maxOutputTokens`, a missing
|
|
91
|
+
* `policy`, a missing `inputs`. `parseRecipe` REFUSED ALL TEN; `prepareDeclarative` SERVED ALL
|
|
92
|
+
* TEN, and they executed. The validator was available and imported by the test that was
|
|
93
|
+
* supposed to cover this path — and bypassed by the only path that runs a recipe.
|
|
94
|
+
*
|
|
95
|
+
* A cast is a claim about a value the compiler cannot check, and here the claim was false for
|
|
96
|
+
* exactly the inputs an untrusted package would supply.
|
|
97
|
+
*/
|
|
98
|
+
const parsed = parseRecipe(entry.recipe);
|
|
99
|
+
if (!parsed.ok) {
|
|
100
|
+
return {
|
|
101
|
+
ok: false,
|
|
102
|
+
code: 'recipe-rejected',
|
|
103
|
+
detail: `${entry.id}: the recipe did not validate: ${JSON.stringify(parsed).slice(0, 300)}`,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const recipe = parsed.recipe;
|
|
107
|
+
/**
|
|
108
|
+
* AUTHORIZATION IS PER TOOL NAME, and it happens BEFORE anything is served. A recipe whose
|
|
109
|
+
* name was never authorized must not become callable, or the broker would refuse at
|
|
110
|
+
* invocation — a failure far from its cause.
|
|
111
|
+
*/
|
|
112
|
+
const toolName = recipe.tool.name;
|
|
113
|
+
try {
|
|
114
|
+
broker.authorize(toolName, composition.provider);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
return {
|
|
118
|
+
ok: false,
|
|
119
|
+
code: 'recipe-rejected',
|
|
120
|
+
detail: `${entry.id}: the broker refused to authorize ${toolName}: `
|
|
121
|
+
+ `${error instanceof Error ? error.message : String(error)}`,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
served.push({
|
|
125
|
+
implementationId: entry.id,
|
|
126
|
+
contractId: entry.contractId,
|
|
127
|
+
toolName,
|
|
128
|
+
async invoke(args, signal) {
|
|
129
|
+
const outcome = await broker.run(recipe, args, signal === undefined ? {} : { signal });
|
|
130
|
+
if (outcome.kind === 'completed')
|
|
131
|
+
return outcome.text;
|
|
132
|
+
/**
|
|
133
|
+
* THE BROKER'S NON-COMPLETED VARIANTS ARE `failed` AND `cancelled` — and an earlier
|
|
134
|
+
* version of this comment named `refused`, `truncated` and `tool_call` instead.
|
|
135
|
+
*
|
|
136
|
+
* Those are variants of `LlmCompletion`, the PROVIDER's reply, not of `BrokerOutcome`,
|
|
137
|
+
* what `run` returns. They were plausible and wrong, and the difference is not academic:
|
|
138
|
+
* a reader trusting the comment would handle cases that cannot occur here and miss the
|
|
139
|
+
* one that can.
|
|
140
|
+
*
|
|
141
|
+
* CANCELLATION IS NOT A FAILURE, and it used to be thrown as an indistinguishable Error.
|
|
142
|
+
* The same discipline applies here as in the invocation accounting: a caller who walked
|
|
143
|
+
* away must be able to tell that from a malfunction, or every cancellation inflates the
|
|
144
|
+
* error rate. `HarnessCancelledError` exists so it can.
|
|
145
|
+
*/
|
|
146
|
+
if (outcome.kind === 'cancelled') {
|
|
147
|
+
throw new HarnessCancelledError(toolName, outcome.reason);
|
|
148
|
+
}
|
|
149
|
+
// `failed` carries the broker's own machine-readable code, so a caller can branch on the
|
|
150
|
+
// CAUSE rather than matching on a message.
|
|
151
|
+
throw new HarnessFailedError(toolName, outcome.code, outcome.reason);
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return { ok: true, served };
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=harness-serving.js.map
|