tune-sdk 0.2.1 → 0.2.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/config/default.ctx.js +5 -2
- package/config/package.json +2 -2
- package/dist/cli.js +131 -18
- package/dist/rpc.js +33 -18
- package/dist/tune.js +14 -11
- package/package.json +1 -1
- package/tools/json_format.proc.mjs +3 -0
- package/tools/log.proc.js +9 -6
- package/tools/message.schema.json +3 -3
- package/tools/nu.schema.json +13 -0
- package/tools/nu.tool.mjs +14 -0
- package/tools/antrophic.ctx.js +0 -34
- package/tools/default.ctx.js +0 -25
- package/tools/gemini.ctx.js +0 -49
- package/tools/groq.ctx.js +0 -33
- package/tools/mistral.ctx.js +0 -64
- package/tools/openai.ctx.js +0 -33
- package/tools/openrouter.ctx.js +0 -38
package/config/default.ctx.js
CHANGED
package/config/package.json
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,17 +1,95 @@
|
|
|
1
|
-
var tune, rpc, path, fs, os, cp, stream;
|
|
1
|
+
var assert, tune, rpc, path, fs, os, cp, stream;
|
|
2
|
+
assert = require("assert");
|
|
3
|
+
|
|
4
|
+
function showHelp() {
|
|
5
|
+
console.log("TUNE-CLI - Command Line Interface for Tune SDK");
|
|
6
|
+
console.log("");
|
|
7
|
+
console.log("USAGE:");
|
|
8
|
+
console.log(" npx tune-sdk [OPTIONS]");
|
|
9
|
+
console.log("");
|
|
10
|
+
console.log("TLDR EXAMPLES:");
|
|
11
|
+
console.log(" # Quick chat with system prompt");
|
|
12
|
+
console.log(" npx tune-sdk --system \"You are Groot\" --user \"Hi how are you?\"");
|
|
13
|
+
console.log("");
|
|
14
|
+
console.log(" # Continue existing chat");
|
|
15
|
+
console.log(" npx tune-sdk --user \"continue the conversation\" --filename chat.chat --save");
|
|
16
|
+
console.log("");
|
|
17
|
+
console.log(" # Set context variables");
|
|
18
|
+
console.log(" npx tune-sdk --set-test=hello --user \"@test\" --system \"Echo assistant\"");
|
|
19
|
+
console.log("");
|
|
20
|
+
console.log(" # RPC mode for editor integration");
|
|
21
|
+
console.log(" npx tune-sdk --rpc");
|
|
22
|
+
console.log("");
|
|
23
|
+
console.log("OPTIONS:");
|
|
24
|
+
console.log(" --user <text> User message to send");
|
|
25
|
+
console.log(" --system <text> System prompt to use");
|
|
26
|
+
console.log(" --filename <file> Chat file to load/save");
|
|
27
|
+
console.log(" --save Save conversation to file");
|
|
28
|
+
console.log(" --stop <mode> Stop condition: assistant|step|<custom>");
|
|
29
|
+
console.log(" --text <content> chat content");
|
|
30
|
+
console.log(" --response <type> Response format: content|json|messages|chat (default: content)");
|
|
31
|
+
console.log(" --set-<name>=<value> Set context parameter");
|
|
32
|
+
console.log(" --rpc Start RPC server mode");
|
|
33
|
+
console.log(" --path <paths> Additional search paths (colon-separated)");
|
|
34
|
+
console.log(" --home <dir> Tune config directory (default: ~/.tune)");
|
|
35
|
+
console.log(" --debug Enable debug output");
|
|
36
|
+
console.log(" --silent Suppress output");
|
|
37
|
+
console.log(" --force-init Force config initialization");
|
|
38
|
+
console.log(" --help Show this help");
|
|
39
|
+
console.log("");
|
|
40
|
+
console.log("EXAMPLES:");
|
|
41
|
+
console.log(" # Start new chat");
|
|
42
|
+
console.log(" npx tune-sdk --system \"You are Groot\" --user \"Hi how are you?\"");
|
|
43
|
+
console.log("");
|
|
44
|
+
console.log(" # Append to existing chat and save");
|
|
45
|
+
console.log(" npx tune-sdk --user \"hi how are you?\" --filename newchat.chat --save");
|
|
46
|
+
console.log("");
|
|
47
|
+
console.log(" # Stop at specific word");
|
|
48
|
+
console.log(" npx tune-sdk --user \"continue\" --filename chat.chat --stop \"END\"");
|
|
49
|
+
console.log("");
|
|
50
|
+
console.log(" #Set context variable");
|
|
51
|
+
console.log(" npx tune-sdk --set-test=\"hello\" --user \"@test\" --system \"You are echo you print everythting back\"");
|
|
52
|
+
return console.log("");
|
|
53
|
+
}
|
|
54
|
+
showHelp;
|
|
55
|
+
|
|
56
|
+
function validateArgs(args) {
|
|
57
|
+
assert(!!args && (typeof args === "object"), "Arguments must be an object");
|
|
58
|
+
if (args.user) assert(typeof args.user === "string", "--user must be a string");
|
|
59
|
+
if (args.system) assert(typeof args.system === "string", "--system must be a string");
|
|
60
|
+
if (args.filename) assert(typeof args.filename === "string", "--filename must be a string");
|
|
61
|
+
if (args.text) assert(typeof args.text === "string", "--text must be a string");
|
|
62
|
+
if (args.response) assert(typeof args.response === "string", "--response must be a string");
|
|
63
|
+
if (args.stop) assert(typeof args.stop === "string", "--stop must be a string");
|
|
64
|
+
if (args.path) assert(typeof args.path === "string", "--path must be a string");
|
|
65
|
+
if (args.home) assert(typeof args.home === "string", "--home must be a string");
|
|
66
|
+
if (!!args.save) assert(typeof args.save === "boolean", "--save must be a boolean");
|
|
67
|
+
if (!!args.rpc) assert(typeof args.rpc === "boolean", "--rpc must be a boolean");
|
|
68
|
+
if (!!args.debug) assert(typeof args.debug === "boolean" || typeof args.debug === "string", "--debug must be a boolean");
|
|
69
|
+
if (!!args.silent) assert(typeof args.silent === "boolean", "--silent must be a boolean");
|
|
70
|
+
if (!!args.forceInit) assert(typeof args.forceInit === "boolean", "--force-init must be a boolean");
|
|
71
|
+
if (args.params) assert(!!args.params && (typeof args.params === "object"), "--set-* parameters must form a valid object");
|
|
72
|
+
if ((args.stop && (typeof args.stop === "string"))) assert((args.stop === "assistant") || (args.stop === "step") || (args.stop.length > 0), "--stop must be 'assistant', 'step', or a non-empty custom string");
|
|
73
|
+
if ((!args.rpc && !args.help && !args.user && !args.filename)) assert(false, "Must specify --user, --filename, --rpc, or --help");
|
|
74
|
+
return args;
|
|
75
|
+
}
|
|
76
|
+
validateArgs;
|
|
2
77
|
|
|
3
78
|
function parseArgs(args) {
|
|
4
79
|
var curKey, res, res1, key, value, stop, _ref, _len;
|
|
80
|
+
assert(Array.isArray(args), "parseArgs expects an array of arguments");
|
|
5
81
|
var curKey;
|
|
6
82
|
curKey = null;
|
|
7
83
|
var res;
|
|
8
84
|
res = args.reduce((function(memo, arg) {
|
|
9
85
|
var key, value, _ref, _i;
|
|
86
|
+
assert(typeof arg === "string", "Each argument must be a string");
|
|
10
87
|
if (arg.startsWith("--")) {
|
|
11
88
|
_ref = arg.substring(2)
|
|
12
89
|
.split("=");
|
|
13
90
|
key = _ref[0];
|
|
14
91
|
value = _ref[1];
|
|
92
|
+
assert((typeof key === "string") && (key.length > 0), "Argument key must be a non-empty string");
|
|
15
93
|
if (!!value) {
|
|
16
94
|
memo[key] = value;
|
|
17
95
|
curKey = null;
|
|
@@ -25,27 +103,38 @@ function parseArgs(args) {
|
|
|
25
103
|
}
|
|
26
104
|
return memo;
|
|
27
105
|
}), {});
|
|
106
|
+
assert(!!res && (typeof res === "object"), "Parsed arguments must form an object");
|
|
28
107
|
var res1;
|
|
29
108
|
res1 = {};
|
|
30
109
|
_ref = res;
|
|
31
110
|
for (key in _ref) {
|
|
32
111
|
value = _ref[key];
|
|
112
|
+
assert(typeof key === "string", "Argument keys must be strings");
|
|
33
113
|
if (key.startsWith("set-")) {
|
|
34
114
|
res1.params = res1.params || {}
|
|
115
|
+
assert(key.substr(4).length > 0, "Set parameter name cannot be empty");
|
|
35
116
|
res1.params[key.substr(4)] = value;
|
|
36
117
|
} else {
|
|
37
118
|
res1[key] = value;
|
|
38
119
|
}
|
|
39
120
|
}
|
|
121
|
+
if ((res1.h || res1.help)) res1.help = true;
|
|
40
122
|
stop = res1.stop;
|
|
41
|
-
if ((!!stop && (stop !== "step" && stop !== "assistant")))
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
123
|
+
if ((!!stop && (stop !== "step" && stop !== "assistant"))) {
|
|
124
|
+
assert(typeof stop === "string", "Custom stop condition must be a string");
|
|
125
|
+
assert(stop.length > 0, "Custom stop condition cannot be empty");
|
|
126
|
+
res1.stop = (function(msgs) {
|
|
127
|
+
var lastMsg;
|
|
128
|
+
assert(Array.isArray(msgs), "Messages must be an array");
|
|
129
|
+
if (!msgs.length) return false;
|
|
130
|
+
var lastMsg;
|
|
131
|
+
lastMsg = msgs["slice"](-1)[0];
|
|
132
|
+
assert(!!lastMsg && (typeof lastMsg === "object"), "Last message must be an object");
|
|
133
|
+
if (!lastMsg.content) return false;
|
|
134
|
+
assert(typeof lastMsg.content === "string", "Message content must be a string");
|
|
135
|
+
return (-1 !== lastMsg.content.indexOf(stop));
|
|
136
|
+
});
|
|
137
|
+
}
|
|
49
138
|
return res1;
|
|
50
139
|
}
|
|
51
140
|
parseArgs;
|
|
@@ -58,14 +147,18 @@ cp = require("child_process");
|
|
|
58
147
|
stream = require("stream");
|
|
59
148
|
|
|
60
149
|
function getHomedir(args) {
|
|
150
|
+
assert(!!args && (typeof args === "object"), "getHomedir expects args to be an object");
|
|
151
|
+
if (args.home) assert(typeof args.home === "string", "args.home must be a string");
|
|
61
152
|
return path.resolve(path.normalize((args.home || process.env.TUNE_HOME || "~/.tune")
|
|
62
153
|
.replace("~", os.homedir())));
|
|
63
154
|
}
|
|
64
155
|
getHomedir;
|
|
65
156
|
async function initConfig(args) {
|
|
66
157
|
var homedir, stdout, stderr, _ref, _i;
|
|
158
|
+
assert(!!args && (typeof args === "object"), "initConfig expects args to be an object");
|
|
67
159
|
var homedir;
|
|
68
160
|
homedir = getHomedir(args);
|
|
161
|
+
assert(typeof homedir === "string", "Home directory must be a string");
|
|
69
162
|
if ((!args.forceInit && fs.existsSync(homedir))) return;
|
|
70
163
|
console.error("[tune-sdk] initialize " + homedir);
|
|
71
164
|
fs.mkdirSync(homedir, {
|
|
@@ -107,6 +200,7 @@ async function suggest(params, ctx) {
|
|
|
107
200
|
return {
|
|
108
201
|
name: item.name,
|
|
109
202
|
dirname: item.dirname,
|
|
203
|
+
source: item.source || item.fullname,
|
|
110
204
|
fullname: item.fullname,
|
|
111
205
|
basename: (item.fullname ? path.basename(item.fullname) : undefined),
|
|
112
206
|
type: item.type
|
|
@@ -140,22 +234,31 @@ async function remoteContext(name, params) {
|
|
|
140
234
|
}
|
|
141
235
|
remoteContext;
|
|
142
236
|
async function runRpc(args) {
|
|
143
|
-
var inStream, outStream, ctx, server;
|
|
237
|
+
var inStream, outStream, debugStream, ctx, server;
|
|
144
238
|
var inStream;
|
|
145
239
|
var outStream;
|
|
240
|
+
var debugStream;
|
|
146
241
|
var ctx;
|
|
147
242
|
var server;
|
|
148
243
|
inStream = stream.Readable.toWeb(process.stdin);
|
|
149
244
|
outStream = stream.Writable.toWeb(process.stdout);
|
|
245
|
+
debugStream = ((typeof args.debug === "string") ? fs.createWriteStream(args.debug, {
|
|
246
|
+
flags: "a"
|
|
247
|
+
}) : undefined);
|
|
150
248
|
ctx = await initContext(args);
|
|
151
249
|
server = rpc.jsonrpc({
|
|
152
250
|
inStream: inStream,
|
|
153
251
|
outStream: outStream,
|
|
154
|
-
debug: args.debug
|
|
252
|
+
debug: ((typeof args.debug === "string") ? (function() {
|
|
253
|
+
var _i;
|
|
254
|
+
var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []);
|
|
255
|
+
return debugStream.write(args.join(" ") + "\n", "utf8");
|
|
256
|
+
}) : true),
|
|
155
257
|
name: "server"
|
|
156
258
|
}, {
|
|
157
259
|
init: (async function(methods) {
|
|
158
|
-
|
|
260
|
+
if ((-1 !== methods.indexOf("resolve"))) ctx.use(remoteContext.bind(server));
|
|
261
|
+
return "done";
|
|
159
262
|
}),
|
|
160
263
|
file2run: (async function(params, stream) {
|
|
161
264
|
return tune.file2run({
|
|
@@ -186,7 +289,7 @@ async function run(args) {
|
|
|
186
289
|
delete args.params;
|
|
187
290
|
var res;
|
|
188
291
|
res = await ctx.file2run(args, params);
|
|
189
|
-
return (!args.
|
|
292
|
+
return (!args.silient ? console.log(res) : undefined);
|
|
190
293
|
}
|
|
191
294
|
run;
|
|
192
295
|
async function initContext(args) {
|
|
@@ -195,13 +298,17 @@ async function initContext(args) {
|
|
|
195
298
|
var pwd;
|
|
196
299
|
dirs = [];
|
|
197
300
|
pwd = process.cwd();
|
|
198
|
-
args.path
|
|
301
|
+
if (args.path) dirs = args.path.split(path.delimiter)
|
|
199
302
|
.map((function(dir) {
|
|
200
303
|
return path.resolve(pwd, dir);
|
|
201
|
-
}))
|
|
202
|
-
dirs.push(
|
|
304
|
+
}));
|
|
305
|
+
dirs.push(getHomedir(args));
|
|
306
|
+
dirs.unshift(pwd);
|
|
203
307
|
process.env.TUNE_PATH = dirs.join(path.delimiter);
|
|
204
|
-
ctx = tune.makeContext(
|
|
308
|
+
ctx = tune.makeContext({
|
|
309
|
+
TUNE_PATH: process.env.TUNE_PATH,
|
|
310
|
+
TUNE_HOME: getHomedir(args)
|
|
311
|
+
});
|
|
205
312
|
_ref = dirs;
|
|
206
313
|
for (_i = 0, _len = _ref.length; _i < _len; ++_i) {
|
|
207
314
|
dir = _ref[_i];
|
|
@@ -254,10 +361,16 @@ async function main() {
|
|
|
254
361
|
try {
|
|
255
362
|
var args;
|
|
256
363
|
args = parseArgs(process.argv.slice(2));
|
|
364
|
+
if (args.help) {
|
|
365
|
+
showHelp();
|
|
366
|
+
process.exit(0);
|
|
367
|
+
}
|
|
368
|
+
validateArgs(args);
|
|
257
369
|
await initConfig(args);
|
|
258
370
|
_ref = args.rpc ? await runRpc(args) : await run(args);
|
|
259
371
|
} catch (e) {
|
|
260
|
-
|
|
372
|
+
console.error(e);
|
|
373
|
+
_ref = process.exit(1);
|
|
261
374
|
}
|
|
262
375
|
return _ref;
|
|
263
376
|
}
|
package/dist/rpc.js
CHANGED
|
@@ -69,9 +69,24 @@ function assert(cond, msg) {
|
|
|
69
69
|
assert;
|
|
70
70
|
|
|
71
71
|
function JSONRPC(params, exports) {
|
|
72
|
-
var self;
|
|
72
|
+
var debugWriter, self, _ref;
|
|
73
|
+
var debugWriter;
|
|
74
|
+
debugWriter;
|
|
73
75
|
this.msgId = 1;
|
|
74
|
-
|
|
76
|
+
if (!params.debug) {
|
|
77
|
+
_ref = (function() {});
|
|
78
|
+
} else if (typeof params.debug === "boolean") {
|
|
79
|
+
_ref = (function() {
|
|
80
|
+
var _i;
|
|
81
|
+
var args = 1 <= arguments.length ? [].slice.call(arguments, 0, _i = arguments.length - 0) : (_i = 0, []);
|
|
82
|
+
return console.error.apply(console, [].concat(args));
|
|
83
|
+
});
|
|
84
|
+
} else if (typeof params.debug === "function") {
|
|
85
|
+
_ref = params.debug;
|
|
86
|
+
} else {
|
|
87
|
+
_ref = undefined;
|
|
88
|
+
}
|
|
89
|
+
this.debug = _ref;
|
|
75
90
|
this.name = params.name;
|
|
76
91
|
this.exports = exports || params.exports || {}
|
|
77
92
|
this.callbacks = {};
|
|
@@ -82,7 +97,7 @@ function JSONRPC(params, exports) {
|
|
|
82
97
|
assert(params.inStream, "inStream has to be defined and be a ReadableStream");
|
|
83
98
|
assert(params.outStream, "outStream has to be defined and be a WritableStream");
|
|
84
99
|
async function pump() {
|
|
85
|
-
var res, value, done, newlineIdx, line, msg, cb, iter, err,
|
|
100
|
+
var res, value, done, newlineIdx, line, msg, cb, iter, err, _ref0, _err;
|
|
86
101
|
var res;
|
|
87
102
|
var value;
|
|
88
103
|
var done;
|
|
@@ -97,15 +112,15 @@ function JSONRPC(params, exports) {
|
|
|
97
112
|
var line;
|
|
98
113
|
line = new TextDecoder().decode(self.buf.subarray(0, newlineIdx));
|
|
99
114
|
self.buf = self.buf.subarray(newlineIdx + 1);
|
|
100
|
-
|
|
115
|
+
self.debug(self.name, "<==", line);
|
|
101
116
|
var msg;
|
|
102
117
|
try {
|
|
103
|
-
|
|
118
|
+
_ref0 = JSON.parse(line);
|
|
104
119
|
} catch (_err) {
|
|
105
|
-
|
|
106
|
-
|
|
120
|
+
self.debug(self.name, " cant parse json: ", line);
|
|
121
|
+
_ref0 = {}
|
|
107
122
|
}
|
|
108
|
-
msg =
|
|
123
|
+
msg = _ref0;
|
|
109
124
|
if (!msg.id) continue;
|
|
110
125
|
var cb;
|
|
111
126
|
var iter;
|
|
@@ -137,31 +152,31 @@ function JSONRPC(params, exports) {
|
|
|
137
152
|
self._error(msg.id, "method not found: " + msg.method);
|
|
138
153
|
continue;
|
|
139
154
|
}(function(m, r, chunk) {
|
|
140
|
-
var
|
|
155
|
+
var _ref1;
|
|
141
156
|
try {
|
|
142
|
-
|
|
157
|
+
_ref1 = self.exports[m.method](msg.params, msg.stream)
|
|
143
158
|
.then((async function(r) {
|
|
144
|
-
var _res,
|
|
159
|
+
var _res, _ref1, _ref2;
|
|
145
160
|
if (((typeof r !== 'undefined') && !!r[Symbol.asyncIterator])) {
|
|
146
161
|
_res = [];
|
|
147
162
|
while (!chunk.done) {
|
|
148
163
|
chunk = await r.next();
|
|
149
164
|
if (chunk.err) throw chunk.err;
|
|
150
|
-
if (typeof(
|
|
165
|
+
if (typeof(_ref1 = (!!chunk.value ? self._result(m.id, chunk.value, chunk.done) : undefined)) !== 'undefined') _res.push(_ref1);
|
|
151
166
|
}
|
|
152
|
-
|
|
167
|
+
_ref2 = _res;
|
|
153
168
|
} else {
|
|
154
|
-
|
|
169
|
+
_ref2 = self._result(m.id, r, true);
|
|
155
170
|
}
|
|
156
|
-
return
|
|
171
|
+
return _ref2;
|
|
157
172
|
}))
|
|
158
173
|
.catch((function(e) {
|
|
159
174
|
return self._error(m.id, e.message, e.stack);
|
|
160
175
|
}));
|
|
161
176
|
} catch (e) {
|
|
162
|
-
|
|
177
|
+
_ref1 = self._error(m.id, e.message, e.stack);
|
|
163
178
|
}
|
|
164
|
-
return
|
|
179
|
+
return _ref1;
|
|
165
180
|
})(msg, undefined, {});
|
|
166
181
|
}
|
|
167
182
|
}
|
|
@@ -178,7 +193,7 @@ JSONRPC.prototype._write = (async function(payload) {
|
|
|
178
193
|
var data;
|
|
179
194
|
encoder = new TextEncoder();
|
|
180
195
|
data = encoder.encode(JSON.stringify(payload) + "\n");
|
|
181
|
-
|
|
196
|
+
this.debug(this.name, "==>", JSON.stringify(payload));
|
|
182
197
|
return await this.writer.write(data);
|
|
183
198
|
});
|
|
184
199
|
JSONRPC.prototype._error = (function(msgId, message, stack) {
|
package/dist/tune.js
CHANGED
|
@@ -1772,7 +1772,7 @@ function ast2payload(ast) {
|
|
|
1772
1772
|
}))
|
|
1773
1773
|
.map((function(item) {
|
|
1774
1774
|
item.content = item.nodes.reduce((function(memo, node) {
|
|
1775
|
-
var lastNode, _ref;
|
|
1775
|
+
var lastStack, lastNode, _ref;
|
|
1776
1776
|
if ((node.type === "image")) {
|
|
1777
1777
|
if ((typeof memo === "string")) memo = Array({
|
|
1778
1778
|
type: "text",
|
|
@@ -1820,6 +1820,10 @@ function ast2payload(ast) {
|
|
|
1820
1820
|
text: node.value
|
|
1821
1821
|
});
|
|
1822
1822
|
}
|
|
1823
|
+
} else {
|
|
1824
|
+
var lastStack;
|
|
1825
|
+
lastStack = node.stack["slice"](-1)[0];
|
|
1826
|
+
throw new TuneError(tpl("unknown node type '{type}' for '{name}'", node), (((typeof lastStack !== "undefined") && (lastStack !== null) && !Number.isNaN(lastStack) && (typeof lastStack.filename !== "undefined") && (lastStack.filename !== null) && !Number.isNaN(lastStack.filename)) ? lastStack.filename : undefined), (((typeof lastStack !== "undefined") && (lastStack !== null) && !Number.isNaN(lastStack) && (typeof lastStack.row !== "undefined") && (lastStack.row !== null) && !Number.isNaN(lastStack.row)) ? lastStack.row : undefined), (((typeof lastStack !== "undefined") && (lastStack !== null) && !Number.isNaN(lastStack) && (typeof lastStack.col !== "undefined") && (lastStack.col !== null) && !Number.isNaN(lastStack.col)) ? lastStack.col : undefined), node.stack);
|
|
1823
1827
|
}
|
|
1824
1828
|
return memo;
|
|
1825
1829
|
}), "");
|
|
@@ -2111,7 +2115,7 @@ function text2run(text, ctx, opts) {
|
|
|
2111
2115
|
}
|
|
2112
2116
|
text2run;
|
|
2113
2117
|
async function file2run(args, params, ctx) {
|
|
2114
|
-
var lctx, text, stop, node, response, res, r, chunk,
|
|
2118
|
+
var lctx, text, stop, node, response, res, r, chunk, itergeDPeG9, _ref;
|
|
2115
2119
|
var lctx;
|
|
2116
2120
|
lctx = ctx.clone();
|
|
2117
2121
|
lctx.ms.unshift(envmd(params));
|
|
@@ -2121,10 +2125,9 @@ async function file2run(args, params, ctx) {
|
|
|
2121
2125
|
stop = (((typeof args !== "undefined") && (args !== null) && !Number.isNaN(args) && (typeof args.stop !== "undefined") && (args.stop !== null) && !Number.isNaN(args.stop)) ? args.stop : (((typeof "assistant" !== "undefined") && ("assistant" !== null) && !Number.isNaN("assistant")) ? "assistant" : undefined));
|
|
2122
2126
|
if (args.filename) {
|
|
2123
2127
|
node = await ctx.resolve(args.filename);
|
|
2124
|
-
if (node)
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
}
|
|
2128
|
+
if (node) lctx.stack.push(node);
|
|
2129
|
+
if ((node && !text)) text = await node.read();
|
|
2130
|
+
if ((!node && !text)) throw new TuneError(tpl("'{}' not found", args.filename));
|
|
2128
2131
|
}
|
|
2129
2132
|
if ((!text && args.system)) text = tpl("system:\n{system}", args);
|
|
2130
2133
|
if (args.user) text += tpl("\nuser:\n{user}", args);
|
|
@@ -2178,7 +2181,7 @@ async function file2run(args, params, ctx) {
|
|
|
2178
2181
|
stream: true
|
|
2179
2182
|
});
|
|
2180
2183
|
chunk = {};
|
|
2181
|
-
|
|
2184
|
+
itergeDPeG9 = new AsyncIter();
|
|
2182
2185
|
(async function($lastRes) {
|
|
2183
2186
|
var _ref;
|
|
2184
2187
|
try {
|
|
@@ -2187,20 +2190,20 @@ async function file2run(args, params, ctx) {
|
|
|
2187
2190
|
res = (chunk.value || "");
|
|
2188
2191
|
if (chunk.done) await save();
|
|
2189
2192
|
$lastRes = transformOutput(res) || $lastRes;
|
|
2190
|
-
|
|
2193
|
+
itergeDPeG9.result = {
|
|
2191
2194
|
value: $lastRes
|
|
2192
2195
|
}
|
|
2193
2196
|
}
|
|
2194
|
-
_ref =
|
|
2197
|
+
_ref = itergeDPeG9.result = {
|
|
2195
2198
|
value: $lastRes,
|
|
2196
2199
|
done: true
|
|
2197
2200
|
}
|
|
2198
2201
|
} catch (e) {
|
|
2199
|
-
_ref = (
|
|
2202
|
+
_ref = (itergeDPeG9.err = e);
|
|
2200
2203
|
}
|
|
2201
2204
|
return _ref;
|
|
2202
2205
|
})();
|
|
2203
|
-
_ref =
|
|
2206
|
+
_ref = itergeDPeG9;
|
|
2204
2207
|
}
|
|
2205
2208
|
return _ref;
|
|
2206
2209
|
}
|
package/package.json
CHANGED
package/tools/log.proc.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
const fs = require("fs")
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
const path = require("path")
|
|
3
|
+
|
|
4
|
+
module.exports = async (node, args, ctx) => ({
|
|
5
|
+
...node,
|
|
6
|
+
exec: async function(payload, ctx) {
|
|
5
7
|
const res = await node.exec(payload, ctx)
|
|
6
8
|
const body = JSON.parse(res.body)
|
|
7
9
|
payload = {...res, body};
|
|
8
|
-
|
|
10
|
+
const filename = args.trim() || "log.json"
|
|
11
|
+
const content = path.extname(filename) == ".chat" ? ctx.msg2text(payload.body.messages, true) : JSON.stringify(payload, null, " ")
|
|
12
|
+
fs.writeFileSync(filename, content);
|
|
9
13
|
return res
|
|
10
14
|
}
|
|
11
|
-
|
|
12
|
-
}
|
|
15
|
+
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "
|
|
2
|
+
"description": "this tool sends a message to another ai chat as 'user' role, result of the tool is an 'assistant' reply",
|
|
3
3
|
"parameters": {
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
},
|
|
10
10
|
"system": {
|
|
11
11
|
"type": "string",
|
|
12
|
-
"description": "Filename that contains system prompt,
|
|
12
|
+
"description": "Filename that contains system prompt, required once at the beginning of simulation"
|
|
13
13
|
},
|
|
14
14
|
"text": {
|
|
15
15
|
"type": "string",
|
|
16
|
-
"description": "User
|
|
16
|
+
"description": "User message to send"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"required": ["filename", "text"]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import util from 'node:util'
|
|
3
|
+
|
|
4
|
+
export default async function nu({ text }) {
|
|
5
|
+
let result = ""
|
|
6
|
+
try {
|
|
7
|
+
result = spawnSync("nu",
|
|
8
|
+
["-c", text, "--error-style", "plain"],
|
|
9
|
+
{ encoding: "utf8", shell: false })
|
|
10
|
+
} catch (e) {
|
|
11
|
+
result = e.stderr + e.stdout
|
|
12
|
+
}
|
|
13
|
+
return (result.stdout || result.stderr || "").replaceAll("@", "\\@");
|
|
14
|
+
}
|
package/tools/antrophic.ctx.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
const { createProviderContext } = require("./llm-utils");
|
|
2
|
-
|
|
3
|
-
async function fetchAnthropicModels(apiKey) {
|
|
4
|
-
const res = await fetch("https://api.anthropic.com/v1/models", {
|
|
5
|
-
headers: {
|
|
6
|
-
"x-api-key": apiKey,
|
|
7
|
-
"anthropic-version": "2023-06-01"
|
|
8
|
-
}
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
if (!res.ok) throw new Error(`Error: ${res.status} ${res.statusText}`);
|
|
12
|
-
|
|
13
|
-
const content = await res.json();
|
|
14
|
-
return content.data;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module.exports = createProviderContext("anthropic", {
|
|
18
|
-
apiKeyEnv: "ANTHROPIC_KEY",
|
|
19
|
-
apiModelFetcher: fetchAnthropicModels,
|
|
20
|
-
createExecFunction: (model, payload, key) => {
|
|
21
|
-
return {
|
|
22
|
-
url: "https://api.anthropic.com/v1/chat/completions",
|
|
23
|
-
method: "POST",
|
|
24
|
-
headers: {
|
|
25
|
-
"content-type": "application/json",
|
|
26
|
-
authorization: `Bearer ${key}`,
|
|
27
|
-
},
|
|
28
|
-
body: JSON.stringify({
|
|
29
|
-
model: model.id,
|
|
30
|
-
...payload,
|
|
31
|
-
}),
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
});
|
package/tools/default.ctx.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
|
|
4
|
-
const { curFile, fsMix, defaultWrite } = require("../dist/fsctx.js");
|
|
5
|
-
const { file2run, makeContext } = require("../dist/tune.js");
|
|
6
|
-
|
|
7
|
-
async function makeSchema(params, ctx) {
|
|
8
|
-
return file2run({ filename: path.join(__dirname, "schema.tool.chat")}, params, ctx);
|
|
9
|
-
}
|
|
10
|
-
let dirs = [];
|
|
11
|
-
if (process.env.TUNE_PATH) {
|
|
12
|
-
dirs = process.env.TUNE_PATH.split(path.delimiter);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
module.exports = [
|
|
16
|
-
curFile,
|
|
17
|
-
fsMix(dirs, { makeSchema }),
|
|
18
|
-
require("./openai.ctx.js"),
|
|
19
|
-
require("./openrouter.ctx.js"),
|
|
20
|
-
require("./antrophic.ctx.js"),
|
|
21
|
-
require("./gemini.ctx.js"),
|
|
22
|
-
require("./mistral.ctx.js"),
|
|
23
|
-
require("./groq.ctx.js"),
|
|
24
|
-
defaultWrite()
|
|
25
|
-
]
|
package/tools/gemini.ctx.js
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
const { createProviderContext } = require("./llm-utils");
|
|
2
|
-
|
|
3
|
-
async function fetchGeminiModels(apiKey) {
|
|
4
|
-
const res = await fetch(
|
|
5
|
-
`https://generativelanguage.googleapis.com/v1beta/models?key=${apiKey}&pageSize=200`,
|
|
6
|
-
);
|
|
7
|
-
|
|
8
|
-
if (!res.ok) throw new Error(`Error: ${res.status} ${res.statusText}`);
|
|
9
|
-
|
|
10
|
-
const content = await res.json();
|
|
11
|
-
content.models.forEach(model => {
|
|
12
|
-
model.id = model.name.split("/")[1]
|
|
13
|
-
})
|
|
14
|
-
return content.models;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module.exports = createProviderContext("gemini", {
|
|
18
|
-
apiKeyEnv: "GEMINI_KEY",
|
|
19
|
-
apiModelFetcher: fetchGeminiModels,
|
|
20
|
-
//modelMatcher: (name) => name.indexOf("google/") === 0,
|
|
21
|
-
// modelFilter: (models, name, args) => {
|
|
22
|
-
// const shortName = name.split("/")[1];
|
|
23
|
-
// return models
|
|
24
|
-
// .map((item) => ({ ...item, shortName: item.name.split("/")[1] }))
|
|
25
|
-
// .filter((item) => item.shortName === shortName);
|
|
26
|
-
// },
|
|
27
|
-
createExecFunction: (model, payload, key) => {
|
|
28
|
-
// google does not like content to be null
|
|
29
|
-
payload.messages.forEach((message) => {
|
|
30
|
-
if (message.content === null) {
|
|
31
|
-
message.content = [];
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
url: "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions",
|
|
37
|
-
method: "POST",
|
|
38
|
-
headers: {
|
|
39
|
-
"content-type": "application/json",
|
|
40
|
-
authorization: `Bearer ${key}`,
|
|
41
|
-
},
|
|
42
|
-
body: JSON.stringify({
|
|
43
|
-
model: model.shortName || model.name.split("/")[1],
|
|
44
|
-
...payload,
|
|
45
|
-
messages: payload.messages.filter(msg => msg.role !== 'comment'),
|
|
46
|
-
}),
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
});
|
package/tools/groq.ctx.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
const { createProviderContext } = require("./llm-utils");
|
|
2
|
-
|
|
3
|
-
async function fetchGroqModels(apiKey) {
|
|
4
|
-
const res = await fetch("https://api.groq.com/openai/v1/models", {
|
|
5
|
-
headers: {
|
|
6
|
-
Authorization: `Bearer ${apiKey}`,
|
|
7
|
-
},
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
if (!res.ok) throw new Error(`Error: ${res.status} ${res.statusText}`);
|
|
11
|
-
const content = await res.json();
|
|
12
|
-
return content.data;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
module.exports = createProviderContext("groq", {
|
|
16
|
-
apiKeyEnv: "GROQ_KEY",
|
|
17
|
-
apiModelFetcher: fetchGroqModels,
|
|
18
|
-
createExecFunction: (model, payload, key) => {
|
|
19
|
-
return {
|
|
20
|
-
url: "https://api.groq.com/openai/v1/chat/completions",
|
|
21
|
-
method: "POST",
|
|
22
|
-
headers: {
|
|
23
|
-
"content-type": "application/json",
|
|
24
|
-
authorization: `Bearer ${key}`,
|
|
25
|
-
},
|
|
26
|
-
body: JSON.stringify({
|
|
27
|
-
model: model.id,
|
|
28
|
-
...payload,
|
|
29
|
-
messages: payload.messages.filter(msg => msg.role !== 'comment'),
|
|
30
|
-
}),
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
});
|
package/tools/mistral.ctx.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
const { createProviderContext } = require("./llm-utils");
|
|
2
|
-
|
|
3
|
-
async function fetchMistralModels(apiKey) {
|
|
4
|
-
const res = await fetch("https://api.mistral.ai/v1/models", {
|
|
5
|
-
headers: {
|
|
6
|
-
authorization: `Bearer ${apiKey}`,
|
|
7
|
-
},
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
if (!res.ok) throw new Error(`Error: ${res.status} ${res.statusText}`);
|
|
11
|
-
const content = await res.json();
|
|
12
|
-
return content.data;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function hashIntegerToBase62(num) {
|
|
16
|
-
const crypto = require("crypto");
|
|
17
|
-
const base62chars =
|
|
18
|
-
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
19
|
-
const buffer = crypto.createHash("sha256").update(num.toString()).digest();
|
|
20
|
-
|
|
21
|
-
let hashValue = "";
|
|
22
|
-
for (let i = 0; hashValue.length < 9 && i < buffer.length; i++) {
|
|
23
|
-
const index = buffer[i] % base62chars.length;
|
|
24
|
-
hashValue += base62chars.charAt(index);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return hashValue.padEnd(9, "0");
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
module.exports = createProviderContext("mistral", {
|
|
31
|
-
apiKeyEnv: "MISTRAL_KEY",
|
|
32
|
-
apiModelFetcher: fetchMistralModels,
|
|
33
|
-
// modelMatcher: (name) => true, // Handle all names and filter later
|
|
34
|
-
// modelFilter: (models, name) => models.filter(item => item.id === name),
|
|
35
|
-
createExecFunction: (model, payload, key, context) => {
|
|
36
|
-
const { messages, ...rest } = payload;
|
|
37
|
-
|
|
38
|
-
// Format tool IDs for Mistral (must be 9 symbols)
|
|
39
|
-
messages.forEach((msg) => {
|
|
40
|
-
if (msg.role === "tool") {
|
|
41
|
-
msg.tool_call_id = hashIntegerToBase62(msg.tool_call_id);
|
|
42
|
-
}
|
|
43
|
-
if (msg.tool_calls) {
|
|
44
|
-
msg.tool_calls.forEach((tc) => {
|
|
45
|
-
tc.id = hashIntegerToBase62(tc.id);
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
url: "https://api.mistral.ai/v1/chat/completions",
|
|
52
|
-
method: "POST",
|
|
53
|
-
headers: {
|
|
54
|
-
"content-type": "application/json",
|
|
55
|
-
authorization: `Bearer ${key}`,
|
|
56
|
-
},
|
|
57
|
-
body: JSON.stringify({
|
|
58
|
-
model: model.id,
|
|
59
|
-
messages: messages.filter(msg => msg.role !== 'comment'),
|
|
60
|
-
...rest,
|
|
61
|
-
}),
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
});
|
package/tools/openai.ctx.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
const { createProviderContext } = require("./llm-utils");
|
|
2
|
-
|
|
3
|
-
async function fetchOpenAIModels(apiKey) {
|
|
4
|
-
const res = await fetch("https://api.openai.com/v1/models", {
|
|
5
|
-
headers: {
|
|
6
|
-
Authorization: `Bearer ${apiKey}`,
|
|
7
|
-
},
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
if (!res.ok) throw new Error(`Error: ${res.status} ${res.statusText}`);
|
|
11
|
-
const content = await res.json();
|
|
12
|
-
return content.data;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
module.exports = createProviderContext("openai", {
|
|
16
|
-
apiKeyEnv: "OPENAI_KEY",
|
|
17
|
-
apiModelFetcher: fetchOpenAIModels,
|
|
18
|
-
createExecFunction: (model, payload, key) => {
|
|
19
|
-
return {
|
|
20
|
-
url: "https://api.openai.com/v1/chat/completions",
|
|
21
|
-
method: "POST",
|
|
22
|
-
headers: {
|
|
23
|
-
"content-type": "application/json",
|
|
24
|
-
authorization: `Bearer ${key}`,
|
|
25
|
-
},
|
|
26
|
-
body: JSON.stringify({
|
|
27
|
-
model: model.id,
|
|
28
|
-
...payload,
|
|
29
|
-
messages: payload.messages.filter(msg => msg.role !== 'comment'),
|
|
30
|
-
}),
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
});
|
package/tools/openrouter.ctx.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
const { createProviderContext } = require("./llm-utils");
|
|
2
|
-
|
|
3
|
-
async function fetchOpenRouterModels() {
|
|
4
|
-
const res = await fetch("https://openrouter.ai/api/v1/models", {
|
|
5
|
-
method: "GET",
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
if (!res.ok) throw new Error(`Error: ${res.status} ${res.statusText}`);
|
|
9
|
-
const content = await res.json();
|
|
10
|
-
return content.data;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
module.exports = createProviderContext("openrouter", {
|
|
14
|
-
apiKeyEnv: "OPENROUTER_KEY",
|
|
15
|
-
apiModelFetcher: fetchOpenRouterModels,
|
|
16
|
-
//modelMatcher: (name) => true, // Handle all names
|
|
17
|
-
// modelFilter: (models, name) => {
|
|
18
|
-
// const baseName = name.split(":")[0];
|
|
19
|
-
// return models.filter(item => item.id === baseName);
|
|
20
|
-
// },
|
|
21
|
-
createExecFunction: (model, payload, key) => {
|
|
22
|
-
return {
|
|
23
|
-
url: "https://openrouter.ai/api/v1/chat/completions",
|
|
24
|
-
method: "POST",
|
|
25
|
-
headers: {
|
|
26
|
-
"content-type": "application/json",
|
|
27
|
-
authorization: `Bearer ${key}`,
|
|
28
|
-
"HTTP-Referer": "https://iovdin.github.io/tune",
|
|
29
|
-
"X-Title": "tune"
|
|
30
|
-
},
|
|
31
|
-
body: JSON.stringify({
|
|
32
|
-
model: model.id,
|
|
33
|
-
...payload,
|
|
34
|
-
messages: payload.messages.filter(msg => msg.role !== 'comment'),
|
|
35
|
-
}),
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
});
|