tune-sdk 0.1.9 → 0.1.12
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 +51 -4
- package/bin/cli.js +122 -104
- package/dist/fsctx.js +324 -274
- package/dist/rpc.js +211 -0
- package/dist/tune.js +48 -0
- package/package.json +4 -1
- package/tools/README.md +2 -2
- package/tools/default.ctx.js +8 -43
- package/tools/groq_whisper.schema.json +48 -0
- package/tools/groq_whisper.tool.mjs +59 -0
- package/tools/openai_stt.schema.json +49 -0
- package/tools/openai_stt.tool.mjs +66 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Tune
|
|
1
|
+
# Tune - AI chat in text file
|
|
2
2
|
|
|
3
3
|
Tune is a handy [extension](https://marketplace.visualstudio.com/items?itemName=iovdin.tune) for Visual Studio Code and [plugin](https://github.com/iovdin/tune.nvim) for Neovim that lets you chat with large language models (LLMs) in a text file.
|
|
4
4
|
With tune [javascript sdk](https://www.npmjs.com/package/tune-sdk) you can make apps and agents.
|
|
@@ -6,10 +6,57 @@ With tune [javascript sdk](https://www.npmjs.com/package/tune-sdk) you can make
|
|
|
6
6
|
## Demo
|
|
7
7
|
<img src="https://github.com/iovdin/tune/blob/770f382a03a25e15eeef293f553b6aee0f3531f6/docs/assets/gifs/tune.gif">
|
|
8
8
|
|
|
9
|
+
## Template Language
|
|
10
|
+
|
|
11
|
+
```chat
|
|
12
|
+
@myprompt include file
|
|
13
|
+
@image include image
|
|
14
|
+
@path/to/file include file at path
|
|
15
|
+
@gpt-4.1 connect model
|
|
16
|
+
@shell connect tool
|
|
17
|
+
@@prompt include file recursively
|
|
18
|
+
|
|
19
|
+
@{ name with whitespaces } - include file with whitespaces
|
|
20
|
+
@{ image | resize 512 } - modify with processors
|
|
21
|
+
@{ largefile | tail 100 } - modify with processors
|
|
22
|
+
@{| sh tree } - insert generated content with processors
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
[read more](https://iovdin.github.io/tune/template-language)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## Batteries Included
|
|
29
|
+
**Anthropic/OpenAI/Gemini/Openrouter/Mistral/Groq** models providers are supported and **30+ tools** come with text editor.
|
|
30
|
+
```chat
|
|
31
|
+
system:
|
|
32
|
+
@gemini-2.5-pro @openai_imgen
|
|
33
|
+
|
|
34
|
+
user:
|
|
35
|
+
draw a stickman with talking bubble "Hello world"
|
|
36
|
+
|
|
37
|
+
assistant:
|
|
38
|
+
tool_call: openai_imgen {"filename":"stickman_hello_world.png"}
|
|
39
|
+
a simple stickman drawing with a talking bubble saying 'Hello world'
|
|
40
|
+
|
|
41
|
+
tool_result:
|
|
42
|
+
image generated
|
|
43
|
+
```
|
|
44
|
+
[read more](tools/README.md)
|
|
45
|
+
|
|
46
|
+
## CLI
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# append user message to newchat.chat run and save
|
|
50
|
+
npx tune-sdk --user "hi how are you?" --filename newchat.chat --save
|
|
51
|
+
|
|
52
|
+
# start new chat with system prompt and initial user message
|
|
53
|
+
# print result to console
|
|
54
|
+
npx tune-sdk --system "You are Groot" --user "Hi how are you?"
|
|
55
|
+
|
|
56
|
+
#set context variable
|
|
57
|
+
npx tune-sdk --set "test=hello" --user "@test" --system "You are echo you print everythting back"
|
|
58
|
+
```
|
|
9
59
|
|
|
10
|
-
## Read more about
|
|
11
|
-
How to [connect LLMs](https://iovdin.github.io/tune/template-language/connect-llm)
|
|
12
|
-
or how to [use tools](https://iovdin.github.io/tune/template-language/tools)
|
|
13
60
|
|
|
14
61
|
## Javascript SDK
|
|
15
62
|
`npm install tune-sdk`
|
package/bin/cli.js
CHANGED
|
@@ -1,115 +1,133 @@
|
|
|
1
|
-
|
|
1
|
+
var tune, rpc;
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
function parseArgs(args) {
|
|
4
|
+
var curKey, res, res1, key, value, _ref, _len;
|
|
5
|
+
var curKey;
|
|
6
|
+
curKey = null;
|
|
7
|
+
var res;
|
|
8
|
+
res = args.reduce((function(memo, arg) {
|
|
9
|
+
var key, value, _ref, _i;
|
|
10
|
+
if (arg.startsWith("--")) {
|
|
11
|
+
_ref = arg.substring(2)
|
|
12
|
+
.split("=");
|
|
13
|
+
key = _ref[0];
|
|
14
|
+
value = _ref[1];
|
|
15
|
+
if (!!value) {
|
|
16
|
+
memo[key] = value;
|
|
17
|
+
curKey = null;
|
|
18
|
+
} else {
|
|
19
|
+
curKey = key;
|
|
20
|
+
memo[key] = true;
|
|
21
|
+
}
|
|
22
|
+
} else if (curKey) {
|
|
23
|
+
memo[curKey] = arg;
|
|
24
|
+
curKey = null;
|
|
25
|
+
}
|
|
26
|
+
return memo;
|
|
27
|
+
}), {});
|
|
28
|
+
var res1;
|
|
29
|
+
res1 = {};
|
|
30
|
+
_ref = res;
|
|
31
|
+
for (key in _ref) {
|
|
32
|
+
value = _ref[key];
|
|
33
|
+
if (key.startsWith("set-")) {
|
|
34
|
+
res1.params = res1.params || {}
|
|
35
|
+
res1.params[key.substr(4)] = value;
|
|
13
36
|
} else {
|
|
14
|
-
|
|
15
|
-
args[currentKey] = true
|
|
37
|
+
res1[key] = value;
|
|
16
38
|
}
|
|
17
|
-
} else if (currentKey) {
|
|
18
|
-
args[currentKey] = arg;
|
|
19
|
-
currentKey = null;
|
|
20
39
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
40
|
+
return res1;
|
|
41
|
+
}
|
|
42
|
+
parseArgs;
|
|
43
|
+
tune = require("../dist/tune.js");
|
|
44
|
+
rpc = require("../dist/rpc.js");
|
|
45
|
+
async function rpc(args, ctx) {
|
|
46
|
+
var server;
|
|
47
|
+
var server;
|
|
48
|
+
return (server = jsonrpc());
|
|
49
|
+
}
|
|
50
|
+
rpc;
|
|
51
|
+
async function run(args, ctx) {
|
|
52
|
+
var stopVal, params;
|
|
53
|
+
var stopVal;
|
|
54
|
+
stopVal = args.stop || "assistant";
|
|
55
|
+
if ((stopVal !== "step" && stopVal !== "assistant")) stopVal = (function(msgs) {
|
|
56
|
+
var lastMsg;
|
|
57
|
+
if (!msgs.length) return false;
|
|
58
|
+
var lastMsg;
|
|
59
|
+
lastMsg = msgs["slice"](-1)[0];
|
|
60
|
+
if (!lastMsg.content) return false;
|
|
61
|
+
return (-1 !== lastMsg.content.inexOf(args.stop || "assistant"));
|
|
62
|
+
});
|
|
63
|
+
var params;
|
|
64
|
+
params = args.params;
|
|
65
|
+
delete args.params;
|
|
66
|
+
return ctx.file2run(args, params);
|
|
67
|
+
}
|
|
68
|
+
run;
|
|
28
69
|
async function main() {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
70
|
+
var dirs, args, ctx, dir, ctxName, ext, module, m, _i, _res, _ref, _len, _ref0, _i0, _res0, _ref1, _len0, _ref2;
|
|
71
|
+
var dirs;
|
|
72
|
+
var args;
|
|
73
|
+
dirs = [];
|
|
74
|
+
args = parseArgs(process.argv.slice(2));
|
|
75
|
+
if (args.path) {
|
|
76
|
+
dirs = args.path.split(path.delimiter);
|
|
77
|
+
} else {
|
|
78
|
+
if (process.env.TUNE_PATH) dirs = process.env.TUNE_PATH.split(path.delimiter);
|
|
79
|
+
dirs.push(process.cwd());
|
|
80
|
+
}
|
|
81
|
+
ctx = tune.makeContext(process.env);
|
|
82
|
+
_res = [];
|
|
83
|
+
_ref = dirs;
|
|
84
|
+
for (_i = 0, _len = _ref.length; _i < _len; ++_i) {
|
|
85
|
+
dir = _ref[_i];
|
|
86
|
+
var ctxName;
|
|
87
|
+
ctxName = ["default.ctx.js", "default.ctx.cjs", "default.ctx.mjs"]
|
|
88
|
+
.map((function(name) {
|
|
89
|
+
return path.join(dir, name);
|
|
90
|
+
}))
|
|
91
|
+
.find((function(name) {
|
|
92
|
+
return fs.existsSync(name);
|
|
93
|
+
}));
|
|
94
|
+
if (!ctxName) continue;
|
|
95
|
+
var ext;
|
|
96
|
+
var module;
|
|
97
|
+
ext = path.extname(filename);
|
|
98
|
+
module = null;
|
|
99
|
+
if ((ext === ".js" || ext === ".cjs")) {
|
|
100
|
+
module = require(ctxName);
|
|
101
|
+
} else {
|
|
102
|
+
module = await import(ctxName);
|
|
103
|
+
module = module.default;
|
|
60
104
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
module = module.default;
|
|
74
|
-
}
|
|
75
|
-
if (typeof module === "function") {
|
|
76
|
-
ctx.use(module);
|
|
77
|
-
} else if (Array.isArray(module)) {
|
|
78
|
-
for (const m of module) {
|
|
79
|
-
if (typeof m === "function") {
|
|
80
|
-
ctx.use(m)
|
|
81
|
-
} else {
|
|
82
|
-
throw(Error(`err: Context file export is not an array of functions or function ${filename}`))
|
|
83
|
-
}
|
|
105
|
+
if ((typeof module === "function")) {
|
|
106
|
+
_ref0 = ctx.use(module);
|
|
107
|
+
} else if (Array.isArray(module)) {
|
|
108
|
+
_res0 = [];
|
|
109
|
+
_ref1 = module;
|
|
110
|
+
for (_i0 = 0, _len0 = _ref1.length; _i0 < _len0; ++_i0) {
|
|
111
|
+
m = _ref1[_i0];
|
|
112
|
+
if ((typeof m === "function")) {
|
|
113
|
+
_ref2 = ctx.use(module);
|
|
114
|
+
} else {
|
|
115
|
+
_ref2 = undefined;
|
|
116
|
+
throw Error(tpl("err: Context file export is not an array of functions or function {}", ctxName));
|
|
84
117
|
}
|
|
85
|
-
|
|
86
|
-
throw(Error(`err: Context file export is not an array of functions or function ${filename}`))
|
|
118
|
+
if (typeof _ref2 !== 'undefined') _res0.push(_ref2);
|
|
87
119
|
}
|
|
120
|
+
_ref0 = _res0;
|
|
121
|
+
} else {
|
|
122
|
+
_ref0 = undefined;
|
|
123
|
+
throw Error(tpl("err: Context file export is not an array of functions or function {}", ctxName));
|
|
88
124
|
}
|
|
89
|
-
|
|
90
|
-
if (stopVal !== "step" && stopVal != "assistant") {
|
|
91
|
-
stopVal = function(msgs) {
|
|
92
|
-
if (!msgs.length) return false
|
|
93
|
-
const lastMsg = msgs[msgs.length - 1]
|
|
94
|
-
if (!lastMsg.content) return false
|
|
95
|
-
return (lastMsg.content.indexOf(args.stop) !== -1)
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
let res = await tune.text2run(chat, ctx, { stop: stopVal })
|
|
100
|
-
|
|
101
|
-
const longFormatRegex = /^(system|user|tool_call|tool_result|assistant|error):/;
|
|
102
|
-
res = tune.msg2text(res, longFormatRegex.test(chat))
|
|
103
|
-
if (args.filename && args.save) {
|
|
104
|
-
chat += "\n" + res
|
|
105
|
-
fs.writeFileSync(args.filename, chat)
|
|
106
|
-
}
|
|
107
|
-
if (!args.save) {
|
|
108
|
-
console.log(res)
|
|
109
|
-
}
|
|
110
|
-
} catch (e) {
|
|
111
|
-
console.error(e)
|
|
125
|
+
if (typeof _ref0 !== 'undefined') _res.push(_ref0);
|
|
112
126
|
}
|
|
127
|
+
return _res;
|
|
113
128
|
}
|
|
114
|
-
|
|
115
|
-
|
|
129
|
+
main;
|
|
130
|
+
exports.parseArgs = parseArgs;
|
|
131
|
+
exports.rpc = rpc;
|
|
132
|
+
exports.main = main;
|
|
133
|
+
exports.run = run;
|