@jsonstudio/llms 0.6.567 → 0.6.586
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/dist/conversion/codecs/gemini-openai-codec.js +33 -4
- package/dist/conversion/codecs/openai-openai-codec.js +2 -1
- package/dist/conversion/codecs/responses-openai-codec.js +3 -2
- package/dist/conversion/compat/actions/glm-history-image-trim.d.ts +2 -0
- package/dist/conversion/compat/actions/glm-history-image-trim.js +88 -0
- package/dist/conversion/hub/pipeline/hub-pipeline.d.ts +6 -2
- package/dist/conversion/hub/pipeline/hub-pipeline.js +72 -81
- package/dist/conversion/hub/pipeline/stages/resp_outbound/resp_outbound_stage1_client_remap/index.js +0 -34
- package/dist/conversion/hub/process/chat-process.js +68 -24
- package/dist/conversion/hub/response/provider-response.js +0 -8
- package/dist/conversion/hub/semantic-mappers/gemini-mapper.js +22 -3
- package/dist/conversion/hub/semantic-mappers/responses-mapper.js +267 -14
- package/dist/conversion/hub/types/chat-envelope.d.ts +1 -0
- package/dist/conversion/responses/responses-openai-bridge.d.ts +3 -2
- package/dist/conversion/responses/responses-openai-bridge.js +1 -13
- package/dist/conversion/shared/anthropic-message-utils.js +54 -0
- package/dist/conversion/shared/args-mapping.js +11 -3
- package/dist/conversion/shared/responses-output-builder.js +42 -21
- package/dist/conversion/shared/streaming-text-extractor.d.ts +25 -0
- package/dist/conversion/shared/streaming-text-extractor.js +31 -38
- package/dist/conversion/shared/text-markup-normalizer.d.ts +20 -0
- package/dist/conversion/shared/text-markup-normalizer.js +118 -31
- package/dist/conversion/shared/tool-filter-pipeline.js +56 -30
- package/dist/conversion/shared/tool-harvester.js +43 -12
- package/dist/conversion/shared/tool-mapping.d.ts +1 -0
- package/dist/conversion/shared/tool-mapping.js +33 -19
- package/dist/filters/index.d.ts +1 -0
- package/dist/filters/index.js +1 -0
- package/dist/filters/special/request-tools-normalize.js +14 -4
- package/dist/filters/special/response-apply-patch-toon-decode.d.ts +23 -0
- package/dist/filters/special/response-apply-patch-toon-decode.js +117 -0
- package/dist/filters/special/response-tool-arguments-toon-decode.d.ts +10 -0
- package/dist/filters/special/response-tool-arguments-toon-decode.js +154 -26
- package/dist/guidance/index.js +71 -42
- package/dist/router/virtual-router/bootstrap.js +10 -5
- package/dist/router/virtual-router/classifier.js +16 -7
- package/dist/router/virtual-router/engine-health.d.ts +11 -0
- package/dist/router/virtual-router/engine-health.js +217 -4
- package/dist/router/virtual-router/engine-logging.d.ts +2 -1
- package/dist/router/virtual-router/engine-logging.js +35 -3
- package/dist/router/virtual-router/engine.d.ts +17 -1
- package/dist/router/virtual-router/engine.js +184 -6
- package/dist/router/virtual-router/routing-instructions.d.ts +2 -0
- package/dist/router/virtual-router/routing-instructions.js +19 -1
- package/dist/router/virtual-router/tool-signals.d.ts +2 -1
- package/dist/router/virtual-router/tool-signals.js +324 -119
- package/dist/router/virtual-router/types.d.ts +31 -1
- package/dist/router/virtual-router/types.js +2 -2
- package/dist/servertool/engine.js +3 -0
- package/dist/servertool/handlers/iflow-model-error-retry.d.ts +1 -0
- package/dist/servertool/handlers/iflow-model-error-retry.js +93 -0
- package/dist/servertool/handlers/stop-message-auto.js +61 -4
- package/dist/servertool/server-side-tools.d.ts +1 -0
- package/dist/servertool/server-side-tools.js +27 -0
- package/dist/sse/json-to-sse/event-generators/responses.js +9 -2
- package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +23 -3
- package/dist/tools/apply-patch-structured.d.ts +20 -0
- package/dist/tools/apply-patch-structured.js +240 -0
- package/dist/tools/tool-description-utils.d.ts +5 -0
- package/dist/tools/tool-description-utils.js +50 -0
- package/dist/tools/tool-registry.js +11 -193
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Tool registry and validator (single source of truth)
|
|
2
|
+
import { buildStructuredPatch, isStructuredApplyPatchPayload, StructuredApplyPatchError } from './apply-patch-structured.js';
|
|
2
3
|
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
3
4
|
const asString = (value) => {
|
|
4
5
|
if (typeof value === 'string' && value.trim().length > 0) {
|
|
@@ -43,164 +44,6 @@ const toJson = (value) => {
|
|
|
43
44
|
return '{}';
|
|
44
45
|
}
|
|
45
46
|
};
|
|
46
|
-
const APPLY_PATCH_SECTION_RE = /^\*\*\*\s+(Add|Update|Delete|Copy|Move)\s+File:\s*(.+)$/;
|
|
47
|
-
const sanitizeRelativePath = (value) => {
|
|
48
|
-
if (!value)
|
|
49
|
-
return null;
|
|
50
|
-
const trimmed = value.trim().replace(/\\/g, '/');
|
|
51
|
-
if (!trimmed)
|
|
52
|
-
return null;
|
|
53
|
-
if (trimmed.startsWith('/'))
|
|
54
|
-
return null;
|
|
55
|
-
if (/^[a-zA-Z]:/.test(trimmed))
|
|
56
|
-
return null;
|
|
57
|
-
if (trimmed.includes('\0'))
|
|
58
|
-
return null;
|
|
59
|
-
if (trimmed.includes('..')) {
|
|
60
|
-
const segments = trimmed.split('/');
|
|
61
|
-
if (segments.some((seg) => seg === '..')) {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return trimmed.replace(/\/{2,}/g, '/');
|
|
66
|
-
};
|
|
67
|
-
const collectExplicitPaths = (record) => {
|
|
68
|
-
const bucket = [];
|
|
69
|
-
const invalid = [];
|
|
70
|
-
const pushPath = (candidate) => {
|
|
71
|
-
const str = asString(candidate);
|
|
72
|
-
const normalized = sanitizeRelativePath(str);
|
|
73
|
-
if (normalized)
|
|
74
|
-
bucket.push(normalized);
|
|
75
|
-
else if (typeof candidate === 'string')
|
|
76
|
-
invalid.push(candidate);
|
|
77
|
-
};
|
|
78
|
-
const entries = [
|
|
79
|
-
record.paths,
|
|
80
|
-
record.path,
|
|
81
|
-
record.files,
|
|
82
|
-
record.file,
|
|
83
|
-
record.targets,
|
|
84
|
-
record.target_path
|
|
85
|
-
];
|
|
86
|
-
for (const entry of entries) {
|
|
87
|
-
if (!entry)
|
|
88
|
-
continue;
|
|
89
|
-
if (typeof entry === 'string') {
|
|
90
|
-
pushPath(entry);
|
|
91
|
-
}
|
|
92
|
-
else if (Array.isArray(entry)) {
|
|
93
|
-
entry.forEach((item) => {
|
|
94
|
-
if (typeof item === 'string')
|
|
95
|
-
pushPath(item);
|
|
96
|
-
else if (isRecord(item))
|
|
97
|
-
pushPath(item.path);
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
else if (isRecord(entry)) {
|
|
101
|
-
pushPath(entry.path ?? entry.value);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return { paths: bucket, invalid };
|
|
105
|
-
};
|
|
106
|
-
const looksLikePatchBody = (text) => {
|
|
107
|
-
const trimmed = text.trim();
|
|
108
|
-
if (!trimmed)
|
|
109
|
-
return false;
|
|
110
|
-
const hunkRe = /^@@/m;
|
|
111
|
-
const diffLineRe = /^[ +-]/m;
|
|
112
|
-
return hunkRe.test(trimmed) || diffLineRe.test(trimmed);
|
|
113
|
-
};
|
|
114
|
-
const applyPathOverrides = (lines, overridePaths) => {
|
|
115
|
-
if (!overridePaths.length)
|
|
116
|
-
return;
|
|
117
|
-
const sections = [];
|
|
118
|
-
for (let i = 0; i < lines.length; i += 1) {
|
|
119
|
-
const match = lines[i].match(APPLY_PATCH_SECTION_RE);
|
|
120
|
-
if (match) {
|
|
121
|
-
sections.push({ index: i, action: match[1] });
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
if (!sections.length) {
|
|
125
|
-
const beginIdx = lines.findIndex((line) => line.trim() === '*** Begin Patch');
|
|
126
|
-
if (beginIdx >= 0) {
|
|
127
|
-
lines.splice(beginIdx + 1, 0, `*** Update File: ${overridePaths[0]}`);
|
|
128
|
-
}
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const limit = Math.min(sections.length, overridePaths.length);
|
|
132
|
-
for (let i = 0; i < limit; i += 1) {
|
|
133
|
-
lines[sections[i].index] = `*** ${sections[i].action} File: ${overridePaths[i]}`;
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
const normalizeApplyPatchInput = (rawPatch, options) => {
|
|
137
|
-
if (typeof rawPatch !== 'string') {
|
|
138
|
-
return null;
|
|
139
|
-
}
|
|
140
|
-
const text = rawPatch.replace(/\r\n/g, '\n');
|
|
141
|
-
const beginIdx = text.toLowerCase().indexOf('*** begin patch');
|
|
142
|
-
const endIdx = text.toLowerCase().lastIndexOf('*** end patch');
|
|
143
|
-
let candidate = '';
|
|
144
|
-
if (beginIdx >= 0 && endIdx >= 0 && endIdx > beginIdx) {
|
|
145
|
-
candidate = text.slice(beginIdx, endIdx + '*** End Patch'.length);
|
|
146
|
-
}
|
|
147
|
-
else if (options?.overridePaths && options.overridePaths.length) {
|
|
148
|
-
if (!looksLikePatchBody(text)) {
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
const headerPath = options.overridePaths[0];
|
|
152
|
-
candidate = ['*** Begin Patch', `*** Update File: ${headerPath}`, text.trim(), '*** End Patch'].join('\n');
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
const lines = candidate.split(/\r?\n/);
|
|
158
|
-
if (!lines.length) {
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
let firstIdx = 0;
|
|
162
|
-
while (firstIdx < lines.length && lines[firstIdx].trim().length === 0) {
|
|
163
|
-
firstIdx += 1;
|
|
164
|
-
}
|
|
165
|
-
if (firstIdx >= lines.length) {
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
|
-
const firstLineRaw = lines[firstIdx];
|
|
169
|
-
const firstLineTrimmed = firstLineRaw.trim();
|
|
170
|
-
if (!firstLineTrimmed.toLowerCase().startsWith('*** begin patch')) {
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
-
if (firstLineTrimmed !== '*** Begin Patch') {
|
|
174
|
-
lines[firstIdx] = '*** Begin Patch';
|
|
175
|
-
}
|
|
176
|
-
let lastIdx = lines.length - 1;
|
|
177
|
-
while (lastIdx > firstIdx && lines[lastIdx].trim().length === 0) {
|
|
178
|
-
lastIdx -= 1;
|
|
179
|
-
}
|
|
180
|
-
if (lastIdx > firstIdx) {
|
|
181
|
-
const lastLineTrimmed = lines[lastIdx].trim();
|
|
182
|
-
if (lastLineTrimmed.toLowerCase().startsWith('*** end patch') && lastLineTrimmed !== '*** End Patch') {
|
|
183
|
-
lines[lastIdx] = '*** End Patch';
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
if (options?.overridePaths && options.overridePaths.length) {
|
|
187
|
-
applyPathOverrides(lines, options.overridePaths);
|
|
188
|
-
}
|
|
189
|
-
const normalized = lines.join('\n');
|
|
190
|
-
if (!normalized.includes('*** Begin Patch') || !normalized.includes('*** End Patch')) {
|
|
191
|
-
return null;
|
|
192
|
-
}
|
|
193
|
-
return normalized;
|
|
194
|
-
};
|
|
195
|
-
const logApplyPatchValidatorError = (message) => {
|
|
196
|
-
try {
|
|
197
|
-
// eslint-disable-next-line no-console
|
|
198
|
-
console.error(`\x1b[31m[apply_patch][validator] ${message}\x1b[0m`);
|
|
199
|
-
}
|
|
200
|
-
catch {
|
|
201
|
-
/* ignore */
|
|
202
|
-
}
|
|
203
|
-
};
|
|
204
47
|
const detectForbiddenWrite = (script) => {
|
|
205
48
|
const normalized = script.toLowerCase();
|
|
206
49
|
if (!normalized) {
|
|
@@ -254,44 +97,19 @@ export function validateToolCall(name, argsString) {
|
|
|
254
97
|
switch (normalizedName) {
|
|
255
98
|
case 'apply_patch': {
|
|
256
99
|
const record = rawArgs;
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
const rawStr = typeof argsString === 'string' ? argsString : '';
|
|
260
|
-
let patchRaw = null;
|
|
261
|
-
if (patchField) {
|
|
262
|
-
patchRaw = patchField;
|
|
263
|
-
}
|
|
264
|
-
else if (inputField) {
|
|
265
|
-
patchRaw = inputField;
|
|
266
|
-
}
|
|
267
|
-
else if (rawStr && /\*\*\*\s+Begin Patch/i.test(rawStr)) {
|
|
268
|
-
patchRaw = rawStr;
|
|
100
|
+
if (!isStructuredApplyPatchPayload(record)) {
|
|
101
|
+
return { ok: false, reason: 'missing_changes' };
|
|
269
102
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return { ok:
|
|
103
|
+
try {
|
|
104
|
+
const patchText = buildStructuredPatch(record);
|
|
105
|
+
return { ok: true, normalizedArgs: toJson({ patch: patchText, input: patchText }) };
|
|
273
106
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
if (!normalizedPatch) {
|
|
280
|
-
logApplyPatchValidatorError('patch text missing *** Begin Patch/*** End Patch or failed to auto-wrap with provided paths');
|
|
281
|
-
return { ok: false, reason: 'invalid_patch_header' };
|
|
282
|
-
}
|
|
283
|
-
// Canonical, parameterized shape; keep input for backwards compatibility.
|
|
284
|
-
const payload = {
|
|
285
|
-
patch: normalizedPatch,
|
|
286
|
-
input: normalizedPatch
|
|
287
|
-
};
|
|
288
|
-
if (explicitPaths.length) {
|
|
289
|
-
payload.paths = explicitPaths;
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (error instanceof StructuredApplyPatchError) {
|
|
109
|
+
return { ok: false, reason: error.reason || 'invalid_patch_payload' };
|
|
110
|
+
}
|
|
111
|
+
return { ok: false, reason: 'invalid_patch_payload' };
|
|
290
112
|
}
|
|
291
|
-
return {
|
|
292
|
-
ok: true,
|
|
293
|
-
normalizedArgs: toJson(payload)
|
|
294
|
-
};
|
|
295
113
|
}
|
|
296
114
|
case 'shell': {
|
|
297
115
|
const rawCommand = rawArgs.command;
|