@buoy-gg/agent-core 7.0.41 → 7.0.43
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/commonjs/blocks/receipts.js +1 -761
- package/lib/commonjs/blocks/runId.js +1 -31
- package/lib/commonjs/blocks/types.js +1 -140
- package/lib/commonjs/blocks/uiTool.js +6 -1405
- package/lib/commonjs/catalog/catalog.g.js +5 -4556
- package/lib/commonjs/catalog/catalog.source.json +249 -0
- package/lib/commonjs/catalog/catalog.types.g.js +1 -46
- package/lib/commonjs/catalog/normalizeParams.js +2 -332
- package/lib/commonjs/catalog/signature.js +1 -68
- package/lib/commonjs/catalog/snapshotReads.js +1 -263
- package/lib/commonjs/catalog/toProviderTools.js +2 -145
- package/lib/commonjs/catalog/validateParams.js +1 -129
- package/lib/commonjs/context/buildContextPack.js +1 -489
- package/lib/commonjs/effects/digest.js +1 -34
- package/lib/commonjs/effects/ledger.js +1 -345
- package/lib/commonjs/engine/askGate.js +1 -287
- package/lib/commonjs/engine/effectFor.js +1 -223
- package/lib/commonjs/engine/evidence.js +3 -111
- package/lib/commonjs/engine/historyBudget.js +1 -363
- package/lib/commonjs/engine/retrieve.js +1 -214
- package/lib/commonjs/engine/runAgentTurn.js +8 -1836
- package/lib/commonjs/engine/systemPrompt.js +54 -163
- package/lib/commonjs/engine/textToolCalls.js +1 -276
- package/lib/commonjs/engine/tokenCalibration.js +1 -81
- package/lib/commonjs/engine/verify.js +4 -297
- package/lib/commonjs/index.js +1 -384
- package/lib/commonjs/policy/labels.js +1 -319
- package/lib/commonjs/policy/policy.js +1 -148
- package/lib/commonjs/policy/redact.js +1 -172
- package/lib/commonjs/providers/anthropic.js +3 -445
- package/lib/commonjs/providers/openai.js +4 -324
- package/lib/commonjs/providers/problem.js +1 -98
- package/lib/commonjs/providers/sse.js +1 -240
- package/lib/commonjs/providers/streamTimer.js +1 -123
- package/lib/commonjs/providers/transport.js +1 -123
- package/lib/commonjs/providers/types.js +1 -6
- package/lib/commonjs/providers/xhrStream.js +1 -212
- package/lib/commonjs/realNow.js +1 -0
- package/lib/commonjs/session.js +1 -393
- package/lib/commonjs/types.js +0 -1
- package/lib/module/blocks/receipts.js +1 -755
- package/lib/module/blocks/runId.js +1 -26
- package/lib/module/blocks/types.js +1 -134
- package/lib/module/blocks/uiTool.js +6 -1396
- package/lib/module/catalog/catalog.g.js +5 -4552
- package/lib/module/catalog/catalog.source.json +249 -0
- package/lib/module/catalog/catalog.types.g.js +1 -42
- package/lib/module/catalog/normalizeParams.js +2 -326
- package/lib/module/catalog/signature.js +1 -63
- package/lib/module/catalog/snapshotReads.js +1 -259
- package/lib/module/catalog/toProviderTools.js +2 -139
- package/lib/module/catalog/validateParams.js +1 -124
- package/lib/module/context/buildContextPack.js +1 -485
- package/lib/module/effects/digest.js +1 -29
- package/lib/module/effects/ledger.js +1 -339
- package/lib/module/engine/askGate.js +1 -280
- package/lib/module/engine/effectFor.js +1 -220
- package/lib/module/engine/evidence.js +3 -105
- package/lib/module/engine/historyBudget.js +1 -355
- package/lib/module/engine/retrieve.js +1 -210
- package/lib/module/engine/runAgentTurn.js +8 -1827
- package/lib/module/engine/systemPrompt.js +54 -157
- package/lib/module/engine/textToolCalls.js +1 -270
- package/lib/module/engine/tokenCalibration.js +1 -75
- package/lib/module/engine/verify.js +4 -289
- package/lib/module/index.js +1 -35
- package/lib/module/policy/labels.js +1 -312
- package/lib/module/policy/policy.js +1 -142
- package/lib/module/policy/redact.js +1 -165
- package/lib/module/providers/anthropic.js +3 -441
- package/lib/module/providers/openai.js +4 -320
- package/lib/module/providers/problem.js +1 -92
- package/lib/module/providers/sse.js +1 -231
- package/lib/module/providers/streamTimer.js +1 -118
- package/lib/module/providers/transport.js +1 -119
- package/lib/module/providers/types.js +1 -4
- package/lib/module/providers/xhrStream.js +1 -207
- package/lib/module/realNow.js +1 -0
- package/lib/module/session.js +1 -369
- package/lib/module/types.js +0 -1
- package/lib/typescript/catalog/catalog.g.d.ts +3 -3
- package/lib/typescript/catalog/catalog.types.g.d.ts +3 -2
- package/lib/typescript/providers/problem.d.ts +0 -20
- package/lib/typescript/providers/streamTimer.d.ts +0 -24
- package/lib/typescript/realNow.d.ts +18 -0
- package/lib/web/index.mjs +52 -53
- package/package.json +1 -1
- package/lib/commonjs/blocks/receipts.js.map +0 -1
- package/lib/commonjs/blocks/runId.js.map +0 -1
- package/lib/commonjs/blocks/types.js.map +0 -1
- package/lib/commonjs/blocks/uiTool.js.map +0 -1
- package/lib/commonjs/catalog/catalog.g.js.map +0 -1
- package/lib/commonjs/catalog/catalog.types.g.js.map +0 -1
- package/lib/commonjs/catalog/normalizeParams.js.map +0 -1
- package/lib/commonjs/catalog/signature.js.map +0 -1
- package/lib/commonjs/catalog/snapshotReads.js.map +0 -1
- package/lib/commonjs/catalog/toProviderTools.js.map +0 -1
- package/lib/commonjs/catalog/validateParams.js.map +0 -1
- package/lib/commonjs/context/buildContextPack.js.map +0 -1
- package/lib/commonjs/effects/digest.js.map +0 -1
- package/lib/commonjs/effects/ledger.js.map +0 -1
- package/lib/commonjs/engine/askGate.js.map +0 -1
- package/lib/commonjs/engine/effectFor.js.map +0 -1
- package/lib/commonjs/engine/evidence.js.map +0 -1
- package/lib/commonjs/engine/historyBudget.js.map +0 -1
- package/lib/commonjs/engine/retrieve.js.map +0 -1
- package/lib/commonjs/engine/runAgentTurn.js.map +0 -1
- package/lib/commonjs/engine/systemPrompt.js.map +0 -1
- package/lib/commonjs/engine/textToolCalls.js.map +0 -1
- package/lib/commonjs/engine/tokenCalibration.js.map +0 -1
- package/lib/commonjs/engine/verify.js.map +0 -1
- package/lib/commonjs/index.js.map +0 -1
- package/lib/commonjs/policy/labels.js.map +0 -1
- package/lib/commonjs/policy/policy.js.map +0 -1
- package/lib/commonjs/policy/redact.js.map +0 -1
- package/lib/commonjs/providers/anthropic.js.map +0 -1
- package/lib/commonjs/providers/openai.js.map +0 -1
- package/lib/commonjs/providers/problem.js.map +0 -1
- package/lib/commonjs/providers/sse.js.map +0 -1
- package/lib/commonjs/providers/streamTimer.js.map +0 -1
- package/lib/commonjs/providers/transport.js.map +0 -1
- package/lib/commonjs/providers/types.js.map +0 -1
- package/lib/commonjs/providers/xhrStream.js.map +0 -1
- package/lib/commonjs/session.js.map +0 -1
- package/lib/commonjs/types.js.map +0 -1
- package/lib/module/blocks/receipts.js.map +0 -1
- package/lib/module/blocks/runId.js.map +0 -1
- package/lib/module/blocks/types.js.map +0 -1
- package/lib/module/blocks/uiTool.js.map +0 -1
- package/lib/module/catalog/catalog.g.js.map +0 -1
- package/lib/module/catalog/catalog.types.g.js.map +0 -1
- package/lib/module/catalog/normalizeParams.js.map +0 -1
- package/lib/module/catalog/signature.js.map +0 -1
- package/lib/module/catalog/snapshotReads.js.map +0 -1
- package/lib/module/catalog/toProviderTools.js.map +0 -1
- package/lib/module/catalog/validateParams.js.map +0 -1
- package/lib/module/context/buildContextPack.js.map +0 -1
- package/lib/module/effects/digest.js.map +0 -1
- package/lib/module/effects/ledger.js.map +0 -1
- package/lib/module/engine/askGate.js.map +0 -1
- package/lib/module/engine/effectFor.js.map +0 -1
- package/lib/module/engine/evidence.js.map +0 -1
- package/lib/module/engine/historyBudget.js.map +0 -1
- package/lib/module/engine/retrieve.js.map +0 -1
- package/lib/module/engine/runAgentTurn.js.map +0 -1
- package/lib/module/engine/systemPrompt.js.map +0 -1
- package/lib/module/engine/textToolCalls.js.map +0 -1
- package/lib/module/engine/tokenCalibration.js.map +0 -1
- package/lib/module/engine/verify.js.map +0 -1
- package/lib/module/index.js.map +0 -1
- package/lib/module/policy/labels.js.map +0 -1
- package/lib/module/policy/policy.js.map +0 -1
- package/lib/module/policy/redact.js.map +0 -1
- package/lib/module/providers/anthropic.js.map +0 -1
- package/lib/module/providers/openai.js.map +0 -1
- package/lib/module/providers/problem.js.map +0 -1
- package/lib/module/providers/sse.js.map +0 -1
- package/lib/module/providers/streamTimer.js.map +0 -1
- package/lib/module/providers/transport.js.map +0 -1
- package/lib/module/providers/types.js.map +0 -1
- package/lib/module/providers/xhrStream.js.map +0 -1
- package/lib/module/session.js.map +0 -1
- package/lib/module/types.js.map +0 -1
- package/lib/typescript/blocks/receipts.d.ts.map +0 -1
- package/lib/typescript/blocks/runId.d.ts.map +0 -1
- package/lib/typescript/blocks/types.d.ts.map +0 -1
- package/lib/typescript/blocks/uiTool.d.ts.map +0 -1
- package/lib/typescript/catalog/catalog.g.d.ts.map +0 -1
- package/lib/typescript/catalog/catalog.types.g.d.ts.map +0 -1
- package/lib/typescript/catalog/normalizeParams.d.ts.map +0 -1
- package/lib/typescript/catalog/signature.d.ts.map +0 -1
- package/lib/typescript/catalog/snapshotReads.d.ts.map +0 -1
- package/lib/typescript/catalog/toProviderTools.d.ts.map +0 -1
- package/lib/typescript/catalog/validateParams.d.ts.map +0 -1
- package/lib/typescript/context/buildContextPack.d.ts.map +0 -1
- package/lib/typescript/effects/digest.d.ts.map +0 -1
- package/lib/typescript/effects/ledger.d.ts.map +0 -1
- package/lib/typescript/engine/askGate.d.ts.map +0 -1
- package/lib/typescript/engine/effectFor.d.ts.map +0 -1
- package/lib/typescript/engine/evidence.d.ts.map +0 -1
- package/lib/typescript/engine/historyBudget.d.ts.map +0 -1
- package/lib/typescript/engine/retrieve.d.ts.map +0 -1
- package/lib/typescript/engine/runAgentTurn.d.ts.map +0 -1
- package/lib/typescript/engine/systemPrompt.d.ts.map +0 -1
- package/lib/typescript/engine/textToolCalls.d.ts.map +0 -1
- package/lib/typescript/engine/tokenCalibration.d.ts.map +0 -1
- package/lib/typescript/engine/verify.d.ts.map +0 -1
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/policy/labels.d.ts.map +0 -1
- package/lib/typescript/policy/policy.d.ts.map +0 -1
- package/lib/typescript/policy/redact.d.ts.map +0 -1
- package/lib/typescript/providers/anthropic.d.ts.map +0 -1
- package/lib/typescript/providers/openai.d.ts.map +0 -1
- package/lib/typescript/providers/problem.d.ts.map +0 -1
- package/lib/typescript/providers/sse.d.ts.map +0 -1
- package/lib/typescript/providers/streamTimer.d.ts.map +0 -1
- package/lib/typescript/providers/transport.d.ts.map +0 -1
- package/lib/typescript/providers/types.d.ts.map +0 -1
- package/lib/typescript/providers/xhrStream.d.ts.map +0 -1
- package/lib/typescript/session.d.ts.map +0 -1
- package/lib/typescript/types.d.ts.map +0 -1
|
@@ -1,139 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Catalog -> provider tool definitions.
|
|
5
|
-
*
|
|
6
|
-
* WHY ONE TOOL PER BUOY TOOL, NOT ONE PER ACTION: tool-selection accuracy
|
|
7
|
-
* degrades past roughly 30-50 tools. Buoy has ~179 actions across 22 tools, so
|
|
8
|
-
* a 1:1 mapping is far past the point where the model starts picking wrong.
|
|
9
|
-
* Each Buoy tool therefore becomes ONE provider tool whose `action` property is
|
|
10
|
-
* an enum, with the per-action summaries folded into that enum's description.
|
|
11
|
-
*
|
|
12
|
-
* `params` stays an open object at the provider boundary — a discriminated
|
|
13
|
-
* union across 179 branches is unusable by any model and unreadable by a human.
|
|
14
|
-
* The real per-action schema is enforced one layer in, by `validateParams`,
|
|
15
|
-
* which returns a structured error the model can correct on the next turn.
|
|
16
|
-
* That is strictly stronger than the MCP server's `z.record(z.unknown())`,
|
|
17
|
-
* which validates nothing.
|
|
18
|
-
*/
|
|
19
|
-
import { paramsLine } from "./signature";
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Provider-agnostic tool definition; the adapters reshape it per protocol.
|
|
23
|
-
*
|
|
24
|
-
* The description comes in three forms because the two protocols cap it
|
|
25
|
-
* differently. Anthropic takes `description` whole. OpenAI (and Azure, and
|
|
26
|
-
* every OpenAI-compatible gateway) caps a function description at 1024
|
|
27
|
-
* chars, and the catalog renders the summary first and the `Actions:` list
|
|
28
|
-
* LAST — so trimming `description` to fit dropped every action line for 23
|
|
29
|
-
* of 24 tools (the 24th kept one line of sixteen), and a model on that
|
|
30
|
-
* protocol saw a summary cut mid-sentence plus a bare `action` enum. Hence
|
|
31
|
-
* the split: `summaryDescription` is the part that fits the cap,
|
|
32
|
-
* `actionsBlock` goes into the `action` property's description, which
|
|
33
|
-
* nothing caps. `description` stays their concatenation
|
|
34
|
-
* so the Anthropic request is byte-identical to what it was.
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Both Anthropic and OpenAI cap tool names at `[a-zA-Z0-9_-]`, so Buoy's
|
|
39
|
-
* dashed ids survive but the `custom:<id>` sync namespace does not. Anthropic's
|
|
40
|
-
* docs say 64 chars while its reference schema says 128 — we code to 64.
|
|
41
|
-
*/
|
|
42
|
-
const MAX_TOOL_NAME = 64;
|
|
43
|
-
export function toProviderToolName(toolId) {
|
|
44
|
-
return `buoy_${toolId.replace(/[^a-zA-Z0-9_-]/g, "_")}`.slice(0, MAX_TOOL_NAME);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** Reverse of {@link toProviderToolName}, resolved against the live catalog. */
|
|
48
|
-
export function fromProviderToolName(name, catalog) {
|
|
49
|
-
return catalog.find(t => toProviderToolName(t.toolId) === name)?.toolId;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* One line per action, in the `action` enum's description. This is where the
|
|
54
|
-
* model actually learns what each action does, so it carries the effect and
|
|
55
|
-
* the release caveat inline rather than hiding them in a separate field the
|
|
56
|
-
* model never sees.
|
|
57
|
-
*/
|
|
58
|
-
function actionLine(a, isRelease) {
|
|
59
|
-
const bits = [`${a.action} — ${a.summary}`];
|
|
60
|
-
if (a.effect === "destructive") bits.push("[DESTRUCTIVE]");else if (a.effect === "write") bits.push("[changes state]");
|
|
61
|
-
if (isRelease && a.release !== "works") {
|
|
62
|
-
bits.push(`[UNAVAILABLE in this build: ${a.release}]`);
|
|
63
|
-
}
|
|
64
|
-
if (a.requires?.length) bits.push(`[needs: ${a.requires.join(", ")}]`);
|
|
65
|
-
// The field names, from the SAME schema `validateParams` enforces. Without
|
|
66
|
-
// them the model reconstructs parameter names from prose and invents one on
|
|
67
|
-
// ~18% of param-carrying calls (measured across three agents); five of the
|
|
68
|
-
// commonest misses are patched up by `normalizeParams`, the rest just fail.
|
|
69
|
-
// `buoy_ui` already ships its signatures for exactly this reason — see the
|
|
70
|
-
// note above `signature()` in catalog/signature.ts.
|
|
71
|
-
const sig = paramsLine(a.params);
|
|
72
|
-
return sig ? `${bits.join(" ")}\n ${sig}` : bits.join(" ");
|
|
73
|
-
}
|
|
74
|
-
export function toProviderTools(catalog, opts = {}) {
|
|
75
|
-
const {
|
|
76
|
-
availableToolIds,
|
|
77
|
-
availableActions,
|
|
78
|
-
isRelease = false,
|
|
79
|
-
hideUnavailable = false
|
|
80
|
-
} = opts;
|
|
81
|
-
const tools = [];
|
|
82
|
-
for (const tool of catalog) {
|
|
83
|
-
if (availableToolIds && !availableToolIds.includes(tool.toolId)) continue;
|
|
84
|
-
const live = availableActions?.[tool.toolId];
|
|
85
|
-
// An engine-served action needs no adapter to advertise it — the engine
|
|
86
|
-
// is the adapter — so it rides with the tool whenever the tool is here.
|
|
87
|
-
let actions = live ? tool.actions.filter(a => live.includes(a.action) || a.servedBy === "engine") : tool.actions;
|
|
88
|
-
if (isRelease && hideUnavailable) {
|
|
89
|
-
actions = actions.filter(a => a.release === "works");
|
|
90
|
-
}
|
|
91
|
-
if (actions.length === 0) continue;
|
|
92
|
-
|
|
93
|
-
// The summary ALONE is what has to fit OpenAI's 1024-char cap (it does for
|
|
94
|
-
// 23 of 24 tools); the availability caveat rides with the actions block,
|
|
95
|
-
// which nothing caps. Concatenated they are the same bytes as before.
|
|
96
|
-
const summaryDescription = tool.summary;
|
|
97
|
-
// These prose lines look like the expensive part of the catalog and are
|
|
98
|
-
// the CHEAPEST part of it. Measured against a real tokenizer (fal ->
|
|
99
|
-
// gpt-4o-mini): the whole catalog is 79,601 chars but only 7,902 tokens
|
|
100
|
-
// — 10.1 chars/token, because English prose is what BPE compresses best.
|
|
101
|
-
// An index that replaced these lines with a bare list of action names
|
|
102
|
-
// sent 48% fewer characters and cost MORE tokens (7,986), since dotted
|
|
103
|
-
// camelCase identifiers tokenize at ~5 chars/token. Do not "shrink" this
|
|
104
|
-
// by counting characters; measure tokens or leave it alone.
|
|
105
|
-
const actionsBlock = [tool.unavailableWhen ? `Unavailable when: ${tool.unavailableWhen}` : "", "Actions:", ...actions.map(a => `- ${actionLine(a, isRelease)}`)].join("\n");
|
|
106
|
-
// No blank line between the two: the single-list render this replaced
|
|
107
|
-
// filtered its "" separator out, and this string is the prefix Anthropic
|
|
108
|
-
// caches — it must not move by a byte.
|
|
109
|
-
const desc = [summaryDescription, actionsBlock].filter(Boolean).join("\n");
|
|
110
|
-
const inputExamples = actions.flatMap(a => a.inputExamples ?? []);
|
|
111
|
-
tools.push({
|
|
112
|
-
name: toProviderToolName(tool.toolId),
|
|
113
|
-
...(inputExamples.length ? {
|
|
114
|
-
inputExamples
|
|
115
|
-
} : {}),
|
|
116
|
-
description: desc,
|
|
117
|
-
summaryDescription,
|
|
118
|
-
actionsBlock,
|
|
119
|
-
inputSchema: {
|
|
120
|
-
type: "object",
|
|
121
|
-
properties: {
|
|
122
|
-
action: {
|
|
123
|
-
type: "string",
|
|
124
|
-
enum: actions.map(a => a.action),
|
|
125
|
-
description: "Which action to run. See the list in this tool's description."
|
|
126
|
-
},
|
|
127
|
-
params: {
|
|
128
|
-
type: "object",
|
|
129
|
-
description: "Arguments for the action. Each action's `params:` line in this tool's description lists its exact fields — `*` marks a required one. Send EXACTLY those names; a field that is not listed is rejected."
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
required: ["action"],
|
|
133
|
-
additionalProperties: false
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
return tools;
|
|
138
|
-
}
|
|
139
|
-
//# sourceMappingURL=toProviderTools.js.map
|
|
1
|
+
"use strict";import{paramsLine as h}from"./signature";const v=64;export function toProviderToolName(e){return`buoy_${e.replace(/[^a-zA-Z0-9_-]/g,"_")}`.slice(0,v)}export function fromProviderToolName(e,s){return s.find(t=>toProviderToolName(t.toolId)===e)?.toolId}function b(e,s){const t=[`${e.action} \u2014 ${e.summary}`];if(e.effect==="destructive")t.push("[DESTRUCTIVE]");else if(e.effect==="write")t.push("[changes state]");if(s&&e.release!=="works"){t.push(`[UNAVAILABLE in this build: ${e.release}]`)}if(e.requires?.length)t.push(`[needs: ${e.requires.join(", ")}]`);const r=h(e.params);return r?`${t.join(" ")}
|
|
2
|
+
${r}`:t.join(" ")}export function toProviderTools(e,s={}){const{availableToolIds:t,availableActions:r,isRelease:a=false,hideUnavailable:f=false}=s;const l=[];for(const o of e){if(t&&!t.includes(o.toolId))continue;const c=r?.[o.toolId];let n=c?o.actions.filter(i=>c.includes(i.action)||i.servedBy==="engine"):o.actions;if(a&&f){n=n.filter(i=>i.release==="works")}if(n.length===0)continue;const u=o.summary;const p=[o.unavailableWhen?`Unavailable when: ${o.unavailableWhen}`:"","Actions:",...n.map(i=>`- ${b(i,a)}`)].join("\n");const m=[u,p].filter(Boolean).join("\n");const d=n.flatMap(i=>i.inputExamples??[]);l.push({name:toProviderToolName(o.toolId),...d.length?{inputExamples:d}:{},description:m,summaryDescription:u,actionsBlock:p,inputSchema:{type:"object",properties:{action:{type:"string",enum:n.map(i=>i.action),description:"Which action to run. See the list in this tool's description."},params:{type:"object",description:"Arguments for the action. Each action's `params:` line in this tool's description lists its exact fields \u2014 `*` marks a required one. Send EXACTLY those names; a field that is not listed is rejected."}},required:["action"],additionalProperties:false}})}return l}
|
|
@@ -1,124 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A deliberately small JSON Schema validator.
|
|
5
|
-
*
|
|
6
|
-
* Buoy's adapters validate nothing — every handler takes `params?: unknown` and
|
|
7
|
-
* hand-casts (`(params as { id?: string })?.id`), so a wrong shape becomes an
|
|
8
|
-
* undefined read, and an LLM omitting an optional flag can do real damage:
|
|
9
|
-
* `zustand.setState` defaults `replace ?? true`, so calling it without
|
|
10
|
-
* `replace` REPLACES the entire store rather than merging it.
|
|
11
|
-
*
|
|
12
|
-
* So the agent validates before it dispatches. The point is not spec
|
|
13
|
-
* compliance — it is that a rejection comes back to the model as a readable
|
|
14
|
-
* error naming the expected schema, which it can fix on the next turn. That is
|
|
15
|
-
* why this covers exactly the subset `JsonSchema` describes and nothing more:
|
|
16
|
-
* a rule the validator silently skips is a rule that isn't enforced.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
function typeOf(v) {
|
|
20
|
-
if (v === null) return "null";
|
|
21
|
-
if (Array.isArray(v)) return "array";
|
|
22
|
-
return typeof v;
|
|
23
|
-
}
|
|
24
|
-
function checkType(value, type) {
|
|
25
|
-
switch (type) {
|
|
26
|
-
case "integer":
|
|
27
|
-
return typeof value === "number" && Number.isInteger(value);
|
|
28
|
-
case "number":
|
|
29
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
30
|
-
case "null":
|
|
31
|
-
return value === null;
|
|
32
|
-
case "array":
|
|
33
|
-
return Array.isArray(value);
|
|
34
|
-
case "object":
|
|
35
|
-
return typeOf(value) === "object";
|
|
36
|
-
default:
|
|
37
|
-
return typeof value === type;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function validate(value, schema, path, errors) {
|
|
41
|
-
if (schema.anyOf?.length) {
|
|
42
|
-
const anyOk = schema.anyOf.some(s => {
|
|
43
|
-
const sub = [];
|
|
44
|
-
validate(value, s, path, sub);
|
|
45
|
-
return sub.length === 0;
|
|
46
|
-
});
|
|
47
|
-
if (!anyOk) {
|
|
48
|
-
const kinds = schema.anyOf.map(s => s.type ?? "?").join(" | ");
|
|
49
|
-
errors.push(`${path}: expected ${kinds}, got ${typeOf(value)}`);
|
|
50
|
-
}
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
if (schema.type && !checkType(value, schema.type)) {
|
|
54
|
-
errors.push(`${path}: expected ${schema.type}, got ${typeOf(value)}`);
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
if (schema.enum && !schema.enum.includes(value)) {
|
|
58
|
-
errors.push(`${path}: expected one of ${schema.enum.map(e => JSON.stringify(e)).join(", ")}, got ${JSON.stringify(value)}`);
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
if (schema.type === "array" && Array.isArray(value)) {
|
|
62
|
-
if (schema.minItems !== undefined && value.length < schema.minItems) {
|
|
63
|
-
errors.push(`${path}: expected at least ${schema.minItems} item(s), got ${value.length}`);
|
|
64
|
-
}
|
|
65
|
-
if (schema.maxItems !== undefined && value.length > schema.maxItems) {
|
|
66
|
-
errors.push(`${path}: expected at most ${schema.maxItems} item(s), got ${value.length}`);
|
|
67
|
-
}
|
|
68
|
-
if (schema.items) {
|
|
69
|
-
value.forEach((item, i) => validate(item, schema.items, `${path}[${i}]`, errors));
|
|
70
|
-
}
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
if (schema.type === "object" && typeOf(value) === "object") {
|
|
74
|
-
const obj = value;
|
|
75
|
-
for (const key of schema.required ?? []) {
|
|
76
|
-
if (obj[key] === undefined) errors.push(`${path}.${key}: required`);
|
|
77
|
-
}
|
|
78
|
-
if (schema.properties) {
|
|
79
|
-
for (const [key, sub] of Object.entries(schema.properties)) {
|
|
80
|
-
if (obj[key] !== undefined) validate(obj[key], sub, `${path}.${key}`, errors);
|
|
81
|
-
}
|
|
82
|
-
// Only flag unknown keys when the schema says so. Several adapters read
|
|
83
|
-
// params they never documented, and rejecting an extra key the handler
|
|
84
|
-
// happens to use would break a call that would have worked.
|
|
85
|
-
if (schema.additionalProperties === false) {
|
|
86
|
-
const known = new Set(Object.keys(schema.properties));
|
|
87
|
-
for (const key of Object.keys(obj)) {
|
|
88
|
-
if (!known.has(key)) errors.push(`${path}.${key}: unexpected property`);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
export function validateParams(params, schema) {
|
|
95
|
-
const errors = [];
|
|
96
|
-
// A no-param action called with nothing is the common case, not an error.
|
|
97
|
-
const value = params === undefined || params === null ? {} : params;
|
|
98
|
-
validate(value, schema, "params", errors);
|
|
99
|
-
return {
|
|
100
|
-
ok: errors.length === 0,
|
|
101
|
-
errors
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Fill in documented defaults the model left out.
|
|
107
|
-
*
|
|
108
|
-
* This is the counter-measure to the omitted-flag class of bug. Several Buoy
|
|
109
|
-
* actions invert the usual assumption — `focus-inspector.setTracking` reads
|
|
110
|
-
* `params?.enabled !== false`, so calling it with `{}` turns tracking ON — and
|
|
111
|
-
* the catalog records the real default. Applying it explicitly means the model
|
|
112
|
-
* omitting a flag produces the documented behaviour rather than the accidental
|
|
113
|
-
* one.
|
|
114
|
-
*/
|
|
115
|
-
export function applyDefaults(params, schema) {
|
|
116
|
-
const out = typeOf(params) === "object" ? {
|
|
117
|
-
...params
|
|
118
|
-
} : {};
|
|
119
|
-
for (const [key, sub] of Object.entries(schema.properties ?? {})) {
|
|
120
|
-
if (out[key] === undefined && sub.default !== undefined) out[key] = sub.default;
|
|
121
|
-
}
|
|
122
|
-
return out;
|
|
123
|
-
}
|
|
124
|
-
//# sourceMappingURL=validateParams.js.map
|
|
1
|
+
"use strict";function u(t){if(t===null)return"null";if(Array.isArray(t))return"array";return typeof t}function s(t,e){switch(e){case"integer":return typeof t==="number"&&Number.isInteger(t);case"number":return typeof t==="number"&&Number.isFinite(t);case"null":return t===null;case"array":return Array.isArray(t);case"object":return u(t)==="object";default:return typeof t===e}}function y(t,e,n,i){if(e.anyOf?.length){const f=e.anyOf.some(r=>{const o=[];y(t,r,n,o);return o.length===0});if(!f){const r=e.anyOf.map(o=>o.type??"?").join(" | ");i.push(`${n}: expected ${r}, got ${u(t)}`)}return}if(e.type&&!s(t,e.type)){i.push(`${n}: expected ${e.type}, got ${u(t)}`);return}if(e.enum&&!e.enum.includes(t)){i.push(`${n}: expected one of ${e.enum.map(f=>JSON.stringify(f)).join(", ")}, got ${JSON.stringify(t)}`);return}if(e.type==="array"&&Array.isArray(t)){if(e.minItems!==void 0&&t.length<e.minItems){i.push(`${n}: expected at least ${e.minItems} item(s), got ${t.length}`)}if(e.maxItems!==void 0&&t.length>e.maxItems){i.push(`${n}: expected at most ${e.maxItems} item(s), got ${t.length}`)}if(e.items){t.forEach((f,r)=>y(f,e.items,`${n}[${r}]`,i))}return}if(e.type==="object"&&u(t)==="object"){const f=t;for(const r of e.required??[]){if(f[r]===void 0)i.push(`${n}.${r}: required`)}if(e.properties){for(const[r,o]of Object.entries(e.properties)){if(f[r]!==void 0)y(f[r],o,`${n}.${r}`,i)}if(e.additionalProperties===false){const r=new Set(Object.keys(e.properties));for(const o of Object.keys(f)){if(!r.has(o))i.push(`${n}.${o}: unexpected property`)}}}}}export function validateParams(t,e){const n=[];const i=t===void 0||t===null?{}:t;y(i,e,"params",n);return{ok:n.length===0,errors:n}}export function applyDefaults(t,e){const n=u(t)==="object"?{...t}:{};for(const[i,f]of Object.entries(e.properties??{})){if(n[i]===void 0&&f.default!==void 0)n[i]=f.default}return n}
|