@avantf/dsh-plugin-base 0.3.1
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/LICENSE +21 -0
- package/README.md +303 -0
- package/dist/artifact.d.ts +29 -0
- package/dist/artifact.d.ts.map +1 -0
- package/dist/artifact.js +60 -0
- package/dist/artifact.js.map +1 -0
- package/dist/bootstrap.d.ts +54 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +334 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +37 -0
- package/dist/cli.js.map +1 -0
- package/dist/compat.d.ts +413 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/compat.js +742 -0
- package/dist/compat.js.map +1 -0
- package/dist/conformance.d.ts +55 -0
- package/dist/conformance.d.ts.map +1 -0
- package/dist/conformance.js +702 -0
- package/dist/conformance.js.map +1 -0
- package/dist/errors.d.ts +26 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +28 -0
- package/dist/errors.js.map +1 -0
- package/dist/fs.d.ts +18 -0
- package/dist/fs.d.ts.map +1 -0
- package/dist/fs.js +152 -0
- package/dist/fs.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/integrity.d.ts +5 -0
- package/dist/integrity.d.ts.map +1 -0
- package/dist/integrity.js +33 -0
- package/dist/integrity.js.map +1 -0
- package/dist/interface.d.ts +262 -0
- package/dist/interface.d.ts.map +1 -0
- package/dist/interface.js +136 -0
- package/dist/interface.js.map +1 -0
- package/dist/interface_gate.d.ts +61 -0
- package/dist/interface_gate.d.ts.map +1 -0
- package/dist/interface_gate.js +103 -0
- package/dist/interface_gate.js.map +1 -0
- package/dist/internal.d.ts +23 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +18 -0
- package/dist/internal.js.map +1 -0
- package/dist/kit/family.d.ts +52 -0
- package/dist/kit/family.d.ts.map +1 -0
- package/dist/kit/family.js +65 -0
- package/dist/kit/family.js.map +1 -0
- package/dist/kit/index.d.ts +26 -0
- package/dist/kit/index.d.ts.map +1 -0
- package/dist/kit/index.js +26 -0
- package/dist/kit/index.js.map +1 -0
- package/dist/kit/logger.d.ts +41 -0
- package/dist/kit/logger.d.ts.map +1 -0
- package/dist/kit/logger.js +42 -0
- package/dist/kit/logger.js.map +1 -0
- package/dist/kit/prompt_files.d.ts +90 -0
- package/dist/kit/prompt_files.d.ts.map +1 -0
- package/dist/kit/prompt_files.js +121 -0
- package/dist/kit/prompt_files.js.map +1 -0
- package/dist/kit/typert.d.ts +40 -0
- package/dist/kit/typert.d.ts.map +1 -0
- package/dist/kit/typert.js +17 -0
- package/dist/kit/typert.js.map +1 -0
- package/dist/layout.d.ts +28 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +84 -0
- package/dist/layout.js.map +1 -0
- package/dist/lint.d.ts +33 -0
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +271 -0
- package/dist/lint.js.map +1 -0
- package/dist/lock.d.ts +12 -0
- package/dist/lock.d.ts.map +1 -0
- package/dist/lock.js +93 -0
- package/dist/lock.js.map +1 -0
- package/dist/manifest.d.ts +12 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +75 -0
- package/dist/manifest.js.map +1 -0
- package/dist/net.d.ts +23 -0
- package/dist/net.d.ts.map +1 -0
- package/dist/net.js +112 -0
- package/dist/net.js.map +1 -0
- package/dist/package-name.d.ts +3 -0
- package/dist/package-name.d.ts.map +1 -0
- package/dist/package-name.js +13 -0
- package/dist/package-name.js.map +1 -0
- package/dist/preset.d.ts +46 -0
- package/dist/preset.d.ts.map +1 -0
- package/dist/preset.js +230 -0
- package/dist/preset.js.map +1 -0
- package/dist/providers/archive.d.ts +32 -0
- package/dist/providers/archive.d.ts.map +1 -0
- package/dist/providers/archive.js +248 -0
- package/dist/providers/archive.js.map +1 -0
- package/dist/providers/model.d.ts +25 -0
- package/dist/providers/model.d.ts.map +1 -0
- package/dist/providers/model.js +550 -0
- package/dist/providers/model.js.map +1 -0
- package/dist/providers/npm.d.ts +21 -0
- package/dist/providers/npm.d.ts.map +1 -0
- package/dist/providers/npm.js +458 -0
- package/dist/providers/npm.js.map +1 -0
- package/dist/provisioner.d.ts +21 -0
- package/dist/provisioner.d.ts.map +1 -0
- package/dist/provisioner.js +962 -0
- package/dist/provisioner.js.map +1 -0
- package/dist/semver.d.ts +31 -0
- package/dist/semver.d.ts.map +1 -0
- package/dist/semver.js +244 -0
- package/dist/semver.js.map +1 -0
- package/dist/state.d.ts +71 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +225 -0
- package/dist/state.js.map +1 -0
- package/dist/tar.d.ts +10 -0
- package/dist/tar.d.ts.map +1 -0
- package/dist/tar.js +178 -0
- package/dist/tar.js.map +1 -0
- package/dist/types.d.ts +431 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/zip.d.ts +8 -0
- package/dist/zip.d.ts.map +1 -0
- package/dist/zip.js +109 -0
- package/dist/zip.js.map +1 -0
- package/package.json +84 -0
package/dist/compat.d.ts
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every line this module logs carries this token, so a support question can be answered
|
|
3
|
+
* with one grep of the host log.
|
|
4
|
+
*/
|
|
5
|
+
export declare const COMPAT_PREFIX = "compat:";
|
|
6
|
+
/** What the gate needs from a live context: one service lookup. Cordis's `Context` satisfies it. */
|
|
7
|
+
export interface CompatContext {
|
|
8
|
+
get(name: string): unknown;
|
|
9
|
+
}
|
|
10
|
+
/** One service a plugin calls, and the methods it calls on it. */
|
|
11
|
+
export interface ServiceContract {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
/**
|
|
14
|
+
* `true` ⇒ refuse to load when it (or one of its methods) is gone. This is the CALLER's refusal
|
|
15
|
+
* policy, not cordis's `inject`: cordis has no optional injection, so a service the plugin can
|
|
16
|
+
* degrade without is read with `ctx.get()` and declared here as `required: false`.
|
|
17
|
+
*/
|
|
18
|
+
readonly required: boolean;
|
|
19
|
+
readonly methods: readonly string[];
|
|
20
|
+
}
|
|
21
|
+
/** What a plugin declares about itself, so the rules can stay generic. */
|
|
22
|
+
export interface CompatSpec {
|
|
23
|
+
/** The plugin's package id: probe keys and the post-registration check are `<id>#<name>`. */
|
|
24
|
+
readonly packageId: string;
|
|
25
|
+
readonly services: readonly ServiceContract[];
|
|
26
|
+
/**
|
|
27
|
+
* Package released in lockstep with dsh → the version THIS BUILD was compiled against. Feed it
|
|
28
|
+
* {@link readBuildVersions} over the JSON the build baked next to the entry, with the peer range's
|
|
29
|
+
* floor ({@link readDeclaredVersions}) as the per-package fallback: a range floor is a lower bound
|
|
30
|
+
* the artifact tolerates, not "the dsh I built against".
|
|
31
|
+
*/
|
|
32
|
+
readonly declared: Readonly<Record<string, string | undefined>>;
|
|
33
|
+
/**
|
|
34
|
+
* What THIS BUILD's links resolve to, read by the CALLER from its own module URL
|
|
35
|
+
* (`readRuntimeVersions(packages, import.meta.url)`). It is NOT the host's identity — a plugin
|
|
36
|
+
* cannot observe that; see the module header. Omitted ⇒ this package resolves them, which is only
|
|
37
|
+
* as good as the links IT has.
|
|
38
|
+
*/
|
|
39
|
+
readonly runtime?: Readonly<Record<string, string | undefined>>;
|
|
40
|
+
/** Whether `ctx.interval` (the timer plugin's effect-scoped timer) is needed. */
|
|
41
|
+
readonly needsInterval?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Build the throwaway tool the tools probe registers, e.g.
|
|
44
|
+
* `toolProbeDeclaration(defineTool)`. Omitted ⇒ that probe is skipped ("not probed", never a break).
|
|
45
|
+
*/
|
|
46
|
+
readonly probeTool?: () => unknown;
|
|
47
|
+
/**
|
|
48
|
+
* Build the throwaway Typert contribution the wire probe registers. **Pass your real declaration**
|
|
49
|
+
* (`() => myContribution`), so a pass proves the registration you are about to perform. Omitted ⇒
|
|
50
|
+
* the wire contract is not probed at all (recorded as a note, never a refusal).
|
|
51
|
+
*
|
|
52
|
+
* The rule is absolute, and it is not a style note: this package once shipped a MINIMAL stand-in
|
|
53
|
+
* (one schema, no invocations, no codecs) as the convenient default, and a live 0.1.6 host proved
|
|
54
|
+
* the cost — the stand-in passed (it carried no codec to validate) while the plugin's REAL
|
|
55
|
+
* contribution threw on `strict codec has no create() factory` halfway through `apply`. A probe
|
|
56
|
+
* that is not the real declaration turns "the host API moved" into a half-mounted plugin, which is
|
|
57
|
+
* the one outcome this gate exists to prevent.
|
|
58
|
+
*/
|
|
59
|
+
readonly probeTypert?: (packageId: string) => unknown;
|
|
60
|
+
/** Wire schema names to verify after registration; omitted means "no post-registration check". */
|
|
61
|
+
readonly schemaNames?: readonly string[];
|
|
62
|
+
/** Events the plugin listens to. Reported as an unprovable limit, never checked. */
|
|
63
|
+
readonly events?: readonly string[];
|
|
64
|
+
}
|
|
65
|
+
/** Coarse outcome of one gate run. */
|
|
66
|
+
export type CompatStatus = 'ok' | 'version-mismatch' | 'version-unknown' | 'probe-skipped' | 'probe-failed';
|
|
67
|
+
/** One service as the live context answers for it. */
|
|
68
|
+
export interface ServiceProbe {
|
|
69
|
+
readonly name: string;
|
|
70
|
+
readonly required: boolean;
|
|
71
|
+
readonly present: boolean;
|
|
72
|
+
/** Methods the plugin calls that the mounted service does not expose. */
|
|
73
|
+
readonly missing: readonly string[];
|
|
74
|
+
}
|
|
75
|
+
/** One registry probe: what was tried, and what came back. */
|
|
76
|
+
export interface ProbeOutcome {
|
|
77
|
+
/** The registry exposed the query surface, so the probe actually ran. */
|
|
78
|
+
readonly ran: boolean;
|
|
79
|
+
readonly passed: boolean;
|
|
80
|
+
/** Expected-vs-actual detail, one entry per failed step (empty when it passed). */
|
|
81
|
+
readonly problems: readonly string[];
|
|
82
|
+
}
|
|
83
|
+
/** One version comparison: what this build was compiled against vs what its own links resolve now. */
|
|
84
|
+
export interface VersionProbe {
|
|
85
|
+
readonly package: string;
|
|
86
|
+
/**
|
|
87
|
+
* The version this build was compiled against: the exact one baked into the build when there is a
|
|
88
|
+
* `dsh-build.json` next to the entry, else the peer range's floor (`^0.1.5-rc.2` → `0.1.5-rc.2`).
|
|
89
|
+
*/
|
|
90
|
+
readonly declared: string | undefined;
|
|
91
|
+
/** What this build's own links resolve to NOW. The host's identity is never observed. */
|
|
92
|
+
readonly runtime: string | undefined;
|
|
93
|
+
}
|
|
94
|
+
/** Everything the verdict needs, as plain data. */
|
|
95
|
+
export interface CompatEvidence {
|
|
96
|
+
readonly services: readonly ServiceProbe[];
|
|
97
|
+
/** `ctx.interval` — the timer plugin's effect-scoped timer, which the sweep may need. */
|
|
98
|
+
readonly interval: boolean;
|
|
99
|
+
/** Whether the caller needs that timer (a plugin with no sweep does not). */
|
|
100
|
+
readonly needsInterval: boolean;
|
|
101
|
+
readonly toolsProbe: ProbeOutcome | undefined;
|
|
102
|
+
readonly typertProbe: ProbeOutcome | undefined;
|
|
103
|
+
readonly versions: readonly VersionProbe[];
|
|
104
|
+
/** Events the caller listens to; reported as unprovable, never blocking. */
|
|
105
|
+
readonly events: readonly string[];
|
|
106
|
+
}
|
|
107
|
+
/** One line to log; `error` marks a proven break. */
|
|
108
|
+
export interface CompatLine {
|
|
109
|
+
readonly level: 'info' | 'warn' | 'error';
|
|
110
|
+
readonly message: string;
|
|
111
|
+
}
|
|
112
|
+
/** The decision `apply` branches on, plus everything worth printing. */
|
|
113
|
+
export interface CompatVerdict {
|
|
114
|
+
/** `false` ⇒ refuse to load: register nothing. */
|
|
115
|
+
readonly load: boolean;
|
|
116
|
+
/** No active probe could run: the surface checks still happened, but nothing was proven either way. */
|
|
117
|
+
readonly skipped: boolean;
|
|
118
|
+
readonly status: CompatStatus;
|
|
119
|
+
readonly problems: readonly string[];
|
|
120
|
+
readonly warnings: readonly string[];
|
|
121
|
+
readonly notes: readonly string[];
|
|
122
|
+
readonly lines: readonly CompatLine[];
|
|
123
|
+
/** One line for the `load: false` case (empty otherwise), for an envelope or a command. */
|
|
124
|
+
readonly reason: string;
|
|
125
|
+
}
|
|
126
|
+
/** Minimal logging surface the caller supplies (the plugin's own logger satisfies it). */
|
|
127
|
+
export interface CompatLogger {
|
|
128
|
+
info: (message: string) => void;
|
|
129
|
+
warn: (message: string) => void;
|
|
130
|
+
error: (message: string) => void;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Turn one declared peer range into the version FLOOR it names.
|
|
134
|
+
*
|
|
135
|
+
* The `declared` side's FALLBACK, used only when a build left no baked version
|
|
136
|
+
* ({@link readBuildVersions}). Only the floor is read — a caret range's upper bound is a promise
|
|
137
|
+
* about the future, while the floor is the exact release the range was written against.
|
|
138
|
+
*
|
|
139
|
+
* Compound ranges are the everyday form (`>=4.4.3 <5`, `>=0.1.5-rc.2 <0.2.0`), so the FIRST
|
|
140
|
+
* comparator is read and its trailing bounds are ignored: spacing, a `<`/`<=` bound, or a `||`
|
|
141
|
+
* alternative must not turn a readable floor into `undefined`. A range whose first comparator is
|
|
142
|
+
* itself an upper bound (`<2.0.0`, `<=2.0.0`), a tag (`latest`), or a protocol (`workspace:`) names
|
|
143
|
+
* no floor and yields `undefined`, which reports as unverified rather than as a mismatch.
|
|
144
|
+
* @param range - the peer range as written in `package.json`.
|
|
145
|
+
* @returns the version, or `undefined` when it cannot be read out.
|
|
146
|
+
*/
|
|
147
|
+
export declare function floorOf(range: string | undefined): string | undefined;
|
|
148
|
+
/**
|
|
149
|
+
* Read the version FLOORS a caller declares for the packages that identify the host.
|
|
150
|
+
*
|
|
151
|
+
* Taken from the caller's own `package.json` peer ranges, so the value travels with the artifact (a
|
|
152
|
+
* plugin's manifest ships with it) and cannot drift away from the contract it declares. A floor is a
|
|
153
|
+
* LOWER BOUND, which is why this is the fallback and not the preferred source: it cannot say which
|
|
154
|
+
* release the artifact was actually compiled against. {@link readBuildVersions} reads that, and falls
|
|
155
|
+
* back to these floors only for packages its build did not bake.
|
|
156
|
+
* @param manifestUrl - the caller's `package.json` (`new URL('../package.json', import.meta.url)`).
|
|
157
|
+
* @param packages - the packages to read, usually `['@deepseek-ai/dsh-tools', ...]`.
|
|
158
|
+
* @returns one entry per package; `undefined` means the manifest declares nothing for it.
|
|
159
|
+
*/
|
|
160
|
+
export declare function readDeclaredVersions(manifestUrl: string | URL, packages: readonly string[]): Record<string, string | undefined>;
|
|
161
|
+
/**
|
|
162
|
+
* The file a build bakes its exact versions into, next to the built entry.
|
|
163
|
+
*
|
|
164
|
+
* Named once here so the producer (a repo's build script) and the consumer (its `provision.ts`)
|
|
165
|
+
* cannot disagree about where it lives. It is a plain JSON object of `package → version`.
|
|
166
|
+
*/
|
|
167
|
+
export declare const BUILD_VERSIONS_FILE = "dsh-build.json";
|
|
168
|
+
/**
|
|
169
|
+
* Read the exact versions THIS BUILD was compiled against, out of the JSON its build emitted.
|
|
170
|
+
*
|
|
171
|
+
* The `declared` side's PREFERRED source. A peer range only records a floor — the lowest release the
|
|
172
|
+
* artifact tolerates — so after an in-place upgrade of the installed dsh it says nothing about the
|
|
173
|
+
* copy this build actually linked and compiled against, and the comparison degrades to a weak one.
|
|
174
|
+
* The build knows that copy exactly, so it bakes it next to the entry (`lib/dsh-build.json`) and this
|
|
175
|
+
* reads it back from `new URL('./dsh-build.json', import.meta.url)`.
|
|
176
|
+
*
|
|
177
|
+
* The file is OPTIONAL by design: a dev tree, a test run and a build made before this file existed
|
|
178
|
+
* all lack it, and none of them may crash or invent a version. The fallback is per PACKAGE rather
|
|
179
|
+
* than all-or-nothing, so a partially written file still reports honestly for the entries it has.
|
|
180
|
+
* @param buildUrl - where the build wrote the JSON (`new URL('./dsh-build.json', import.meta.url)`).
|
|
181
|
+
* @param packages - the packages to read, usually `['@deepseek-ai/dsh-tools', ...]`.
|
|
182
|
+
* @param fallback - per-package value for entries the file has none for (the peer floors).
|
|
183
|
+
* @returns one entry per package; `undefined` means neither source has a version.
|
|
184
|
+
*/
|
|
185
|
+
export declare function readBuildVersions(buildUrl: string | URL, packages: readonly string[], fallback?: Readonly<Record<string, string | undefined>>): Record<string, string | undefined>;
|
|
186
|
+
/**
|
|
187
|
+
* Resolve the version of a peer copy THIS BUILD's links point at.
|
|
188
|
+
*
|
|
189
|
+
* This is the `runtime` side: it answers "what do this artifact's own links resolve to", NOT "which
|
|
190
|
+
* host is running". The two coincide when the plugin shares the host's copy, and diverge whenever
|
|
191
|
+
* the links point elsewhere — a checkout host loading a plugin linked to an installed dsh is the
|
|
192
|
+
* everyday case. Nothing inside a plugin can observe the host's own version (no dsh service exposes
|
|
193
|
+
* it), so the log wording never claims to; see `README.md` «已知边界».
|
|
194
|
+
*
|
|
195
|
+
* A plugin cannot resolve `@deepseek-ai/dsh/package.json` (the core package is not in its
|
|
196
|
+
* `node_modules`), but the packages below ship in lockstep with it and ARE resolvable
|
|
197
|
+
* through the same links the rest of the plugin uses. Any failure is "unknown", never a
|
|
198
|
+
* throw.
|
|
199
|
+
* `base` decides WHOSE links are used. It defaults to this package, which is right when this package
|
|
200
|
+
* is the only consumer — but a plugin should pass its own `import.meta.url`: the packages that
|
|
201
|
+
* identify the host are ITS peers, and the shared package may not be able to see all of them.
|
|
202
|
+
* @param name - the peer package.
|
|
203
|
+
* @param base - module URL to resolve from (defaults to this package).
|
|
204
|
+
* @returns the version string, or `undefined`.
|
|
205
|
+
*/
|
|
206
|
+
export declare function resolveRuntimeVersion(name: string, base?: string | URL): string | undefined;
|
|
207
|
+
/**
|
|
208
|
+
* Ask the live context for one entry per declared service.
|
|
209
|
+
*
|
|
210
|
+
* A service that is present but missing a method the caller declared is a BREAK, not a note: the
|
|
211
|
+
* caller's code will call it. A service that is absent is a problem only when it is required.
|
|
212
|
+
* @param ctx - the live context (structural).
|
|
213
|
+
* @param contracts - what the caller calls.
|
|
214
|
+
* @returns one probe per contract.
|
|
215
|
+
*/
|
|
216
|
+
export declare function checkServices(ctx: CompatContext, contracts: readonly ServiceContract[]): ServiceProbe[];
|
|
217
|
+
/** Whether the timer plugin's effect-scoped timer is reachable as `ctx.interval`. */
|
|
218
|
+
export declare function checkInterval(ctx: CompatContext): boolean;
|
|
219
|
+
/**
|
|
220
|
+
* The throwaway tool the probe registers: the same declaration shape `tools.ts` uses,
|
|
221
|
+
* including the `output` contract the model-facing render depends on.
|
|
222
|
+
*
|
|
223
|
+
* Withdrawn in `finally`, so a successful probe leaves the registry exactly as it found
|
|
224
|
+
* it (a failed withdrawal would show up as a tenth tool in the mount smoke).
|
|
225
|
+
*/
|
|
226
|
+
export declare const COMPAT_PROBE_TOOL = "__dshCompatProbe";
|
|
227
|
+
/**
|
|
228
|
+
* The caller's declaration helper, typed loosely on purpose: naming `@deepseek-ai/dsh-tools`'s own
|
|
229
|
+
* options type here is exactly the compile-time dependency on a dsh version this package avoids. The
|
|
230
|
+
* literal below is verified against the REAL registry by this package's tests, so a wrong shape fails
|
|
231
|
+
* there rather than silently.
|
|
232
|
+
*/
|
|
233
|
+
export type ToolDeclarationHelper = (options: any) => unknown;
|
|
234
|
+
/**
|
|
235
|
+
* Build the tools-probe declaration from the CALLER's own declaration helper.
|
|
236
|
+
*
|
|
237
|
+
* The helper is injected rather than imported on purpose. This package is a base module: pinning a
|
|
238
|
+
* dsh version would make it stale with every dsh release, and a dsh-free source is what lets one copy
|
|
239
|
+
* serve every plugin. The caller also happens to be the right owner — the probe must mirror the
|
|
240
|
+
* declaration path the caller's REAL tools use, and only the caller has that helper.
|
|
241
|
+
* @param defineTool - the caller's `defineTool` (from its own `@deepseek-ai/dsh-tools`).
|
|
242
|
+
* @returns a zero-argument builder for `CompatSpec.probeTool`.
|
|
243
|
+
*/
|
|
244
|
+
export declare function toolProbeDeclaration(defineTool: ToolDeclarationHelper): () => unknown;
|
|
245
|
+
/**
|
|
246
|
+
* Register the probe tool, check the registry kept it, and withdraw it.
|
|
247
|
+
*
|
|
248
|
+
* What this proves that a method-presence check cannot: the registry ACCEPTED our
|
|
249
|
+
* declaration shape and still lists it. It is the difference between "`register` is a
|
|
250
|
+
* function" and "registering what we register works".
|
|
251
|
+
* @param registry - `ctx.tools`.
|
|
252
|
+
* @returns the outcome; never throws.
|
|
253
|
+
*/
|
|
254
|
+
export declare function probeToolsRegistry(registry: unknown, buildProbe: (() => unknown) | undefined): ProbeOutcome;
|
|
255
|
+
/**
|
|
256
|
+
* Register the caller's Typert declaration, verify the query surface, and withdraw it.
|
|
257
|
+
*
|
|
258
|
+
* The schema is a LIVE zod object, which is the point: `toJSONSchema` runs the HOST's
|
|
259
|
+
* projector over OUR schema, the cross-copy step that breaks when the codec contract
|
|
260
|
+
* moves (`TypertSchema{schema}` → `TypertSchemaFactory{create}` did exactly this once).
|
|
261
|
+
* What is verified — the schema names AND the package face — is read off the declaration, so
|
|
262
|
+
* handing over the real contribution makes a pass mean "the real registration will land too".
|
|
263
|
+
* @param registry - `ctx.typert`.
|
|
264
|
+
* @param packageId - this plugin's package id, which the probe key is built from.
|
|
265
|
+
* @returns the outcome; never throws.
|
|
266
|
+
*/
|
|
267
|
+
export declare function probeTypertRegistry(registry: unknown, packageId: string, buildProbe: ((packageId: string) => unknown) | undefined): ProbeOutcome;
|
|
268
|
+
/**
|
|
269
|
+
* Resolve several versions at once, from one caller's links.
|
|
270
|
+
*
|
|
271
|
+
* "From one caller's links" is the whole boundary: these are the versions that caller resolves, not
|
|
272
|
+
* the host's. Pass the caller's own `import.meta.url` so the answer covers its peers.
|
|
273
|
+
* @param packages - the packages to resolve.
|
|
274
|
+
* @param base - module URL to resolve from (defaults to this package).
|
|
275
|
+
* @returns one entry per package; `undefined` means it could not be resolved.
|
|
276
|
+
*/
|
|
277
|
+
export declare function readRuntimeVersions(packages: readonly string[], base?: string | URL): Record<string, string | undefined>;
|
|
278
|
+
/**
|
|
279
|
+
* Read a live context into the plain evidence the rules consume.
|
|
280
|
+
*
|
|
281
|
+
* The probes are throwaway declarations shaped like the real ones: "`register` is a function" and
|
|
282
|
+
* "registering what we register works" are different claims, and only the second one catches a
|
|
283
|
+
* moved contract.
|
|
284
|
+
* @param ctx - the live context (structural: only `get` is used).
|
|
285
|
+
* @param spec - what the caller declared about itself.
|
|
286
|
+
* @returns the evidence.
|
|
287
|
+
*/
|
|
288
|
+
export declare function gatherEvidence(ctx: CompatContext, spec: CompatSpec): CompatEvidence;
|
|
289
|
+
/**
|
|
290
|
+
* The rule set: plain evidence in, decision plus log lines out.
|
|
291
|
+
*
|
|
292
|
+
* Kept pure so every branch — including the ones a live host cannot be made to produce —
|
|
293
|
+
* is unit-tested without a Context.
|
|
294
|
+
*
|
|
295
|
+
* Logging policy, so a healthy mount stays one line: warnings and problems are always
|
|
296
|
+
* logged, and everything merely UNDETERMINABLE lands in `notes` — returned for tests and
|
|
297
|
+
* support, not printed. A note is not a finding; the plugin that cannot probe a registry
|
|
298
|
+
* still says so in the verdict the caller holds.
|
|
299
|
+
* @param evidence - what {@link gatherEvidence} observed.
|
|
300
|
+
* @returns the verdict.
|
|
301
|
+
*/
|
|
302
|
+
export declare function verdictOf(evidence: CompatEvidence): CompatVerdict;
|
|
303
|
+
/**
|
|
304
|
+
* Run the check against a live context and log every line.
|
|
305
|
+
*
|
|
306
|
+
* Call this FIRST in `apply()`: on a refusal nothing has been registered yet, so "do not
|
|
307
|
+
* load" costs nothing to unwind. Never throws — a check that cannot be performed leaves
|
|
308
|
+
* the plugin loading, because "cannot tell" is not "incompatible".
|
|
309
|
+
* @param ctx - the plugin's context.
|
|
310
|
+
* @param log - the plugin's logger.
|
|
311
|
+
* @returns the verdict `apply` branches on.
|
|
312
|
+
*/
|
|
313
|
+
export declare function provision(ctx: CompatContext, log: CompatLogger, spec: CompatSpec): CompatVerdict;
|
|
314
|
+
/**
|
|
315
|
+
* The caller's copy for {@link compatReport}: the STRUCTURE is the base's, every string is the
|
|
316
|
+
* caller's (see the function's note). Exported so the interface type
|
|
317
|
+
* (`BaseRuntimeV1.compatReport`) can name the same shape the implementation takes — a second,
|
|
318
|
+
* structurally-identical declaration would be exactly the kind of drift the interface snapshot exists
|
|
319
|
+
* to catch.
|
|
320
|
+
*/
|
|
321
|
+
export interface CompatReportWords {
|
|
322
|
+
readonly heading: string;
|
|
323
|
+
readonly fix: string;
|
|
324
|
+
readonly warningsLabel: string;
|
|
325
|
+
readonly warnings: readonly string[];
|
|
326
|
+
/**
|
|
327
|
+
* Optional because base is a published package: a plugin compiled against an earlier base does not
|
|
328
|
+
* pass it, and the honest result is no tail line at all rather than one in a language it never
|
|
329
|
+
* chose.
|
|
330
|
+
*/
|
|
331
|
+
readonly logPointer?: (prefix: string) => string;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Build the standard refusal report, so every plugin says the same thing in its own words.
|
|
335
|
+
*
|
|
336
|
+
* The STRUCTURE belongs here (heading, problems, warnings, the fix, where the full log is); the
|
|
337
|
+
* wording belongs to the caller, which passes every string in its own language. That includes the
|
|
338
|
+
* last line — this used to be a hardcoded Chinese sentence, which meant a caller that had translated
|
|
339
|
+
* everything else still got half a sentence in a language it never chose.
|
|
340
|
+
*
|
|
341
|
+
* `logPointer` is OPTIONAL because base is a published package: a plugin compiled against an earlier
|
|
342
|
+
* base does not pass it, and the honest result for that caller is no tail line at all rather than one
|
|
343
|
+
* in the wrong language.
|
|
344
|
+
* @param verdict - the refusal to report.
|
|
345
|
+
* @param words - the caller's copy.
|
|
346
|
+
* @param words.logPointer - the caller's sentence for "the full diagnostics are the log lines that
|
|
347
|
+
* start with `<prefix>`"; receive the prefix so the sentence can place it naturally.
|
|
348
|
+
* @returns the report text.
|
|
349
|
+
*/
|
|
350
|
+
export declare function compatReport(verdict: CompatVerdict, words: CompatReportWords): string;
|
|
351
|
+
/**
|
|
352
|
+
* Keep one megaphone when a plugin refuses to load.
|
|
353
|
+
*
|
|
354
|
+
* Registering a command in a broken host is a judgment call: the plugin provides nothing else, and
|
|
355
|
+
* the alternative is a user watching a surface that says "not available" with no way to ask why. A
|
|
356
|
+
* host too broken to register one leaves the log as the only channel — which must not throw either.
|
|
357
|
+
* @param input - the context, the logger, the command to register, and the text it should print.
|
|
358
|
+
*/
|
|
359
|
+
export declare function registerMegaphone(input: {
|
|
360
|
+
readonly ctx: CompatContext;
|
|
361
|
+
readonly log: CompatLogger;
|
|
362
|
+
readonly command: {
|
|
363
|
+
readonly name: string;
|
|
364
|
+
readonly description: string;
|
|
365
|
+
};
|
|
366
|
+
readonly text: string;
|
|
367
|
+
}): void;
|
|
368
|
+
/**
|
|
369
|
+
* The schema names a Typert contribution declares, read from the contribution itself.
|
|
370
|
+
*
|
|
371
|
+
* Derived, never hardcoded: a schema added to a wire face must widen the post-registration check on
|
|
372
|
+
* its own.
|
|
373
|
+
* @param contribution - the object passed to `register` (`{ schemas: [{ name }] }`).
|
|
374
|
+
* @returns the names, in declaration order.
|
|
375
|
+
*/
|
|
376
|
+
export declare function schemaNamesFrom(contribution: unknown): string[];
|
|
377
|
+
/**
|
|
378
|
+
* The registry keys those names become: `<packageId>#<name>`.
|
|
379
|
+
* @param packageId - the contributing package.
|
|
380
|
+
* @param names - the schema names.
|
|
381
|
+
* @returns the keys the registry is expected to list.
|
|
382
|
+
*/
|
|
383
|
+
export declare function declaredSchemaKeys(packageId: string, names: readonly string[]): string[];
|
|
384
|
+
/**
|
|
385
|
+
* The SECOND phase: after the real faces registered, confirm every one of them is visible.
|
|
386
|
+
*
|
|
387
|
+
* The pre-load probe proves the declaration SHAPE is accepted; it cannot prove that all of the real
|
|
388
|
+
* registrations landed. A silently dropped schema or tool fails exactly the way this whole module
|
|
389
|
+
* exists to prevent — the panel renders nothing, or the model never sees a tool — with no error
|
|
390
|
+
* anywhere. So the keys are counted by EXACT key after registration (never by a bare total, which
|
|
391
|
+
* an un-withdrawn probe would inflate) and every tool name is read back.
|
|
392
|
+
*
|
|
393
|
+
* Warn-only, for the reason the memory plugin records for its own post-registration count: by now
|
|
394
|
+
* the plugin is mounted, so there is no clean "do not load" left to take. Silent when everything is
|
|
395
|
+
* there — a healthy boot keeps its single `compat: ok` line.
|
|
396
|
+
*
|
|
397
|
+
* Known limit: invocation ENDPOINTS are not observable through the documented query surface
|
|
398
|
+
* (`list`/`listPackages` expose schemas and the package model only), so the four descriptors are
|
|
399
|
+
* covered through the schema keys they use, not counted themselves.
|
|
400
|
+
* @param input - the live context, the real tool names, and the logger.
|
|
401
|
+
* @returns the registrations that did not show up (empty on success).
|
|
402
|
+
*/
|
|
403
|
+
export declare function verifyRegisteredFaces(input: {
|
|
404
|
+
readonly ctx: CompatContext;
|
|
405
|
+
readonly packageId: string;
|
|
406
|
+
/** Wire schema names the caller registered; skipped when omitted. */
|
|
407
|
+
readonly schemaNames?: readonly string[];
|
|
408
|
+
readonly toolNames: readonly string[];
|
|
409
|
+
readonly log: CompatLogger;
|
|
410
|
+
}): {
|
|
411
|
+
readonly missing: readonly string[];
|
|
412
|
+
};
|
|
413
|
+
//# sourceMappingURL=compat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compat.d.ts","sourceRoot":"","sources":["../src/compat.ts"],"names":[],"mappings":"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"}
|