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.
@@ -15,8 +15,11 @@ if (process.env.TUNE_PATH) {
15
15
 
16
16
 
17
17
  module.exports = [
18
- curFile,
18
+ // curFile,
19
19
  fsMix(dirs, { makeSchema }),
20
- models(),
20
+ models({
21
+ default: "gpt-4.1-mini",
22
+ alias: { "sonnet": "claude-sonnet-4-20250514"}
23
+ }),
21
24
  defaultWrite()
22
25
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "dependencies": {
3
- "tune-models": "/Users/iovdin/projects/tune-models",
4
- "tune-sdk": "/Users/iovdin/projects/tune"
3
+ "tune-models": "latest",
4
+ "tune-sdk": "latest"
5
5
  }
6
6
  }
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"))) res1.stop = (function(msgs) {
42
- var lastMsg;
43
- if (!msgs.length) return false;
44
- var lastMsg;
45
- lastMsg = msgs["slice"](-1)[0];
46
- if (!lastMsg.content) return false;
47
- return (-1 !== lastMsg.content.inexOf(stop));
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
- return ((-1 !== methods.indexOf("resolve")) ? ctx.use(remoteContext.bind(server)) : undefined);
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.filename ? console.log(res) : undefined);
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 ? dirs = args.path.split(path.delimiter)
301
+ if (args.path) dirs = args.path.split(path.delimiter)
199
302
  .map((function(dir) {
200
303
  return path.resolve(pwd, dir);
201
- })) : dirs.push(getHomedir(args));
202
- dirs.push(pwd);
304
+ }));
305
+ dirs.push(getHomedir(args));
306
+ dirs.unshift(pwd);
203
307
  process.env.TUNE_PATH = dirs.join(path.delimiter);
204
- ctx = tune.makeContext(process.env);
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
- _ref = console.error(e);
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
- this.debug = params.debug;
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, _ref, _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
- if (self.debug) console.error(self.name, "<==", line);
115
+ self.debug(self.name, "<==", line);
101
116
  var msg;
102
117
  try {
103
- _ref = JSON.parse(line);
118
+ _ref0 = JSON.parse(line);
104
119
  } catch (_err) {
105
- console.error(self.name, ":", line);
106
- _ref = {}
120
+ self.debug(self.name, " cant parse json: ", line);
121
+ _ref0 = {}
107
122
  }
108
- msg = _ref;
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 _ref0;
155
+ var _ref1;
141
156
  try {
142
- _ref0 = self.exports[m.method](msg.params, msg.stream)
157
+ _ref1 = self.exports[m.method](msg.params, msg.stream)
143
158
  .then((async function(r) {
144
- var _res, _ref0, _ref1;
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(_ref0 = (!!chunk.value ? self._result(m.id, chunk.value, chunk.done) : undefined)) !== 'undefined') _res.push(_ref0);
165
+ if (typeof(_ref1 = (!!chunk.value ? self._result(m.id, chunk.value, chunk.done) : undefined)) !== 'undefined') _res.push(_ref1);
151
166
  }
152
- _ref1 = _res;
167
+ _ref2 = _res;
153
168
  } else {
154
- _ref1 = self._result(m.id, r, true);
169
+ _ref2 = self._result(m.id, r, true);
155
170
  }
156
- return _ref1;
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
- _ref0 = self._error(m.id, e.message, e.stack);
177
+ _ref1 = self._error(m.id, e.message, e.stack);
163
178
  }
164
- return _ref0;
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
- if (this.debug) console.error(this.name, "==>", JSON.stringify(payload));
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, itergQageqc, _ref;
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
- lctx.stack.push(node);
2126
- if (!text) text = await node.read();
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
- itergQageqc = new AsyncIter();
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
- itergQageqc.result = {
2193
+ itergeDPeG9.result = {
2191
2194
  value: $lastRes
2192
2195
  }
2193
2196
  }
2194
- _ref = itergQageqc.result = {
2197
+ _ref = itergeDPeG9.result = {
2195
2198
  value: $lastRes,
2196
2199
  done: true
2197
2200
  }
2198
2201
  } catch (e) {
2199
- _ref = (itergQageqc.err = e);
2202
+ _ref = (itergeDPeG9.err = e);
2200
2203
  }
2201
2204
  return _ref;
2202
2205
  })();
2203
- _ref = itergQageqc;
2206
+ _ref = itergeDPeG9;
2204
2207
  }
2205
2208
  return _ref;
2206
2209
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tune-sdk",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "tune - LLM chat in text file",
5
5
  "main": "dist/tune.js",
6
6
  "module": "dist/tune.mjs",
@@ -1,6 +1,9 @@
1
1
  import path from 'path';
2
2
 
3
3
  export default async function json_format(node, args, ctx) {
4
+ if (!node) {
5
+ return
6
+ }
4
7
  let response_format = { "type": "json_object" }
5
8
  if (args.trim()) {
6
9
 
package/tools/log.proc.js CHANGED
@@ -1,12 +1,15 @@
1
1
  const fs = require("fs")
2
- module.exports = async (node, args, ctx) => {
3
- const newNode = Object.assign({}, node);
4
- newNode.exec = async function(payload, ctx) {
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
- fs.writeFileSync(args.trim() || "log.json", JSON.stringify(payload, null, " "));
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
- return newNode
12
- }
15
+ })
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "Process and generate messages based on input parameters and file context",
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, used once when filename is empty"
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 input message to process"
16
+ "description": "User message to send"
17
17
  }
18
18
  },
19
19
  "required": ["filename", "text"]
@@ -0,0 +1,13 @@
1
+ {
2
+ "description": "Execute a nushell command",
3
+ "parameters": {
4
+ "type": "object",
5
+ "properties": {
6
+ "text": {
7
+ "type": "string",
8
+ "description": "The nushell command to execute"
9
+ }
10
+ },
11
+ "required": ["text"]
12
+ }
13
+ }
@@ -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
+ }
@@ -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
- });
@@ -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
- ]
@@ -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
- });
@@ -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
- });
@@ -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
- });
@@ -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
- });