tune-basic-toolset 0.1.4 → 0.1.7

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
@@ -34,6 +34,7 @@ Basic toolset for [Tune](https://github.com/iovdin/tune).
34
34
  - [tail](#tail) take last N lines of a file or LLM payload
35
35
  - [slice](#slice) take lines from <start> to <finish> of a file
36
36
  - [random](#random) random selection, sampling, shuffling, uniform ranges
37
+ - [curry](#curry) change a tool by setting a parameter
37
38
 
38
39
 
39
40
  ## Setup
@@ -386,6 +387,10 @@ pipe filename content to shell command
386
387
  @{ a.log | shp tail }
387
388
 
388
389
  @{ a.log | shp grep pattern }
390
+
391
+ print screen of one of tmux session
392
+ @{| shp tmux capture-pane -t 0 -p }
393
+
389
394
  ```
390
395
 
391
396
  ### `init`
@@ -575,10 +580,46 @@ user:
575
580
  @{| random uniform -2.5..7.5 } # floats
576
581
  @{| random uniform 10 20 } # two-number form
577
582
 
578
- comment:
583
+ ```
579
584
  Notes:
580
585
  - Quotes are respected for tokens with spaces.
581
586
  - Files referenced as @file are expanded to non-empty trimmed lines.
582
587
  - Integer ranges like a..b can be mixed with discrete values and files; float ranges cannot be mixed in lists.
583
588
  - sample and shuffle require a discrete set; float ranges are not supported there.
584
589
  - choices and sample output multiple lines (one item per line).
590
+
591
+
592
+ ### `curry`
593
+ Modify a tool by setting parameter or name or description.
594
+ Narrow possible usage of a tool so that LLM wont mess up
595
+
596
+ ```chat
597
+ user:
598
+ @{ sh | curry text=ls $name=ls_cwd}
599
+
600
+ what is in my current directory?
601
+
602
+ assistant:
603
+
604
+ tool_call: ls_cwd
605
+ tool_result:
606
+ node_modules
607
+ package.json
608
+ README.md
609
+ src
610
+
611
+
612
+ user:
613
+ @{ sqlite | curry filename=db.sqlite format=table}
614
+
615
+ what tables are outhere?
616
+
617
+ user:
618
+ @{ list | curry filename=mylist.todo $name=todo }
619
+
620
+ create sample todo list
621
+ tool_call: todo
622
+ [] - Create sample todo list
623
+ tool_result:
624
+ list updated
625
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tune-basic-toolset",
3
- "version": "0.1.4",
3
+ "version": "0.1.7",
4
4
  "description": "Basic toolset for tune",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -0,0 +1,56 @@
1
+ module.exports = async function curry(node, args, ctx) {
2
+ if (!node || node.type !== 'tool' ) {
3
+ throw Error('curry can only modify tool')
4
+ }
5
+
6
+ // parse args string to object
7
+ // supports key=value pairs where value can be quoted string
8
+ // 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
+ });
28
+ const schema = { ...node.schema }
29
+ const curryParams = {}
30
+ const newNode = {
31
+ ...node,
32
+ schema,
33
+ exec: async(params, ctx) => node.exec({...params, ...curryParams}, ctx)
34
+ }
35
+ for(const key in parsedArgs) {
36
+ if (key.indexOf("$") === -1) {
37
+ curryParams[key] = parsedArgs[key]
38
+ if (!schema.parameters.properties[key]) {
39
+ throw Error(`parameter ${key} is not defined in ${node.name}'s schema`)
40
+ }
41
+ delete schema.parameters.properties[key]
42
+ const idx = (schema.parameters.required || []).indexOf(key)
43
+ if (idx !== -1) {
44
+ schema.parameters.required.splice(idx, 1)
45
+ }
46
+ } else {
47
+ const path = key.slice(1).split(".")
48
+ if (path[0] !== "name" && path[0] !== "description") {
49
+ throw Error(`path should start with $name or with $description`)
50
+ }
51
+ newNode[path[0]] = parsedArgs[key]
52
+ }
53
+ }
54
+
55
+ return newNode
56
+ }
@@ -6,7 +6,7 @@
6
6
  "properties": {
7
7
  "text": {
8
8
  "type": "string",
9
- "description": "lines in format 'status - item', they'll be used to update list or to insert to the list, to delete item change its status to deleted or cancelled\nThe lines should contain only those items that needs to be changed - inserted/updated/deleted"
9
+ "description": "text where each line is in format 'status - item', they'll be used to update list or to insert to the list, to delete item change its status to deleted or cancelled\nThe lines should contain only those items that needs to be changed - inserted/updated/deleted"
10
10
  },
11
11
  "filename": {
12
12
  "type": "string",
package/src/patch.tool.js CHANGED
@@ -17,7 +17,7 @@ module.exports = async function patch({ text, filename }, ctx) {
17
17
  }
18
18
 
19
19
  if (patches.length === 0) {
20
- throw new Error("No valid patch segments found");
20
+ return "No valid patch segments found";
21
21
  }
22
22
 
23
23
  let fileContent = await ctx.read(filename);
@@ -35,4 +35,4 @@ module.exports = async function patch({ text, filename }, ctx) {
35
35
 
36
36
  await ctx.write(filename, fileContent);
37
37
  return "patched";
38
- };
38
+ };
@@ -6,5 +6,11 @@ module.exports = async function resolve(node, args, ctx) {
6
6
  throw Error(`can resolve only text nodes, got ${node.type}`)
7
7
  }
8
8
  const filename = await node.read()
9
- return ctx.resolve(filename.trim())
9
+ const result = await ctx.resolve(filename.trim())
10
+ if (result) return result
11
+
12
+ return {
13
+ type: "text",
14
+ read: async () => args || "Not found"
15
+ }
10
16
  }
package/src/rf.tool.js CHANGED
@@ -16,5 +16,8 @@ module.exports = async function readFile({ filename, linenum }, ctx) {
16
16
  if (pathArr.length > 1) {
17
17
  return`@{ ${pathArr.join(" | ")} }`;
18
18
  }
19
+ if (relFile.match(/\s+/)) {
20
+ return `@{${relFile}}`;
21
+ }
19
22
  return `@${relFile}`;
20
- };
23
+ };
package/src/shp.proc.js CHANGED
@@ -12,7 +12,7 @@ const shp = async (node, args, ctx) => ({
12
12
  let result;
13
13
  try {
14
14
  if (input !== null) {
15
- const res = spawnSync(args.trim(), {
15
+ const res = spawnSync(args.trim() || "sh", {
16
16
  input,
17
17
  encoding: 'utf8',
18
18
  shell: true
@@ -28,4 +28,4 @@ const shp = async (node, args, ctx) => ({
28
28
  }
29
29
  });
30
30
 
31
- module.exports = shp;
31
+ module.exports = shp;