tune-sdk 0.1.0 → 0.1.2
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 +30 -140
- package/dist/tune.js +18 -9
- package/dist/tune.mjs +2 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,153 +1,43 @@
|
|
|
1
|
-
# Tune
|
|
1
|
+
# Tune your everyday LLM toolkit
|
|
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
|
+
With tune [javascript sdk](https://www.npmjs.com/package/tune-sdk) you can make apps and agents.
|
|
4
5
|
|
|
6
|
+
## Demo
|
|
7
|
+
<img src="https://github.com/iovdin/tune/blob/770f382a03a25e15eeef293f553b6aee0f3531f6/docs/assets/gifs/tune.gif">
|
|
5
8
|
|
|
6
|
-
## 🚀 Features
|
|
7
|
-
### 💬 .chat file
|
|
8
9
|
|
|
9
|
-
|
|
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)
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
## Javascript SDK
|
|
15
|
+
`npm install tune-sdk`
|
|
12
16
|
|
|
13
|
-
### 🔗 Variable expansion
|
|
14
|
-
|
|
15
|
-
You can use `{filename}` to inject filename contents to the chat.
|
|
16
|
-
file can be any text file or image.
|
|
17
|
-
|
|
18
|
-
<img src=https://raw.githubusercontent.com/iovdin/tune/main/gifs/variables.gif width=800 height=450>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
## 🛠️ Setup
|
|
22
|
-
|
|
23
|
-
1. Install nodejs.
|
|
24
|
-
2. Set OPENAI_KEY in settings. By default Tune uses gpt4o-mini. But you can change it
|
|
25
|
-
|
|
26
|
-
<img src=https://raw.githubusercontent.com/iovdin/tune/main/gifs/set_openai_key.gif width=800 height=450>
|
|
27
|
-
|
|
28
|
-
## ⚙️ Support for Multiple LLMs
|
|
29
|
-
|
|
30
|
-
Configure different LLMs by creating a `.config.js` file that defines the HTTP payload.
|
|
31
|
-
|
|
32
|
-
Example: Setting up Claude with [openrouter.ai](https://openrouter.ai)
|
|
33
|
-
|
|
34
|
-
```javascript
|
|
35
|
-
({
|
|
36
|
-
url: "https://openrouter.ai/api/v1/chat/completions",
|
|
37
|
-
method: "POST",
|
|
38
|
-
headers: {
|
|
39
|
-
"content-type": "application/json",
|
|
40
|
-
authorization: `Bearer ${OPEN_ROUTER_KEY}`,
|
|
41
|
-
},
|
|
42
|
-
body: JSON.stringify({
|
|
43
|
-
...payload,
|
|
44
|
-
model: "anthropic/claude-3.5-sonnet"
|
|
45
|
-
})
|
|
46
|
-
})
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
- Add your `OPEN_ROUTER_KEY` to the `.env` file.
|
|
50
|
-
- Use the config in your `.chat` file:
|
|
51
|
-
|
|
52
|
-
```chat
|
|
53
|
-
u: {claude}
|
|
54
|
-
What is the meaning of life?
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
- Naming the config `default.config.js` makes it the default LLM used by Tune.
|
|
58
|
-
|
|
59
|
-
**Note**: Tune supports OpenAI and Ollama for streaming. For Anthropic models, use services like OpenRouter.ai.
|
|
60
|
-
|
|
61
|
-
<img src=https://raw.githubusercontent.com/iovdin/tune/main/gifs/config.gif width=800 height=450>
|
|
62
|
-
|
|
63
|
-
### 🛠️ Tools
|
|
64
|
-
Tools are functions or scripts that LLMs can call to perform tasks beyond their native capabilities, such as querying a database or calling an external API.
|
|
65
|
-
|
|
66
|
-
Easily create tools using JavaScript, Python, or PHP. Name your tool files as `toolname.tool.mjs/js/cjs/py/php/chat`.
|
|
67
|
-
|
|
68
|
-
Here is a shell tool example as ESM module
|
|
69
|
-
|
|
70
|
-
**`sh.tool.mjs`**.
|
|
71
|
-
|
|
72
|
-
```javascript
|
|
73
|
-
import { execSync } from 'node:child_process';
|
|
74
|
-
|
|
75
|
-
export default async function sh({ text }) {
|
|
76
|
-
return execSync(text, { encoding: "utf8" });
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
To use the tool, just expand the file
|
|
81
|
-
```chat
|
|
82
|
-
u: {sh}
|
|
83
|
-
what is contents fo the current directory?
|
|
84
|
-
tc: sh
|
|
85
|
-
ls -la
|
|
86
|
-
tr: total 944
|
|
87
|
-
-rw-r--r-- 1 iovdin staff 248 3 Oct 22:12 4o.config.js
|
|
88
|
-
-rw-r--r-- 1 iovdin staff 253 17 Sep 16:10 4om.config.js
|
|
89
|
-
-rw-r--r-- 1 iovdin staff 2128 8 Oct 17:18 README.md
|
|
90
|
-
c:
|
|
91
|
-
tc: stands for tool call
|
|
92
|
-
tr: tool result
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Here are the shell tool in other languages
|
|
96
|
-
|
|
97
|
-
**`sh.tool.cjs`**
|
|
98
17
|
```javascript
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
18
|
+
const tune = require("tune-sdk");
|
|
19
|
+
const sonnet = require("./sonnet.llm.js");
|
|
20
|
+
|
|
21
|
+
require('dotenv').config();
|
|
22
|
+
|
|
23
|
+
async function main() {
|
|
24
|
+
const ctx = tune.makeContext({
|
|
25
|
+
echo: "You are echo, you print everything back",
|
|
26
|
+
OPENROUTER_KEY: process.env.OPENROUTER_KEY,
|
|
27
|
+
"default": {
|
|
28
|
+
type: "llm",
|
|
29
|
+
exec: sonnet
|
|
30
|
+
}
|
|
31
|
+
})
|
|
113
32
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return shell_exec($params['text']);
|
|
33
|
+
const text = "s: @echo\nu: hello world";
|
|
34
|
+
const messages = await tune.text2run(text, ctx)
|
|
35
|
+
console.log(tune.msg2text(messages))
|
|
36
|
+
// a: hello world
|
|
119
37
|
}
|
|
120
|
-
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
<img src=https://raw.githubusercontent.com/iovdin/tune/main/gifs/tool.gif width=800 height=450>
|
|
124
|
-
|
|
125
|
-
It is possible to make tool out of another chat.
|
|
126
|
-
Lets create a tool that gives file a name given text content
|
|
127
|
-
|
|
128
|
-
**`filename.tool.chat`**
|
|
129
|
-
```chat
|
|
130
|
-
s: You're given text content, please come up with a filename for the content.
|
|
131
|
-
it should use camel case
|
|
132
|
-
u: {text}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
How to use it?
|
|
136
|
-
```chat
|
|
137
|
-
s: {filename}
|
|
138
|
-
tc: filename
|
|
139
|
-
console.log("hello world")
|
|
140
|
-
tr: HelloWorld.js
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
Checkout more tools at [Tune GitHub](https://github.com/iovdin/tune)
|
|
144
|
-
|
|
145
|
-
## Help System Prompt
|
|
146
|
-
You can ask for help using
|
|
147
|
-
```chat
|
|
148
|
-
s: {esc:tune_help}
|
|
149
|
-
u: how to make a tool?
|
|
38
|
+
main()
|
|
150
39
|
```
|
|
40
|
+
[read more](https://iovdin.github.io/tune/api) about javascript sdk
|
|
151
41
|
|
|
152
42
|
### 📫 Contact
|
|
153
43
|
|
package/dist/tune.js
CHANGED
|
@@ -914,7 +914,6 @@ $roles = {
|
|
|
914
914
|
"a": "assistant",
|
|
915
915
|
"au": "audio",
|
|
916
916
|
"tc": "tool_call",
|
|
917
|
-
"v": "variable",
|
|
918
917
|
"err": "error",
|
|
919
918
|
"c": "comment",
|
|
920
919
|
"tr": "tool_result",
|
|
@@ -1643,7 +1642,7 @@ function text2run(text, ctx, opts) {
|
|
|
1643
1642
|
if ((stopVal === "step")) {
|
|
1644
1643
|
_ref = !!lastMsg;
|
|
1645
1644
|
} else if (stopVal === "assistant") {
|
|
1646
|
-
_ref = (!!lastMsg && (lastMsg.role === "assistant") && !!lastMsg.content);
|
|
1645
|
+
_ref = (!!lastMsg && (lastMsg.role === "assistant") && !!lastMsg.content && !lastMsg.tool_calls);
|
|
1647
1646
|
} else if (typeof stopVal === "function") {
|
|
1648
1647
|
_ref = stopVal(msgs);
|
|
1649
1648
|
} else {
|
|
@@ -1675,13 +1674,13 @@ function text2run(text, ctx, opts) {
|
|
|
1675
1674
|
ctype = res.headers.get("content-type");
|
|
1676
1675
|
if ((!stream || ctype.includes("application/json"))) {
|
|
1677
1676
|
res = await res.json();
|
|
1678
|
-
if ((((typeof res !== "undefined") && (res !== null) && !Number.isNaN(res) && (typeof res.error !== "undefined") && (res.error !== null) && !Number.isNaN(res.error)) ? res.error : undefined)) {
|
|
1677
|
+
if (((((typeof res !== "undefined") && (res !== null) && !Number.isNaN(res) && (typeof res.error !== "undefined") && (res.error !== null) && !Number.isNaN(res.error)) ? res.error : undefined) || (res.object === "error"))) {
|
|
1679
1678
|
var err;
|
|
1680
|
-
err = new TuneError(tpl("{type: }{message}", res.error));
|
|
1679
|
+
err = new TuneError(tpl("{type: }{message}", (((typeof res !== "undefined") && (res !== null) && !Number.isNaN(res) && (typeof res.error !== "undefined") && (res.error !== null) && !Number.isNaN(res.error)) ? res.error : (((typeof res !== "undefined") && (res !== null) && !Number.isNaN(res)) ? res : undefined))));
|
|
1681
1680
|
err.stack = TuneError.ctx2stack(ctx);
|
|
1682
1681
|
throw err;
|
|
1683
1682
|
}
|
|
1684
|
-
msgs.push(res.choices[0].message);
|
|
1683
|
+
msgs.push((((typeof res !== "undefined") && (res !== null) && !Number.isNaN(res) && (typeof res.message !== "undefined") && (res.message !== null) && !Number.isNaN(res.message)) ? res.message : (((typeof res !== "undefined") && (res !== null) && !Number.isNaN(res) && (typeof res.choices !== "undefined") && (res.choices !== null) && !Number.isNaN(res.choices) && (typeof res.choices[0] !== "undefined") && (res.choices[0] !== null) && !Number.isNaN(res.choices[0]) && (typeof res.choices[0].message !== "undefined") && (res.choices[0].message !== null) && !Number.isNaN(res.choices[0].message)) ? res.choices[0].message : undefined)));
|
|
1685
1684
|
continue;
|
|
1686
1685
|
}
|
|
1687
1686
|
var reader;
|
|
@@ -1779,10 +1778,14 @@ function msg2text(msg, long) {
|
|
|
1779
1778
|
var _ref, _ref0, _ref1;
|
|
1780
1779
|
|
|
1781
1780
|
function mkline(role, content) {
|
|
1782
|
-
return tpl("{role}:
|
|
1783
|
-
role:
|
|
1781
|
+
return (long ? tpl("{role}:{new_line}{content}", {
|
|
1782
|
+
role: role,
|
|
1783
|
+
content: content,
|
|
1784
|
+
new_line: ((role === "system" || role === "user" || role === "assistant" || role === "tool_result") ? "\n" : " ")
|
|
1785
|
+
}) : tpl("{role}: {content}", {
|
|
1786
|
+
role: $roles.long2short[role],
|
|
1784
1787
|
content: content
|
|
1785
|
-
});
|
|
1788
|
+
}));
|
|
1786
1789
|
}
|
|
1787
1790
|
mkline;
|
|
1788
1791
|
if (Array.isArray(msg)) {
|
|
@@ -1825,7 +1828,7 @@ function msg2text(msg, long) {
|
|
|
1825
1828
|
break;
|
|
1826
1829
|
case "assistant":
|
|
1827
1830
|
_ref = (function(res) {
|
|
1828
|
-
if (((typeof msg.content === "string") || (msg.content instanceof String))) {
|
|
1831
|
+
if ((msg.content && ((typeof msg.content === "string") || (msg.content instanceof String)))) {
|
|
1829
1832
|
res.push(mkline("assistant", msg.content));
|
|
1830
1833
|
} else if (Array.isArray(msg.content)) {
|
|
1831
1834
|
res.push(msg.content
|
|
@@ -1879,6 +1882,12 @@ function msg2text(msg, long) {
|
|
|
1879
1882
|
case "tool":
|
|
1880
1883
|
_ref = mkline("tool_result", msg.content);
|
|
1881
1884
|
break;
|
|
1885
|
+
case "system":
|
|
1886
|
+
_ref = mkline("system", msg.content);
|
|
1887
|
+
break;
|
|
1888
|
+
case "comment":
|
|
1889
|
+
_ref = mkline("comment", msg.content);
|
|
1890
|
+
break;
|
|
1882
1891
|
case "error":
|
|
1883
1892
|
_ref = mkline("error ", msg.content);
|
|
1884
1893
|
break;
|
package/dist/tune.mjs
CHANGED
|
@@ -1,24 +1,5 @@
|
|
|
1
1
|
import { createRequire } from 'module';
|
|
2
2
|
const require = createRequire(import.meta.url);
|
|
3
3
|
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
export const makeContext = tune.makeContext;
|
|
7
|
-
export const env2vars = tune.env2vars;
|
|
8
|
-
export const text2roles = tune.text2roles;
|
|
9
|
-
export const roles2text = tune.roles2text;
|
|
10
|
-
export const text2call = tune.text2call;
|
|
11
|
-
export const text2expand = tune.text2expand;
|
|
12
|
-
export const chat2expand = tune.chat2expand;
|
|
13
|
-
export const text2api = tune.text2api;
|
|
14
|
-
export const payload2api = tune.payload2api;
|
|
15
|
-
export const toolCall = tune.toolCall;
|
|
16
|
-
export const makeTool = tune.makeTool;
|
|
17
|
-
export const text2run = tune.text2run;
|
|
18
|
-
export const text2stream = tune.text2stream;
|
|
19
|
-
export const msg2text = tune.msg2text;
|
|
20
|
-
export const msg2role = tune.msg2role;
|
|
21
|
-
export const text2cut = tune.text2cut;
|
|
22
|
-
export const TuneError = tune.TuneError;
|
|
23
|
-
export const pparse = tune.pparse;
|
|
24
|
-
export const text2var = tune.text2var;
|
|
4
|
+
const { makeContext, text2roles, roles2text, text2call, text2ast, ast2payload, toolCall, text2run, msg2text, msg2role, text2cut, TuneError, text2cut, text2payload, payload2http, envmd, unescape, escape } = require('./tune.js');
|
|
5
|
+
export { makeContext, text2roles, roles2text, text2call, text2ast, ast2payload, toolCall, text2run, msg2text, msg2role, text2cut, TuneError, text2cut, text2payload, payload2http, envmd, unescape, escape }
|