tune-basic-toolset 0.1.15 → 0.1.17
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/README.md +95 -30
- package/package.json +1 -1
- package/src/js_ctx.schema.json +13 -0
- package/src/js_ctx.tool.js +48 -0
- package/src/{js.schema.json → js_node.schema.json} +1 -1
- package/src/sh.schema.json +4 -0
- package/src/sh.tool.js +15 -3
- package/src/shp.proc.js +0 -31
- /package/src/{js.tool.js → js_node.tool.js} +0 -0
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Basic toolset for [Tune](https://github.com/iovdin/tune).
|
|
|
10
10
|
- [wf](#wf) write file
|
|
11
11
|
- [patch](#patch) patch file
|
|
12
12
|
- [append](#append) append to file
|
|
13
|
-
- [sh](#sh) execute shell command
|
|
13
|
+
- [sh](#sh) execute shell command locally and remotely
|
|
14
14
|
- [cmd](#cmd) execute Windows cmd command
|
|
15
15
|
- [powershell](#powershell) execute PowerShell command
|
|
16
16
|
- [grep](#grep) search for patterns in text or files
|
|
@@ -20,12 +20,12 @@ Basic toolset for [Tune](https://github.com/iovdin/tune).
|
|
|
20
20
|
- [list](#list) keep list of tasks todo (loops for LLM)
|
|
21
21
|
- [sqlite](#sqlite) execute sqlite queries
|
|
22
22
|
- [py](#py) run python code
|
|
23
|
-
- [
|
|
23
|
+
- [js_node](#js_node) run javascript code in node process
|
|
24
|
+
- [js_ctx](#js_ctx) run javascript code that shares context with LLM
|
|
24
25
|
- [turn](#turn) handoff based agent (shared context)
|
|
25
26
|
- [message](#message) talk to another chat/agent (separate context)
|
|
26
27
|
- [Processors](#processors)
|
|
27
28
|
- [proc](#proc) converts tool to processor
|
|
28
|
-
- [shp](#shp) include shell command output
|
|
29
29
|
- [init](#init) set initial value
|
|
30
30
|
- [json_format](#json_format) make LLM respond with JSON
|
|
31
31
|
- [log](#log) save LLM payload
|
|
@@ -130,7 +130,7 @@ appended
|
|
|
130
130
|
```
|
|
131
131
|
|
|
132
132
|
### `sh`
|
|
133
|
-
Execute shell command
|
|
133
|
+
Execute shell command locally or with ssh
|
|
134
134
|
```chat
|
|
135
135
|
user: @sh
|
|
136
136
|
find with ripgrep where echo is used
|
|
@@ -141,6 +141,15 @@ tool_result:
|
|
|
141
141
|
./README.md: const text = "s: \@echo\nu: hello world";
|
|
142
142
|
./tools/echo.txt:you are echo, you print everything back
|
|
143
143
|
./tools/README.md:* `echo.txt` - to debug variable expansions and context
|
|
144
|
+
|
|
145
|
+
user:
|
|
146
|
+
check contents directory on root\@host.com
|
|
147
|
+
assistant:
|
|
148
|
+
tool_call: sh {"host": "root@host.com"}
|
|
149
|
+
ls
|
|
150
|
+
tool_result:
|
|
151
|
+
file1
|
|
152
|
+
file2
|
|
144
153
|
```
|
|
145
154
|
|
|
146
155
|
### `cmd`
|
|
@@ -342,10 +351,10 @@ tool_result:
|
|
|
342
351
|
5545
|
|
343
352
|
```
|
|
344
353
|
|
|
345
|
-
### `
|
|
346
|
-
execute javascript code
|
|
354
|
+
### `js_node`
|
|
355
|
+
execute javascript code in nodejs
|
|
347
356
|
```chat
|
|
348
|
-
user: @
|
|
357
|
+
user: @js_node
|
|
349
358
|
1234 + 4311
|
|
350
359
|
|
|
351
360
|
tool_call: js {"inputType":"commonjs"}
|
|
@@ -356,6 +365,85 @@ tool_result:
|
|
|
356
365
|
|
|
357
366
|
```
|
|
358
367
|
|
|
368
|
+
### `js_ctx`
|
|
369
|
+
execute javascript code but also call tools available to llm or trigger LLM response from code
|
|
370
|
+
It is useful when you need to trigger loops and ifs or chain few tool calls together
|
|
371
|
+
```chat
|
|
372
|
+
user:
|
|
373
|
+
@js_ctx @sh
|
|
374
|
+
1234 + 4311
|
|
375
|
+
|
|
376
|
+
tool_call: sh
|
|
377
|
+
ls
|
|
378
|
+
tool_result:
|
|
379
|
+
__pycache__
|
|
380
|
+
append.schema.json
|
|
381
|
+
append.tool.js
|
|
382
|
+
... file list
|
|
383
|
+
|
|
384
|
+
user:
|
|
385
|
+
can you do the same using js_ctx tool?
|
|
386
|
+
|
|
387
|
+
assistant:
|
|
388
|
+
|
|
389
|
+
tool_call: js_ctx
|
|
390
|
+
|
|
391
|
+
const result = await ctx.exec("sh", { text: "ls" });
|
|
392
|
+
return result;
|
|
393
|
+
|
|
394
|
+
tool_result:
|
|
395
|
+
__pycache__
|
|
396
|
+
append.schema.json
|
|
397
|
+
append.tool.js
|
|
398
|
+
....
|
|
399
|
+
|
|
400
|
+
user:
|
|
401
|
+
can you loop throught the .js files and summarize its content using llm?
|
|
402
|
+
assistant:
|
|
403
|
+
|
|
404
|
+
tool_call: js_ctx
|
|
405
|
+
|
|
406
|
+
// Get all .js files (excluding .proc.js and .schema.json files)
|
|
407
|
+
const files = await ctx.exec("sh", { text: "ls *.js | grep -v '.proc.js'" });
|
|
408
|
+
const jsFiles = files.trim().split('\n').filter(f => f.endsWith('.js'));
|
|
409
|
+
|
|
410
|
+
const summaries = [];
|
|
411
|
+
|
|
412
|
+
// Loop through each .js file
|
|
413
|
+
for (const file of jsFiles) {
|
|
414
|
+
// Read the file content
|
|
415
|
+
const content = await ctx.exec("sh", { text: `cat ${file}` });
|
|
416
|
+
|
|
417
|
+
// Use LLM to summarize
|
|
418
|
+
const summary = await ctx.file2run({
|
|
419
|
+
system: "@mistral-tiny You are a code analyst. Provide a brief 1-2 sentence summary of what this JavaScript file does.",
|
|
420
|
+
user: "Summarize this code:\n\n@code"
|
|
421
|
+
}, {
|
|
422
|
+
code: content
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
summaries.push({
|
|
426
|
+
file: file,
|
|
427
|
+
summary: summary.trim()
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Format and return results
|
|
432
|
+
return summaries.map(s => `**${s.file}**\n${s.summary}\n`).join('\n');
|
|
433
|
+
|
|
434
|
+
tool_result:
|
|
435
|
+
**append.tool.js**
|
|
436
|
+
This JavaScript file exports an asynchronous function that appends the given text to the end of a specified file, and returns "done" once the operation is completed.
|
|
437
|
+
|
|
438
|
+
**cmd.tool.js**
|
|
439
|
+
This JavaScript file exports an asynchronous function `cmd` that executes a system command (Windows-specific, using 'cmd.exe' as the shell) passed as a string, and returns the command's output or an error message containing both stderr and stdout.
|
|
440
|
+
|
|
441
|
+
**grep.tool.js**
|
|
442
|
+
This JavaScript module exports an asynchronous function named `grep` that reads a file (if provided) or a provided text and searches for lines matching a given regular expression. It returns the lines that match, separated by newlines. If the file is not found or the content is empty, it returns appropriate error messages.
|
|
443
|
+
....
|
|
444
|
+
|
|
445
|
+
```
|
|
446
|
+
|
|
359
447
|
### `turn`
|
|
360
448
|
A way to switch roles when building multistep agents [read more](https://iovdin.github.io/tune/examples/multi-agent)
|
|
361
449
|
```chat
|
|
@@ -463,29 +551,6 @@ execut python script text="384 * 123" and insert back result
|
|
|
463
551
|
@{| proc py 384 * 123 }
|
|
464
552
|
```
|
|
465
553
|
|
|
466
|
-
### `shp`
|
|
467
|
-
Insert shell command output
|
|
468
|
-
```chat
|
|
469
|
-
system:
|
|
470
|
-
include project file list to system prompt
|
|
471
|
-
@{| shp git ls-files }
|
|
472
|
-
|
|
473
|
-
include buffer content on osx
|
|
474
|
-
@{| shp pbpaste }
|
|
475
|
-
|
|
476
|
-
include current date
|
|
477
|
-
@{| shp date }
|
|
478
|
-
|
|
479
|
-
pipe filename content to shell command
|
|
480
|
-
@{ a.log | shp tail }
|
|
481
|
-
|
|
482
|
-
@{ a.log | shp grep pattern }
|
|
483
|
-
|
|
484
|
-
print screen of one of tmux session
|
|
485
|
-
@{| shp tmux capture-pane -t 0 -p }
|
|
486
|
-
|
|
487
|
-
```
|
|
488
|
-
|
|
489
554
|
### `init`
|
|
490
555
|
Set default value for non set variables
|
|
491
556
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "run js code",
|
|
3
|
+
"parameters": {
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"text": {
|
|
7
|
+
"type": "string",
|
|
8
|
+
"description": "js code to execute. You can use 'ctx' inside code to call tools available, e.g. await ctx.exec(\"tool_name\", { param: value }), it is also possible to call LLM from code: await ctx.file2run({ system: \"You are helpful assistant\" user: \"user request: @data \" }, { data: \"value of template variable\") to proper escape user input file2run template engine instead of javascripts ${}"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"required": ["text"]
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const { parseScript } = require('esprima');
|
|
2
|
+
const { generate } = require('escodegen');
|
|
3
|
+
const vm = require('node:vm');
|
|
4
|
+
module.exports = async function js({ text }, ctx) {
|
|
5
|
+
|
|
6
|
+
let code = `(async () =>{\n${text}\n})()`
|
|
7
|
+
const ast = parseScript(code, { range: true });
|
|
8
|
+
|
|
9
|
+
const bodyAst = ast.body[ast.body.length - 1].expression.callee.body;
|
|
10
|
+
const lastNode = bodyAst.body[bodyAst.body.length - 1];
|
|
11
|
+
|
|
12
|
+
if (lastNode.type === 'ExpressionStatement') {
|
|
13
|
+
bodyAst.body[bodyAst.body.length - 1] = {
|
|
14
|
+
type: 'ReturnStatement',
|
|
15
|
+
argument: lastNode.expression
|
|
16
|
+
}
|
|
17
|
+
code = generate(ast);
|
|
18
|
+
}
|
|
19
|
+
if (bodyAst.length === 0) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let logs = [];
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
let result = vm.runInContext(code, vm.createContext({
|
|
27
|
+
ctx,
|
|
28
|
+
console: {
|
|
29
|
+
log: (...args) => logs.push(args),
|
|
30
|
+
error: (...args) => logs.push(args),
|
|
31
|
+
warn: (...args) => logs.push(args),
|
|
32
|
+
debug: (...args) => logs.push(args),
|
|
33
|
+
}
|
|
34
|
+
}))
|
|
35
|
+
result = await result
|
|
36
|
+
return result
|
|
37
|
+
if (typeof(result) === "object") {
|
|
38
|
+
result = JSON.stringify(result, null, " ")
|
|
39
|
+
} else {
|
|
40
|
+
result = String(result)
|
|
41
|
+
}
|
|
42
|
+
logs = logs.map(log => log.join(" ")).join("\n")
|
|
43
|
+
result = logs.trim() + "\n" + (result || "").trim()
|
|
44
|
+
return result.trim()
|
|
45
|
+
} catch (e) {
|
|
46
|
+
return e.stack
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/sh.schema.json
CHANGED
package/src/sh.tool.js
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
|
-
const { execSync } = require('child_process');
|
|
1
|
+
const { spawnSync, execSync } = require('child_process');
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
//TODO look back do not escape escaped
|
|
4
|
+
const escape = (str) => str.replace(/'/g, "\\'")
|
|
5
|
+
|
|
6
|
+
module.exports = async function sh({ text, host }) {
|
|
4
7
|
let result = "";
|
|
5
8
|
try {
|
|
9
|
+
let cmd = text
|
|
10
|
+
let args = []
|
|
11
|
+
if (host) {
|
|
12
|
+
cmd = "ssh"
|
|
13
|
+
args = [host, text]
|
|
14
|
+
}
|
|
6
15
|
// Increase maxBuffer to reduce ERR_CHILD_PROCESS_STDIO_MAXBUFFER risk on large outputs
|
|
7
|
-
result =
|
|
16
|
+
result = spawnSync(cmd, args, { encoding: "utf8", maxBuffer: 10 * 1024 * 1024, shell: true });
|
|
17
|
+
result = (result.stdout || "") + (result.stderr || "")
|
|
18
|
+
return result
|
|
8
19
|
} catch (e) {
|
|
20
|
+
return e
|
|
9
21
|
const stderr = e && typeof e.stderr !== "undefined" ? String(e.stderr || "") : "";
|
|
10
22
|
const stdout = e && typeof e.stdout !== "undefined" ? String(e.stdout || "") : "";
|
|
11
23
|
|
package/src/shp.proc.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
const { execSync, spawnSync } = require('child_process');
|
|
2
|
-
|
|
3
|
-
const shp = async (node, args, ctx) => ({
|
|
4
|
-
type: 'text',
|
|
5
|
-
read: async () => {
|
|
6
|
-
let input = null;
|
|
7
|
-
|
|
8
|
-
if (node && node.type === 'text') {
|
|
9
|
-
input = await node.read();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
let result;
|
|
13
|
-
try {
|
|
14
|
-
if (input !== null) {
|
|
15
|
-
const res = spawnSync(args.trim() || "sh", {
|
|
16
|
-
input,
|
|
17
|
-
encoding: 'utf8',
|
|
18
|
-
shell: true
|
|
19
|
-
});
|
|
20
|
-
result = (res.stdout || '') + (res.stderr || '');
|
|
21
|
-
} else {
|
|
22
|
-
result = execSync(args.trim(), { encoding: 'utf8' });
|
|
23
|
-
}
|
|
24
|
-
} catch (e) {
|
|
25
|
-
result = e.stderr + e.stdout;
|
|
26
|
-
}
|
|
27
|
-
return result;
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
module.exports = shp;
|
|
File without changes
|