@matatbread/matbot-plugin-api 0.4.12 → 0.4.13
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/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/provider-patch.ts +33 -0
- package/src/types/builtin-tools.ts +28 -0
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ProviderConfig } from './types.js';
|
|
2
|
+
import type { ProviderPatch } from './types/builtin-tools.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The `provider update` policy, written once so every implementer of it behaves identically — the same
|
|
6
|
+
* reasoning as `applyCreateSecret` in `vault.ts`. Two hosts apply this patch (the node `provider` tool
|
|
7
|
+
* against matbot.yaml, the browser bootstrap against its persisted map) and the *semantics* of a patch
|
|
8
|
+
* must not be one of the things they differ on: `null` clears a field, absent leaves it alone.
|
|
9
|
+
*
|
|
10
|
+
* `parameters` is replaced wholesale rather than merged per key. Its values are forwarded to the
|
|
11
|
+
* endpoint unmodified and so have no shape to merge against — and `provider list` reports them in full,
|
|
12
|
+
* which is what makes a read-modify-write something a caller can actually carry out. (Contrast
|
|
13
|
+
* `default_settings`, which merges per key: there the keys are matbot's own.)
|
|
14
|
+
*
|
|
15
|
+
* `credentials` and `module` are absent from `ProviderPatch` and therefore ride through untouched; see
|
|
16
|
+
* that type for why neither belongs in an update.
|
|
17
|
+
*/
|
|
18
|
+
export function applyProviderPatch(cur: ProviderConfig, patch: ProviderPatch): ProviderConfig {
|
|
19
|
+
const next: ProviderConfig = { ...cur };
|
|
20
|
+
// Spelled out per field rather than looped: `exactOptionalPropertyTypes` makes "assign, or delete if
|
|
21
|
+
// null" a different statement for each type, and a loop only reaches them through a cast that would
|
|
22
|
+
// stop the compiler checking the one thing worth checking here.
|
|
23
|
+
if (patch.model !== undefined) next.model = patch.model;
|
|
24
|
+
if (patch.endpoint !== undefined) { if (patch.endpoint === null) delete next.endpoint; else next.endpoint = patch.endpoint; }
|
|
25
|
+
if (patch.parameters !== undefined) { if (patch.parameters === null) delete next.parameters; else next.parameters = patch.parameters; }
|
|
26
|
+
if (patch.maxRounds !== undefined) { if (patch.maxRounds === null) delete next.maxRounds; else next.maxRounds = patch.maxRounds; }
|
|
27
|
+
return next;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The fields a patch actually changes, in a stable order — for a confirmation prompt or a result message. */
|
|
31
|
+
export function patchedFields(patch: ProviderPatch): readonly ('model' | 'endpoint' | 'parameters' | 'maxRounds')[] {
|
|
32
|
+
return (['model', 'endpoint', 'parameters', 'maxRounds'] as const).filter(f => patch[f] !== undefined);
|
|
33
|
+
}
|
|
@@ -174,6 +174,31 @@ export interface ProviderActionResult {
|
|
|
174
174
|
message: string;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
/**
|
|
178
|
+
* The fields `provider update` can change on an existing profile, and the whole of them.
|
|
179
|
+
*
|
|
180
|
+
* `null` clears a field, absent leaves it alone — `undefined` cannot mean "clear", since it is already
|
|
181
|
+
* what an unsupplied optional looks like. `model` takes no `null`: a profile without one is unrunnable.
|
|
182
|
+
*
|
|
183
|
+
* Two fields are deliberately absent. **`credentials`**, because it is the one member of a profile that
|
|
184
|
+
* `provider list` does not report back (it projects to `hasCredentials`, and a secret must not ride the
|
|
185
|
+
* transcript) — so a caller cannot read-modify-write it, and an `update` that accepted it would have to
|
|
186
|
+
* guess between rewriting a `${NAME}` reference and replacing a literal. Credentials are
|
|
187
|
+
* `plugin store-key`'s, which addresses the vault name directly. And **`module`**, because changing the
|
|
188
|
+
* adapter re-opens every resolution question `add` answers (is it loaded, does it resolve by package
|
|
189
|
+
* name, is it even a provider adapter); `remove` + `add` is the honest route for that.
|
|
190
|
+
*
|
|
191
|
+
* A named shape rather than an inline arm because the browser's `ProviderAdmin.update` takes the same
|
|
192
|
+
* patch, and because it is the augmentable half — a host whose profiles carry an extra field adds it
|
|
193
|
+
* here without touching `ToolContracts`.
|
|
194
|
+
*/
|
|
195
|
+
export interface ProviderPatch {
|
|
196
|
+
model?: string;
|
|
197
|
+
endpoint?: string | null;
|
|
198
|
+
parameters?: ModelParameters | null;
|
|
199
|
+
maxRounds?: number | null;
|
|
200
|
+
}
|
|
201
|
+
|
|
177
202
|
/**
|
|
178
203
|
* The `provider` tool's contract. Both implementations declare `provider: ProviderToolContract`.
|
|
179
204
|
*
|
|
@@ -181,6 +206,8 @@ export interface ProviderActionResult {
|
|
|
181
206
|
* supplies its own, while node's executor requires one; `credentialKey`/`credentialEnvVar` name where
|
|
182
207
|
* node's vault should hold the secret, and the browser (which prompts and stores under its own key)
|
|
183
208
|
* ignores them.
|
|
209
|
+
*
|
|
210
|
+
* `update` carries no credential of any kind — see {@link ProviderPatch}.
|
|
184
211
|
*/
|
|
185
212
|
export type ProviderToolContract =
|
|
186
213
|
| ToolContract<ProviderListResult, { action: 'list' }>
|
|
@@ -195,4 +222,5 @@ export type ProviderToolContract =
|
|
|
195
222
|
parameters?: ModelParameters;
|
|
196
223
|
maxRounds?: number;
|
|
197
224
|
}>
|
|
225
|
+
| ToolContract<ProviderActionResult, { action: 'update'; name: string } & ProviderPatch>
|
|
198
226
|
| ToolContract<ProviderActionResult, { action: 'remove'; name: string }>;
|