@xiaoso/dsh-tool-plus 0.1.16 → 0.1.17-beta.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.
Files changed (109) hide show
  1. package/lib/{abort-DZ54CaKU.mjs → abort-BTblp0Rt.mjs} +2 -2
  2. package/lib/{alibaba-coding-plan-DODpkcqi.mjs → alibaba-coding-plan-t3R4YKCB.mjs} +3 -3
  3. package/lib/{alibaba-token-plan-C6lpKCda.mjs → alibaba-token-plan-CO4djG1y.mjs} +4 -4
  4. package/lib/{alibaba-token-plan-CHGyWOfX.mjs → alibaba-token-plan-CUjYJX0-.mjs} +1 -1
  5. package/lib/{anthropic-Dv_GGX6g.mjs → anthropic-nf7w6so1.mjs} +48 -21
  6. package/lib/{api-key-validation-MnMf_ihX.mjs → api-key-validation-C_tZ7Y9a.mjs} +2 -2
  7. package/lib/behavior-BwvTUtag.mjs +111 -0
  8. package/lib/{browser-render-BZXt548F.mjs → browser-render-BQaEVK_n.mjs} +4 -4
  9. package/lib/{reference-CtvM4zLU.mjs → bundled-references-CrQ4dQcT.mjs} +57 -4
  10. package/lib/cascade-BWjRTD1q.mjs +30265 -0
  11. package/lib/{cline-pass-BT9CBEOj.mjs → cline-pass-Bjm-O8GG.mjs} +2 -2
  12. package/lib/cloudflare-CKXRJ0l9.mjs +37 -0
  13. package/lib/{cloudflare-ai-gateway-DReN6ohJ.mjs → cloudflare-ai-gateway-BpnBSjwV.mjs} +8 -4
  14. package/lib/cloudflare-workers-ai-odj9XswL.mjs +32 -0
  15. package/lib/collapse-_nkb2dn7.mjs +1945 -0
  16. package/lib/{coreweave-C82HrLpb.mjs → coreweave-CGDZOD8-.mjs} +1 -1
  17. package/lib/{coreweave-C68UgRQO.mjs → coreweave-DwffcgW5.mjs} +4 -4
  18. package/lib/cursor-BgOuV7Qf.mjs +794 -0
  19. package/lib/{cursor-_gHHq-Dq.mjs → cursor-CF1iHHbv.mjs} +68 -19
  20. package/lib/{cursor-proto-Cr_WEMuv.mjs → cursor-proto-BuNTjX3L.mjs} +823 -23
  21. package/lib/{devin-QpfTSl9H.mjs → devin-7OEeEb80.mjs} +112 -31
  22. package/lib/{devin-proto-DYhp4Ty6.mjs → devin-proto-C-QreeAv.mjs} +71 -5
  23. package/lib/{dom-DG3sPESc.mjs → dom-BmbZv4v9.mjs} +598 -182
  24. package/lib/{error-O63pC8zg.mjs → error-8LVo7tug.mjs} +725 -104
  25. package/lib/factory-droid-ChhmsGWb.mjs +71 -0
  26. package/lib/{fs-promises-shim-B2YFWkcd.mjs → fs-promises-shim-CANAxFWh.mjs} +10 -1
  27. package/lib/{github-copilot-BMEcw8N1.mjs → github-copilot-QwevdT30.mjs} +4 -4
  28. package/lib/{github-copilot-headers-DnjGEbko.mjs → github-copilot-headers-CAUZ0rUD.mjs} +138 -26
  29. package/lib/{gitlab-duo-DnHqJjFY.mjs → gitlab-duo-DigV7k_o.mjs} +2 -2
  30. package/lib/{google-antigravity-B1mSckrK.mjs → google-antigravity-D-oe0r8A.mjs} +6 -7
  31. package/lib/{google-gemini-cli-DJwThCCn.mjs → google-gemini-cli-CQBHgGJT.mjs} +5 -6
  32. package/lib/{google-oauth-shared-BctLpVUN.mjs → google-oauth-shared-CvgVIUwJ.mjs} +2 -2
  33. package/lib/google-validation-CdvRj4ec.mjs +126 -0
  34. package/lib/id-EJwVLDHE.mjs +2548 -0
  35. package/lib/index.mjs +248 -258
  36. package/lib/{kilo-BEgEwMJQ.mjs → kilo-5r6OffCa.mjs} +2 -2
  37. package/lib/{kimi-T9NldEIJ.mjs → kimi-DOOtbXmm.mjs} +9 -10
  38. package/lib/{launch-BIWNyrBB.mjs → launch-DkAjib7h.mjs} +1 -1
  39. package/lib/{markit-Dvp2JPdT.mjs → markit-CCcyeAds.mjs} +359 -140
  40. package/lib/{models-DnXMYGcJ.mjs → models-DCpDT_im.mjs} +199203 -112275
  41. package/lib/{muse-code-CNvqqAp6.mjs → muse-code-CYf8zj_B.mjs} +5 -5
  42. package/lib/{openai-codex-D5-CyTxa.mjs → openai-codex-Cj-TvSFh.mjs} +13 -10
  43. package/lib/{perplexity-A2PEoGaC.mjs → perplexity-Dh_Qgsmx.mjs} +68 -25
  44. package/lib/{pkce-BYjmugmw.mjs → pkce-DO-jBJLV.mjs} +1 -1
  45. package/lib/pricing-DusBEhwm.mjs +593 -0
  46. package/lib/{readability-uGhqb4GC.mjs → readability-XHK0o3bv.mjs} +287 -27
  47. package/lib/{scrapers-C1ujjV8k.mjs → scrapers-B6PADOVm.mjs} +13 -13
  48. package/lib/slugify-ynYWBIA5.mjs +11 -0
  49. package/lib/snowflake-B_jap6lz.mjs +666 -0
  50. package/lib/snowflake-Cu1ZyOp6.mjs +151 -0
  51. package/lib/{src-AELUUb5U.mjs → src-BhinCSpi.mjs} +1172 -458
  52. package/lib/{stream-AVOoe5Hj.mjs → stream-D2ivg3GH.mjs} +3740 -5311
  53. package/lib/{turndown-D6fof1OX.mjs → turndown-Vya8SavL.mjs} +82 -30
  54. package/lib/types/tools/hashline/native/index.d.ts +2 -2
  55. package/lib/types/tools/hashline/native/policy.d.ts +19 -21
  56. package/lib/types/tools/omp/session/agent-storage.d.ts +3 -3
  57. package/lib/types/tools/shared/bun-named-shim.d.ts +5 -0
  58. package/lib/{types-BLrLohwK.mjs → types-tH1v9uRm.mjs} +2 -2
  59. package/lib/{utils-cZX3f_Ls.mjs → utils-C_Ncya1r.mjs} +1737 -509
  60. package/lib/utils-D2tK38xq.mjs +34006 -0
  61. package/lib/{utils-I4I8azHN.mjs → utils-DrDwmNtu.mjs} +8 -3
  62. package/lib/{xai-oauth-CbeldUSV.mjs → xai-oauth-DLLzX6my.mjs} +4 -4
  63. package/lib/{xiaomi-Dl3VSs04.mjs → xiaomi-CqK-KivK.mjs} +2 -2
  64. package/lib/{zai-FyjGSypr.mjs → zai-DoJ2xPIH.mjs} +2 -2
  65. package/lib/{zip-DRrycScC.mjs → zip-DG1mUV6X.mjs} +1 -1
  66. package/package.json +8 -8
  67. package/lib/amazon-bedrock-Dx0rr9dY.mjs +0 -996
  68. package/lib/anthropic-ClCw0PV_.mjs +0 -3624
  69. package/lib/anthropic-wire-lbGAFzYb.mjs +0 -927
  70. package/lib/azure-openai-responses-WE_bgFWp.mjs +0 -285
  71. package/lib/bundled-references-DY3EJxZV.mjs +0 -56
  72. package/lib/cloudflare-ai-gateway-CrMa97Ap.mjs +0 -44
  73. package/lib/collapse-CkMNRNr7.mjs +0 -2304
  74. package/lib/cursor-C6jaIJDg.mjs +0 -283
  75. package/lib/cursor-D-XZYDf_.mjs +0 -4544
  76. package/lib/deterministic-id-CUEIMSqR.mjs +0 -17
  77. package/lib/devin-ExGIghmx.mjs +0 -69
  78. package/lib/devin-u0ljw5P6.mjs +0 -628
  79. package/lib/effort-BdtQMN-_.mjs +0 -23
  80. package/lib/event-stream-BKEtb45Y.mjs +0 -167
  81. package/lib/gemini-headers-Co9cVvex.mjs +0 -54
  82. package/lib/google-auth-qAN-6DMW.mjs +0 -232
  83. package/lib/google-gemini-cli-B2Aw1S5w.mjs +0 -844
  84. package/lib/google-lTxuq28n.mjs +0 -38
  85. package/lib/google-shared-Y01j9xOr.mjs +0 -856
  86. package/lib/google-validation-BEkNs-Bx.mjs +0 -18
  87. package/lib/google-vertex-DcM-FRC5.mjs +0 -99
  88. package/lib/hosts-00rjRzUD.mjs +0 -203
  89. package/lib/id-AL5obQzR.mjs +0 -71
  90. package/lib/idle-iterator-D0ZXEcUq.mjs +0 -366
  91. package/lib/ollama-6R0oXZks.mjs +0 -574
  92. package/lib/openai-codex-responses-C8bnBWOe.mjs +0 -3232
  93. package/lib/openai-completions-DNr3mUsn.mjs +0 -1430
  94. package/lib/openai-configuration-update-xMYUjaK_.mjs +0 -150
  95. package/lib/openai-reasoning-fallback-Ju-5pSR8.mjs +0 -380
  96. package/lib/openai-responses-CjpafAEr.mjs +0 -861
  97. package/lib/protobuf-BMgDYu_U.mjs +0 -717
  98. package/lib/provider-response-SqKSkkUc.mjs +0 -22
  99. package/lib/proxy-DxvCQOCA.mjs +0 -230
  100. package/lib/request-debug-BwPOqN_j.mjs +0 -183
  101. package/lib/sanitize-text-BCf5KmCf.mjs +0 -33
  102. package/lib/sse-debug-B-tkLCPW.mjs +0 -11
  103. package/lib/stream-markup-healing-CN3RsqG9.mjs +0 -267
  104. package/lib/strict-tool-validation-CBTz1dAA.mjs +0 -105
  105. package/lib/taxonomy-DSIM99rS.mjs +0 -15392
  106. package/lib/thinking-ngMwf_1Y.mjs +0 -336
  107. package/lib/type-guards-CttAANEx.mjs +0 -11
  108. package/lib/utils-CE3DSebh.mjs +0 -11763
  109. package/lib/vision-guard-BCpXWUj3.mjs +0 -77
@@ -1,267 +0,0 @@
1
- import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
- __installBunShim();
3
- import { E as createInbandScanner } from "./utils-cZX3f_Ls.mjs";
4
- import { t as ThinkingInbandScanner } from "./thinking-ngMwf_1Y.mjs";
5
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/dialect/qwen-xml.ts
6
- const SECTION_OPEN = "<tool_calls>";
7
- const SECTION_CLOSE = "</tool_calls>";
8
- const TOOL_ELEMENT = /^<([A-Za-z_][\w.-]*)(\s[^<>]*?)?\s*\/>$/s;
9
- const ATTRIBUTE = /([A-Za-z_][\w.-]*)\s*=\s*("([^"]*)"|'([^']*)')/g;
10
- var QwenXmlInbandScanner = class {
11
- #buffer = "";
12
- #insideSection = false;
13
- feed(chunk) {
14
- this.#buffer += chunk;
15
- return this.#drain(false);
16
- }
17
- flush() {
18
- return this.#drain(true);
19
- }
20
- #drain(flush) {
21
- const events = [];
22
- while (this.#buffer.length > 0) {
23
- if (!this.#insideSection) {
24
- const open = this.#buffer.indexOf(SECTION_OPEN);
25
- if (open >= 0) {
26
- if (open > 0) events.push({
27
- type: "text",
28
- text: this.#buffer.slice(0, open)
29
- });
30
- this.#buffer = this.#buffer.slice(open + 12);
31
- this.#insideSection = true;
32
- continue;
33
- }
34
- if (flush) {
35
- events.push({
36
- type: "text",
37
- text: this.#buffer
38
- });
39
- this.#buffer = "";
40
- break;
41
- }
42
- const held = longestSuffixPrefix(this.#buffer, SECTION_OPEN);
43
- const visibleLength = this.#buffer.length - held;
44
- if (visibleLength > 0) {
45
- events.push({
46
- type: "text",
47
- text: this.#buffer.slice(0, visibleLength)
48
- });
49
- this.#buffer = this.#buffer.slice(visibleLength);
50
- }
51
- break;
52
- }
53
- const close = this.#buffer.indexOf(SECTION_CLOSE);
54
- if (close < 0) {
55
- if (flush) this.#buffer = "";
56
- break;
57
- }
58
- const section = this.#buffer.slice(0, close);
59
- for (const element of section.match(/<[^<>]+\/>/gs) ?? []) {
60
- const call = parseToolElement(element);
61
- if (!call) continue;
62
- const id = `call_${crypto.randomUUID().replace(/-/g, "").slice(0, 24)}`;
63
- events.push({
64
- type: "toolStart",
65
- id,
66
- name: call.name
67
- });
68
- events.push({
69
- type: "toolEnd",
70
- id,
71
- name: call.name,
72
- arguments: call.arguments,
73
- rawBlock: element
74
- });
75
- }
76
- this.#buffer = this.#buffer.slice(close + 13);
77
- this.#insideSection = false;
78
- }
79
- return events;
80
- }
81
- };
82
- function parseToolElement(element) {
83
- const match = TOOL_ELEMENT.exec(element);
84
- if (!match) return void 0;
85
- const args = {};
86
- for (const attribute of match[2]?.matchAll(ATTRIBUTE) ?? []) args[attribute[1]] = attribute[3] ?? attribute[4] ?? "";
87
- return {
88
- name: match[1],
89
- arguments: args
90
- };
91
- }
92
- function longestSuffixPrefix(text, target) {
93
- const max = Math.min(text.length, target.length - 1);
94
- for (let length = max; length > 0; length--) if (text.endsWith(target.slice(0, length))) return length;
95
- return 0;
96
- }
97
- //#endregion
98
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/utils/stream-markup-healing.ts
99
- /**
100
- * Streaming-safe filters for leaked chat-template tool-call and thinking markup.
101
- *
102
- * Hosted models sometimes leak raw template markup into visible `content` instead
103
- * of returning structured events. Tool-call healing delegates to the same
104
- * dialect scanners used by owned in-band tool calling; this file keeps the
105
- * provider-facing compatibility wrapper and model/provider gating.
106
- */
107
- const KIMI_SECTION_END = "<|tool_calls_section_end|>";
108
- const DSML_TOOL_CALLS_CLOSE_FULLWIDTH = "</|DSML|tool_calls>";
109
- const DSML_TOOL_CALLS_CLOSE_ASCII = "</|DSML|tool_calls>";
110
- /**
111
- * State machine that consumes streamed visible text and emits cleaned text,
112
- * thinking deltas, and reconstructed tool calls.
113
- *
114
- * A {@link ThinkingInbandScanner} always heals leaked reasoning idioms
115
- * (`<think>`, `<thinking>`, ` ```thinking `, Gemma/Harmony channels, …) out of
116
- * the visible channel. For Kimi / DeepSeek-DSML the provider tool-call grammar
117
- * runs first and its cleaned text is piped through that thinking healer, so a
118
- * model can leak tool-call markup and reasoning in the same stream.
119
- *
120
- * Feed only one stream channel (usually `delta.content` / `message.content`).
121
- * Mixing reasoning and visible text into the same instance can corrupt held-back
122
- * partial tag buffers.
123
- */
124
- var StreamMarkupHealing = class {
125
- #pattern;
126
- /** Provider tool-call grammar (Kimi tokens / DSML envelope); absent for plain text streams. */
127
- #toolScanner;
128
- /** Always-on healer for leaked reasoning idioms in the visible text channel. */
129
- #thinkingScanner = new ThinkingInbandScanner();
130
- #sectionTerminated = false;
131
- #completed = [];
132
- constructor(options) {
133
- this.#pattern = options.pattern;
134
- this.#toolScanner = options.pattern === "kimi" ? createInbandScanner("kimi") : options.pattern === "dsml" ? createInbandScanner("xml", { xmlTagset: "dsml" }) : options.pattern === "qwen" ? new QwenXmlInbandScanner() : void 0;
135
- }
136
- get pattern() {
137
- return this.#pattern;
138
- }
139
- /**
140
- * Feed a chunk and return visible text only. Reconstructed tool calls are
141
- * stored for {@link drainCompleted}; thinking blocks are intentionally not
142
- * returned by this compatibility helper. Use {@link feedEvents} when the caller
143
- * needs ordered text/thinking/tool-call events.
144
- */
145
- feed(text) {
146
- let clean = "";
147
- for (const event of this.feedEvents(text)) if (event.type === "text") clean += event.text;
148
- else if (event.type === "toolCall") this.#completed.push(event.call);
149
- return clean;
150
- }
151
- /** Feed a chunk and return cleaned text/thinking/tool-call events in stream order. */
152
- feedEvents(text) {
153
- if (text.length === 0) return [];
154
- this.#markSectionClosed(text);
155
- if (!this.#toolScanner) return this.#convertScannerEvents(this.#thinkingScanner.feed(text));
156
- return this.#convertScannerEvents(this.#healThinking(this.#toolScanner.feed(text)));
157
- }
158
- /**
159
- * Feed a chunk and return cleaned events, excluding synthesized tool calls.
160
- * Used when the upstream chunk also carries structured `tool_calls`, keeping
161
- * that structured payload as the single source of truth while preserving
162
- * adjacent text and thinking events.
163
- */
164
- feedEventsWithoutCalls(text) {
165
- const events = this.feedEvents(text);
166
- let out;
167
- for (let i = 0; i < events.length; i++) {
168
- const event = events[i];
169
- if (event.type === "toolCall") out ??= events.slice(0, i);
170
- else if (out) out.push(event);
171
- }
172
- return out ?? events;
173
- }
174
- /** Drain accumulated tool calls from calls to {@link feed}. */
175
- drainCompleted() {
176
- if (this.#completed.length === 0) return [];
177
- return this.#completed.splice(0, this.#completed.length);
178
- }
179
- /**
180
- * Flush held-back stream-end fragments as ordered events. Partial tool-call
181
- * sections/envelopes are dropped by the delegated scanners; unterminated
182
- * thinking blocks are emitted as thinking, matching the previous MiniMax parser
183
- * behavior.
184
- */
185
- flushEvents() {
186
- const tail = this.#toolScanner ? this.#healThinking(this.#toolScanner.flush()) : [];
187
- tail.push(...this.#thinkingScanner.flush());
188
- return this.#convertScannerEvents(tail);
189
- }
190
- /** Flush held-back text only. Reconstructed calls are retained for {@link drainCompleted}. */
191
- flushPending() {
192
- let clean = "";
193
- for (const event of this.flushEvents()) if (event.type === "text") clean += event.text;
194
- else if (event.type === "toolCall") this.#completed.push(event.call);
195
- return clean;
196
- }
197
- /** True once any configured tool-call section/envelope has fully closed. */
198
- get sectionClosed() {
199
- return this.#sectionTerminated;
200
- }
201
- #markSectionClosed(text) {
202
- if (this.#sectionTerminated || !this.#toolScanner) return;
203
- if (this.#pattern === "kimi") {
204
- this.#sectionTerminated = text.includes(KIMI_SECTION_END);
205
- return;
206
- }
207
- if (this.#pattern === "qwen") {
208
- this.#sectionTerminated = text.includes("</tool_calls>");
209
- return;
210
- }
211
- this.#sectionTerminated = text.includes(DSML_TOOL_CALLS_CLOSE_FULLWIDTH) || text.includes(DSML_TOOL_CALLS_CLOSE_ASCII);
212
- }
213
- /**
214
- * Re-scan the tool scanner's visible text through the always-on thinking
215
- * healer: `text` events are healed for leaked reasoning idioms, while the tool
216
- * scanner's own thinking / tool-call events pass through in stream order.
217
- */
218
- #healThinking(toolEvents) {
219
- const out = [];
220
- for (const event of toolEvents) if (event.type === "text") out.push(...this.#thinkingScanner.feed(event.text));
221
- else out.push(event);
222
- return out;
223
- }
224
- #convertScannerEvents(events) {
225
- const out = [];
226
- for (const event of events) switch (event.type) {
227
- case "text":
228
- out.push({
229
- type: "text",
230
- text: event.text
231
- });
232
- break;
233
- case "thinkingDelta":
234
- if (event.delta.length > 0) out.push({
235
- type: "thinking",
236
- thinking: event.delta
237
- });
238
- break;
239
- case "toolEnd": out.push({
240
- type: "toolCall",
241
- call: {
242
- id: generateHealedToolCallId(),
243
- name: event.name,
244
- arguments: JSON.stringify(event.arguments)
245
- }
246
- });
247
- }
248
- return out;
249
- }
250
- };
251
- function generateHealedToolCallId() {
252
- return `call_${crypto.randomUUID().replace(/-/g, "").slice(0, 24)}`;
253
- }
254
- /**
255
- * Pick the leaked-markup healer for an OpenAI-compatible / Ollama visible-text
256
- * stream. Kimi chat-template tokens and DeepSeek DSML envelopes need their
257
- * dedicated tool-call grammars; every other model uses `"thinking"`. All three
258
- * patterns run the generic {@link ThinkingInbandScanner}, so leaked reasoning
259
- * idioms (e.g. a Gemini ` ```thinking ` fence on OpenRouter) are always healed.
260
- */
261
- function getStreamMarkupHealingPattern(model) {
262
- if (model.identity.class === "kimi") return "kimi";
263
- if (model.identity.class === "deepseek") return "dsml";
264
- return "thinking";
265
- }
266
- //#endregion
267
- export { getStreamMarkupHealingPattern as n, StreamMarkupHealing as t };
@@ -1,105 +0,0 @@
1
- import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
- __installBunShim();
3
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/utils/schema/strict-tool-validation.ts
4
- const SCHEMA_TYPE_NAMES = {
5
- string: true,
6
- number: true,
7
- integer: true,
8
- boolean: true,
9
- object: true,
10
- array: true,
11
- null: true
12
- };
13
- function jsonValueMatchesType(value, type) {
14
- switch (type) {
15
- case "string": return typeof value === "string";
16
- case "number": return typeof value === "number";
17
- case "integer": return typeof value === "number" && Number.isInteger(value);
18
- case "boolean": return typeof value === "boolean";
19
- case "null": return value === null;
20
- case "object": return typeof value === "object" && value !== null && !Array.isArray(value);
21
- case "array": return Array.isArray(value);
22
- default: return true;
23
- }
24
- }
25
- function declaredTypes(node) {
26
- const t = node.type;
27
- if (typeof t === "string") return t in SCHEMA_TYPE_NAMES ? [t] : [];
28
- if (Array.isArray(t)) return t.filter((x) => typeof x === "string" && x in SCHEMA_TYPE_NAMES);
29
- return [];
30
- }
31
- const CHILD_MAP_KEYS = [
32
- "properties",
33
- "patternProperties",
34
- "$defs",
35
- "definitions",
36
- "dependentSchemas"
37
- ];
38
- const CHILD_SCHEMA_KEYS = [
39
- "items",
40
- "contains",
41
- "not",
42
- "if",
43
- "then",
44
- "else",
45
- "propertyNames",
46
- "additionalProperties",
47
- "unevaluatedProperties",
48
- "unevaluatedItems"
49
- ];
50
- const CHILD_ARRAY_KEYS = [
51
- "anyOf",
52
- "oneOf",
53
- "allOf",
54
- "prefixItems"
55
- ];
56
- /**
57
- * Walk a tool parameter schema for OpenAI-strict `enum`/`const`-vs-`type`
58
- * contradictions. Returns a JSON-pointer-ish path to the first offending node,
59
- * or `null` when the schema is safe to emit.
60
- */
61
- function findStrictToolSchemaViolation(schema, path = "#", options) {
62
- if (Array.isArray(schema)) {
63
- for (let i = 0; i < schema.length; i++) {
64
- const hit = findStrictToolSchemaViolation(schema[i], `${path}/${i}`, options);
65
- if (hit) return hit;
66
- }
67
- return null;
68
- }
69
- if (typeof schema !== "object" || schema === null) return null;
70
- const node = schema;
71
- const types = declaredTypes(node);
72
- if (types.length > 0) {
73
- if (Array.isArray(node.enum) && node.enum.some((v) => !types.some((t) => jsonValueMatchesType(v, t)))) return `${path}/enum`;
74
- if ("const" in node && !types.some((t) => jsonValueMatchesType(node.const, t))) return `${path}/const`;
75
- }
76
- if (options?.rejectRootObjectUnion && path === "#" && (types.includes("object") || node.properties !== void 0 && typeof node.properties === "object")) for (const key of ["anyOf", "oneOf"]) {
77
- const arr = node[key];
78
- if (!Array.isArray(arr) || arr.length === 0) continue;
79
- if (arr.some((branch) => {
80
- if (typeof branch !== "object" || branch === null || Array.isArray(branch)) return true;
81
- return !declaredTypes(branch).includes("object");
82
- })) return `${path}/${key}`;
83
- }
84
- for (const key of CHILD_MAP_KEYS) {
85
- const sub = node[key];
86
- if (sub && typeof sub === "object" && !Array.isArray(sub)) for (const k of Object.keys(sub)) {
87
- const hit = findStrictToolSchemaViolation(sub[k], `${path}/${key}/${k}`, options);
88
- if (hit) return hit;
89
- }
90
- }
91
- for (const key of CHILD_SCHEMA_KEYS) if (key in node) {
92
- const hit = findStrictToolSchemaViolation(node[key], `${path}/${key}`, options);
93
- if (hit) return hit;
94
- }
95
- for (const key of CHILD_ARRAY_KEYS) {
96
- const arr = node[key];
97
- if (Array.isArray(arr)) {
98
- const hit = findStrictToolSchemaViolation(arr, `${path}/${key}`, options);
99
- if (hit) return hit;
100
- }
101
- }
102
- return null;
103
- }
104
- //#endregion
105
- export { findStrictToolSchemaViolation as t };