Skip to content

Commit 7954a80

Browse files
committed
Refactor: Centralize argument parsing and remove @ escaping
Extract argument parsing into `utils.js` and use it in `curry.proc.js`. This commit also removes explicit `@` escaping from several tool outputs (`cmd`, `grep`, `jina_r`, `js`, `powershell`, `sh`, `sqlite`) as the behavior seems to be implicitly handled or no longer required, leading to cleaner output logic. Additionally: - Incremented version to 0.1.14. - Updated `log.proc.js` to ensure it only wraps `llm` nodes. - Modified `rf.schema.json` to enable `$escape_output: false`. - Added `autotext` handling to `rf.tool.js`. - Refactored `proc.proc.js` to remove duplicated argument parsing logic.
1 parent a54d8e1 commit 7954a80

15 files changed

Lines changed: 152 additions & 158 deletions

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tune-basic-toolset",
3-
"version": "0.1.13",
3+
"version": "0.1.14",
44
"description": "Basic toolset for tune",
55
"main": "src/index.js",
66
"files": [

src/cmd.tool.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ module.exports = async function cmd({ text }) {
1212
} catch (e) {
1313
result = e.stderr + e.stdout;
1414
}
15-
return (result || "").replaceAll("@", "\\@");
15+
return (result || "")
1616
};

src/curry.proc.js

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const { parseArgs } = require('./utils.js')
2+
13
module.exports = async function curry(node, args, ctx) {
24
if (!node || node.type !== 'tool' ) {
35
throw Error('curry can only modify tool')
@@ -6,25 +8,7 @@ module.exports = async function curry(node, args, ctx) {
68
// parse args string to object
79
// supports key=value pairs where value can be quoted string
810
// keys can optionally start with $
9-
10-
const parsedArgs = {};
11-
// regex to split on spaces but keep quoted substrings together
12-
const regex = /([^\s"']+|"[^"]*"|'[^']*')+/g;
13-
const tokens = args.match(regex) || [];
14-
15-
tokens.forEach(token => {
16-
const equalIndex = token.indexOf('=');
17-
if (equalIndex > 0) {
18-
const key = token.substring(0, equalIndex);
19-
let value = token.substring(equalIndex + 1);
20-
21-
// strip double or single quotes from value if present
22-
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
23-
value = value.substring(1, value.length - 1);
24-
}
25-
parsedArgs[key] = value;
26-
}
27-
});
11+
const parsedArgs = parseArgs(args.trim())
2812
const schema = { ...node.schema }
2913
const curryParams = {}
3014
const newNode = {
@@ -35,10 +19,10 @@ module.exports = async function curry(node, args, ctx) {
3519
for(const key in parsedArgs) {
3620
if (key.indexOf("$") === -1) {
3721
curryParams[key] = parsedArgs[key]
38-
if (!schema.parameters.properties[key]) {
39-
throw Error(`parameter ${key} is not defined in ${node.name}'s schema`)
22+
if (schema.parameters.properties[key]) {
23+
// throw Error(`parameter ${key} is not defined in ${node.name}'s schema`)
24+
delete schema.parameters.properties[key]
4025
}
41-
delete schema.parameters.properties[key]
4226
const idx = (schema.parameters.required || []).indexOf(key)
4327
if (idx !== -1) {
4428
schema.parameters.required.splice(idx, 1)

src/grep.tool.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ module.exports = async function grep({filename, text, regex, regex_flags}, ctx)
1212
}
1313

1414
const r = new RegExp(regex, regex_flags)
15-
return text.split(/\r?\n/).filter(line => r.test(line)).join("\n").replaceAll("@", "\\@")
15+
return text.split(/\r?\n/).filter(line => r.test(line)).join("\n")
1616
}

src/jina_r.tool.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ module.exports = async function fetchFromUrl({ url, filename, links }, ctx) {
2323
await ctx.write(filename, res);
2424
return `@${filename}`;
2525
}
26-
return res.replace(/@/g, "\\@");
27-
};
26+
return res
27+
};

src/js.tool.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ module.exports = async function execute({ text, inputType }, ctx) {
5353
input: modifiedCode,
5454
});
5555

56-
return (res.stderr + res.stdout).trim().replace(/@/g, "\\@");
56+
return (res.stderr + res.stdout).trim()
5757
} finally {
5858
unlinkSync(filename);
5959
}
60-
};
60+
};

src/log.proc.js

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
const fs = require("fs")
22
const path = require("path")
33

4-
module.exports = async (node, args, ctx) => ({
5-
...node,
6-
exec: async function(payload, ctx) {
7-
const res = await node.exec(payload, ctx)
8-
const body = JSON.parse(res.body)
9-
payload = {...res, body};
10-
const filename = args.trim() || "log.json"
11-
const content = path.extname(filename) == ".chat" ? ctx.msg2text(payload.body.messages, true) : JSON.stringify(payload, null, " ")
12-
fs.writeFileSync(filename, content);
13-
return res
4+
module.exports = async (node, args, ctx) => {
5+
if (!node || node.type !== 'llm') {
6+
throw Error("llm required for 'log' processor")
147
}
15-
})
8+
return ({
9+
...node,
10+
exec: async function(payload, ctx) {
11+
const res = await node.exec(payload, ctx)
12+
const body = JSON.parse(res.body)
13+
payload = {...res, body};
14+
const filename = args.trim() || "log.json"
15+
const content = path.extname(filename) == ".chat" ? ctx.msg2text(payload.body.messages, true) : JSON.stringify(payload, null, " ")
16+
fs.writeFileSync(filename, content);
17+
return res
18+
}
19+
})
20+
}

src/powershell.tool.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ module.exports = async function powershell({ text }) {
1212
} catch (e) {
1313
result = e.stderr + e.stdout;
1414
}
15-
return (result || "").replaceAll("@", "\\@");
15+
return (result || "")
1616
};

src/proc.proc.js

Lines changed: 1 addition & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const { parseCommandLine } = require('./utils.js')
12

23
module.exports = async function proc(node, args, ctx) {
34
/*
@@ -25,113 +26,4 @@ module.exports = async function proc(node, args, ctx) {
2526
}
2627
}
2728

28-
// Examples:
29-
// parseCommandLine('command hello world bla bla')
30-
// -> ["command", { text: "hello world bla bla" }]
31-
//
32-
// parseCommandLine('cmd hello=world num=8 text="bla \\"bla"')
33-
// -> ["cmd", { hello: "world", num: 8, text: 'bla "bla' }]
34-
//
35-
// parseCommandLine('cmd')
36-
// -> ["cmd", {}]
3729

38-
function parseCommandLine(input) {
39-
const s = String(input);
40-
let i = 0, len = s.length;
41-
42-
function skipWS() { while (i < len && /\s/.test(s[i])) i++; }
43-
44-
// 1) Parse leading alphanumeric command
45-
skipWS();
46-
const cmdStart = i;
47-
while (i < len && /[A-Za-z0-9_\-]/.test(s[i])) i++;
48-
const command = s.slice(cmdStart, i);
49-
if (!command) return [null, {}];
50-
51-
// 2) Parse the remainder as args
52-
skipWS();
53-
const r = s.slice(i);
54-
if (!r.trim()) return [command, {}];
55-
56-
function parseArgs(str) {
57-
if (!/^\s*[A-Za-z0-9]+=/.test(str)) {
58-
return { text: str.trim() };
59-
}
60-
61-
let j = 0;
62-
const L = str.length;
63-
const out = {};
64-
65-
function skipW() { while (j < L && /\s/.test(str[j])) j++; }
66-
67-
function parseKey() {
68-
const start = j;
69-
while (j < L && str[j] !== '=' && !/\s/.test(str[j])) j++;
70-
return str.slice(start, j);
71-
}
72-
73-
function parseQuotedValue(q) {
74-
j++; // skip opening quote
75-
let val = '';
76-
while (j < L) {
77-
const ch = str[j++];
78-
if (ch === '\\') {
79-
if (j >= L) break;
80-
const esc = str[j++];
81-
if (esc === 'n') val += '\n';
82-
else if (esc === 't') val += '\t';
83-
else if (esc === 'r') val += '\r';
84-
else val += esc; // includes \" \\ \'
85-
} else if (ch === q) {
86-
return val;
87-
} else {
88-
val += ch;
89-
}
90-
}
91-
return val; // best-effort if unclosed
92-
}
93-
94-
function parseUnquotedValue() {
95-
const start = j;
96-
while (j < L && !/\s/.test(str[j])) j++;
97-
return str.slice(start, j);
98-
}
99-
100-
function coerce(v) {
101-
if (/^-?\d+(\.\d+)?$/.test(v)) return Number(v);
102-
const low = v.toLowerCase();
103-
if (low === 'true') return true;
104-
if (low === 'false') return false;
105-
if (low === 'null') return null;
106-
return v;
107-
}
108-
109-
while (j < L) {
110-
skipW();
111-
if (j >= L) break;
112-
113-
const key = parseKey();
114-
if (!key) return { text: str.trim() };
115-
116-
skipW();
117-
if (j < L && str[j] === '=') {
118-
j++; // skip '='
119-
skipW();
120-
let valueStr = '';
121-
if (j < L && (str[j] === '"' || str[j] === "'")) {
122-
valueStr = parseQuotedValue(str[j]);
123-
} else {
124-
valueStr = parseUnquotedValue();
125-
}
126-
out[key] = coerce(valueStr);
127-
} else {
128-
// If a non key=value token appears, treat the whole remainder as text
129-
return { text: str.trim() };
130-
}
131-
}
132-
133-
return out;
134-
}
135-
136-
return [command, parseArgs(r)];
137-
}

src/rf.schema.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
}
1414
},
1515
"required": ["filename"]
16-
}
16+
},
17+
"$escape_output": false
1718
}

0 commit comments

Comments
 (0)