@lazyingart/agintiflow 0.20.9 → 0.20.11

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazyingart/agintiflow",
3
- "version": "0.20.9",
3
+ "version": "0.20.11",
4
4
  "type": "module",
5
5
  "description": "AgInTiFlow is a web-first coding agent and CLI with DeepSeek routing, sandboxed tools, model providers, canvas artifacts, and optional wrappers.",
6
6
  "license": "Apache-2.0",
@@ -150,6 +150,17 @@ assert(nativeMarkerText.length === 0, "native marker text should not be treated
150
150
  const jsonBlockToolCalls = parseTextToolCalls('TOOL_CALLS:\n```json\n[{"name":"list_files","arguments":{"path":"/workspace"}}]\n```');
151
151
  assert(jsonBlockToolCalls.length === 1, "Venice JSON text tool-call parser did not detect JSON block calls");
152
152
  assert(jsonBlockToolCalls[0].function.arguments.includes("/workspace"), "Venice JSON text tool-call parser returned wrong arguments");
153
+ const requestedToolCalls = parseTextToolCalls(
154
+ 'Requested tools: write_file({"path":"story-ja.txt","content":"雨の夜、彼女は「また会える」と笑った。","mode":"create"})'
155
+ );
156
+ assert(requestedToolCalls.length === 1, "Requested tools parser did not detect function-call text");
157
+ assert(requestedToolCalls[0].function.name === "write_file", "Requested tools parser returned wrong tool name");
158
+ assert(requestedToolCalls[0].function.arguments.includes("story-ja.txt"), "Requested tools parser returned wrong arguments");
159
+ const multipleRequestedToolCalls = parseTextToolCalls(
160
+ 'Requested tools: list_files({"path":"."}); inspect_project({"path":".","maxDepth":2})'
161
+ );
162
+ assert(multipleRequestedToolCalls.length === 2, "Requested tools parser did not detect multiple function-call texts");
163
+ assert(multipleRequestedToolCalls[1].function.name === "inspect_project", "Requested tools parser returned wrong second requested tool");
153
164
  assert(usesTextToolProtocol({ provider: "venice", model: "gemma-4-uncensored" }), "Venice Gemma should use text tool protocol");
154
165
  assert(usesTextToolProtocol({ provider: "venice", model: "e2ee-venice-uncensored-24b-p" }), "Venice 1.1 should use text tool protocol");
155
166
  assert(usesTextToolProtocol({ provider: "venice", model: "venice-uncensored" }), "Venice legacy 1.1 should use text tool protocol");
@@ -180,6 +191,7 @@ console.log(
180
191
  "auxiliary-catalog",
181
192
  "shared-model-selectors",
182
193
  "venice-text-tool-parser",
194
+ "requested-tools-parser",
183
195
  "cli-models-command",
184
196
  "venice-shortcut",
185
197
  ],
package/src/cli.js CHANGED
@@ -33,6 +33,11 @@ import { fileURLToPath } from "node:url";
33
33
  const packageDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
34
34
  const packageJson = JSON.parse(await fs.readFile(path.join(packageDir, "package.json"), "utf8"));
35
35
 
36
+ process.stdout.on("error", (error) => {
37
+ if (error?.code === "EPIPE") process.exit(0);
38
+ throw error;
39
+ });
40
+
36
41
  function readOption(argv, index) {
37
42
  const value = argv[index + 1];
38
43
  if (!value || value.startsWith("--")) return "";
@@ -614,7 +619,7 @@ async function handleQueueCommand(argv) {
614
619
  }
615
620
 
616
621
  export async function main(argv = process.argv.slice(2)) {
617
- if (argv[0] === "--help" || argv[0] === "help" || argv[0] === "-h") {
622
+ if (argv[0] === "help" || argv.includes("--help") || argv.includes("-h")) {
618
623
  printUsage();
619
624
  return;
620
625
  }
@@ -140,9 +140,10 @@ function messagesWithTextToolProtocol(config, messages, tools) {
140
140
 
141
141
  export function parseTextToolCalls(content = "") {
142
142
  const text = String(content || "");
143
- if (!text.includes("[TOOL_CALLS]") && !/TOOL_CALLS\s*:/i.test(text)) return [];
143
+ if (!text.includes("[TOOL_CALLS]") && !/TOOL_CALLS\s*:/i.test(text) && !/Requested tools?\s*:/i.test(text)) return [];
144
144
 
145
145
  const calls = [];
146
+ for (const call of parseRequestedToolCalls(text)) calls.push(call);
146
147
  const jsonBlock = text.match(/TOOL_CALLS\s*:\s*```(?:json)?\s*([\s\S]*?)```/i);
147
148
  if (jsonBlock?.[1]) {
148
149
  try {
@@ -195,10 +196,75 @@ export function parseTextToolCalls(content = "") {
195
196
  return calls;
196
197
  }
197
198
 
199
+ function findMatchingParen(text = "", openIndex = 0) {
200
+ let depth = 0;
201
+ let quote = "";
202
+ let escaped = false;
203
+ for (let index = openIndex; index < text.length; index += 1) {
204
+ const char = text[index];
205
+ if (escaped) {
206
+ escaped = false;
207
+ continue;
208
+ }
209
+ if (quote) {
210
+ if (char === "\\") escaped = true;
211
+ else if (char === quote) quote = "";
212
+ continue;
213
+ }
214
+ if (char === '"' || char === "'") {
215
+ quote = char;
216
+ continue;
217
+ }
218
+ if (char === "(") depth += 1;
219
+ if (char === ")") {
220
+ depth -= 1;
221
+ if (depth === 0) return index;
222
+ }
223
+ }
224
+ return -1;
225
+ }
226
+
227
+ function parseRequestedToolCalls(content = "") {
228
+ const marker = String(content || "").match(/Requested tools?\s*:/i);
229
+ if (!marker) return [];
230
+
231
+ const text = String(content).slice(marker.index + marker[0].length);
232
+ const calls = [];
233
+ let offset = 0;
234
+ while (offset < text.length) {
235
+ const match = text.slice(offset).match(/([A-Za-z0-9_-]+)\s*\(/);
236
+ if (!match) break;
237
+
238
+ const name = match[1]?.trim();
239
+ const openIndex = offset + match.index + match[0].lastIndexOf("(");
240
+ const closeIndex = findMatchingParen(text, openIndex);
241
+ if (!name || closeIndex < 0) break;
242
+
243
+ const rawArgs = text.slice(openIndex + 1, closeIndex).trim() || "{}";
244
+ try {
245
+ JSON.parse(rawArgs);
246
+ } catch {
247
+ offset = closeIndex + 1;
248
+ continue;
249
+ }
250
+ calls.push({
251
+ id: `text-tool-${calls.length + 1}`,
252
+ type: "function",
253
+ function: {
254
+ name,
255
+ arguments: rawArgs,
256
+ },
257
+ });
258
+ offset = closeIndex + 1;
259
+ }
260
+ return calls;
261
+ }
262
+
198
263
  function textBeforeToolCallMarker(content = "") {
199
264
  return String(content || "")
200
265
  .split("[TOOL_CALLS]")[0]
201
266
  .split("TOOL_CALLS:")[0]
267
+ .split(/Requested tools?\s*:/i)[0]
202
268
  .split("<|tool_call>")[0]
203
269
  .trim();
204
270
  }