tune-basic-toolset 0.1.8 → 0.1.10

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
@@ -15,12 +15,12 @@ Basic toolset for [Tune](https://github.com/iovdin/tune).
15
15
  - [powershell](#powershell) execute PowerShell command
16
16
  - [osa](#osa) manage reminders/notes/calendar (AppleScript/macOS)
17
17
  - [jina_r](#jina_r) fetch webpage content
18
- - [turn](#turn) turn based agent
19
18
  - [list](#list) keep list of tasks todo (loops for LLM)
20
19
  - [sqlite](#sqlite) execute sqlite queries
21
20
  - [py](#py) run python code
22
21
  - [js](#js) run javascript code
23
- - [message](#message) talk to another chat/agent
22
+ - [turn](#turn) handoff based agent (shared context)
23
+ - [message](#message) talk to another chat/agent (separate context)
24
24
  - [Processors](#processors)
25
25
  - [proc](#proc) converts tool to processor
26
26
  - [shp](#shp) include shell command output
@@ -220,39 +220,6 @@ Tune is a versatile toolkit designed for developers and users to effectively int
220
220
  ```
221
221
 
222
222
 
223
- ### `turn`
224
- A way to switch roles when building multistep agents [read more](https://iovdin.github.io/tune/examples/multi-agent)
225
- ```chat
226
- system: @turn @gpt-4o
227
- You're playing 20 questions game.
228
- You switch turns between 'thinker' and 'player' agent.
229
- Current agent stored in agent.txt file
230
- 'player' always plays first
231
-
232
- @@agent|init
233
- assistant:
234
- Is it a living thing?
235
-
236
- tool_call: turn {"role":"thinker","filename":"agent.txt"}
237
- tool_result: now it is turn of thinker to reply
238
-
239
- assistant:
240
- No.
241
-
242
- tool_call: turn {"role":"player","filename":"agent.txt"}
243
- tool_result: now it is turn of player to reply
244
-
245
- assistant:
246
- Is it something that can be used indoors?
247
-
248
- tool_call: turn {"role":"thinker","filename":"agent.txt"}
249
- tool_result: now it is turn of thinker to reply
250
-
251
- assistant:
252
- Yes.
253
-
254
- ...
255
- ```
256
223
 
257
224
  ### `list`
258
225
  Keep list of tasks to do
@@ -353,6 +320,41 @@ tool_result:
353
320
 
354
321
  ```
355
322
 
323
+ ### `turn`
324
+ A way to switch roles when building multistep agents [read more](https://iovdin.github.io/tune/examples/multi-agent)
325
+ ```chat
326
+ system: @gpt-4o
327
+ @{ turn | curry filename=agent.txt}
328
+ You're playing 20 questions game.
329
+ You switch turns between 'thinker' and 'player' agent.
330
+ 'player' always plays first
331
+
332
+ @@agent|init
333
+ assistant:
334
+ Is it a living thing?
335
+
336
+ tool_call: turn {"name": "thinker"}
337
+ tool_result:
338
+ now it is turn of thinker to reply
339
+
340
+ assistant:
341
+ No.
342
+
343
+ tool_call: turn {"role":"player"}
344
+ tool_result: now it is turn of player to reply
345
+
346
+ assistant:
347
+ Is it something that can be used indoors?
348
+
349
+ tool_call: turn {"role":"thinker"}
350
+ tool_result: now it is turn of thinker to reply
351
+
352
+ assistant:
353
+ Yes.
354
+
355
+ ...
356
+ ```
357
+
356
358
  ### `message`
357
359
  Talk to another chat/agent via tool call.
358
360
  Orchestrate or evaulate other agents/chats.
@@ -362,19 +364,19 @@ system:
362
364
  Your goal is to talk to Groot at `groot.prompt` system prompt
363
365
  and try to make him say anything but 'I am Groot'
364
366
 
365
- tool_call: message {"filename":"groot.chat","system":"groot.prompt"}
367
+ tool_call: message {"filename":"groot.chat","system":"@@groot.prompt"}
366
368
  Hello Groot! How are you feeling today?
367
369
 
368
370
  tool_result:
369
371
  I am Groot!
370
372
 
371
- tool_call: message {"filename":"groot.chat","system":"groot.prompt"}
373
+ tool_call: message {"filename":"groot.chat"}
372
374
  What do you think about trees?
373
375
 
374
376
  tool_result:
375
377
  I am Groot!
376
378
 
377
- tool_call: message {"filename":"groot.chat","system":"groot.prompt"}
379
+ tool_call: message {"filename":"groot.chat"}
378
380
  Can you tell me a joke?
379
381
 
380
382
  tool_result:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tune-basic-toolset",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Basic toolset for tune",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -8,6 +8,10 @@
8
8
  "README.md",
9
9
  "LICENSE"
10
10
  ],
11
+ "scripts": {
12
+ "test": "node test/index.js",
13
+ "test:watch": "node --watch test/index.js"
14
+ },
11
15
  "keywords": [
12
16
  "ai",
13
17
  "chat",
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "system": {
11
11
  "type": "string",
12
- "description": "Filename that contains system prompt, required once at the beginning of simulation"
12
+ "description": "System prompt, to include file use @@path/to/file or @@file syntax"
13
13
  },
14
14
  "text": {
15
15
  "type": "string",
@@ -1,14 +1,6 @@
1
- module.exports = async function message({ filename, system, text, stop }, ctx) {
2
- let chat = await ctx.read(filename);
3
- if (!chat && system) {
4
- chat = `system: @@${system}`
1
+ module.exports = async function message({ filename, system, text, stop, save, ...args }, ctx) {
2
+ if (typeof(save) === "undefined") {
3
+ save = !!filename
5
4
  }
6
- chat = `${chat}\nuser:\n${text}`
7
- const messages = await ctx.text2run(chat, {stop: "assistant" })
8
- chat = `${chat}\n${ctx.msg2text(messages, true)}`
9
- await ctx.write(filename, chat)
10
- if (messages.length) {
11
- return messages[messages.length - 1].content
12
- }
13
- return ""
5
+ return ctx.file2run({ stop, filename, system, user: text, save }, args, ctx)
14
6
  }
package/src/mock.proc.js CHANGED
@@ -1,4 +1,5 @@
1
1
  module.exports = async function mock(node, args, ctx) {
2
+ //TODO it is not resolved into sub prompts
2
3
  const re = /(?<name>\w+)\s*=/
3
4
  let lastName;
4
5
  let m;
package/src/patch.tool.js CHANGED
@@ -23,10 +23,11 @@ module.exports = async function patch({ text, filename }, ctx) {
23
23
  let fileContent = await ctx.read(filename);
24
24
 
25
25
  for (const { oldPart, newPart } of patches) {
26
- // Escape regex special chars in oldPart, then allow flexible whitespace
27
- const escaped = oldPart
28
- .replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
29
- .replace(/\s+/g, "\\s+");
26
+ // Escape regex special chars in oldPart.
27
+ // Do NOT relax all whitespace to \s+; that can swallow preceding newlines.
28
+ // Only normalize line endings so CRLF in patches can match LF in files.
29
+ let escaped = oldPart.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
30
+ escaped = escaped.replace(/\r?\n/g, "\\r?\\n");
30
31
  const oldRegex = new RegExp(escaped, "g");
31
32
 
32
33
  // Perform replacement using a function to avoid replacement string ambiguities
@@ -35,4 +36,4 @@ module.exports = async function patch({ text, filename }, ctx) {
35
36
 
36
37
  await ctx.write(filename, fileContent);
37
38
  return "patched";
38
- };
39
+ };
package/src/sh.tool.js CHANGED
@@ -1,12 +1,33 @@
1
1
  const { execSync } = require('child_process');
2
- const util = require('util');
3
2
 
4
3
  module.exports = async function sh({ text }) {
5
4
  let result = "";
6
5
  try {
7
- result = execSync(text, { encoding: "utf8" });
6
+ // Increase maxBuffer to reduce ERR_CHILD_PROCESS_STDIO_MAXBUFFER risk on large outputs
7
+ result = execSync(text, { encoding: "utf8", maxBuffer: 10 * 1024 * 1024 });
8
8
  } catch (e) {
9
- result = e.stderr + e.stdout;
9
+ const stderr = e && typeof e.stderr !== "undefined" ? String(e.stderr || "") : "";
10
+ const stdout = e && typeof e.stdout !== "undefined" ? String(e.stdout || "") : "";
11
+
12
+ if (stderr || stdout) {
13
+ // Process started and produced output
14
+ result = stderr + stdout;
15
+ } else {
16
+ // Spawn/configuration errors or cases without stdio
17
+ const parts = [];
18
+ if (e && e.code) parts.push(`code=${e.code}`);
19
+ if (e && typeof e.status === "number") parts.push(`exit=${e.status}`);
20
+ if (e && e.signal) parts.push(`signal=${e.signal}`);
21
+ if (e && e.errno) parts.push(`errno=${e.errno}`);
22
+ if (e && e.path) parts.push(`path=${e.path}`);
23
+ const meta = parts.length ? ` (${parts.join(", ")})` : "";
24
+
25
+ if (e && e.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER") {
26
+ result = `Command output exceeded maxBuffer${meta}.`;
27
+ } else {
28
+ result = `Failed to spawn/execute command${meta}: ${e && e.message ? e.message : String(e)}`;
29
+ }
30
+ }
10
31
  }
11
32
  return (result || "").replaceAll("@", "\\@");
12
33
  };
package/src/turn.tool.js CHANGED
@@ -1,5 +1,3 @@
1
- const fs = require("fs");
2
-
3
1
  module.exports = async function turn({ role, filename }, ctx) {
4
2
  if (filename) {
5
3
  await ctx.write(filename, `@@${role}`);