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 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
- - [js](#js) run javascript code
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
- ### `js`
346
- execute javascript code
354
+ ### `js_node`
355
+ execute javascript code in nodejs
347
356
  ```chat
348
- user: @js
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tune-basic-toolset",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "Basic toolset for tune",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -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
+ }
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "Execute a given JavaScript code snippet and return the result",
2
+ "description": "Execute a given JavaScript code snippet and return the result using new node process",
3
3
  "parameters": {
4
4
  "type": "object",
5
5
  "properties": {
@@ -6,6 +6,10 @@
6
6
  "text": {
7
7
  "type": "string",
8
8
  "description": "The shell command to execute"
9
+ },
10
+ "host": {
11
+ "type": "string",
12
+ "description": "remote host like user@host.com to execute the shell comand on (uses ssh)"
9
13
  }
10
14
  },
11
15
  "required": ["text"]
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
- module.exports = async function sh({ text }) {
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 = execSync(text, { encoding: "utf8", maxBuffer: 10 * 1024 * 1024 });
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