@codedir/mimir-code 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 +53 -47
- package/dist/binaries/resources/sql-wasm.wasm +0 -0
- package/dist/{cli.js → cli.mjs} +945 -1388
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.ts +19 -19
- package/dist/index.js +6 -10
- package/dist/index.js.map +1 -1
- package/package.json +23 -11
- package/scripts/templates/commands/{docs.yml → update-docs.yml} +5 -5
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js.map +0 -1
- package/scripts/templates/commands/perf.yml +0 -56
- package/scripts/templates/commands/refactor.yml +0 -52
- package/scripts/templates/commands/review.yml +0 -62
- package/scripts/templates/commands/security.yml +0 -51
- package/scripts/templates/commands/test.yml +0 -50
package/dist/{cli.js → cli.mjs}
RENAMED
|
@@ -1,852 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
9
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
10
|
-
}) : x)(function(x) {
|
|
11
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
12
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
13
|
-
});
|
|
14
|
-
var __esm = (fn, res) => function __init() {
|
|
15
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
16
|
-
};
|
|
17
|
-
var __commonJS = (cb, mod) => function __require2() {
|
|
18
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
19
|
-
};
|
|
20
|
-
var __export = (target, all) => {
|
|
21
|
-
for (var name in all)
|
|
22
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
23
|
-
};
|
|
24
|
-
var __copyProps = (to, from, except, desc) => {
|
|
25
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
26
|
-
for (let key of __getOwnPropNames(from))
|
|
27
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
28
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
29
|
-
}
|
|
30
|
-
return to;
|
|
31
|
-
};
|
|
32
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
33
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
34
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
35
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
36
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
37
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
38
|
-
mod
|
|
39
|
-
));
|
|
40
|
-
|
|
41
|
-
// node_modules/tsup/assets/esm_shims.js
|
|
42
|
-
import path from "path";
|
|
43
|
-
import { fileURLToPath } from "url";
|
|
44
|
-
var getFilename, __filename;
|
|
45
|
-
var init_esm_shims = __esm({
|
|
46
|
-
"node_modules/tsup/assets/esm_shims.js"() {
|
|
47
|
-
"use strict";
|
|
48
|
-
getFilename = () => fileURLToPath(import.meta.url);
|
|
49
|
-
__filename = /* @__PURE__ */ getFilename();
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
// node_modules/better-sqlite3/lib/util.js
|
|
54
|
-
var require_util = __commonJS({
|
|
55
|
-
"node_modules/better-sqlite3/lib/util.js"(exports) {
|
|
56
|
-
"use strict";
|
|
57
|
-
init_esm_shims();
|
|
58
|
-
exports.getBooleanOption = (options, key) => {
|
|
59
|
-
let value = false;
|
|
60
|
-
if (key in options && typeof (value = options[key]) !== "boolean") {
|
|
61
|
-
throw new TypeError(`Expected the "${key}" option to be a boolean`);
|
|
62
|
-
}
|
|
63
|
-
return value;
|
|
64
|
-
};
|
|
65
|
-
exports.cppdb = Symbol();
|
|
66
|
-
exports.inspect = Symbol.for("nodejs.util.inspect.custom");
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// node_modules/better-sqlite3/lib/sqlite-error.js
|
|
71
|
-
var require_sqlite_error = __commonJS({
|
|
72
|
-
"node_modules/better-sqlite3/lib/sqlite-error.js"(exports, module) {
|
|
73
|
-
"use strict";
|
|
74
|
-
init_esm_shims();
|
|
75
|
-
var descriptor = { value: "SqliteError", writable: true, enumerable: false, configurable: true };
|
|
76
|
-
function SqliteError(message, code) {
|
|
77
|
-
if (new.target !== SqliteError) {
|
|
78
|
-
return new SqliteError(message, code);
|
|
79
|
-
}
|
|
80
|
-
if (typeof code !== "string") {
|
|
81
|
-
throw new TypeError("Expected second argument to be a string");
|
|
82
|
-
}
|
|
83
|
-
Error.call(this, message);
|
|
84
|
-
descriptor.value = "" + message;
|
|
85
|
-
Object.defineProperty(this, "message", descriptor);
|
|
86
|
-
Error.captureStackTrace(this, SqliteError);
|
|
87
|
-
this.code = code;
|
|
88
|
-
}
|
|
89
|
-
Object.setPrototypeOf(SqliteError, Error);
|
|
90
|
-
Object.setPrototypeOf(SqliteError.prototype, Error.prototype);
|
|
91
|
-
Object.defineProperty(SqliteError.prototype, "name", descriptor);
|
|
92
|
-
module.exports = SqliteError;
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// node_modules/file-uri-to-path/index.js
|
|
97
|
-
var require_file_uri_to_path = __commonJS({
|
|
98
|
-
"node_modules/file-uri-to-path/index.js"(exports, module) {
|
|
99
|
-
"use strict";
|
|
100
|
-
init_esm_shims();
|
|
101
|
-
var sep = __require("path").sep || "/";
|
|
102
|
-
module.exports = fileUriToPath;
|
|
103
|
-
function fileUriToPath(uri) {
|
|
104
|
-
if ("string" != typeof uri || uri.length <= 7 || "file://" != uri.substring(0, 7)) {
|
|
105
|
-
throw new TypeError("must pass in a file:// URI to convert to a file path");
|
|
106
|
-
}
|
|
107
|
-
var rest = decodeURI(uri.substring(7));
|
|
108
|
-
var firstSlash = rest.indexOf("/");
|
|
109
|
-
var host = rest.substring(0, firstSlash);
|
|
110
|
-
var path9 = rest.substring(firstSlash + 1);
|
|
111
|
-
if ("localhost" == host) host = "";
|
|
112
|
-
if (host) {
|
|
113
|
-
host = sep + sep + host;
|
|
114
|
-
}
|
|
115
|
-
path9 = path9.replace(/^(.+)\|/, "$1:");
|
|
116
|
-
if (sep == "\\") {
|
|
117
|
-
path9 = path9.replace(/\//g, "\\");
|
|
118
|
-
}
|
|
119
|
-
if (/^.+\:/.test(path9)) {
|
|
120
|
-
} else {
|
|
121
|
-
path9 = sep + path9;
|
|
122
|
-
}
|
|
123
|
-
return host + path9;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
// node_modules/bindings/bindings.js
|
|
129
|
-
var require_bindings = __commonJS({
|
|
130
|
-
"node_modules/bindings/bindings.js"(exports, module) {
|
|
131
|
-
"use strict";
|
|
132
|
-
init_esm_shims();
|
|
133
|
-
var fs4 = __require("fs");
|
|
134
|
-
var path9 = __require("path");
|
|
135
|
-
var fileURLToPath3 = require_file_uri_to_path();
|
|
136
|
-
var join = path9.join;
|
|
137
|
-
var dirname3 = path9.dirname;
|
|
138
|
-
var exists = fs4.accessSync && function(path10) {
|
|
139
|
-
try {
|
|
140
|
-
fs4.accessSync(path10);
|
|
141
|
-
} catch (e) {
|
|
142
|
-
return false;
|
|
143
|
-
}
|
|
144
|
-
return true;
|
|
145
|
-
} || fs4.existsSync || path9.existsSync;
|
|
146
|
-
var defaults = {
|
|
147
|
-
arrow: process.env.NODE_BINDINGS_ARROW || " \u2192 ",
|
|
148
|
-
compiled: process.env.NODE_BINDINGS_COMPILED_DIR || "compiled",
|
|
149
|
-
platform: process.platform,
|
|
150
|
-
arch: process.arch,
|
|
151
|
-
nodePreGyp: "node-v" + process.versions.modules + "-" + process.platform + "-" + process.arch,
|
|
152
|
-
version: process.versions.node,
|
|
153
|
-
bindings: "bindings.node",
|
|
154
|
-
try: [
|
|
155
|
-
// node-gyp's linked version in the "build" dir
|
|
156
|
-
["module_root", "build", "bindings"],
|
|
157
|
-
// node-waf and gyp_addon (a.k.a node-gyp)
|
|
158
|
-
["module_root", "build", "Debug", "bindings"],
|
|
159
|
-
["module_root", "build", "Release", "bindings"],
|
|
160
|
-
// Debug files, for development (legacy behavior, remove for node v0.9)
|
|
161
|
-
["module_root", "out", "Debug", "bindings"],
|
|
162
|
-
["module_root", "Debug", "bindings"],
|
|
163
|
-
// Release files, but manually compiled (legacy behavior, remove for node v0.9)
|
|
164
|
-
["module_root", "out", "Release", "bindings"],
|
|
165
|
-
["module_root", "Release", "bindings"],
|
|
166
|
-
// Legacy from node-waf, node <= 0.4.x
|
|
167
|
-
["module_root", "build", "default", "bindings"],
|
|
168
|
-
// Production "Release" buildtype binary (meh...)
|
|
169
|
-
["module_root", "compiled", "version", "platform", "arch", "bindings"],
|
|
170
|
-
// node-qbs builds
|
|
171
|
-
["module_root", "addon-build", "release", "install-root", "bindings"],
|
|
172
|
-
["module_root", "addon-build", "debug", "install-root", "bindings"],
|
|
173
|
-
["module_root", "addon-build", "default", "install-root", "bindings"],
|
|
174
|
-
// node-pre-gyp path ./lib/binding/{node_abi}-{platform}-{arch}
|
|
175
|
-
["module_root", "lib", "binding", "nodePreGyp", "bindings"]
|
|
176
|
-
]
|
|
177
|
-
};
|
|
178
|
-
function bindings(opts) {
|
|
179
|
-
if (typeof opts == "string") {
|
|
180
|
-
opts = { bindings: opts };
|
|
181
|
-
} else if (!opts) {
|
|
182
|
-
opts = {};
|
|
183
|
-
}
|
|
184
|
-
Object.keys(defaults).map(function(i2) {
|
|
185
|
-
if (!(i2 in opts)) opts[i2] = defaults[i2];
|
|
186
|
-
});
|
|
187
|
-
if (!opts.module_root) {
|
|
188
|
-
opts.module_root = exports.getRoot(exports.getFileName());
|
|
189
|
-
}
|
|
190
|
-
if (path9.extname(opts.bindings) != ".node") {
|
|
191
|
-
opts.bindings += ".node";
|
|
192
|
-
}
|
|
193
|
-
var requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
|
|
194
|
-
var tries = [], i = 0, l = opts.try.length, n, b, err;
|
|
195
|
-
for (; i < l; i++) {
|
|
196
|
-
n = join.apply(
|
|
197
|
-
null,
|
|
198
|
-
opts.try[i].map(function(p) {
|
|
199
|
-
return opts[p] || p;
|
|
200
|
-
})
|
|
201
|
-
);
|
|
202
|
-
tries.push(n);
|
|
203
|
-
try {
|
|
204
|
-
b = opts.path ? requireFunc.resolve(n) : requireFunc(n);
|
|
205
|
-
if (!opts.path) {
|
|
206
|
-
b.path = n;
|
|
207
|
-
}
|
|
208
|
-
return b;
|
|
209
|
-
} catch (e) {
|
|
210
|
-
if (e.code !== "MODULE_NOT_FOUND" && e.code !== "QUALIFIED_PATH_RESOLUTION_FAILED" && !/not find/i.test(e.message)) {
|
|
211
|
-
throw e;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
err = new Error(
|
|
216
|
-
"Could not locate the bindings file. Tried:\n" + tries.map(function(a) {
|
|
217
|
-
return opts.arrow + a;
|
|
218
|
-
}).join("\n")
|
|
219
|
-
);
|
|
220
|
-
err.tries = tries;
|
|
221
|
-
throw err;
|
|
222
|
-
}
|
|
223
|
-
module.exports = exports = bindings;
|
|
224
|
-
exports.getFileName = function getFileName(calling_file) {
|
|
225
|
-
var origPST = Error.prepareStackTrace, origSTL = Error.stackTraceLimit, dummy = {}, fileName;
|
|
226
|
-
Error.stackTraceLimit = 10;
|
|
227
|
-
Error.prepareStackTrace = function(e, st) {
|
|
228
|
-
for (var i = 0, l = st.length; i < l; i++) {
|
|
229
|
-
fileName = st[i].getFileName();
|
|
230
|
-
if (fileName !== __filename) {
|
|
231
|
-
if (calling_file) {
|
|
232
|
-
if (fileName !== calling_file) {
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
} else {
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
Error.captureStackTrace(dummy);
|
|
242
|
-
dummy.stack;
|
|
243
|
-
Error.prepareStackTrace = origPST;
|
|
244
|
-
Error.stackTraceLimit = origSTL;
|
|
245
|
-
var fileSchema = "file://";
|
|
246
|
-
if (fileName.indexOf(fileSchema) === 0) {
|
|
247
|
-
fileName = fileURLToPath3(fileName);
|
|
248
|
-
}
|
|
249
|
-
return fileName;
|
|
250
|
-
};
|
|
251
|
-
exports.getRoot = function getRoot(file) {
|
|
252
|
-
var dir = dirname3(file), prev;
|
|
253
|
-
while (true) {
|
|
254
|
-
if (dir === ".") {
|
|
255
|
-
dir = process.cwd();
|
|
256
|
-
}
|
|
257
|
-
if (exists(join(dir, "package.json")) || exists(join(dir, "node_modules"))) {
|
|
258
|
-
return dir;
|
|
259
|
-
}
|
|
260
|
-
if (prev === dir) {
|
|
261
|
-
throw new Error(
|
|
262
|
-
'Could not find module root given file: "' + file + '". Do you have a `package.json` file? '
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
prev = dir;
|
|
266
|
-
dir = join(dir, "..");
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
// node_modules/better-sqlite3/lib/methods/wrappers.js
|
|
273
|
-
var require_wrappers = __commonJS({
|
|
274
|
-
"node_modules/better-sqlite3/lib/methods/wrappers.js"(exports) {
|
|
275
|
-
"use strict";
|
|
276
|
-
init_esm_shims();
|
|
277
|
-
var { cppdb } = require_util();
|
|
278
|
-
exports.prepare = function prepare(sql2) {
|
|
279
|
-
return this[cppdb].prepare(sql2, this, false);
|
|
280
|
-
};
|
|
281
|
-
exports.exec = function exec(sql2) {
|
|
282
|
-
this[cppdb].exec(sql2);
|
|
283
|
-
return this;
|
|
284
|
-
};
|
|
285
|
-
exports.close = function close() {
|
|
286
|
-
this[cppdb].close();
|
|
287
|
-
return this;
|
|
288
|
-
};
|
|
289
|
-
exports.loadExtension = function loadExtension(...args) {
|
|
290
|
-
this[cppdb].loadExtension(...args);
|
|
291
|
-
return this;
|
|
292
|
-
};
|
|
293
|
-
exports.defaultSafeIntegers = function defaultSafeIntegers(...args) {
|
|
294
|
-
this[cppdb].defaultSafeIntegers(...args);
|
|
295
|
-
return this;
|
|
296
|
-
};
|
|
297
|
-
exports.unsafeMode = function unsafeMode(...args) {
|
|
298
|
-
this[cppdb].unsafeMode(...args);
|
|
299
|
-
return this;
|
|
300
|
-
};
|
|
301
|
-
exports.getters = {
|
|
302
|
-
name: {
|
|
303
|
-
get: function name() {
|
|
304
|
-
return this[cppdb].name;
|
|
305
|
-
},
|
|
306
|
-
enumerable: true
|
|
307
|
-
},
|
|
308
|
-
open: {
|
|
309
|
-
get: function open() {
|
|
310
|
-
return this[cppdb].open;
|
|
311
|
-
},
|
|
312
|
-
enumerable: true
|
|
313
|
-
},
|
|
314
|
-
inTransaction: {
|
|
315
|
-
get: function inTransaction() {
|
|
316
|
-
return this[cppdb].inTransaction;
|
|
317
|
-
},
|
|
318
|
-
enumerable: true
|
|
319
|
-
},
|
|
320
|
-
readonly: {
|
|
321
|
-
get: function readonly() {
|
|
322
|
-
return this[cppdb].readonly;
|
|
323
|
-
},
|
|
324
|
-
enumerable: true
|
|
325
|
-
},
|
|
326
|
-
memory: {
|
|
327
|
-
get: function memory() {
|
|
328
|
-
return this[cppdb].memory;
|
|
329
|
-
},
|
|
330
|
-
enumerable: true
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
// node_modules/better-sqlite3/lib/methods/transaction.js
|
|
337
|
-
var require_transaction = __commonJS({
|
|
338
|
-
"node_modules/better-sqlite3/lib/methods/transaction.js"(exports, module) {
|
|
339
|
-
"use strict";
|
|
340
|
-
init_esm_shims();
|
|
341
|
-
var { cppdb } = require_util();
|
|
342
|
-
var controllers = /* @__PURE__ */ new WeakMap();
|
|
343
|
-
module.exports = function transaction(fn) {
|
|
344
|
-
if (typeof fn !== "function") throw new TypeError("Expected first argument to be a function");
|
|
345
|
-
const db = this[cppdb];
|
|
346
|
-
const controller = getController(db, this);
|
|
347
|
-
const { apply } = Function.prototype;
|
|
348
|
-
const properties = {
|
|
349
|
-
default: { value: wrapTransaction(apply, fn, db, controller.default) },
|
|
350
|
-
deferred: { value: wrapTransaction(apply, fn, db, controller.deferred) },
|
|
351
|
-
immediate: { value: wrapTransaction(apply, fn, db, controller.immediate) },
|
|
352
|
-
exclusive: { value: wrapTransaction(apply, fn, db, controller.exclusive) },
|
|
353
|
-
database: { value: this, enumerable: true }
|
|
354
|
-
};
|
|
355
|
-
Object.defineProperties(properties.default.value, properties);
|
|
356
|
-
Object.defineProperties(properties.deferred.value, properties);
|
|
357
|
-
Object.defineProperties(properties.immediate.value, properties);
|
|
358
|
-
Object.defineProperties(properties.exclusive.value, properties);
|
|
359
|
-
return properties.default.value;
|
|
360
|
-
};
|
|
361
|
-
var getController = (db, self) => {
|
|
362
|
-
let controller = controllers.get(db);
|
|
363
|
-
if (!controller) {
|
|
364
|
-
const shared = {
|
|
365
|
-
commit: db.prepare("COMMIT", self, false),
|
|
366
|
-
rollback: db.prepare("ROLLBACK", self, false),
|
|
367
|
-
savepoint: db.prepare("SAVEPOINT ` _bs3. `", self, false),
|
|
368
|
-
release: db.prepare("RELEASE ` _bs3. `", self, false),
|
|
369
|
-
rollbackTo: db.prepare("ROLLBACK TO ` _bs3. `", self, false)
|
|
370
|
-
};
|
|
371
|
-
controllers.set(db, controller = {
|
|
372
|
-
default: Object.assign({ begin: db.prepare("BEGIN", self, false) }, shared),
|
|
373
|
-
deferred: Object.assign({ begin: db.prepare("BEGIN DEFERRED", self, false) }, shared),
|
|
374
|
-
immediate: Object.assign({ begin: db.prepare("BEGIN IMMEDIATE", self, false) }, shared),
|
|
375
|
-
exclusive: Object.assign({ begin: db.prepare("BEGIN EXCLUSIVE", self, false) }, shared)
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
return controller;
|
|
379
|
-
};
|
|
380
|
-
var wrapTransaction = (apply, fn, db, { begin, commit, rollback, savepoint, release, rollbackTo }) => function sqliteTransaction() {
|
|
381
|
-
let before, after, undo;
|
|
382
|
-
if (db.inTransaction) {
|
|
383
|
-
before = savepoint;
|
|
384
|
-
after = release;
|
|
385
|
-
undo = rollbackTo;
|
|
386
|
-
} else {
|
|
387
|
-
before = begin;
|
|
388
|
-
after = commit;
|
|
389
|
-
undo = rollback;
|
|
390
|
-
}
|
|
391
|
-
before.run();
|
|
392
|
-
try {
|
|
393
|
-
const result = apply.call(fn, this, arguments);
|
|
394
|
-
if (result && typeof result.then === "function") {
|
|
395
|
-
throw new TypeError("Transaction function cannot return a promise");
|
|
396
|
-
}
|
|
397
|
-
after.run();
|
|
398
|
-
return result;
|
|
399
|
-
} catch (ex) {
|
|
400
|
-
if (db.inTransaction) {
|
|
401
|
-
undo.run();
|
|
402
|
-
if (undo !== rollback) after.run();
|
|
403
|
-
}
|
|
404
|
-
throw ex;
|
|
405
|
-
}
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
// node_modules/better-sqlite3/lib/methods/pragma.js
|
|
411
|
-
var require_pragma = __commonJS({
|
|
412
|
-
"node_modules/better-sqlite3/lib/methods/pragma.js"(exports, module) {
|
|
413
|
-
"use strict";
|
|
414
|
-
init_esm_shims();
|
|
415
|
-
var { getBooleanOption, cppdb } = require_util();
|
|
416
|
-
module.exports = function pragma(source, options) {
|
|
417
|
-
if (options == null) options = {};
|
|
418
|
-
if (typeof source !== "string") throw new TypeError("Expected first argument to be a string");
|
|
419
|
-
if (typeof options !== "object") throw new TypeError("Expected second argument to be an options object");
|
|
420
|
-
const simple = getBooleanOption(options, "simple");
|
|
421
|
-
const stmt = this[cppdb].prepare(`PRAGMA ${source}`, this, true);
|
|
422
|
-
return simple ? stmt.pluck().get() : stmt.all();
|
|
423
|
-
};
|
|
424
|
-
}
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
// node_modules/better-sqlite3/lib/methods/backup.js
|
|
428
|
-
var require_backup = __commonJS({
|
|
429
|
-
"node_modules/better-sqlite3/lib/methods/backup.js"(exports, module) {
|
|
430
|
-
"use strict";
|
|
431
|
-
init_esm_shims();
|
|
432
|
-
var fs4 = __require("fs");
|
|
433
|
-
var path9 = __require("path");
|
|
434
|
-
var { promisify } = __require("util");
|
|
435
|
-
var { cppdb } = require_util();
|
|
436
|
-
var fsAccess = promisify(fs4.access);
|
|
437
|
-
module.exports = async function backup(filename, options) {
|
|
438
|
-
if (options == null) options = {};
|
|
439
|
-
if (typeof filename !== "string") throw new TypeError("Expected first argument to be a string");
|
|
440
|
-
if (typeof options !== "object") throw new TypeError("Expected second argument to be an options object");
|
|
441
|
-
filename = filename.trim();
|
|
442
|
-
const attachedName = "attached" in options ? options.attached : "main";
|
|
443
|
-
const handler = "progress" in options ? options.progress : null;
|
|
444
|
-
if (!filename) throw new TypeError("Backup filename cannot be an empty string");
|
|
445
|
-
if (filename === ":memory:") throw new TypeError('Invalid backup filename ":memory:"');
|
|
446
|
-
if (typeof attachedName !== "string") throw new TypeError('Expected the "attached" option to be a string');
|
|
447
|
-
if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
|
|
448
|
-
if (handler != null && typeof handler !== "function") throw new TypeError('Expected the "progress" option to be a function');
|
|
449
|
-
await fsAccess(path9.dirname(filename)).catch(() => {
|
|
450
|
-
throw new TypeError("Cannot save backup because the directory does not exist");
|
|
451
|
-
});
|
|
452
|
-
const isNewFile = await fsAccess(filename).then(() => false, () => true);
|
|
453
|
-
return runBackup(this[cppdb].backup(this, attachedName, filename, isNewFile), handler || null);
|
|
454
|
-
};
|
|
455
|
-
var runBackup = (backup, handler) => {
|
|
456
|
-
let rate = 0;
|
|
457
|
-
let useDefault = true;
|
|
458
|
-
return new Promise((resolve, reject) => {
|
|
459
|
-
setImmediate(function step() {
|
|
460
|
-
try {
|
|
461
|
-
const progress = backup.transfer(rate);
|
|
462
|
-
if (!progress.remainingPages) {
|
|
463
|
-
backup.close();
|
|
464
|
-
resolve(progress);
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
if (useDefault) {
|
|
468
|
-
useDefault = false;
|
|
469
|
-
rate = 100;
|
|
470
|
-
}
|
|
471
|
-
if (handler) {
|
|
472
|
-
const ret = handler(progress);
|
|
473
|
-
if (ret !== void 0) {
|
|
474
|
-
if (typeof ret === "number" && ret === ret) rate = Math.max(0, Math.min(2147483647, Math.round(ret)));
|
|
475
|
-
else throw new TypeError("Expected progress callback to return a number or undefined");
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
setImmediate(step);
|
|
479
|
-
} catch (err) {
|
|
480
|
-
backup.close();
|
|
481
|
-
reject(err);
|
|
482
|
-
}
|
|
483
|
-
});
|
|
484
|
-
});
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
// node_modules/better-sqlite3/lib/methods/serialize.js
|
|
490
|
-
var require_serialize = __commonJS({
|
|
491
|
-
"node_modules/better-sqlite3/lib/methods/serialize.js"(exports, module) {
|
|
492
|
-
"use strict";
|
|
493
|
-
init_esm_shims();
|
|
494
|
-
var { cppdb } = require_util();
|
|
495
|
-
module.exports = function serialize(options) {
|
|
496
|
-
if (options == null) options = {};
|
|
497
|
-
if (typeof options !== "object") throw new TypeError("Expected first argument to be an options object");
|
|
498
|
-
const attachedName = "attached" in options ? options.attached : "main";
|
|
499
|
-
if (typeof attachedName !== "string") throw new TypeError('Expected the "attached" option to be a string');
|
|
500
|
-
if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
|
|
501
|
-
return this[cppdb].serialize(attachedName);
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
|
-
});
|
|
505
|
-
|
|
506
|
-
// node_modules/better-sqlite3/lib/methods/function.js
|
|
507
|
-
var require_function = __commonJS({
|
|
508
|
-
"node_modules/better-sqlite3/lib/methods/function.js"(exports, module) {
|
|
509
|
-
"use strict";
|
|
510
|
-
init_esm_shims();
|
|
511
|
-
var { getBooleanOption, cppdb } = require_util();
|
|
512
|
-
module.exports = function defineFunction(name, options, fn) {
|
|
513
|
-
if (options == null) options = {};
|
|
514
|
-
if (typeof options === "function") {
|
|
515
|
-
fn = options;
|
|
516
|
-
options = {};
|
|
517
|
-
}
|
|
518
|
-
if (typeof name !== "string") throw new TypeError("Expected first argument to be a string");
|
|
519
|
-
if (typeof fn !== "function") throw new TypeError("Expected last argument to be a function");
|
|
520
|
-
if (typeof options !== "object") throw new TypeError("Expected second argument to be an options object");
|
|
521
|
-
if (!name) throw new TypeError("User-defined function name cannot be an empty string");
|
|
522
|
-
const safeIntegers = "safeIntegers" in options ? +getBooleanOption(options, "safeIntegers") : 2;
|
|
523
|
-
const deterministic = getBooleanOption(options, "deterministic");
|
|
524
|
-
const directOnly = getBooleanOption(options, "directOnly");
|
|
525
|
-
const varargs = getBooleanOption(options, "varargs");
|
|
526
|
-
let argCount = -1;
|
|
527
|
-
if (!varargs) {
|
|
528
|
-
argCount = fn.length;
|
|
529
|
-
if (!Number.isInteger(argCount) || argCount < 0) throw new TypeError("Expected function.length to be a positive integer");
|
|
530
|
-
if (argCount > 100) throw new RangeError("User-defined functions cannot have more than 100 arguments");
|
|
531
|
-
}
|
|
532
|
-
this[cppdb].function(fn, name, argCount, safeIntegers, deterministic, directOnly);
|
|
533
|
-
return this;
|
|
534
|
-
};
|
|
535
|
-
}
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
// node_modules/better-sqlite3/lib/methods/aggregate.js
|
|
539
|
-
var require_aggregate = __commonJS({
|
|
540
|
-
"node_modules/better-sqlite3/lib/methods/aggregate.js"(exports, module) {
|
|
541
|
-
"use strict";
|
|
542
|
-
init_esm_shims();
|
|
543
|
-
var { getBooleanOption, cppdb } = require_util();
|
|
544
|
-
module.exports = function defineAggregate(name, options) {
|
|
545
|
-
if (typeof name !== "string") throw new TypeError("Expected first argument to be a string");
|
|
546
|
-
if (typeof options !== "object" || options === null) throw new TypeError("Expected second argument to be an options object");
|
|
547
|
-
if (!name) throw new TypeError("User-defined function name cannot be an empty string");
|
|
548
|
-
const start = "start" in options ? options.start : null;
|
|
549
|
-
const step = getFunctionOption(options, "step", true);
|
|
550
|
-
const inverse = getFunctionOption(options, "inverse", false);
|
|
551
|
-
const result = getFunctionOption(options, "result", false);
|
|
552
|
-
const safeIntegers = "safeIntegers" in options ? +getBooleanOption(options, "safeIntegers") : 2;
|
|
553
|
-
const deterministic = getBooleanOption(options, "deterministic");
|
|
554
|
-
const directOnly = getBooleanOption(options, "directOnly");
|
|
555
|
-
const varargs = getBooleanOption(options, "varargs");
|
|
556
|
-
let argCount = -1;
|
|
557
|
-
if (!varargs) {
|
|
558
|
-
argCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);
|
|
559
|
-
if (argCount > 0) argCount -= 1;
|
|
560
|
-
if (argCount > 100) throw new RangeError("User-defined functions cannot have more than 100 arguments");
|
|
561
|
-
}
|
|
562
|
-
this[cppdb].aggregate(start, step, inverse, result, name, argCount, safeIntegers, deterministic, directOnly);
|
|
563
|
-
return this;
|
|
564
|
-
};
|
|
565
|
-
var getFunctionOption = (options, key, required) => {
|
|
566
|
-
const value = key in options ? options[key] : null;
|
|
567
|
-
if (typeof value === "function") return value;
|
|
568
|
-
if (value != null) throw new TypeError(`Expected the "${key}" option to be a function`);
|
|
569
|
-
if (required) throw new TypeError(`Missing required option "${key}"`);
|
|
570
|
-
return null;
|
|
571
|
-
};
|
|
572
|
-
var getLength = ({ length }) => {
|
|
573
|
-
if (Number.isInteger(length) && length >= 0) return length;
|
|
574
|
-
throw new TypeError("Expected function.length to be a positive integer");
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
// node_modules/better-sqlite3/lib/methods/table.js
|
|
580
|
-
var require_table = __commonJS({
|
|
581
|
-
"node_modules/better-sqlite3/lib/methods/table.js"(exports, module) {
|
|
582
|
-
"use strict";
|
|
583
|
-
init_esm_shims();
|
|
584
|
-
var { cppdb } = require_util();
|
|
585
|
-
module.exports = function defineTable(name, factory) {
|
|
586
|
-
if (typeof name !== "string") throw new TypeError("Expected first argument to be a string");
|
|
587
|
-
if (!name) throw new TypeError("Virtual table module name cannot be an empty string");
|
|
588
|
-
let eponymous = false;
|
|
589
|
-
if (typeof factory === "object" && factory !== null) {
|
|
590
|
-
eponymous = true;
|
|
591
|
-
factory = defer(parseTableDefinition(factory, "used", name));
|
|
592
|
-
} else {
|
|
593
|
-
if (typeof factory !== "function") throw new TypeError("Expected second argument to be a function or a table definition object");
|
|
594
|
-
factory = wrapFactory(factory);
|
|
595
|
-
}
|
|
596
|
-
this[cppdb].table(factory, name, eponymous);
|
|
597
|
-
return this;
|
|
598
|
-
};
|
|
599
|
-
function wrapFactory(factory) {
|
|
600
|
-
return function virtualTableFactory(moduleName, databaseName, tableName, ...args) {
|
|
601
|
-
const thisObject = {
|
|
602
|
-
module: moduleName,
|
|
603
|
-
database: databaseName,
|
|
604
|
-
table: tableName
|
|
605
|
-
};
|
|
606
|
-
const def = apply.call(factory, thisObject, args);
|
|
607
|
-
if (typeof def !== "object" || def === null) {
|
|
608
|
-
throw new TypeError(`Virtual table module "${moduleName}" did not return a table definition object`);
|
|
609
|
-
}
|
|
610
|
-
return parseTableDefinition(def, "returned", moduleName);
|
|
611
|
-
};
|
|
612
|
-
}
|
|
613
|
-
function parseTableDefinition(def, verb, moduleName) {
|
|
614
|
-
if (!hasOwnProperty.call(def, "rows")) {
|
|
615
|
-
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "rows" property`);
|
|
616
|
-
}
|
|
617
|
-
if (!hasOwnProperty.call(def, "columns")) {
|
|
618
|
-
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "columns" property`);
|
|
619
|
-
}
|
|
620
|
-
const rows = def.rows;
|
|
621
|
-
if (typeof rows !== "function" || Object.getPrototypeOf(rows) !== GeneratorFunctionPrototype) {
|
|
622
|
-
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "rows" property (should be a generator function)`);
|
|
623
|
-
}
|
|
624
|
-
let columns = def.columns;
|
|
625
|
-
if (!Array.isArray(columns) || !(columns = [...columns]).every((x) => typeof x === "string")) {
|
|
626
|
-
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "columns" property (should be an array of strings)`);
|
|
627
|
-
}
|
|
628
|
-
if (columns.length !== new Set(columns).size) {
|
|
629
|
-
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate column names`);
|
|
630
|
-
}
|
|
631
|
-
if (!columns.length) {
|
|
632
|
-
throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with zero columns`);
|
|
633
|
-
}
|
|
634
|
-
let parameters;
|
|
635
|
-
if (hasOwnProperty.call(def, "parameters")) {
|
|
636
|
-
parameters = def.parameters;
|
|
637
|
-
if (!Array.isArray(parameters) || !(parameters = [...parameters]).every((x) => typeof x === "string")) {
|
|
638
|
-
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "parameters" property (should be an array of strings)`);
|
|
639
|
-
}
|
|
640
|
-
} else {
|
|
641
|
-
parameters = inferParameters(rows);
|
|
642
|
-
}
|
|
643
|
-
if (parameters.length !== new Set(parameters).size) {
|
|
644
|
-
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate parameter names`);
|
|
645
|
-
}
|
|
646
|
-
if (parameters.length > 32) {
|
|
647
|
-
throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with more than the maximum number of 32 parameters`);
|
|
648
|
-
}
|
|
649
|
-
for (const parameter of parameters) {
|
|
650
|
-
if (columns.includes(parameter)) {
|
|
651
|
-
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with column "${parameter}" which was ambiguously defined as both a column and parameter`);
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
let safeIntegers = 2;
|
|
655
|
-
if (hasOwnProperty.call(def, "safeIntegers")) {
|
|
656
|
-
const bool = def.safeIntegers;
|
|
657
|
-
if (typeof bool !== "boolean") {
|
|
658
|
-
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "safeIntegers" property (should be a boolean)`);
|
|
659
|
-
}
|
|
660
|
-
safeIntegers = +bool;
|
|
661
|
-
}
|
|
662
|
-
let directOnly = false;
|
|
663
|
-
if (hasOwnProperty.call(def, "directOnly")) {
|
|
664
|
-
directOnly = def.directOnly;
|
|
665
|
-
if (typeof directOnly !== "boolean") {
|
|
666
|
-
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "directOnly" property (should be a boolean)`);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
const columnDefinitions = [
|
|
670
|
-
...parameters.map(identifier).map((str) => `${str} HIDDEN`),
|
|
671
|
-
...columns.map(identifier)
|
|
672
|
-
];
|
|
673
|
-
return [
|
|
674
|
-
`CREATE TABLE x(${columnDefinitions.join(", ")});`,
|
|
675
|
-
wrapGenerator(rows, new Map(columns.map((x, i) => [x, parameters.length + i])), moduleName),
|
|
676
|
-
parameters,
|
|
677
|
-
safeIntegers,
|
|
678
|
-
directOnly
|
|
679
|
-
];
|
|
680
|
-
}
|
|
681
|
-
function wrapGenerator(generator, columnMap, moduleName) {
|
|
682
|
-
return function* virtualTable(...args) {
|
|
683
|
-
const output = args.map((x) => Buffer.isBuffer(x) ? Buffer.from(x) : x);
|
|
684
|
-
for (let i = 0; i < columnMap.size; ++i) {
|
|
685
|
-
output.push(null);
|
|
686
|
-
}
|
|
687
|
-
for (const row of generator(...args)) {
|
|
688
|
-
if (Array.isArray(row)) {
|
|
689
|
-
extractRowArray(row, output, columnMap.size, moduleName);
|
|
690
|
-
yield output;
|
|
691
|
-
} else if (typeof row === "object" && row !== null) {
|
|
692
|
-
extractRowObject(row, output, columnMap, moduleName);
|
|
693
|
-
yield output;
|
|
694
|
-
} else {
|
|
695
|
-
throw new TypeError(`Virtual table module "${moduleName}" yielded something that isn't a valid row object`);
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
};
|
|
699
|
-
}
|
|
700
|
-
function extractRowArray(row, output, columnCount, moduleName) {
|
|
701
|
-
if (row.length !== columnCount) {
|
|
702
|
-
throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an incorrect number of columns`);
|
|
703
|
-
}
|
|
704
|
-
const offset = output.length - columnCount;
|
|
705
|
-
for (let i = 0; i < columnCount; ++i) {
|
|
706
|
-
output[i + offset] = row[i];
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
function extractRowObject(row, output, columnMap, moduleName) {
|
|
710
|
-
let count = 0;
|
|
711
|
-
for (const key of Object.keys(row)) {
|
|
712
|
-
const index2 = columnMap.get(key);
|
|
713
|
-
if (index2 === void 0) {
|
|
714
|
-
throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an undeclared column "${key}"`);
|
|
715
|
-
}
|
|
716
|
-
output[index2] = row[key];
|
|
717
|
-
count += 1;
|
|
718
|
-
}
|
|
719
|
-
if (count !== columnMap.size) {
|
|
720
|
-
throw new TypeError(`Virtual table module "${moduleName}" yielded a row with missing columns`);
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
function inferParameters({ length }) {
|
|
724
|
-
if (!Number.isInteger(length) || length < 0) {
|
|
725
|
-
throw new TypeError("Expected function.length to be a positive integer");
|
|
726
|
-
}
|
|
727
|
-
const params = [];
|
|
728
|
-
for (let i = 0; i < length; ++i) {
|
|
729
|
-
params.push(`$${i + 1}`);
|
|
730
|
-
}
|
|
731
|
-
return params;
|
|
732
|
-
}
|
|
733
|
-
var { hasOwnProperty } = Object.prototype;
|
|
734
|
-
var { apply } = Function.prototype;
|
|
735
|
-
var GeneratorFunctionPrototype = Object.getPrototypeOf(function* () {
|
|
736
|
-
});
|
|
737
|
-
var identifier = (str) => `"${str.replace(/"/g, '""')}"`;
|
|
738
|
-
var defer = (x) => () => x;
|
|
739
|
-
}
|
|
740
|
-
});
|
|
741
|
-
|
|
742
|
-
// node_modules/better-sqlite3/lib/methods/inspect.js
|
|
743
|
-
var require_inspect = __commonJS({
|
|
744
|
-
"node_modules/better-sqlite3/lib/methods/inspect.js"(exports, module) {
|
|
745
|
-
"use strict";
|
|
746
|
-
init_esm_shims();
|
|
747
|
-
var DatabaseInspection = function Database2() {
|
|
748
|
-
};
|
|
749
|
-
module.exports = function inspect(depth, opts) {
|
|
750
|
-
return Object.assign(new DatabaseInspection(), this);
|
|
751
|
-
};
|
|
752
|
-
}
|
|
753
|
-
});
|
|
754
|
-
|
|
755
|
-
// node_modules/better-sqlite3/lib/database.js
|
|
756
|
-
var require_database = __commonJS({
|
|
757
|
-
"node_modules/better-sqlite3/lib/database.js"(exports, module) {
|
|
758
|
-
"use strict";
|
|
759
|
-
init_esm_shims();
|
|
760
|
-
var fs4 = __require("fs");
|
|
761
|
-
var path9 = __require("path");
|
|
762
|
-
var util = require_util();
|
|
763
|
-
var SqliteError = require_sqlite_error();
|
|
764
|
-
var DEFAULT_ADDON;
|
|
765
|
-
function Database2(filenameGiven, options) {
|
|
766
|
-
if (new.target == null) {
|
|
767
|
-
return new Database2(filenameGiven, options);
|
|
768
|
-
}
|
|
769
|
-
let buffer;
|
|
770
|
-
if (Buffer.isBuffer(filenameGiven)) {
|
|
771
|
-
buffer = filenameGiven;
|
|
772
|
-
filenameGiven = ":memory:";
|
|
773
|
-
}
|
|
774
|
-
if (filenameGiven == null) filenameGiven = "";
|
|
775
|
-
if (options == null) options = {};
|
|
776
|
-
if (typeof filenameGiven !== "string") throw new TypeError("Expected first argument to be a string");
|
|
777
|
-
if (typeof options !== "object") throw new TypeError("Expected second argument to be an options object");
|
|
778
|
-
if ("readOnly" in options) throw new TypeError('Misspelled option "readOnly" should be "readonly"');
|
|
779
|
-
if ("memory" in options) throw new TypeError('Option "memory" was removed in v7.0.0 (use ":memory:" filename instead)');
|
|
780
|
-
const filename = filenameGiven.trim();
|
|
781
|
-
const anonymous = filename === "" || filename === ":memory:";
|
|
782
|
-
const readonly = util.getBooleanOption(options, "readonly");
|
|
783
|
-
const fileMustExist = util.getBooleanOption(options, "fileMustExist");
|
|
784
|
-
const timeout = "timeout" in options ? options.timeout : 5e3;
|
|
785
|
-
const verbose = "verbose" in options ? options.verbose : null;
|
|
786
|
-
const nativeBinding = "nativeBinding" in options ? options.nativeBinding : null;
|
|
787
|
-
if (readonly && anonymous && !buffer) throw new TypeError("In-memory/temporary databases cannot be readonly");
|
|
788
|
-
if (!Number.isInteger(timeout) || timeout < 0) throw new TypeError('Expected the "timeout" option to be a positive integer');
|
|
789
|
-
if (timeout > 2147483647) throw new RangeError('Option "timeout" cannot be greater than 2147483647');
|
|
790
|
-
if (verbose != null && typeof verbose !== "function") throw new TypeError('Expected the "verbose" option to be a function');
|
|
791
|
-
if (nativeBinding != null && typeof nativeBinding !== "string" && typeof nativeBinding !== "object") throw new TypeError('Expected the "nativeBinding" option to be a string or addon object');
|
|
792
|
-
let addon;
|
|
793
|
-
if (nativeBinding == null) {
|
|
794
|
-
addon = DEFAULT_ADDON || (DEFAULT_ADDON = require_bindings()("better_sqlite3.node"));
|
|
795
|
-
} else if (typeof nativeBinding === "string") {
|
|
796
|
-
const requireFunc = typeof __non_webpack_require__ === "function" ? __non_webpack_require__ : __require;
|
|
797
|
-
addon = requireFunc(path9.resolve(nativeBinding).replace(/(\.node)?$/, ".node"));
|
|
798
|
-
} else {
|
|
799
|
-
addon = nativeBinding;
|
|
800
|
-
}
|
|
801
|
-
if (!addon.isInitialized) {
|
|
802
|
-
addon.setErrorConstructor(SqliteError);
|
|
803
|
-
addon.isInitialized = true;
|
|
804
|
-
}
|
|
805
|
-
if (!anonymous && !fs4.existsSync(path9.dirname(filename))) {
|
|
806
|
-
throw new TypeError("Cannot open database because the directory does not exist");
|
|
807
|
-
}
|
|
808
|
-
Object.defineProperties(this, {
|
|
809
|
-
[util.cppdb]: { value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null) },
|
|
810
|
-
...wrappers.getters
|
|
811
|
-
});
|
|
812
|
-
}
|
|
813
|
-
var wrappers = require_wrappers();
|
|
814
|
-
Database2.prototype.prepare = wrappers.prepare;
|
|
815
|
-
Database2.prototype.transaction = require_transaction();
|
|
816
|
-
Database2.prototype.pragma = require_pragma();
|
|
817
|
-
Database2.prototype.backup = require_backup();
|
|
818
|
-
Database2.prototype.serialize = require_serialize();
|
|
819
|
-
Database2.prototype.function = require_function();
|
|
820
|
-
Database2.prototype.aggregate = require_aggregate();
|
|
821
|
-
Database2.prototype.table = require_table();
|
|
822
|
-
Database2.prototype.loadExtension = wrappers.loadExtension;
|
|
823
|
-
Database2.prototype.exec = wrappers.exec;
|
|
824
|
-
Database2.prototype.close = wrappers.close;
|
|
825
|
-
Database2.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers;
|
|
826
|
-
Database2.prototype.unsafeMode = wrappers.unsafeMode;
|
|
827
|
-
Database2.prototype[util.inspect] = require_inspect();
|
|
828
|
-
module.exports = Database2;
|
|
829
|
-
}
|
|
830
|
-
});
|
|
831
|
-
|
|
832
|
-
// node_modules/better-sqlite3/lib/index.js
|
|
833
|
-
var require_lib = __commonJS({
|
|
834
|
-
"node_modules/better-sqlite3/lib/index.js"(exports, module) {
|
|
835
|
-
"use strict";
|
|
836
|
-
init_esm_shims();
|
|
837
|
-
module.exports = require_database();
|
|
838
|
-
module.exports.SqliteError = require_sqlite_error();
|
|
839
|
-
}
|
|
840
|
-
});
|
|
841
2
|
|
|
842
3
|
// src/cli.ts
|
|
843
|
-
init_esm_shims();
|
|
844
4
|
import { Command } from "commander";
|
|
845
5
|
|
|
846
6
|
// src/platform/FileSystemAdapter.ts
|
|
847
|
-
init_esm_shims();
|
|
848
7
|
import fs from "fs/promises";
|
|
849
|
-
import
|
|
8
|
+
import fg from "fast-glob";
|
|
850
9
|
var FileSystemAdapter = class {
|
|
851
10
|
async readFile(path9, encoding = "utf-8") {
|
|
852
11
|
return fs.readFile(path9, encoding);
|
|
@@ -887,18 +46,102 @@ var FileSystemAdapter = class {
|
|
|
887
46
|
await fs.copyFile(src, dest);
|
|
888
47
|
}
|
|
889
48
|
async glob(pattern, options) {
|
|
890
|
-
return
|
|
49
|
+
return fg(pattern, {
|
|
891
50
|
cwd: options?.cwd,
|
|
892
51
|
ignore: options?.ignore
|
|
893
52
|
});
|
|
894
53
|
}
|
|
895
54
|
};
|
|
896
55
|
|
|
897
|
-
// src/
|
|
898
|
-
|
|
56
|
+
// src/platform/ProcessExecutorAdapter.ts
|
|
57
|
+
import { execa, execaCommand } from "execa";
|
|
58
|
+
var ProcessExecutorAdapter = class {
|
|
59
|
+
/**
|
|
60
|
+
* Execute command and wait for completion
|
|
61
|
+
*/
|
|
62
|
+
async execute(command, args = [], options = {}) {
|
|
63
|
+
try {
|
|
64
|
+
const result = await execa(command, args, {
|
|
65
|
+
cwd: options.cwd,
|
|
66
|
+
env: options.env,
|
|
67
|
+
timeout: options.timeout,
|
|
68
|
+
shell: options.shell,
|
|
69
|
+
input: options.input,
|
|
70
|
+
reject: false
|
|
71
|
+
// Don't throw on non-zero exit codes
|
|
72
|
+
});
|
|
73
|
+
return {
|
|
74
|
+
stdout: result.stdout,
|
|
75
|
+
stderr: result.stderr,
|
|
76
|
+
exitCode: result.exitCode ?? (result.failed ? 1 : 0),
|
|
77
|
+
command: result.command,
|
|
78
|
+
timedOut: result.timedOut ?? false
|
|
79
|
+
};
|
|
80
|
+
} catch (error) {
|
|
81
|
+
const exitCode = error.code === "ENOENT" ? 127 : error.exitCode || 1;
|
|
82
|
+
return {
|
|
83
|
+
stdout: error.stdout || "",
|
|
84
|
+
stderr: error.stderr || error.message || String(error),
|
|
85
|
+
exitCode,
|
|
86
|
+
command: error.command || `${command} ${args.join(" ")}`,
|
|
87
|
+
timedOut: error.timedOut ?? false
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Spawn process (doesn't wait for completion)
|
|
93
|
+
*/
|
|
94
|
+
spawn(command, args = [], options = {}) {
|
|
95
|
+
const subprocess = execa(command, args, {
|
|
96
|
+
cwd: options.cwd,
|
|
97
|
+
env: options.env,
|
|
98
|
+
timeout: options.timeout,
|
|
99
|
+
shell: options.shell,
|
|
100
|
+
stdin: options.input ? "pipe" : "inherit",
|
|
101
|
+
stdout: "pipe",
|
|
102
|
+
stderr: "pipe"
|
|
103
|
+
});
|
|
104
|
+
if (options.input && subprocess.stdin) {
|
|
105
|
+
subprocess.stdin.write(options.input);
|
|
106
|
+
subprocess.stdin.end();
|
|
107
|
+
}
|
|
108
|
+
return subprocess;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Execute command in shell
|
|
112
|
+
*/
|
|
113
|
+
async executeShell(command, options = {}) {
|
|
114
|
+
try {
|
|
115
|
+
const result = await execaCommand(command, {
|
|
116
|
+
cwd: options.cwd,
|
|
117
|
+
env: options.env,
|
|
118
|
+
timeout: options.timeout,
|
|
119
|
+
shell: true,
|
|
120
|
+
input: options.input,
|
|
121
|
+
reject: false
|
|
122
|
+
// Don't throw on non-zero exit codes
|
|
123
|
+
});
|
|
124
|
+
return {
|
|
125
|
+
stdout: result.stdout,
|
|
126
|
+
stderr: result.stderr,
|
|
127
|
+
exitCode: result.exitCode ?? (result.failed ? 1 : 0),
|
|
128
|
+
command: result.command,
|
|
129
|
+
timedOut: result.timedOut ?? false
|
|
130
|
+
};
|
|
131
|
+
} catch (error) {
|
|
132
|
+
const exitCode = error.code === "ENOENT" ? 127 : error.exitCode || 1;
|
|
133
|
+
return {
|
|
134
|
+
stdout: error.stdout || "",
|
|
135
|
+
stderr: error.stderr || error.message || String(error),
|
|
136
|
+
exitCode,
|
|
137
|
+
command: error.command || command,
|
|
138
|
+
timedOut: error.timedOut ?? false
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
|
899
143
|
|
|
900
144
|
// src/config/schemas.ts
|
|
901
|
-
init_esm_shims();
|
|
902
145
|
import { z } from "zod";
|
|
903
146
|
var ThemeSchema = z.enum([
|
|
904
147
|
"mimir",
|
|
@@ -994,21 +237,17 @@ var ConfigSchema = z.object({
|
|
|
994
237
|
rateLimit: RateLimitConfigSchema
|
|
995
238
|
});
|
|
996
239
|
|
|
997
|
-
// src/config/AllowlistLoader.ts
|
|
998
|
-
init_esm_shims();
|
|
999
|
-
|
|
1000
240
|
// src/utils/logger.ts
|
|
1001
|
-
init_esm_shims();
|
|
1002
241
|
import winston from "winston";
|
|
1003
242
|
import DailyRotateFile from "winston-daily-rotate-file";
|
|
1004
243
|
import fs2 from "fs";
|
|
1005
|
-
import
|
|
244
|
+
import path from "path";
|
|
1006
245
|
var Logger = class {
|
|
1007
246
|
logger;
|
|
1008
247
|
fileLoggingEnabled = false;
|
|
1009
248
|
consoleTransport;
|
|
1010
249
|
constructor(logDir = ".mimir/logs") {
|
|
1011
|
-
const absoluteLogDir =
|
|
250
|
+
const absoluteLogDir = path.resolve(process.cwd(), logDir);
|
|
1012
251
|
try {
|
|
1013
252
|
if (!fs2.existsSync(absoluteLogDir)) {
|
|
1014
253
|
fs2.mkdirSync(absoluteLogDir, { recursive: true });
|
|
@@ -1094,7 +333,7 @@ var logger = new Logger();
|
|
|
1094
333
|
|
|
1095
334
|
// src/config/AllowlistLoader.ts
|
|
1096
335
|
import yaml from "yaml";
|
|
1097
|
-
import
|
|
336
|
+
import path2 from "path";
|
|
1098
337
|
import { z as z2 } from "zod";
|
|
1099
338
|
var AllowlistSchema = z2.object({
|
|
1100
339
|
// Command patterns that are always allowed
|
|
@@ -1116,7 +355,7 @@ var AllowlistLoader = class {
|
|
|
1116
355
|
* Load allowlist from project .mimir/allowlist.yml
|
|
1117
356
|
*/
|
|
1118
357
|
async loadProjectAllowlist(projectRoot) {
|
|
1119
|
-
const allowlistPath =
|
|
358
|
+
const allowlistPath = path2.join(projectRoot, ".mimir", "allowlist.yml");
|
|
1120
359
|
return await this.loadAllowlistFile(allowlistPath, "project");
|
|
1121
360
|
}
|
|
1122
361
|
/**
|
|
@@ -1124,7 +363,7 @@ var AllowlistLoader = class {
|
|
|
1124
363
|
*/
|
|
1125
364
|
async loadGlobalAllowlist() {
|
|
1126
365
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "~";
|
|
1127
|
-
const allowlistPath =
|
|
366
|
+
const allowlistPath = path2.join(homeDir, ".mimir", "allowlist.yml");
|
|
1128
367
|
return await this.loadAllowlistFile(allowlistPath, "global");
|
|
1129
368
|
}
|
|
1130
369
|
/**
|
|
@@ -1188,7 +427,7 @@ var AllowlistLoader = class {
|
|
|
1188
427
|
async createExample(filePath, scope) {
|
|
1189
428
|
const exampleContent = scope === "global" ? this.getGlobalExample() : this.getProjectExample();
|
|
1190
429
|
try {
|
|
1191
|
-
const dir =
|
|
430
|
+
const dir = path2.dirname(filePath);
|
|
1192
431
|
if (!await this.fs.exists(dir)) {
|
|
1193
432
|
await this.fs.mkdir(dir, { recursive: true });
|
|
1194
433
|
}
|
|
@@ -1294,7 +533,7 @@ envVars:
|
|
|
1294
533
|
|
|
1295
534
|
// src/config/ConfigLoader.ts
|
|
1296
535
|
import yaml2 from "yaml";
|
|
1297
|
-
import
|
|
536
|
+
import path3 from "path";
|
|
1298
537
|
import os from "os";
|
|
1299
538
|
import dotenv from "dotenv";
|
|
1300
539
|
var ConfigLoader = class {
|
|
@@ -1414,7 +653,7 @@ var ConfigLoader = class {
|
|
|
1414
653
|
}
|
|
1415
654
|
async loadGlobalConfig() {
|
|
1416
655
|
try {
|
|
1417
|
-
const configPath =
|
|
656
|
+
const configPath = path3.join(os.homedir(), ".mimir", "config.yml");
|
|
1418
657
|
if (!await this.fs.exists(configPath)) {
|
|
1419
658
|
return null;
|
|
1420
659
|
}
|
|
@@ -1427,7 +666,7 @@ var ConfigLoader = class {
|
|
|
1427
666
|
}
|
|
1428
667
|
async loadProjectConfig(projectRoot) {
|
|
1429
668
|
try {
|
|
1430
|
-
const configPath =
|
|
669
|
+
const configPath = path3.join(projectRoot, ".mimir", "config.yml");
|
|
1431
670
|
if (!await this.fs.exists(configPath)) {
|
|
1432
671
|
return null;
|
|
1433
672
|
}
|
|
@@ -1440,7 +679,7 @@ var ConfigLoader = class {
|
|
|
1440
679
|
}
|
|
1441
680
|
loadEnvConfig(projectRoot) {
|
|
1442
681
|
try {
|
|
1443
|
-
const envPath = projectRoot ?
|
|
682
|
+
const envPath = projectRoot ? path3.join(projectRoot, ".env") : ".env";
|
|
1444
683
|
dotenv.config({ path: envPath });
|
|
1445
684
|
const envConfig = {};
|
|
1446
685
|
if (process.env.DEEPSEEK_API_KEY || process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY) {
|
|
@@ -1483,8 +722,8 @@ var ConfigLoader = class {
|
|
|
1483
722
|
};
|
|
1484
723
|
}
|
|
1485
724
|
async save(config, scope, projectRoot) {
|
|
1486
|
-
const configPath = scope === "global" ?
|
|
1487
|
-
const configDir =
|
|
725
|
+
const configPath = scope === "global" ? path3.join(os.homedir(), ".mimir", "config.yml") : path3.join(projectRoot || process.cwd(), ".mimir", "config.yml");
|
|
726
|
+
const configDir = path3.dirname(configPath);
|
|
1488
727
|
if (!await this.fs.exists(configDir)) {
|
|
1489
728
|
await this.fs.mkdir(configDir, { recursive: true });
|
|
1490
729
|
}
|
|
@@ -1498,8 +737,7 @@ var ConfigLoader = class {
|
|
|
1498
737
|
};
|
|
1499
738
|
|
|
1500
739
|
// src/cli/utils/firstRunDetector.ts
|
|
1501
|
-
|
|
1502
|
-
import path5 from "path";
|
|
740
|
+
import path4 from "path";
|
|
1503
741
|
import os2 from "os";
|
|
1504
742
|
var FirstRunDetector = class {
|
|
1505
743
|
constructor(fs4) {
|
|
@@ -1512,35 +750,30 @@ var FirstRunDetector = class {
|
|
|
1512
750
|
}
|
|
1513
751
|
getGlobalConfigPath() {
|
|
1514
752
|
const homeDir = os2.homedir();
|
|
1515
|
-
return
|
|
753
|
+
return path4.join(homeDir, ".mimir", "config.yml");
|
|
1516
754
|
}
|
|
1517
755
|
async getGlobalConfigDir() {
|
|
1518
756
|
const homeDir = os2.homedir();
|
|
1519
|
-
return
|
|
757
|
+
return path4.join(homeDir, ".mimir");
|
|
1520
758
|
}
|
|
1521
759
|
};
|
|
1522
760
|
|
|
1523
761
|
// src/cli/commands/SetupCommand.ts
|
|
1524
|
-
init_esm_shims();
|
|
1525
762
|
import React4 from "react";
|
|
1526
763
|
import { render } from "ink";
|
|
1527
764
|
|
|
1528
765
|
// src/cli/components/SetupWizard.tsx
|
|
1529
|
-
init_esm_shims();
|
|
1530
766
|
import { useState as useState2 } from "react";
|
|
1531
767
|
import { Box as Box5 } from "ink";
|
|
1532
768
|
|
|
1533
769
|
// src/cli/components/WizardLayout.tsx
|
|
1534
|
-
init_esm_shims();
|
|
1535
770
|
import { Box as Box2, Text as Text2 } from "ink";
|
|
1536
771
|
|
|
1537
772
|
// src/cli/components/WizardHead.tsx
|
|
1538
|
-
init_esm_shims();
|
|
1539
773
|
import { Box, Text } from "ink";
|
|
1540
774
|
import chalk from "chalk";
|
|
1541
775
|
|
|
1542
776
|
// src/cli/theme-colors.ts
|
|
1543
|
-
init_esm_shims();
|
|
1544
777
|
var MimirColors = {
|
|
1545
778
|
// Polar Night (dark backgrounds)
|
|
1546
779
|
polarNight1: "#2E3440",
|
|
@@ -1569,14 +802,13 @@ var MimirColors = {
|
|
|
1569
802
|
};
|
|
1570
803
|
|
|
1571
804
|
// src/cli/components/logo.ts
|
|
1572
|
-
init_esm_shims();
|
|
1573
805
|
var MIMIR_LOGO = ["\u2597\u2588\u2597\u2588\u2596", "\u2588\u2588\u2588\u2588\u2588", "\u259C\u2586\u2588\u2586\u259B", " \u2586\u2585\u2586 "];
|
|
1574
806
|
|
|
1575
807
|
// src/cli/components/WizardHead.tsx
|
|
1576
808
|
import { jsx } from "react/jsx-runtime";
|
|
1577
809
|
var WizardHead = () => {
|
|
1578
810
|
const nordFrost = chalk.hex(MimirColors.frost3);
|
|
1579
|
-
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginBottom: 1, alignItems: "center", children: MIMIR_LOGO.map((line,
|
|
811
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginBottom: 1, alignItems: "center", children: MIMIR_LOGO.map((line, index) => /* @__PURE__ */ jsx(Text, { children: nordFrost.bold(line) }, index)) });
|
|
1580
812
|
};
|
|
1581
813
|
|
|
1582
814
|
// src/cli/components/WizardLayout.tsx
|
|
@@ -1590,14 +822,12 @@ var WizardLayout = ({ title, children }) => {
|
|
|
1590
822
|
};
|
|
1591
823
|
|
|
1592
824
|
// src/cli/components/SecurityWarning.tsx
|
|
1593
|
-
init_esm_shims();
|
|
1594
825
|
import { useMemo } from "react";
|
|
1595
826
|
import { Box as Box3, Text as Text3, useInput } from "ink";
|
|
1596
827
|
import figures from "figures";
|
|
1597
828
|
import chalk2 from "chalk";
|
|
1598
829
|
|
|
1599
830
|
// src/utils/keyboardFormatter.ts
|
|
1600
|
-
init_esm_shims();
|
|
1601
831
|
import os3 from "os";
|
|
1602
832
|
var KEY_ICONS = {
|
|
1603
833
|
// Arrow keys
|
|
@@ -1665,8 +895,8 @@ function formatSingleShortcut(shortcut, options) {
|
|
|
1665
895
|
let normalized = normalizeKeyName(shortcut);
|
|
1666
896
|
normalized = applyPlatformModifiers(normalized, platform);
|
|
1667
897
|
const parts = normalized.split("+").map((p) => p.trim());
|
|
1668
|
-
const formatted = parts.map((part,
|
|
1669
|
-
const isModifier =
|
|
898
|
+
const formatted = parts.map((part, index) => {
|
|
899
|
+
const isModifier = index < parts.length - 1;
|
|
1670
900
|
const icon = KEY_ICONS[part];
|
|
1671
901
|
if (useIcons && icon) {
|
|
1672
902
|
if (isModifier && !useModifierIcons) {
|
|
@@ -1760,17 +990,12 @@ var SecurityWarning = ({
|
|
|
1760
990
|
};
|
|
1761
991
|
|
|
1762
992
|
// src/cli/components/ThemeSelector.tsx
|
|
1763
|
-
init_esm_shims();
|
|
1764
993
|
import { useState, useMemo as useMemo2 } from "react";
|
|
1765
994
|
import { Box as Box4, Text as Text4 } from "ink";
|
|
1766
995
|
import SelectInput from "ink-select-input";
|
|
1767
996
|
import chalk4 from "chalk";
|
|
1768
997
|
|
|
1769
|
-
// src/config/themes/index.ts
|
|
1770
|
-
init_esm_shims();
|
|
1771
|
-
|
|
1772
998
|
// src/config/themes/theme-schema.ts
|
|
1773
|
-
init_esm_shims();
|
|
1774
999
|
import chalk3 from "chalk";
|
|
1775
1000
|
function parseColor(color) {
|
|
1776
1001
|
let result = chalk3;
|
|
@@ -2147,7 +1372,6 @@ Object.entries(themeDefinitions).forEach(([key, json]) => {
|
|
|
2147
1372
|
});
|
|
2148
1373
|
|
|
2149
1374
|
// src/cli/utils/syntaxHighlight.ts
|
|
2150
|
-
init_esm_shims();
|
|
2151
1375
|
function getPreviewWithDiff() {
|
|
2152
1376
|
return [
|
|
2153
1377
|
{ type: "remove", line: "function getRandomNumber() {" },
|
|
@@ -2178,7 +1402,7 @@ var ThemeSelector = ({
|
|
|
2178
1402
|
const themeColors = getTheme(currentThemeKey);
|
|
2179
1403
|
const preview = getPreviewWithDiff();
|
|
2180
1404
|
const bg = chalk4.bgHex("#1e1e1e");
|
|
2181
|
-
const
|
|
1405
|
+
const fg2 = chalk4.hex("#eceff4");
|
|
2182
1406
|
const footerText = useMemo2(() => {
|
|
2183
1407
|
const navUp = keyBindings.navigateUp[0] ?? "ArrowUp";
|
|
2184
1408
|
const navDown = keyBindings.navigateDown[0] ?? "ArrowDown";
|
|
@@ -2189,7 +1413,7 @@ var ThemeSelector = ({
|
|
|
2189
1413
|
]);
|
|
2190
1414
|
}, [keyBindings]);
|
|
2191
1415
|
return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", children: [
|
|
2192
|
-
/* @__PURE__ */ jsx4(Text4, { children: bg(
|
|
1416
|
+
/* @__PURE__ */ jsx4(Text4, { children: bg(fg2.bold(" Select your theme: ")) }),
|
|
2193
1417
|
/* @__PURE__ */ jsx4(Text4, { children: bg(" ") }),
|
|
2194
1418
|
/* @__PURE__ */ jsx4(Box4, { flexDirection: "column", children: /* @__PURE__ */ jsx4(
|
|
2195
1419
|
SelectInput,
|
|
@@ -2197,18 +1421,18 @@ var ThemeSelector = ({
|
|
|
2197
1421
|
items,
|
|
2198
1422
|
onSelect: (item) => onSelect(item.value),
|
|
2199
1423
|
onHighlight: (item) => {
|
|
2200
|
-
const
|
|
2201
|
-
if (
|
|
1424
|
+
const index = availableThemes.findIndex((t) => t === item.value);
|
|
1425
|
+
if (index !== -1) setHighlightedIndex(index);
|
|
2202
1426
|
}
|
|
2203
1427
|
}
|
|
2204
1428
|
) }),
|
|
2205
1429
|
/* @__PURE__ */ jsx4(Text4, { children: bg(" ") }),
|
|
2206
|
-
/* @__PURE__ */ jsx4(Text4, { children: bg(
|
|
1430
|
+
/* @__PURE__ */ jsx4(Text4, { children: bg(fg2(" Preview: ")) }),
|
|
2207
1431
|
preview.map((item, idx) => /* @__PURE__ */ jsxs3(Text4, { children: [
|
|
2208
1432
|
item.type === "remove" && bg(themeColors.colors.diffRemoveLine(`- ${item.line}`)),
|
|
2209
1433
|
item.type === "add" && bg(themeColors.colors.diffAddLine(`+ ${item.line}`)),
|
|
2210
1434
|
item.type === "normal" && bg(
|
|
2211
|
-
|
|
1435
|
+
fg2(
|
|
2212
1436
|
` ${themeColors.colors.keyword(item.line.match(/return/)?.[0] || "")}${item.line.replace(/return/, "")}`
|
|
2213
1437
|
)
|
|
2214
1438
|
)
|
|
@@ -2311,22 +1535,18 @@ var SetupCommand = class {
|
|
|
2311
1535
|
};
|
|
2312
1536
|
|
|
2313
1537
|
// src/cli/commands/ChatCommand.ts
|
|
2314
|
-
init_esm_shims();
|
|
2315
1538
|
import React10 from "react";
|
|
2316
1539
|
import { render as render2 } from "ink";
|
|
2317
1540
|
|
|
2318
1541
|
// src/cli/components/ChatApp.tsx
|
|
2319
|
-
init_esm_shims();
|
|
2320
1542
|
import { useEffect as useEffect7 } from "react";
|
|
2321
1543
|
import { useStdin } from "ink";
|
|
2322
1544
|
|
|
2323
1545
|
// src/cli/components/ChatInterface.tsx
|
|
2324
|
-
init_esm_shims();
|
|
2325
1546
|
import { useState as useState7, useMemo as useMemo4, useCallback as useCallback2, useRef as useRef2, useEffect as useEffect6 } from "react";
|
|
2326
1547
|
import { Box as Box11, Text as Text10 } from "ink";
|
|
2327
1548
|
|
|
2328
1549
|
// src/cli/components/MimirHeader.tsx
|
|
2329
|
-
init_esm_shims();
|
|
2330
1550
|
import { Box as Box6, Text as Text5 } from "ink";
|
|
2331
1551
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2332
1552
|
var MimirHeader = ({
|
|
@@ -2349,18 +1569,17 @@ var MimirHeader = ({
|
|
|
2349
1569
|
themeDefinition.colors.info(`Theme: ${themeDefinition.name}`)
|
|
2350
1570
|
];
|
|
2351
1571
|
const LOGO_WIDTH = 7;
|
|
2352
|
-
return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", height: MIMIR_LOGO.length, flexShrink: 0, children: MIMIR_LOGO.map((logoLine,
|
|
1572
|
+
return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", height: MIMIR_LOGO.length, flexShrink: 0, children: MIMIR_LOGO.map((logoLine, index) => /* @__PURE__ */ jsxs5(Box6, { children: [
|
|
2353
1573
|
/* @__PURE__ */ jsx6(Box6, { width: LOGO_WIDTH, children: /* @__PURE__ */ jsx6(Text5, { children: logoColor.bold(logoLine) }) }),
|
|
2354
|
-
infoLines[
|
|
2355
|
-
] },
|
|
1574
|
+
infoLines[index] && /* @__PURE__ */ jsx6(Text5, { children: infoLines[index] })
|
|
1575
|
+
] }, index)) });
|
|
2356
1576
|
};
|
|
2357
1577
|
|
|
2358
1578
|
// src/cli/components/MessageList.tsx
|
|
2359
|
-
init_esm_shims();
|
|
2360
1579
|
import { Box as Box7, Text as Text6, Static } from "ink";
|
|
2361
1580
|
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2362
1581
|
var MessageList = ({
|
|
2363
|
-
messages
|
|
1582
|
+
messages,
|
|
2364
1583
|
theme,
|
|
2365
1584
|
syntaxHighlighting: _syntaxHighlighting
|
|
2366
1585
|
}) => {
|
|
@@ -2412,25 +1631,23 @@ var MessageList = ({
|
|
|
2412
1631
|
")"
|
|
2413
1632
|
] }) });
|
|
2414
1633
|
};
|
|
2415
|
-
const renderMessage = (message,
|
|
1634
|
+
const renderMessage = (message, index) => /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", marginBottom: 1, children: [
|
|
2416
1635
|
/* @__PURE__ */ jsx7(Text6, { children: getRoleChalk(message.role).bold(`[${message.role.toUpperCase()}]:`) }),
|
|
2417
1636
|
/* @__PURE__ */ jsx7(Text6, { children: message.content }),
|
|
2418
1637
|
message.role === "assistant" && renderThinkingIndicator(message)
|
|
2419
|
-
] },
|
|
1638
|
+
] }, index);
|
|
2420
1639
|
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", paddingX: 1, paddingY: 1, flexGrow: 1, children: [
|
|
2421
|
-
|
|
2422
|
-
|
|
1640
|
+
messages.length === 0 && /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "No messages yet. Start typing below..." }),
|
|
1641
|
+
messages.length > 0 && /* @__PURE__ */ jsx7(Static, { items: messages, children: (message, index) => renderMessage(message, index) })
|
|
2423
1642
|
] });
|
|
2424
1643
|
};
|
|
2425
1644
|
|
|
2426
1645
|
// src/cli/components/InputBox.tsx
|
|
2427
|
-
init_esm_shims();
|
|
2428
1646
|
import React6, { useState as useState4, useCallback, useEffect as useEffect2 } from "react";
|
|
2429
1647
|
import { Box as Box9, Text as Text8 } from "ink";
|
|
2430
1648
|
import TextInput from "ink-text-input";
|
|
2431
1649
|
|
|
2432
1650
|
// src/core/SlashCommandParser.ts
|
|
2433
|
-
init_esm_shims();
|
|
2434
1651
|
var SlashCommandParser = class {
|
|
2435
1652
|
static COMMAND_REGEX = /^\/(\w+)(?:\s+(.*))?$/;
|
|
2436
1653
|
/**
|
|
@@ -2484,13 +1701,11 @@ var SlashCommandParser = class {
|
|
|
2484
1701
|
};
|
|
2485
1702
|
|
|
2486
1703
|
// src/cli/components/CommandAutocomplete.tsx
|
|
2487
|
-
init_esm_shims();
|
|
2488
1704
|
import React5, { useMemo as useMemo3 } from "react";
|
|
2489
1705
|
import { Box as Box8, Text as Text7 } from "ink";
|
|
2490
1706
|
import chalk5 from "chalk";
|
|
2491
1707
|
|
|
2492
1708
|
// src/cli/hooks/useTerminalSize.ts
|
|
2493
|
-
init_esm_shims();
|
|
2494
1709
|
import { useEffect, useState as useState3 } from "react";
|
|
2495
1710
|
import { useStdout } from "ink";
|
|
2496
1711
|
var useTerminalSize = () => {
|
|
@@ -2559,8 +1774,8 @@ var CommandAutocomplete = ({
|
|
|
2559
1774
|
const paramBg = chalk5.bgHex(paramBgHex);
|
|
2560
1775
|
const { width: terminalWidth } = useTerminalSize();
|
|
2561
1776
|
const maxAllowedWidth = Math.max(30, terminalWidth - 4);
|
|
2562
|
-
const truncateText = (
|
|
2563
|
-
const stripped =
|
|
1777
|
+
const truncateText = (text, maxLen) => {
|
|
1778
|
+
const stripped = text.replace(/\x1B\[[0-9;]*m/g, "");
|
|
2564
1779
|
if (stripped.length <= maxLen) {
|
|
2565
1780
|
return stripped;
|
|
2566
1781
|
}
|
|
@@ -3085,12 +2300,10 @@ var InputBox = React6.memo(
|
|
|
3085
2300
|
InputBox.displayName = "InputBox";
|
|
3086
2301
|
|
|
3087
2302
|
// src/cli/components/Footer.tsx
|
|
3088
|
-
init_esm_shims();
|
|
3089
2303
|
import { useState as useState5, useEffect as useEffect3 } from "react";
|
|
3090
2304
|
import { Box as Box10, Text as Text9 } from "ink";
|
|
3091
2305
|
|
|
3092
2306
|
// src/cli/components/tips.ts
|
|
3093
|
-
init_esm_shims();
|
|
3094
2307
|
function generateTips(keyBindings) {
|
|
3095
2308
|
const modeSwitchKey = formatKeyboardShortcut(keyBindings.modeSwitch, { showFirstOnly: true });
|
|
3096
2309
|
const editKey = formatKeyboardShortcut(keyBindings.editCommand, { showFirstOnly: true });
|
|
@@ -3176,11 +2389,7 @@ var Footer = ({
|
|
|
3176
2389
|
] });
|
|
3177
2390
|
};
|
|
3178
2391
|
|
|
3179
|
-
// src/cli/keyboard/index.ts
|
|
3180
|
-
init_esm_shims();
|
|
3181
|
-
|
|
3182
2392
|
// src/cli/keyboard/KeyboardEventBus.ts
|
|
3183
|
-
init_esm_shims();
|
|
3184
2393
|
import { EventEmitter } from "events";
|
|
3185
2394
|
var KeyboardEventBus = class extends EventEmitter {
|
|
3186
2395
|
constructor(bindingsManager) {
|
|
@@ -3224,9 +2433,9 @@ var KeyboardEventBus = class extends EventEmitter {
|
|
|
3224
2433
|
return () => {
|
|
3225
2434
|
const handlers2 = this.handlers.get(action);
|
|
3226
2435
|
if (handlers2) {
|
|
3227
|
-
const
|
|
3228
|
-
if (
|
|
3229
|
-
handlers2.splice(
|
|
2436
|
+
const index = handlers2.findIndex((h) => h.id === handlerObj.id);
|
|
2437
|
+
if (index !== -1) {
|
|
2438
|
+
handlers2.splice(index, 1);
|
|
3230
2439
|
}
|
|
3231
2440
|
}
|
|
3232
2441
|
};
|
|
@@ -3309,11 +2518,9 @@ var KeyboardEventBus = class extends EventEmitter {
|
|
|
3309
2518
|
};
|
|
3310
2519
|
|
|
3311
2520
|
// src/cli/keyboard/KeyboardContext.tsx
|
|
3312
|
-
init_esm_shims();
|
|
3313
2521
|
import { createContext, useContext, useEffect as useEffect4, useState as useState6 } from "react";
|
|
3314
2522
|
|
|
3315
2523
|
// src/utils/KeyBindings.ts
|
|
3316
|
-
init_esm_shims();
|
|
3317
2524
|
import os4 from "os";
|
|
3318
2525
|
var KeyBindingsManager = class _KeyBindingsManager {
|
|
3319
2526
|
constructor(config) {
|
|
@@ -3523,7 +2730,6 @@ function useKeyboard() {
|
|
|
3523
2730
|
}
|
|
3524
2731
|
|
|
3525
2732
|
// src/cli/keyboard/useKeyboardAction.ts
|
|
3526
|
-
init_esm_shims();
|
|
3527
2733
|
import { useEffect as useEffect5, useRef } from "react";
|
|
3528
2734
|
function useKeyboardAction(action, handler, options = {}) {
|
|
3529
2735
|
const { eventBus } = useKeyboard();
|
|
@@ -3546,7 +2752,6 @@ function useKeyboardAction(action, handler, options = {}) {
|
|
|
3546
2752
|
}
|
|
3547
2753
|
|
|
3548
2754
|
// src/cli/keyboard/useKeyboardInput.ts
|
|
3549
|
-
init_esm_shims();
|
|
3550
2755
|
import { useInput as useInput2 } from "ink";
|
|
3551
2756
|
var CONTROL_CHAR_MAP = {
|
|
3552
2757
|
0: "Space",
|
|
@@ -3641,7 +2846,7 @@ function useKeyboardInput(options = {}) {
|
|
|
3641
2846
|
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3642
2847
|
var ChatInterface = ({
|
|
3643
2848
|
config,
|
|
3644
|
-
messages
|
|
2849
|
+
messages,
|
|
3645
2850
|
onUserInput,
|
|
3646
2851
|
onExit,
|
|
3647
2852
|
currentMode,
|
|
@@ -3831,9 +3036,9 @@ var ChatInterface = ({
|
|
|
3831
3036
|
currentMode: mode,
|
|
3832
3037
|
currentProvider: config.llm.provider,
|
|
3833
3038
|
currentModel: config.llm.model,
|
|
3834
|
-
messageCount:
|
|
3039
|
+
messageCount: messages.length
|
|
3835
3040
|
}),
|
|
3836
|
-
[mode, config.llm.provider, config.llm.model,
|
|
3041
|
+
[mode, config.llm.provider, config.llm.model, messages.length]
|
|
3837
3042
|
);
|
|
3838
3043
|
const fixedUIHeight = 8;
|
|
3839
3044
|
const minMessageLines = 3;
|
|
@@ -3866,7 +3071,7 @@ var ChatInterface = ({
|
|
|
3866
3071
|
/* @__PURE__ */ jsx12(Box11, { height: messageAreaHeight, children: /* @__PURE__ */ jsx12(
|
|
3867
3072
|
MessageList,
|
|
3868
3073
|
{
|
|
3869
|
-
messages
|
|
3074
|
+
messages,
|
|
3870
3075
|
theme: config.ui.theme,
|
|
3871
3076
|
syntaxHighlighting: config.ui.syntaxHighlighting
|
|
3872
3077
|
}
|
|
@@ -3941,7 +3146,6 @@ function ChatApp({ fs: fs4, projectRoot, ...chatProps }) {
|
|
|
3941
3146
|
}
|
|
3942
3147
|
|
|
3943
3148
|
// src/core/SlashCommand.ts
|
|
3944
|
-
init_esm_shims();
|
|
3945
3149
|
var SlashCommandRegistry = class {
|
|
3946
3150
|
commands = /* @__PURE__ */ new Map();
|
|
3947
3151
|
aliases = /* @__PURE__ */ new Map();
|
|
@@ -4006,10 +3210,9 @@ var SlashCommandRegistry = class {
|
|
|
4006
3210
|
};
|
|
4007
3211
|
|
|
4008
3212
|
// src/core/CustomCommandLoader.ts
|
|
4009
|
-
init_esm_shims();
|
|
4010
3213
|
import { z as z3 } from "zod";
|
|
4011
3214
|
import yaml3 from "yaml";
|
|
4012
|
-
import
|
|
3215
|
+
import path5 from "path";
|
|
4013
3216
|
import os5 from "os";
|
|
4014
3217
|
var CustomCommandSchema = z3.object({
|
|
4015
3218
|
name: z3.string().regex(/^[a-z][a-z0-9-]*$/, "Command name must be lowercase alphanumeric with hyphens"),
|
|
@@ -4036,8 +3239,8 @@ var CustomCommand = class {
|
|
|
4036
3239
|
}
|
|
4037
3240
|
async execute(args, context) {
|
|
4038
3241
|
let prompt = this.definition.prompt;
|
|
4039
|
-
args.forEach((arg,
|
|
4040
|
-
const placeholder = `$${
|
|
3242
|
+
args.forEach((arg, index) => {
|
|
3243
|
+
const placeholder = `$${index + 1}`;
|
|
4041
3244
|
prompt = prompt.replace(new RegExp(`\\${placeholder}`, "g"), arg);
|
|
4042
3245
|
});
|
|
4043
3246
|
const allArgs = args.join(" ");
|
|
@@ -4066,12 +3269,12 @@ var CustomCommandLoader = class {
|
|
|
4066
3269
|
async loadAll(projectRoot) {
|
|
4067
3270
|
const commandMap = /* @__PURE__ */ new Map();
|
|
4068
3271
|
const globalCommands = await this.loadFromDirectory(
|
|
4069
|
-
|
|
3272
|
+
path5.join(os5.homedir(), ".mimir", "commands")
|
|
4070
3273
|
);
|
|
4071
3274
|
globalCommands.forEach((cmd) => commandMap.set(cmd.name, cmd));
|
|
4072
3275
|
if (projectRoot) {
|
|
4073
3276
|
const projectCommands = await this.loadFromDirectory(
|
|
4074
|
-
|
|
3277
|
+
path5.join(projectRoot, ".mimir", "commands")
|
|
4075
3278
|
);
|
|
4076
3279
|
projectCommands.forEach((cmd) => {
|
|
4077
3280
|
if (commandMap.has(cmd.name)) {
|
|
@@ -4093,7 +3296,7 @@ var CustomCommandLoader = class {
|
|
|
4093
3296
|
}
|
|
4094
3297
|
const files = await this.fs.glob("*.yml", { cwd: dirPath });
|
|
4095
3298
|
for (const file of files) {
|
|
4096
|
-
const fullPath =
|
|
3299
|
+
const fullPath = path5.join(dirPath, file);
|
|
4097
3300
|
const command = await this.loadCommand(fullPath);
|
|
4098
3301
|
if (command) {
|
|
4099
3302
|
commands.push(command);
|
|
@@ -4147,7 +3350,6 @@ var CustomCommandLoader = class {
|
|
|
4147
3350
|
};
|
|
4148
3351
|
|
|
4149
3352
|
// src/cli/utils/signalHandler.ts
|
|
4150
|
-
init_esm_shims();
|
|
4151
3353
|
var SignalHandler = class {
|
|
4152
3354
|
sigintCount = 0;
|
|
4153
3355
|
cleanupTimeout = null;
|
|
@@ -4308,11 +3510,7 @@ function installSignalHandlers(options = {}) {
|
|
|
4308
3510
|
return handler;
|
|
4309
3511
|
}
|
|
4310
3512
|
|
|
4311
|
-
// src/cli/commands/slashCommands/index.ts
|
|
4312
|
-
init_esm_shims();
|
|
4313
|
-
|
|
4314
3513
|
// src/cli/commands/slashCommands/NewCommand.ts
|
|
4315
|
-
init_esm_shims();
|
|
4316
3514
|
var NewCommand = class {
|
|
4317
3515
|
name = "new";
|
|
4318
3516
|
description = "Start a new chat conversation";
|
|
@@ -4334,7 +3532,6 @@ var NewCommand = class {
|
|
|
4334
3532
|
};
|
|
4335
3533
|
|
|
4336
3534
|
// src/cli/commands/slashCommands/ModelCommand.ts
|
|
4337
|
-
init_esm_shims();
|
|
4338
3535
|
import { z as z4 } from "zod";
|
|
4339
3536
|
var ModelCommand = class {
|
|
4340
3537
|
name = "model";
|
|
@@ -4405,7 +3602,6 @@ var ModelCommand = class {
|
|
|
4405
3602
|
};
|
|
4406
3603
|
|
|
4407
3604
|
// src/cli/commands/slashCommands/ModeCommand.ts
|
|
4408
|
-
init_esm_shims();
|
|
4409
3605
|
import { z as z5 } from "zod";
|
|
4410
3606
|
var ModeCommand = class {
|
|
4411
3607
|
name = "mode";
|
|
@@ -4450,7 +3646,6 @@ var ModeCommand = class {
|
|
|
4450
3646
|
};
|
|
4451
3647
|
|
|
4452
3648
|
// src/cli/commands/slashCommands/HelpCommand.ts
|
|
4453
|
-
init_esm_shims();
|
|
4454
3649
|
var HelpCommand = class {
|
|
4455
3650
|
constructor(registry) {
|
|
4456
3651
|
this.registry = registry;
|
|
@@ -4508,7 +3703,6 @@ var HelpCommand = class {
|
|
|
4508
3703
|
};
|
|
4509
3704
|
|
|
4510
3705
|
// src/cli/commands/slashCommands/ThemeCommand.ts
|
|
4511
|
-
init_esm_shims();
|
|
4512
3706
|
var ThemeCommand = class {
|
|
4513
3707
|
name = "theme";
|
|
4514
3708
|
description = "Show available themes or change to specified theme";
|
|
@@ -4574,250 +3768,10 @@ Use /theme <name> to switch (e.g., /theme dark)`;
|
|
|
4574
3768
|
}
|
|
4575
3769
|
};
|
|
4576
3770
|
|
|
4577
|
-
// src/core/MimirInitializer.ts
|
|
4578
|
-
init_esm_shims();
|
|
4579
|
-
|
|
4580
3771
|
// src/storage/Database.ts
|
|
4581
|
-
|
|
4582
|
-
var import_better_sqlite3 = __toESM(require_lib(), 1);
|
|
4583
|
-
import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
4584
|
-
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
|
4585
|
-
|
|
4586
|
-
// src/storage/schema.ts
|
|
4587
|
-
var schema_exports = {};
|
|
4588
|
-
__export(schema_exports, {
|
|
4589
|
-
checkpoints: () => checkpoints,
|
|
4590
|
-
conversations: () => conversations,
|
|
4591
|
-
costSummary: () => costSummary,
|
|
4592
|
-
messages: () => messages,
|
|
4593
|
-
metrics: () => metrics,
|
|
4594
|
-
migrations: () => migrations,
|
|
4595
|
-
permissions: () => permissions,
|
|
4596
|
-
pricing: () => pricing,
|
|
4597
|
-
sessionState: () => sessionState,
|
|
4598
|
-
toolCalls: () => toolCalls
|
|
4599
|
-
});
|
|
4600
|
-
init_esm_shims();
|
|
4601
|
-
import { sqliteTable, text, integer, real, index, uniqueIndex } from "drizzle-orm/sqlite-core";
|
|
4602
|
-
import { sql } from "drizzle-orm";
|
|
4603
|
-
var migrations = sqliteTable("migrations", {
|
|
4604
|
-
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
4605
|
-
version: text("version").notNull().unique(),
|
|
4606
|
-
appliedAt: integer("applied_at", { mode: "timestamp" }).notNull().default(sql`(strftime('%s', 'now'))`)
|
|
4607
|
-
});
|
|
4608
|
-
var conversations = sqliteTable(
|
|
4609
|
-
"conversations",
|
|
4610
|
-
{
|
|
4611
|
-
id: text("id").primaryKey(),
|
|
4612
|
-
title: text("title"),
|
|
4613
|
-
createdAt: integer("created_at", { mode: "timestamp" }).notNull().default(sql`(strftime('%s', 'now'))`),
|
|
4614
|
-
updatedAt: integer("updated_at", { mode: "timestamp" }).notNull().default(sql`(strftime('%s', 'now'))`),
|
|
4615
|
-
totalTokens: integer("total_tokens").default(0),
|
|
4616
|
-
totalCost: real("total_cost").default(0),
|
|
4617
|
-
provider: text("provider"),
|
|
4618
|
-
model: text("model"),
|
|
4619
|
-
status: text("status", { enum: ["active", "archived", "deleted"] }).default("active")
|
|
4620
|
-
},
|
|
4621
|
-
(table) => ({
|
|
4622
|
-
createdAtIdx: index("idx_conversations_created_at").on(table.createdAt),
|
|
4623
|
-
statusIdx: index("idx_conversations_status").on(table.status)
|
|
4624
|
-
})
|
|
4625
|
-
);
|
|
4626
|
-
var messages = sqliteTable(
|
|
4627
|
-
"messages",
|
|
4628
|
-
{
|
|
4629
|
-
id: text("id").primaryKey(),
|
|
4630
|
-
conversationId: text("conversation_id").notNull().references(() => conversations.id, { onDelete: "cascade" }),
|
|
4631
|
-
role: text("role", { enum: ["system", "user", "assistant"] }).notNull(),
|
|
4632
|
-
content: text("content").notNull(),
|
|
4633
|
-
timestamp: integer("timestamp", { mode: "timestamp" }).notNull().default(sql`(strftime('%s', 'now'))`),
|
|
4634
|
-
inputTokens: integer("input_tokens").default(0),
|
|
4635
|
-
outputTokens: integer("output_tokens").default(0),
|
|
4636
|
-
cost: real("cost").default(0),
|
|
4637
|
-
metadata: text("metadata")
|
|
4638
|
-
// JSON string
|
|
4639
|
-
},
|
|
4640
|
-
(table) => ({
|
|
4641
|
-
conversationIdIdx: index("idx_messages_conversation_id").on(table.conversationId),
|
|
4642
|
-
timestampIdx: index("idx_messages_timestamp").on(table.timestamp)
|
|
4643
|
-
})
|
|
4644
|
-
);
|
|
4645
|
-
var toolCalls = sqliteTable(
|
|
4646
|
-
"tool_calls",
|
|
4647
|
-
{
|
|
4648
|
-
id: text("id").primaryKey(),
|
|
4649
|
-
conversationId: text("conversation_id").notNull().references(() => conversations.id, { onDelete: "cascade" }),
|
|
4650
|
-
messageId: text("message_id").references(() => messages.id, { onDelete: "set null" }),
|
|
4651
|
-
toolName: text("tool_name").notNull(),
|
|
4652
|
-
arguments: text("arguments").notNull(),
|
|
4653
|
-
// JSON string
|
|
4654
|
-
result: text("result"),
|
|
4655
|
-
// JSON string
|
|
4656
|
-
status: text("status", { enum: ["pending", "running", "success", "failed"] }).default(
|
|
4657
|
-
"pending"
|
|
4658
|
-
),
|
|
4659
|
-
error: text("error"),
|
|
4660
|
-
startedAt: integer("started_at", { mode: "timestamp" }).notNull().default(sql`(strftime('%s', 'now'))`),
|
|
4661
|
-
completedAt: integer("completed_at", { mode: "timestamp" }),
|
|
4662
|
-
durationMs: integer("duration_ms")
|
|
4663
|
-
},
|
|
4664
|
-
(table) => ({
|
|
4665
|
-
conversationIdIdx: index("idx_tool_calls_conversation_id").on(table.conversationId),
|
|
4666
|
-
statusIdx: index("idx_tool_calls_status").on(table.status),
|
|
4667
|
-
startedAtIdx: index("idx_tool_calls_started_at").on(table.startedAt)
|
|
4668
|
-
})
|
|
4669
|
-
);
|
|
4670
|
-
var permissions = sqliteTable(
|
|
4671
|
-
"permissions",
|
|
4672
|
-
{
|
|
4673
|
-
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
4674
|
-
conversationId: text("conversation_id").references(() => conversations.id, {
|
|
4675
|
-
onDelete: "set null"
|
|
4676
|
-
}),
|
|
4677
|
-
command: text("command").notNull(),
|
|
4678
|
-
riskLevel: text("risk_level", { enum: ["low", "medium", "high", "critical"] }).notNull(),
|
|
4679
|
-
decision: text("decision", { enum: ["allow", "deny", "always", "never"] }).notNull(),
|
|
4680
|
-
userConfirmed: integer("user_confirmed", { mode: "boolean" }).default(false),
|
|
4681
|
-
timestamp: integer("timestamp", { mode: "timestamp" }).notNull().default(sql`(strftime('%s', 'now'))`),
|
|
4682
|
-
context: text("context")
|
|
4683
|
-
// JSON string
|
|
4684
|
-
},
|
|
4685
|
-
(table) => ({
|
|
4686
|
-
conversationIdIdx: index("idx_permissions_conversation_id").on(table.conversationId),
|
|
4687
|
-
timestampIdx: index("idx_permissions_timestamp").on(table.timestamp),
|
|
4688
|
-
decisionIdx: index("idx_permissions_decision").on(table.decision)
|
|
4689
|
-
})
|
|
4690
|
-
);
|
|
4691
|
-
var checkpoints = sqliteTable(
|
|
4692
|
-
"checkpoints",
|
|
4693
|
-
{
|
|
4694
|
-
id: text("id").primaryKey(),
|
|
4695
|
-
conversationId: text("conversation_id").notNull().references(() => conversations.id, { onDelete: "cascade" }),
|
|
4696
|
-
description: text("description"),
|
|
4697
|
-
filesSnapshot: text("files_snapshot").notNull(),
|
|
4698
|
-
// JSON string
|
|
4699
|
-
gitDiff: text("git_diff"),
|
|
4700
|
-
createdAt: integer("created_at", { mode: "timestamp" }).notNull().default(sql`(strftime('%s', 'now'))`)
|
|
4701
|
-
},
|
|
4702
|
-
(table) => ({
|
|
4703
|
-
conversationIdIdx: index("idx_checkpoints_conversation_id").on(table.conversationId),
|
|
4704
|
-
createdAtIdx: index("idx_checkpoints_created_at").on(table.createdAt)
|
|
4705
|
-
})
|
|
4706
|
-
);
|
|
4707
|
-
var costSummary = sqliteTable(
|
|
4708
|
-
"cost_summary",
|
|
4709
|
-
{
|
|
4710
|
-
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
4711
|
-
date: text("date").notNull(),
|
|
4712
|
-
// YYYY-MM-DD format
|
|
4713
|
-
provider: text("provider").notNull(),
|
|
4714
|
-
model: text("model").notNull(),
|
|
4715
|
-
totalTokens: integer("total_tokens").default(0),
|
|
4716
|
-
inputTokens: integer("input_tokens").default(0),
|
|
4717
|
-
outputTokens: integer("output_tokens").default(0),
|
|
4718
|
-
totalCost: real("total_cost").default(0),
|
|
4719
|
-
requestCount: integer("request_count").default(0)
|
|
4720
|
-
},
|
|
4721
|
-
(table) => ({
|
|
4722
|
-
dateIdx: index("idx_cost_summary_date").on(table.date),
|
|
4723
|
-
providerIdx: index("idx_cost_summary_provider").on(table.provider),
|
|
4724
|
-
uniqueIdx: uniqueIndex("unique_date_provider_model").on(
|
|
4725
|
-
table.date,
|
|
4726
|
-
table.provider,
|
|
4727
|
-
table.model
|
|
4728
|
-
)
|
|
4729
|
-
})
|
|
4730
|
-
);
|
|
4731
|
-
var sessionState = sqliteTable(
|
|
4732
|
-
"session_state",
|
|
4733
|
-
{
|
|
4734
|
-
id: text("id").primaryKey(),
|
|
4735
|
-
conversationId: text("conversation_id").notNull().references(() => conversations.id, { onDelete: "cascade" }),
|
|
4736
|
-
agentState: text("agent_state").notNull(),
|
|
4737
|
-
// JSON string
|
|
4738
|
-
iteration: integer("iteration").default(0),
|
|
4739
|
-
createdAt: integer("created_at", { mode: "timestamp" }).notNull().default(sql`(strftime('%s', 'now'))`)
|
|
4740
|
-
},
|
|
4741
|
-
(table) => ({
|
|
4742
|
-
conversationIdIdx: index("idx_session_state_conversation_id").on(table.conversationId)
|
|
4743
|
-
})
|
|
4744
|
-
);
|
|
4745
|
-
var metrics = sqliteTable(
|
|
4746
|
-
"metrics",
|
|
4747
|
-
{
|
|
4748
|
-
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
4749
|
-
timestamp: integer("timestamp", { mode: "timestamp" }).notNull().default(sql`(strftime('%s', 'now'))`),
|
|
4750
|
-
operation: text("operation").notNull(),
|
|
4751
|
-
// 'llm.chat', 'tool.execute', 'db.query'
|
|
4752
|
-
durationMs: integer("duration_ms").notNull(),
|
|
4753
|
-
// Context
|
|
4754
|
-
conversationId: text("conversation_id"),
|
|
4755
|
-
sessionId: text("session_id"),
|
|
4756
|
-
// LLM specific
|
|
4757
|
-
provider: text("provider"),
|
|
4758
|
-
model: text("model"),
|
|
4759
|
-
inputTokens: integer("input_tokens"),
|
|
4760
|
-
outputTokens: integer("output_tokens"),
|
|
4761
|
-
totalTokens: integer("total_tokens"),
|
|
4762
|
-
cost: real("cost"),
|
|
4763
|
-
// Tool specific
|
|
4764
|
-
toolName: text("tool_name"),
|
|
4765
|
-
toolArgs: text("tool_args"),
|
|
4766
|
-
// JSON
|
|
4767
|
-
toolResultSize: integer("tool_result_size"),
|
|
4768
|
-
// bytes
|
|
4769
|
-
// DB specific
|
|
4770
|
-
queryType: text("query_type"),
|
|
4771
|
-
// 'SELECT', 'INSERT', etc.
|
|
4772
|
-
tableName: text("table_name"),
|
|
4773
|
-
rowsAffected: integer("rows_affected"),
|
|
4774
|
-
// Result
|
|
4775
|
-
success: integer("success", { mode: "boolean" }).default(true),
|
|
4776
|
-
error: text("error"),
|
|
4777
|
-
// Resource usage
|
|
4778
|
-
memoryMb: real("memory_mb"),
|
|
4779
|
-
cpuPercent: real("cpu_percent"),
|
|
4780
|
-
// Additional metadata
|
|
4781
|
-
metadata: text("metadata")
|
|
4782
|
-
// JSON for extensibility
|
|
4783
|
-
},
|
|
4784
|
-
(table) => ({
|
|
4785
|
-
timestampIdx: index("idx_metrics_timestamp").on(table.timestamp),
|
|
4786
|
-
operationIdx: index("idx_metrics_operation").on(table.operation),
|
|
4787
|
-
conversationIdIdx: index("idx_metrics_conversation_id").on(table.conversationId),
|
|
4788
|
-
providerIdx: index("idx_metrics_provider").on(table.provider),
|
|
4789
|
-
successIdx: index("idx_metrics_success").on(table.success)
|
|
4790
|
-
})
|
|
4791
|
-
);
|
|
4792
|
-
var pricing = sqliteTable(
|
|
4793
|
-
"pricing",
|
|
4794
|
-
{
|
|
4795
|
-
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
4796
|
-
provider: text("provider").notNull(),
|
|
4797
|
-
model: text("model").notNull(),
|
|
4798
|
-
inputPricePer1M: real("input_price_per_1m").notNull(),
|
|
4799
|
-
// USD per 1M input tokens
|
|
4800
|
-
outputPricePer1M: real("output_price_per_1m").notNull(),
|
|
4801
|
-
// USD per 1M output tokens
|
|
4802
|
-
effectiveFrom: integer("effective_from", { mode: "timestamp" }).notNull().default(sql`(strftime('%s', 'now'))`),
|
|
4803
|
-
effectiveUntil: integer("effective_until", { mode: "timestamp" }),
|
|
4804
|
-
// NULL = current price
|
|
4805
|
-
currency: text("currency").default("USD"),
|
|
4806
|
-
notes: text("notes")
|
|
4807
|
-
},
|
|
4808
|
-
(table) => ({
|
|
4809
|
-
providerModelIdx: index("idx_pricing_provider_model").on(table.provider, table.model),
|
|
4810
|
-
effectiveIdx: index("idx_pricing_effective").on(table.effectiveFrom),
|
|
4811
|
-
uniqueIdx: uniqueIndex("unique_provider_model_effective").on(
|
|
4812
|
-
table.provider,
|
|
4813
|
-
table.model,
|
|
4814
|
-
table.effectiveFrom
|
|
4815
|
-
)
|
|
4816
|
-
})
|
|
4817
|
-
);
|
|
3772
|
+
import initSqlJs from "sql.js";
|
|
4818
3773
|
|
|
4819
3774
|
// src/storage/seed.ts
|
|
4820
|
-
init_esm_shims();
|
|
4821
3775
|
var defaultPricing = [
|
|
4822
3776
|
// DeepSeek
|
|
4823
3777
|
{
|
|
@@ -4947,24 +3901,67 @@ var defaultPricing = [
|
|
|
4947
3901
|
];
|
|
4948
3902
|
|
|
4949
3903
|
// src/storage/Database.ts
|
|
4950
|
-
import { dirname } from "path";
|
|
3904
|
+
import { dirname, join } from "path";
|
|
3905
|
+
import { fileURLToPath } from "url";
|
|
3906
|
+
import { readFileSync, existsSync } from "fs";
|
|
3907
|
+
function locateWasmFile() {
|
|
3908
|
+
const wasmFileName = "sql-wasm.wasm";
|
|
3909
|
+
const executablePath = process.argv[0] || process.execPath;
|
|
3910
|
+
const binaryDir = dirname(executablePath);
|
|
3911
|
+
const resourcesPaths = [
|
|
3912
|
+
// Next to the binary (same directory) - most common for our installers
|
|
3913
|
+
join(binaryDir, "resources", wasmFileName),
|
|
3914
|
+
// For development/testing
|
|
3915
|
+
join(process.cwd(), "resources", wasmFileName),
|
|
3916
|
+
// Parent directory of binary (for some install layouts)
|
|
3917
|
+
join(binaryDir, "..", "resources", wasmFileName)
|
|
3918
|
+
];
|
|
3919
|
+
for (const resourcePath of resourcesPaths) {
|
|
3920
|
+
if (existsSync(resourcePath)) {
|
|
3921
|
+
const buffer = readFileSync(resourcePath);
|
|
3922
|
+
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
3923
|
+
}
|
|
3924
|
+
}
|
|
3925
|
+
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
3926
|
+
const nodeModulesPaths = [
|
|
3927
|
+
join(currentDir, "..", "..", "node_modules", "sql.js", "dist", wasmFileName),
|
|
3928
|
+
join(process.cwd(), "node_modules", "sql.js", "dist", wasmFileName)
|
|
3929
|
+
];
|
|
3930
|
+
for (const modulePath of nodeModulesPaths) {
|
|
3931
|
+
if (existsSync(modulePath)) {
|
|
3932
|
+
const buffer = readFileSync(modulePath);
|
|
3933
|
+
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
3934
|
+
}
|
|
3935
|
+
}
|
|
3936
|
+
const diagnostics = [
|
|
3937
|
+
`process.argv[0]: ${process.argv[0]}`,
|
|
3938
|
+
`process.execPath: ${process.execPath}`,
|
|
3939
|
+
`executablePath: ${executablePath}`,
|
|
3940
|
+
`binaryDir: ${binaryDir}`,
|
|
3941
|
+
`currentDir: ${currentDir}`,
|
|
3942
|
+
`process.cwd(): ${process.cwd()}`
|
|
3943
|
+
];
|
|
3944
|
+
throw new Error(
|
|
3945
|
+
`Could not locate ${wasmFileName}.
|
|
3946
|
+
|
|
3947
|
+
Diagnostics:
|
|
3948
|
+
${diagnostics.join("\n")}
|
|
3949
|
+
|
|
3950
|
+
Tried:
|
|
3951
|
+
` + [...resourcesPaths, ...nodeModulesPaths].map((p) => ` - ${p}`).join("\n")
|
|
3952
|
+
);
|
|
3953
|
+
}
|
|
4951
3954
|
var DatabaseManager = class _DatabaseManager {
|
|
4952
|
-
sqlite;
|
|
4953
3955
|
db;
|
|
4954
3956
|
config;
|
|
4955
|
-
|
|
3957
|
+
SQL;
|
|
3958
|
+
nodeFs = null;
|
|
3959
|
+
constructor(config, SQL) {
|
|
4956
3960
|
this.config = config;
|
|
4957
|
-
this.
|
|
4958
|
-
verbose: config.verbose ? console.log : void 0
|
|
4959
|
-
});
|
|
4960
|
-
this.sqlite.pragma("journal_mode = WAL");
|
|
4961
|
-
this.sqlite.pragma("foreign_keys = ON");
|
|
4962
|
-
this.db = drizzle(this.sqlite, { schema: schema_exports });
|
|
4963
|
-
this.initialize();
|
|
3961
|
+
this.SQL = SQL;
|
|
4964
3962
|
}
|
|
4965
3963
|
/**
|
|
4966
3964
|
* Create DatabaseManager instance with proper directory setup
|
|
4967
|
-
* Use this factory method instead of constructor for proper async initialization
|
|
4968
3965
|
*/
|
|
4969
3966
|
static async create(config) {
|
|
4970
3967
|
const dbDir = dirname(config.path);
|
|
@@ -4974,72 +3971,103 @@ var DatabaseManager = class _DatabaseManager {
|
|
|
4974
3971
|
await config.fileSystem.mkdir(dbDir, { recursive: true });
|
|
4975
3972
|
}
|
|
4976
3973
|
} else {
|
|
4977
|
-
const { existsSync, mkdirSync } = await import("fs");
|
|
4978
|
-
if (!
|
|
3974
|
+
const { existsSync: existsSync2, mkdirSync } = await import("fs");
|
|
3975
|
+
if (!existsSync2(dbDir)) {
|
|
4979
3976
|
mkdirSync(dbDir, { recursive: true });
|
|
4980
3977
|
}
|
|
4981
3978
|
}
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
console.error("Database initialization failed:", error);
|
|
4993
|
-
throw error;
|
|
4994
|
-
}
|
|
3979
|
+
const wasmBinary = locateWasmFile();
|
|
3980
|
+
const SQL = await initSqlJs({
|
|
3981
|
+
wasmBinary
|
|
3982
|
+
});
|
|
3983
|
+
const manager = new _DatabaseManager(config, SQL);
|
|
3984
|
+
manager.nodeFs = await import("fs");
|
|
3985
|
+
await manager.loadDatabase();
|
|
3986
|
+
manager.initialize();
|
|
3987
|
+
await manager.save();
|
|
3988
|
+
return manager;
|
|
4995
3989
|
}
|
|
4996
3990
|
/**
|
|
4997
|
-
*
|
|
3991
|
+
* Load database from file or create new
|
|
4998
3992
|
*/
|
|
4999
|
-
|
|
3993
|
+
async loadDatabase() {
|
|
5000
3994
|
try {
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
3995
|
+
if (this.config.fileSystem) {
|
|
3996
|
+
const exists = await this.config.fileSystem.exists(this.config.path);
|
|
3997
|
+
if (exists) {
|
|
3998
|
+
const buffer = await this.config.fileSystem.readFile(
|
|
3999
|
+
this.config.path,
|
|
4000
|
+
"binary"
|
|
4001
|
+
);
|
|
4002
|
+
const uint8Array = new Uint8Array(Buffer.from(buffer, "binary"));
|
|
4003
|
+
this.db = new this.SQL.Database(uint8Array);
|
|
4004
|
+
if (this.config.verbose) {
|
|
4005
|
+
console.log("Loaded existing database from", this.config.path);
|
|
4006
|
+
}
|
|
4007
|
+
} else {
|
|
4008
|
+
this.db = new this.SQL.Database();
|
|
4009
|
+
if (this.config.verbose) {
|
|
4010
|
+
console.log("Created new database");
|
|
4011
|
+
}
|
|
4012
|
+
}
|
|
5005
4013
|
} else {
|
|
4014
|
+
const { existsSync: existsSync2, readFileSync: readFileSync2 } = await import("fs");
|
|
4015
|
+
if (existsSync2(this.config.path)) {
|
|
4016
|
+
const buffer = readFileSync2(this.config.path);
|
|
4017
|
+
this.db = new this.SQL.Database(buffer);
|
|
4018
|
+
} else {
|
|
4019
|
+
this.db = new this.SQL.Database();
|
|
4020
|
+
}
|
|
5006
4021
|
}
|
|
5007
4022
|
} catch (error) {
|
|
4023
|
+
this.db = new this.SQL.Database();
|
|
5008
4024
|
if (this.config.verbose) {
|
|
5009
|
-
console.log("
|
|
4025
|
+
console.log("Created new database after error:", error);
|
|
5010
4026
|
}
|
|
5011
4027
|
}
|
|
5012
4028
|
}
|
|
5013
4029
|
/**
|
|
5014
|
-
*
|
|
4030
|
+
* Save database to disk (async version)
|
|
5015
4031
|
*/
|
|
5016
|
-
|
|
5017
|
-
const
|
|
5018
|
-
|
|
5019
|
-
|
|
4032
|
+
async save() {
|
|
4033
|
+
const data = this.db.export();
|
|
4034
|
+
const buffer = Buffer.from(data);
|
|
4035
|
+
if (this.config.fileSystem) {
|
|
4036
|
+
await this.config.fileSystem.writeFile(
|
|
4037
|
+
this.config.path,
|
|
4038
|
+
buffer.toString("binary"),
|
|
4039
|
+
"binary"
|
|
4040
|
+
);
|
|
4041
|
+
} else {
|
|
4042
|
+
const { writeFileSync } = await import("fs");
|
|
4043
|
+
writeFileSync(this.config.path, buffer);
|
|
5020
4044
|
}
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
4045
|
+
}
|
|
4046
|
+
/**
|
|
4047
|
+
* Save database to disk (sync version for auto-save)
|
|
4048
|
+
* Uses sync fs operations to avoid async in execute/transaction
|
|
4049
|
+
*/
|
|
4050
|
+
saveSync() {
|
|
4051
|
+
const data = this.db.export();
|
|
4052
|
+
const buffer = Buffer.from(data);
|
|
4053
|
+
if (this.nodeFs) {
|
|
4054
|
+
this.nodeFs.writeFileSync(this.config.path, buffer);
|
|
5031
4055
|
}
|
|
4056
|
+
}
|
|
4057
|
+
/**
|
|
4058
|
+
* Initialize database with migrations and seed data
|
|
4059
|
+
*/
|
|
4060
|
+
initialize() {
|
|
5032
4061
|
try {
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
this.db.insert(migrations).values({ version: "1.0.0" }).run();
|
|
5036
|
-
}
|
|
4062
|
+
this.createTablesManually();
|
|
4063
|
+
this.seedDatabase();
|
|
5037
4064
|
} catch (error) {
|
|
4065
|
+
console.error("Database initialization failed:", error);
|
|
4066
|
+
throw error;
|
|
5038
4067
|
}
|
|
5039
4068
|
}
|
|
5040
4069
|
/**
|
|
5041
|
-
* Manually create tables from
|
|
5042
|
-
* This is a fallback for when migrations don't exist yet
|
|
4070
|
+
* Manually create tables from schema
|
|
5043
4071
|
*/
|
|
5044
4072
|
createTablesManually() {
|
|
5045
4073
|
const createTablesSQL = `
|
|
@@ -5207,7 +4235,7 @@ var DatabaseManager = class _DatabaseManager {
|
|
|
5207
4235
|
const statements = createTablesSQL.split(";").filter((s) => s.trim());
|
|
5208
4236
|
for (const statement of statements) {
|
|
5209
4237
|
try {
|
|
5210
|
-
this.
|
|
4238
|
+
this.db.run(statement);
|
|
5211
4239
|
} catch (error) {
|
|
5212
4240
|
if (this.config.verbose) {
|
|
5213
4241
|
console.log("Table creation warning:", error);
|
|
@@ -5219,83 +4247,149 @@ var DatabaseManager = class _DatabaseManager {
|
|
|
5219
4247
|
}
|
|
5220
4248
|
}
|
|
5221
4249
|
/**
|
|
5222
|
-
*
|
|
4250
|
+
* Seed database with initial data
|
|
5223
4251
|
*/
|
|
5224
|
-
|
|
5225
|
-
|
|
4252
|
+
seedDatabase() {
|
|
4253
|
+
const pricingCount = this.db.exec(
|
|
4254
|
+
"SELECT COUNT(*) as count FROM sqlite_master WHERE type='table' AND name='pricing'"
|
|
4255
|
+
);
|
|
4256
|
+
if (pricingCount.length === 0 || pricingCount[0]?.values[0]?.[0] === 0) {
|
|
4257
|
+
this.createTablesManually();
|
|
4258
|
+
}
|
|
4259
|
+
const existingPricing = this.db.exec("SELECT COUNT(*) as count FROM pricing");
|
|
4260
|
+
const count = existingPricing.length > 0 ? existingPricing[0]?.values[0]?.[0] : 0;
|
|
4261
|
+
if (count === 0) {
|
|
4262
|
+
for (const price of defaultPricing) {
|
|
4263
|
+
const stmt = this.db.prepare(
|
|
4264
|
+
`INSERT INTO pricing (provider, model, input_price_per_1m, output_price_per_1m, effective_from, currency)
|
|
4265
|
+
VALUES (?, ?, ?, ?, ?, ?)`
|
|
4266
|
+
);
|
|
4267
|
+
const effectiveFrom = price.effectiveFrom ? typeof price.effectiveFrom === "number" ? price.effectiveFrom : Math.floor(price.effectiveFrom.getTime() / 1e3) : Math.floor(Date.now() / 1e3);
|
|
4268
|
+
stmt.run([
|
|
4269
|
+
price.provider,
|
|
4270
|
+
price.model,
|
|
4271
|
+
price.inputPricePer1M,
|
|
4272
|
+
price.outputPricePer1M,
|
|
4273
|
+
effectiveFrom,
|
|
4274
|
+
price.currency ?? "USD"
|
|
4275
|
+
]);
|
|
4276
|
+
stmt.free();
|
|
4277
|
+
}
|
|
4278
|
+
if (this.config.verbose) {
|
|
4279
|
+
console.log(`Seeded ${defaultPricing.length} pricing entries`);
|
|
4280
|
+
}
|
|
4281
|
+
}
|
|
4282
|
+
try {
|
|
4283
|
+
const migrationExists = this.db.exec(
|
|
4284
|
+
"SELECT COUNT(*) as count FROM migrations WHERE version = '1.0.0'"
|
|
4285
|
+
);
|
|
4286
|
+
const migCount = migrationExists.length > 0 ? migrationExists[0]?.values[0]?.[0] : 0;
|
|
4287
|
+
if (migCount === 0) {
|
|
4288
|
+
this.db.run("INSERT INTO migrations (version) VALUES ('1.0.0')");
|
|
4289
|
+
}
|
|
4290
|
+
} catch (error) {
|
|
4291
|
+
}
|
|
5226
4292
|
}
|
|
5227
4293
|
/**
|
|
5228
|
-
*
|
|
4294
|
+
* Execute a raw SQL query (auto-saves for write operations)
|
|
5229
4295
|
*/
|
|
5230
|
-
|
|
5231
|
-
|
|
4296
|
+
execute(sql, params) {
|
|
4297
|
+
const stmt = this.db.prepare(sql);
|
|
4298
|
+
stmt.bind(params || []);
|
|
4299
|
+
stmt.step();
|
|
4300
|
+
const info = this.db.getRowsModified();
|
|
4301
|
+
stmt.free();
|
|
4302
|
+
const isWrite = /^\s*(INSERT|UPDATE|DELETE|CREATE|DROP|ALTER)/i.test(sql);
|
|
4303
|
+
if (isWrite && info > 0) {
|
|
4304
|
+
this.saveSync();
|
|
4305
|
+
}
|
|
4306
|
+
return {
|
|
4307
|
+
changes: info,
|
|
4308
|
+
lastInsertRowid: 0
|
|
4309
|
+
// sql.js doesn't provide this easily
|
|
4310
|
+
};
|
|
5232
4311
|
}
|
|
5233
4312
|
/**
|
|
5234
|
-
*
|
|
4313
|
+
* Query a raw SQL statement
|
|
5235
4314
|
*/
|
|
5236
|
-
|
|
5237
|
-
const stmt = this.
|
|
5238
|
-
|
|
4315
|
+
query(sql, params) {
|
|
4316
|
+
const stmt = this.db.prepare(sql);
|
|
4317
|
+
stmt.bind(params || []);
|
|
4318
|
+
const results = [];
|
|
4319
|
+
while (stmt.step()) {
|
|
4320
|
+
const row = stmt.getAsObject();
|
|
4321
|
+
results.push(row);
|
|
4322
|
+
}
|
|
4323
|
+
stmt.free();
|
|
4324
|
+
return results;
|
|
5239
4325
|
}
|
|
5240
4326
|
/**
|
|
5241
|
-
*
|
|
4327
|
+
* Execute a query and return a single row
|
|
5242
4328
|
*/
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
4329
|
+
queryOne(sql, params) {
|
|
4330
|
+
try {
|
|
4331
|
+
const stmt = this.db.prepare(sql);
|
|
4332
|
+
stmt.bind(params || []);
|
|
4333
|
+
if (stmt.step()) {
|
|
4334
|
+
const row = stmt.getAsObject();
|
|
4335
|
+
stmt.free();
|
|
4336
|
+
return row;
|
|
4337
|
+
}
|
|
4338
|
+
stmt.free();
|
|
4339
|
+
return null;
|
|
4340
|
+
} catch (error) {
|
|
4341
|
+
console.error("Query failed:", error);
|
|
4342
|
+
return null;
|
|
4343
|
+
}
|
|
5246
4344
|
}
|
|
5247
4345
|
/**
|
|
5248
|
-
* Run a transaction
|
|
4346
|
+
* Run a transaction (auto-saves after commit)
|
|
5249
4347
|
*/
|
|
5250
4348
|
transaction(fn) {
|
|
5251
|
-
|
|
4349
|
+
this.db.run("BEGIN TRANSACTION");
|
|
4350
|
+
try {
|
|
4351
|
+
const result = fn(this);
|
|
4352
|
+
this.db.run("COMMIT");
|
|
4353
|
+
this.saveSync();
|
|
4354
|
+
return result;
|
|
4355
|
+
} catch (error) {
|
|
4356
|
+
this.db.run("ROLLBACK");
|
|
4357
|
+
throw error;
|
|
4358
|
+
}
|
|
5252
4359
|
}
|
|
5253
4360
|
/**
|
|
5254
4361
|
* Close database connection
|
|
5255
4362
|
*/
|
|
5256
4363
|
close() {
|
|
5257
|
-
this.
|
|
4364
|
+
this.db.close();
|
|
5258
4365
|
}
|
|
5259
4366
|
/**
|
|
5260
4367
|
* Vacuum database to optimize storage
|
|
5261
4368
|
*/
|
|
5262
4369
|
vacuum() {
|
|
5263
|
-
this.
|
|
4370
|
+
this.db.run("VACUUM");
|
|
5264
4371
|
}
|
|
5265
4372
|
/**
|
|
5266
4373
|
* Get database statistics
|
|
5267
4374
|
*/
|
|
5268
4375
|
getStats() {
|
|
5269
|
-
const pageCount = this.
|
|
5270
|
-
const pageSize = this.
|
|
5271
|
-
const journalMode = this.sqlite.pragma("journal_mode", { simple: true });
|
|
4376
|
+
const pageCount = this.queryOne("PRAGMA page_count");
|
|
4377
|
+
const pageSize = this.queryOne("PRAGMA page_size");
|
|
5272
4378
|
return {
|
|
5273
|
-
pageCount,
|
|
5274
|
-
pageSize,
|
|
5275
|
-
sizeBytes: pageCount * pageSize,
|
|
5276
|
-
walMode:
|
|
4379
|
+
pageCount: pageCount?.page_count || 0,
|
|
4380
|
+
pageSize: pageSize?.page_size || 0,
|
|
4381
|
+
sizeBytes: (pageCount?.page_count || 0) * (pageSize?.page_size || 0),
|
|
4382
|
+
walMode: false
|
|
4383
|
+
// sql.js doesn't support WAL mode
|
|
5277
4384
|
};
|
|
5278
4385
|
}
|
|
5279
|
-
/**
|
|
5280
|
-
* Execute a query and return a single row
|
|
5281
|
-
*/
|
|
5282
|
-
queryOne(sql2, params) {
|
|
5283
|
-
try {
|
|
5284
|
-
const stmt = this.sqlite.prepare(sql2);
|
|
5285
|
-
const result = params ? stmt.get(...params) : stmt.get();
|
|
5286
|
-
return result || null;
|
|
5287
|
-
} catch (error) {
|
|
5288
|
-
console.error("Query failed:", error);
|
|
5289
|
-
return null;
|
|
5290
|
-
}
|
|
5291
|
-
}
|
|
5292
4386
|
/**
|
|
5293
4387
|
* Perform a database health check
|
|
5294
4388
|
*/
|
|
5295
4389
|
async healthCheck() {
|
|
5296
4390
|
try {
|
|
5297
|
-
const result = this.
|
|
5298
|
-
return result === "ok";
|
|
4391
|
+
const result = this.queryOne("PRAGMA integrity_check");
|
|
4392
|
+
return result?.integrity_check === "ok";
|
|
5299
4393
|
} catch (error) {
|
|
5300
4394
|
console.error("Health check failed:", error);
|
|
5301
4395
|
return false;
|
|
@@ -5320,9 +4414,7 @@ function closeDatabaseManager() {
|
|
|
5320
4414
|
}
|
|
5321
4415
|
|
|
5322
4416
|
// src/core/MimirInitializer.ts
|
|
5323
|
-
import
|
|
5324
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5325
|
-
import { dirname as dirname2 } from "path";
|
|
4417
|
+
import path6, { dirname as dirname2 } from "path";
|
|
5326
4418
|
var MimirInitializer = class {
|
|
5327
4419
|
constructor(fs4, configLoader2) {
|
|
5328
4420
|
this.fs = fs4;
|
|
@@ -5341,7 +4433,7 @@ var MimirInitializer = class {
|
|
|
5341
4433
|
configCreated: false
|
|
5342
4434
|
};
|
|
5343
4435
|
try {
|
|
5344
|
-
const mimirDir =
|
|
4436
|
+
const mimirDir = path6.join(workspaceRoot, ".mimir");
|
|
5345
4437
|
if (!await this.fs.exists(mimirDir)) {
|
|
5346
4438
|
await this.fs.mkdir(mimirDir, { recursive: true });
|
|
5347
4439
|
result.created.push(".mimir/");
|
|
@@ -5354,7 +4446,7 @@ var MimirInitializer = class {
|
|
|
5354
4446
|
{ name: "themes", purpose: "UI theme definitions" }
|
|
5355
4447
|
];
|
|
5356
4448
|
for (const { name, purpose } of subdirs) {
|
|
5357
|
-
const subdir =
|
|
4449
|
+
const subdir = path6.join(mimirDir, name);
|
|
5358
4450
|
if (!await this.fs.exists(subdir)) {
|
|
5359
4451
|
await this.fs.mkdir(subdir, { recursive: true });
|
|
5360
4452
|
result.created.push(`.mimir/${name}/`);
|
|
@@ -5380,15 +4472,15 @@ var MimirInitializer = class {
|
|
|
5380
4472
|
* Check if workspace is initialized
|
|
5381
4473
|
*/
|
|
5382
4474
|
async isWorkspaceInitialized(workspaceRoot) {
|
|
5383
|
-
const mimirDir =
|
|
5384
|
-
const dbPath =
|
|
4475
|
+
const mimirDir = path6.join(workspaceRoot, ".mimir");
|
|
4476
|
+
const dbPath = path6.join(mimirDir, "mimir.db");
|
|
5385
4477
|
return await this.fs.exists(mimirDir) && await this.fs.exists(dbPath);
|
|
5386
4478
|
}
|
|
5387
4479
|
/**
|
|
5388
4480
|
* Create .gitignore inside .mimir directory
|
|
5389
4481
|
*/
|
|
5390
4482
|
async createMimirGitignore(mimirDir, result) {
|
|
5391
|
-
const gitignorePath =
|
|
4483
|
+
const gitignorePath = path6.join(mimirDir, ".gitignore");
|
|
5392
4484
|
if (await this.fs.exists(gitignorePath)) {
|
|
5393
4485
|
return;
|
|
5394
4486
|
}
|
|
@@ -5433,7 +4525,7 @@ checkpoints/
|
|
|
5433
4525
|
* Copy default theme files to .mimir/themes/ directory
|
|
5434
4526
|
*/
|
|
5435
4527
|
async copyDefaultThemes(mimirDir, result) {
|
|
5436
|
-
const themesDir =
|
|
4528
|
+
const themesDir = path6.join(mimirDir, "themes");
|
|
5437
4529
|
const defaultThemes = [
|
|
5438
4530
|
"mimir.json",
|
|
5439
4531
|
"dark.json",
|
|
@@ -5442,22 +4534,39 @@ checkpoints/
|
|
|
5442
4534
|
"light-colorblind.json"
|
|
5443
4535
|
];
|
|
5444
4536
|
try {
|
|
5445
|
-
const
|
|
5446
|
-
const
|
|
5447
|
-
const
|
|
4537
|
+
const executablePath = process.argv[0] || process.execPath;
|
|
4538
|
+
const binaryDir = dirname2(executablePath);
|
|
4539
|
+
const possibleSourceDirs = [
|
|
4540
|
+
path6.join(binaryDir, "resources", "themes"),
|
|
4541
|
+
// Compiled binary: ~/.local/bin/resources/themes/
|
|
4542
|
+
path6.join(binaryDir, "../cli/themes"),
|
|
4543
|
+
// Development: dist/core/../cli/themes
|
|
4544
|
+
path6.join(binaryDir, "../../src/cli/themes")
|
|
4545
|
+
// Development: dist/core/../../src/cli/themes
|
|
4546
|
+
];
|
|
5448
4547
|
for (const themeFile of defaultThemes) {
|
|
5449
|
-
const destPath =
|
|
4548
|
+
const destPath = path6.join(themesDir, themeFile);
|
|
5450
4549
|
if (await this.fs.exists(destPath)) {
|
|
5451
4550
|
continue;
|
|
5452
4551
|
}
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
4552
|
+
let copied = false;
|
|
4553
|
+
for (const sourceDir of possibleSourceDirs) {
|
|
4554
|
+
try {
|
|
4555
|
+
const sourcePath = path6.join(sourceDir, themeFile);
|
|
4556
|
+
const themeContent = await this.fs.readFile(sourcePath, "utf-8");
|
|
4557
|
+
await this.fs.writeFile(destPath, themeContent);
|
|
4558
|
+
result.created.push(`.mimir/themes/${themeFile}`);
|
|
4559
|
+
logger.info("Copied default theme", { theme: themeFile, from: sourceDir });
|
|
4560
|
+
copied = true;
|
|
4561
|
+
break;
|
|
4562
|
+
} catch (error) {
|
|
4563
|
+
continue;
|
|
4564
|
+
}
|
|
4565
|
+
}
|
|
4566
|
+
if (!copied) {
|
|
4567
|
+
logger.warn(`Failed to copy theme ${themeFile}, will use built-in fallback`, {
|
|
4568
|
+
triedLocations: possibleSourceDirs
|
|
4569
|
+
});
|
|
5461
4570
|
}
|
|
5462
4571
|
}
|
|
5463
4572
|
} catch (error) {
|
|
@@ -5471,32 +4580,42 @@ checkpoints/
|
|
|
5471
4580
|
* Copy example command files to .mimir/commands/ directory
|
|
5472
4581
|
*/
|
|
5473
4582
|
async copyExampleCommands(mimirDir, result) {
|
|
5474
|
-
const commandsDir =
|
|
5475
|
-
const exampleCommands = [
|
|
5476
|
-
"security.yml",
|
|
5477
|
-
"refactor.yml",
|
|
5478
|
-
"test.yml",
|
|
5479
|
-
"docs.yml",
|
|
5480
|
-
"review.yml",
|
|
5481
|
-
"perf.yml"
|
|
5482
|
-
];
|
|
4583
|
+
const commandsDir = path6.join(mimirDir, "commands");
|
|
4584
|
+
const exampleCommands = ["update-docs.yml"];
|
|
5483
4585
|
try {
|
|
5484
|
-
const
|
|
5485
|
-
const
|
|
5486
|
-
const
|
|
4586
|
+
const executablePath = process.argv[0] || process.execPath;
|
|
4587
|
+
const binaryDir = dirname2(executablePath);
|
|
4588
|
+
const possibleSourceDirs = [
|
|
4589
|
+
path6.join(binaryDir, "resources", "commands"),
|
|
4590
|
+
// Compiled binary: ~/.local/bin/resources/commands/
|
|
4591
|
+
path6.join(binaryDir, "../../scripts/templates/commands"),
|
|
4592
|
+
// Development: dist/core/../../scripts/templates/commands
|
|
4593
|
+
path6.join(binaryDir, "../../../scripts/templates/commands")
|
|
4594
|
+
// Alternative dev path
|
|
4595
|
+
];
|
|
5487
4596
|
for (const commandFile of exampleCommands) {
|
|
5488
|
-
const destPath =
|
|
4597
|
+
const destPath = path6.join(commandsDir, commandFile);
|
|
5489
4598
|
if (await this.fs.exists(destPath)) {
|
|
5490
4599
|
continue;
|
|
5491
4600
|
}
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
4601
|
+
let copied = false;
|
|
4602
|
+
for (const sourceDir of possibleSourceDirs) {
|
|
4603
|
+
try {
|
|
4604
|
+
const sourcePath = path6.join(sourceDir, commandFile);
|
|
4605
|
+
const commandContent = await this.fs.readFile(sourcePath, "utf-8");
|
|
4606
|
+
await this.fs.writeFile(destPath, commandContent);
|
|
4607
|
+
result.created.push(`.mimir/commands/${commandFile}`);
|
|
4608
|
+
logger.info("Copied example command", { command: commandFile, from: sourceDir });
|
|
4609
|
+
copied = true;
|
|
4610
|
+
break;
|
|
4611
|
+
} catch (error) {
|
|
4612
|
+
continue;
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4615
|
+
if (!copied) {
|
|
4616
|
+
logger.warn(`Failed to copy command ${commandFile}, continuing`, {
|
|
4617
|
+
triedLocations: possibleSourceDirs
|
|
4618
|
+
});
|
|
5500
4619
|
}
|
|
5501
4620
|
}
|
|
5502
4621
|
} catch (error) {
|
|
@@ -5510,7 +4629,7 @@ checkpoints/
|
|
|
5510
4629
|
* Initialize SQLite database with Drizzle ORM
|
|
5511
4630
|
*/
|
|
5512
4631
|
async initializeDatabase(mimirDir, result) {
|
|
5513
|
-
const dbPath =
|
|
4632
|
+
const dbPath = path6.join(mimirDir, "mimir.db");
|
|
5514
4633
|
if (await this.fs.exists(dbPath)) {
|
|
5515
4634
|
logger.info("Database already exists, skipping initialization", { path: dbPath });
|
|
5516
4635
|
return;
|
|
@@ -5562,7 +4681,7 @@ checkpoints/
|
|
|
5562
4681
|
* Create config.yml if it doesn't exist
|
|
5563
4682
|
*/
|
|
5564
4683
|
async createConfigIfNeeded(mimirDir, result) {
|
|
5565
|
-
const configPath =
|
|
4684
|
+
const configPath = path6.join(mimirDir, "config.yml");
|
|
5566
4685
|
if (await this.fs.exists(configPath)) {
|
|
5567
4686
|
return;
|
|
5568
4687
|
}
|
|
@@ -5660,7 +4779,7 @@ rateLimit:
|
|
|
5660
4779
|
* Create README in .mimir directory
|
|
5661
4780
|
*/
|
|
5662
4781
|
async createReadme(mimirDir, result) {
|
|
5663
|
-
const readmePath =
|
|
4782
|
+
const readmePath = path6.join(mimirDir, "README.md");
|
|
5664
4783
|
if (await this.fs.exists(readmePath)) {
|
|
5665
4784
|
return;
|
|
5666
4785
|
}
|
|
@@ -5825,7 +4944,7 @@ See the theme documentation for creating custom themes.
|
|
|
5825
4944
|
result.errors.forEach((error) => console.log(` ! ${error}`));
|
|
5826
4945
|
}
|
|
5827
4946
|
console.log("\n\u{1F4C1} Workspace structure:");
|
|
5828
|
-
console.log(` ${
|
|
4947
|
+
console.log(` ${path6.join(workspaceRoot, ".mimir")}`);
|
|
5829
4948
|
console.log(" \u251C\u2500\u2500 config.yml (tracked in git)");
|
|
5830
4949
|
console.log(" \u251C\u2500\u2500 mimir.db (ignored)");
|
|
5831
4950
|
console.log(" \u251C\u2500\u2500 logs/ (ignored)");
|
|
@@ -5845,18 +4964,10 @@ See the theme documentation for creating custom themes.
|
|
|
5845
4964
|
}
|
|
5846
4965
|
};
|
|
5847
4966
|
|
|
5848
|
-
// src/providers/ProviderFactory.ts
|
|
5849
|
-
init_esm_shims();
|
|
5850
|
-
|
|
5851
4967
|
// src/providers/DeepSeekProvider.ts
|
|
5852
|
-
|
|
5853
|
-
import { encoding_for_model } from "tiktoken";
|
|
5854
|
-
|
|
5855
|
-
// src/providers/BaseLLMProvider.ts
|
|
5856
|
-
init_esm_shims();
|
|
4968
|
+
import { encode } from "gpt-tokenizer";
|
|
5857
4969
|
|
|
5858
4970
|
// src/utils/errors.ts
|
|
5859
|
-
init_esm_shims();
|
|
5860
4971
|
var MimirError = class extends Error {
|
|
5861
4972
|
constructor(message) {
|
|
5862
4973
|
super(message);
|
|
@@ -5939,7 +5050,6 @@ var BaseLLMProvider = class {
|
|
|
5939
5050
|
};
|
|
5940
5051
|
|
|
5941
5052
|
// src/providers/utils/apiClient.ts
|
|
5942
|
-
init_esm_shims();
|
|
5943
5053
|
import axios from "axios";
|
|
5944
5054
|
var APIClient = class {
|
|
5945
5055
|
axiosInstance;
|
|
@@ -6047,7 +5157,6 @@ var APIClient = class {
|
|
|
6047
5157
|
};
|
|
6048
5158
|
|
|
6049
5159
|
// src/providers/pricing/pricingData.ts
|
|
6050
|
-
init_esm_shims();
|
|
6051
5160
|
var STATIC_PRICING_TABLE = {
|
|
6052
5161
|
deepseek: {
|
|
6053
5162
|
"deepseek-chat": {
|
|
@@ -6100,7 +5209,6 @@ function getStaticPricing(provider, model) {
|
|
|
6100
5209
|
}
|
|
6101
5210
|
|
|
6102
5211
|
// src/providers/utils/toolFormatters.ts
|
|
6103
|
-
init_esm_shims();
|
|
6104
5212
|
function toOpenAITools(tools) {
|
|
6105
5213
|
return tools.map((tool) => ({
|
|
6106
5214
|
type: "function",
|
|
@@ -6124,8 +5232,8 @@ function toAnthropicTools(tools) {
|
|
|
6124
5232
|
}));
|
|
6125
5233
|
}
|
|
6126
5234
|
function parseOpenAIToolCalls(response) {
|
|
6127
|
-
const
|
|
6128
|
-
return
|
|
5235
|
+
const toolCalls = response.choices?.[0]?.message?.tool_calls || [];
|
|
5236
|
+
return toolCalls.map((tc) => {
|
|
6129
5237
|
let parsedArgs;
|
|
6130
5238
|
try {
|
|
6131
5239
|
parsedArgs = JSON.parse(tc.function.arguments);
|
|
@@ -6180,7 +5288,6 @@ function mapAnthropicFinishReason(reason) {
|
|
|
6180
5288
|
}
|
|
6181
5289
|
|
|
6182
5290
|
// src/providers/utils/streamParsers.ts
|
|
6183
|
-
init_esm_shims();
|
|
6184
5291
|
async function* parseOpenAIStream(stream) {
|
|
6185
5292
|
let buffer = "";
|
|
6186
5293
|
for await (const chunk of stream) {
|
|
@@ -6275,7 +5382,6 @@ async function* parseAnthropicStream(stream) {
|
|
|
6275
5382
|
// src/providers/DeepSeekProvider.ts
|
|
6276
5383
|
var DeepSeekProvider = class extends BaseLLMProvider {
|
|
6277
5384
|
apiClient;
|
|
6278
|
-
encoder;
|
|
6279
5385
|
constructor(config) {
|
|
6280
5386
|
super(config);
|
|
6281
5387
|
const apiKey = config.apiKey || process.env.DEEPSEEK_API_KEY;
|
|
@@ -6293,13 +5399,12 @@ var DeepSeekProvider = class extends BaseLLMProvider {
|
|
|
6293
5399
|
},
|
|
6294
5400
|
timeout: 6e4
|
|
6295
5401
|
});
|
|
6296
|
-
this.encoder = encoding_for_model("gpt-4");
|
|
6297
5402
|
}
|
|
6298
|
-
async chat(
|
|
5403
|
+
async chat(messages, tools) {
|
|
6299
5404
|
return this.withRetry(async () => {
|
|
6300
5405
|
const requestBody = {
|
|
6301
5406
|
model: this.config.model,
|
|
6302
|
-
messages: this.formatMessages(
|
|
5407
|
+
messages: this.formatMessages(messages),
|
|
6303
5408
|
tools: tools ? toOpenAITools(tools) : void 0,
|
|
6304
5409
|
temperature: this.config.temperature,
|
|
6305
5410
|
max_tokens: this.config.maxTokens
|
|
@@ -6311,10 +5416,10 @@ var DeepSeekProvider = class extends BaseLLMProvider {
|
|
|
6311
5416
|
return this.parseResponse(response);
|
|
6312
5417
|
});
|
|
6313
5418
|
}
|
|
6314
|
-
async *streamChat(
|
|
5419
|
+
async *streamChat(messages, tools) {
|
|
6315
5420
|
const requestBody = {
|
|
6316
5421
|
model: this.config.model,
|
|
6317
|
-
messages: this.formatMessages(
|
|
5422
|
+
messages: this.formatMessages(messages),
|
|
6318
5423
|
tools: tools ? toOpenAITools(tools) : void 0,
|
|
6319
5424
|
temperature: this.config.temperature,
|
|
6320
5425
|
max_tokens: this.config.maxTokens,
|
|
@@ -6325,21 +5430,21 @@ var DeepSeekProvider = class extends BaseLLMProvider {
|
|
|
6325
5430
|
yield chunk;
|
|
6326
5431
|
}
|
|
6327
5432
|
}
|
|
6328
|
-
countTokens(
|
|
6329
|
-
return
|
|
5433
|
+
countTokens(text) {
|
|
5434
|
+
return encode(text).length;
|
|
6330
5435
|
}
|
|
6331
5436
|
calculateCost(inputTokens, outputTokens) {
|
|
6332
|
-
const
|
|
6333
|
-
if (!
|
|
5437
|
+
const pricing = getStaticPricing("deepseek", this.config.model);
|
|
5438
|
+
if (!pricing) {
|
|
6334
5439
|
return 0;
|
|
6335
5440
|
}
|
|
6336
|
-
return inputTokens / 1e6 *
|
|
5441
|
+
return inputTokens / 1e6 * pricing.inputPerMillionTokens + outputTokens / 1e6 * pricing.outputPerMillionTokens;
|
|
6337
5442
|
}
|
|
6338
5443
|
/**
|
|
6339
5444
|
* Format messages for OpenAI-compatible API
|
|
6340
5445
|
*/
|
|
6341
|
-
formatMessages(
|
|
6342
|
-
return
|
|
5446
|
+
formatMessages(messages) {
|
|
5447
|
+
return messages.map((msg) => ({
|
|
6343
5448
|
role: msg.role,
|
|
6344
5449
|
content: msg.content,
|
|
6345
5450
|
name: msg.name
|
|
@@ -6369,11 +5474,9 @@ var DeepSeekProvider = class extends BaseLLMProvider {
|
|
|
6369
5474
|
};
|
|
6370
5475
|
|
|
6371
5476
|
// src/providers/AnthropicProvider.ts
|
|
6372
|
-
|
|
6373
|
-
import { encoding_for_model as encoding_for_model2 } from "tiktoken";
|
|
5477
|
+
import { encode as encode2 } from "gpt-tokenizer";
|
|
6374
5478
|
var AnthropicProvider = class extends BaseLLMProvider {
|
|
6375
5479
|
apiClient;
|
|
6376
|
-
encoder;
|
|
6377
5480
|
constructor(config) {
|
|
6378
5481
|
super(config);
|
|
6379
5482
|
const apiKey = config.apiKey || process.env.ANTHROPIC_API_KEY;
|
|
@@ -6392,11 +5495,10 @@ var AnthropicProvider = class extends BaseLLMProvider {
|
|
|
6392
5495
|
},
|
|
6393
5496
|
timeout: 6e4
|
|
6394
5497
|
});
|
|
6395
|
-
this.encoder = encoding_for_model2("gpt-4");
|
|
6396
5498
|
}
|
|
6397
|
-
async chat(
|
|
5499
|
+
async chat(messages, tools) {
|
|
6398
5500
|
return this.withRetry(async () => {
|
|
6399
|
-
const { system, messages: userMessages } = this.formatAnthropicMessages(
|
|
5501
|
+
const { system, messages: userMessages } = this.formatAnthropicMessages(messages);
|
|
6400
5502
|
const requestBody = {
|
|
6401
5503
|
model: this.config.model,
|
|
6402
5504
|
messages: userMessages,
|
|
@@ -6416,8 +5518,8 @@ var AnthropicProvider = class extends BaseLLMProvider {
|
|
|
6416
5518
|
return this.parseResponse(response);
|
|
6417
5519
|
});
|
|
6418
5520
|
}
|
|
6419
|
-
async *streamChat(
|
|
6420
|
-
const { system, messages: userMessages } = this.formatAnthropicMessages(
|
|
5521
|
+
async *streamChat(messages, tools) {
|
|
5522
|
+
const { system, messages: userMessages } = this.formatAnthropicMessages(messages);
|
|
6421
5523
|
const requestBody = {
|
|
6422
5524
|
model: this.config.model,
|
|
6423
5525
|
messages: userMessages,
|
|
@@ -6436,23 +5538,23 @@ var AnthropicProvider = class extends BaseLLMProvider {
|
|
|
6436
5538
|
yield chunk;
|
|
6437
5539
|
}
|
|
6438
5540
|
}
|
|
6439
|
-
countTokens(
|
|
6440
|
-
return
|
|
5541
|
+
countTokens(text) {
|
|
5542
|
+
return encode2(text).length;
|
|
6441
5543
|
}
|
|
6442
5544
|
calculateCost(inputTokens, outputTokens) {
|
|
6443
|
-
const
|
|
6444
|
-
if (!
|
|
5545
|
+
const pricing = getStaticPricing("anthropic", this.config.model);
|
|
5546
|
+
if (!pricing) {
|
|
6445
5547
|
return 0;
|
|
6446
5548
|
}
|
|
6447
|
-
return inputTokens / 1e6 *
|
|
5549
|
+
return inputTokens / 1e6 * pricing.inputPerMillionTokens + outputTokens / 1e6 * pricing.outputPerMillionTokens;
|
|
6448
5550
|
}
|
|
6449
5551
|
/**
|
|
6450
5552
|
* Format messages for Anthropic API
|
|
6451
5553
|
* Extracts system messages into separate parameter
|
|
6452
5554
|
*/
|
|
6453
|
-
formatAnthropicMessages(
|
|
6454
|
-
const systemMessages =
|
|
6455
|
-
const userMessages =
|
|
5555
|
+
formatAnthropicMessages(messages) {
|
|
5556
|
+
const systemMessages = messages.filter((m) => m.role === "system");
|
|
5557
|
+
const userMessages = messages.filter((m) => m.role !== "system");
|
|
6456
5558
|
const system = systemMessages.length > 0 ? systemMessages.map((m) => m.content).join("\n\n") : void 0;
|
|
6457
5559
|
return {
|
|
6458
5560
|
system,
|
|
@@ -6510,7 +5612,7 @@ var ProviderFactory = class {
|
|
|
6510
5612
|
};
|
|
6511
5613
|
|
|
6512
5614
|
// src/cli/commands/ChatCommand.ts
|
|
6513
|
-
import
|
|
5615
|
+
import path7 from "path";
|
|
6514
5616
|
import yaml4 from "yaml";
|
|
6515
5617
|
var ChatCommand = class {
|
|
6516
5618
|
constructor(configLoader2, firstRunDetector2, setupCommand2, fs4) {
|
|
@@ -6562,7 +5664,7 @@ var ChatCommand = class {
|
|
|
6562
5664
|
*/
|
|
6563
5665
|
async saveConfig(projectRoot, config) {
|
|
6564
5666
|
try {
|
|
6565
|
-
const configPath =
|
|
5667
|
+
const configPath = path7.join(projectRoot, ".mimir", "config.yml");
|
|
6566
5668
|
const yamlContent = yaml4.stringify(config);
|
|
6567
5669
|
await this.fs.writeFile(configPath, yamlContent);
|
|
6568
5670
|
logger.info("Config saved", { path: configPath });
|
|
@@ -6574,15 +5676,15 @@ var ChatCommand = class {
|
|
|
6574
5676
|
/**
|
|
6575
5677
|
* Process user message through LLM provider
|
|
6576
5678
|
*/
|
|
6577
|
-
async processMessage(provider,
|
|
5679
|
+
async processMessage(provider, messages, userInput) {
|
|
6578
5680
|
const startTime = Date.now();
|
|
6579
5681
|
try {
|
|
6580
5682
|
const userMessage = {
|
|
6581
5683
|
role: "user",
|
|
6582
5684
|
content: userInput
|
|
6583
5685
|
};
|
|
6584
|
-
|
|
6585
|
-
const response = await provider.chat(
|
|
5686
|
+
messages.push(userMessage);
|
|
5687
|
+
const response = await provider.chat(messages);
|
|
6586
5688
|
const duration = Date.now() - startTime;
|
|
6587
5689
|
const assistantMessage = {
|
|
6588
5690
|
role: "assistant",
|
|
@@ -6596,7 +5698,7 @@ var ChatCommand = class {
|
|
|
6596
5698
|
provider: provider.getProviderName()
|
|
6597
5699
|
}
|
|
6598
5700
|
};
|
|
6599
|
-
|
|
5701
|
+
messages.push(assistantMessage);
|
|
6600
5702
|
return assistantMessage;
|
|
6601
5703
|
} catch (error) {
|
|
6602
5704
|
const duration = Date.now() - startTime;
|
|
@@ -6611,7 +5713,7 @@ var ChatCommand = class {
|
|
|
6611
5713
|
provider: provider.getProviderName()
|
|
6612
5714
|
}
|
|
6613
5715
|
};
|
|
6614
|
-
|
|
5716
|
+
messages.push(errorMessage);
|
|
6615
5717
|
return errorMessage;
|
|
6616
5718
|
}
|
|
6617
5719
|
}
|
|
@@ -7019,35 +6121,484 @@ Available providers: deepseek, anthropic`
|
|
|
7019
6121
|
};
|
|
7020
6122
|
|
|
7021
6123
|
// src/cli/commands/InitCommand.ts
|
|
7022
|
-
init_esm_shims();
|
|
7023
6124
|
var InitCommand = class {
|
|
7024
6125
|
initializer;
|
|
7025
6126
|
constructor(_fs, _configLoader) {
|
|
7026
6127
|
this.initializer = new MimirInitializer(_fs, _configLoader);
|
|
7027
6128
|
}
|
|
7028
|
-
async execute(projectRoot) {
|
|
6129
|
+
async execute(projectRoot, options = {}) {
|
|
7029
6130
|
const root = projectRoot || process.cwd();
|
|
7030
|
-
|
|
6131
|
+
if (!options.quiet) {
|
|
6132
|
+
logger.info("Initializing Mimir workspace", { projectRoot: root });
|
|
6133
|
+
}
|
|
7031
6134
|
if (await this.initializer.isWorkspaceInitialized(root)) {
|
|
7032
|
-
|
|
7033
|
-
|
|
6135
|
+
if (!options.quiet) {
|
|
6136
|
+
logger.info("Mimir workspace is already initialized in this directory.");
|
|
6137
|
+
logger.info('Run "mimir" to start an interactive chat session.');
|
|
6138
|
+
}
|
|
7034
6139
|
return;
|
|
7035
6140
|
}
|
|
7036
6141
|
const result = await this.initializer.initializeWorkspace(root);
|
|
7037
|
-
|
|
6142
|
+
if (!options.quiet) {
|
|
6143
|
+
this.initializer.printSummary(result, root);
|
|
6144
|
+
}
|
|
7038
6145
|
if (!result.success) {
|
|
7039
6146
|
process.exit(1);
|
|
7040
6147
|
}
|
|
7041
6148
|
}
|
|
7042
6149
|
};
|
|
7043
6150
|
|
|
6151
|
+
// src/cli/commands/UninstallCommand.ts
|
|
6152
|
+
import path8 from "path";
|
|
6153
|
+
import os6 from "os";
|
|
6154
|
+
import React11 from "react";
|
|
6155
|
+
import { render as render3, Box as Box12, Text as Text11 } from "ink";
|
|
6156
|
+
import Spinner from "ink-spinner";
|
|
6157
|
+
import TextInput2 from "ink-text-input";
|
|
6158
|
+
var UninstallCommand = class {
|
|
6159
|
+
constructor(fs4, executor2) {
|
|
6160
|
+
this.fs = fs4;
|
|
6161
|
+
this.executor = executor2;
|
|
6162
|
+
}
|
|
6163
|
+
async execute(options = {}) {
|
|
6164
|
+
try {
|
|
6165
|
+
const autoConfirm = options.yes || options.quiet;
|
|
6166
|
+
let confirmed = autoConfirm;
|
|
6167
|
+
if (!autoConfirm) {
|
|
6168
|
+
confirmed = await this.promptConfirmation();
|
|
6169
|
+
}
|
|
6170
|
+
if (!confirmed) {
|
|
6171
|
+
if (!options.quiet) {
|
|
6172
|
+
logger.info("Uninstall cancelled.");
|
|
6173
|
+
}
|
|
6174
|
+
return;
|
|
6175
|
+
}
|
|
6176
|
+
let keepConfig;
|
|
6177
|
+
if (options.removeConfig !== void 0) {
|
|
6178
|
+
keepConfig = !options.removeConfig;
|
|
6179
|
+
} else if (options.keepConfig !== void 0) {
|
|
6180
|
+
keepConfig = options.keepConfig;
|
|
6181
|
+
} else if (autoConfirm) {
|
|
6182
|
+
keepConfig = true;
|
|
6183
|
+
} else {
|
|
6184
|
+
keepConfig = await this.promptKeepConfig();
|
|
6185
|
+
}
|
|
6186
|
+
const result = await this.uninstall(keepConfig, options.quiet);
|
|
6187
|
+
if (!options.quiet) {
|
|
6188
|
+
this.printSummary(result);
|
|
6189
|
+
}
|
|
6190
|
+
if (!result.success) {
|
|
6191
|
+
process.exit(1);
|
|
6192
|
+
}
|
|
6193
|
+
} catch (error) {
|
|
6194
|
+
if (!options.quiet) {
|
|
6195
|
+
logger.error("Uninstall failed", { error });
|
|
6196
|
+
}
|
|
6197
|
+
process.exit(1);
|
|
6198
|
+
}
|
|
6199
|
+
}
|
|
6200
|
+
async promptConfirmation() {
|
|
6201
|
+
return new Promise((resolve) => {
|
|
6202
|
+
const ConfirmPrompt = () => {
|
|
6203
|
+
const [input, setInput] = React11.useState("");
|
|
6204
|
+
const [submitted, setSubmitted] = React11.useState(false);
|
|
6205
|
+
React11.useEffect(() => {
|
|
6206
|
+
if (submitted) {
|
|
6207
|
+
const answer = input.toLowerCase();
|
|
6208
|
+
resolve(answer === "y" || answer === "yes");
|
|
6209
|
+
}
|
|
6210
|
+
}, [submitted, input]);
|
|
6211
|
+
if (submitted) {
|
|
6212
|
+
return null;
|
|
6213
|
+
}
|
|
6214
|
+
return React11.createElement(
|
|
6215
|
+
Box12,
|
|
6216
|
+
{ flexDirection: "column", marginY: 1 },
|
|
6217
|
+
React11.createElement(
|
|
6218
|
+
Box12,
|
|
6219
|
+
{ marginBottom: 1 },
|
|
6220
|
+
React11.createElement(
|
|
6221
|
+
Text11,
|
|
6222
|
+
{ bold: true, color: "yellow" },
|
|
6223
|
+
"\u26A0\uFE0F WARNING: This will uninstall Mimir from your system."
|
|
6224
|
+
)
|
|
6225
|
+
),
|
|
6226
|
+
React11.createElement(
|
|
6227
|
+
Box12,
|
|
6228
|
+
null,
|
|
6229
|
+
React11.createElement(Text11, null, "Are you sure you want to continue? (y/N): "),
|
|
6230
|
+
React11.createElement(TextInput2, {
|
|
6231
|
+
value: input,
|
|
6232
|
+
onChange: setInput,
|
|
6233
|
+
onSubmit: () => setSubmitted(true)
|
|
6234
|
+
})
|
|
6235
|
+
)
|
|
6236
|
+
);
|
|
6237
|
+
};
|
|
6238
|
+
render3(React11.createElement(ConfirmPrompt));
|
|
6239
|
+
});
|
|
6240
|
+
}
|
|
6241
|
+
async promptKeepConfig() {
|
|
6242
|
+
return new Promise((resolve) => {
|
|
6243
|
+
const ConfigPrompt = () => {
|
|
6244
|
+
const [input, setInput] = React11.useState("");
|
|
6245
|
+
const [submitted, setSubmitted] = React11.useState(false);
|
|
6246
|
+
React11.useEffect(() => {
|
|
6247
|
+
if (submitted) {
|
|
6248
|
+
const answer = input.toLowerCase();
|
|
6249
|
+
resolve(answer !== "n" && answer !== "no");
|
|
6250
|
+
}
|
|
6251
|
+
}, [submitted, input]);
|
|
6252
|
+
if (submitted) {
|
|
6253
|
+
return null;
|
|
6254
|
+
}
|
|
6255
|
+
return React11.createElement(
|
|
6256
|
+
Box12,
|
|
6257
|
+
{ flexDirection: "column", marginY: 1 },
|
|
6258
|
+
React11.createElement(
|
|
6259
|
+
Box12,
|
|
6260
|
+
{ marginBottom: 1 },
|
|
6261
|
+
React11.createElement(
|
|
6262
|
+
Text11,
|
|
6263
|
+
null,
|
|
6264
|
+
"Do you want to keep your Mimir configuration and data in ~/.mimir?"
|
|
6265
|
+
)
|
|
6266
|
+
),
|
|
6267
|
+
React11.createElement(
|
|
6268
|
+
Box12,
|
|
6269
|
+
null,
|
|
6270
|
+
React11.createElement(Text11, null, "Keep configuration? (Y/n): "),
|
|
6271
|
+
React11.createElement(TextInput2, {
|
|
6272
|
+
value: input,
|
|
6273
|
+
onChange: setInput,
|
|
6274
|
+
onSubmit: () => setSubmitted(true)
|
|
6275
|
+
})
|
|
6276
|
+
)
|
|
6277
|
+
);
|
|
6278
|
+
};
|
|
6279
|
+
render3(React11.createElement(ConfigPrompt));
|
|
6280
|
+
});
|
|
6281
|
+
}
|
|
6282
|
+
async uninstall(keepConfig, quiet = false) {
|
|
6283
|
+
const result = {
|
|
6284
|
+
success: true,
|
|
6285
|
+
removed: [],
|
|
6286
|
+
errors: [],
|
|
6287
|
+
keepConfig
|
|
6288
|
+
};
|
|
6289
|
+
let clear;
|
|
6290
|
+
if (!quiet) {
|
|
6291
|
+
const UninstallProgress = () => React11.createElement(
|
|
6292
|
+
Box12,
|
|
6293
|
+
null,
|
|
6294
|
+
React11.createElement(
|
|
6295
|
+
Text11,
|
|
6296
|
+
{ color: "cyan" },
|
|
6297
|
+
React11.createElement(Spinner, { type: "dots" }),
|
|
6298
|
+
" Uninstalling Mimir..."
|
|
6299
|
+
)
|
|
6300
|
+
);
|
|
6301
|
+
const rendered = render3(React11.createElement(UninstallProgress));
|
|
6302
|
+
clear = rendered.clear;
|
|
6303
|
+
}
|
|
6304
|
+
try {
|
|
6305
|
+
const homeDir = os6.homedir();
|
|
6306
|
+
const installType = await this.detectInstallType();
|
|
6307
|
+
if (!quiet) {
|
|
6308
|
+
logger.info(`Detected installation type: ${installType}`);
|
|
6309
|
+
}
|
|
6310
|
+
if (installType === "binary") {
|
|
6311
|
+
await this.removeBinaryInstallation(homeDir, result, quiet);
|
|
6312
|
+
}
|
|
6313
|
+
if (installType === "npm") {
|
|
6314
|
+
await this.removeNpmInstallation(result, quiet);
|
|
6315
|
+
}
|
|
6316
|
+
if (!keepConfig) {
|
|
6317
|
+
await this.removeGlobalConfig(homeDir, result, quiet);
|
|
6318
|
+
} else if (!quiet) {
|
|
6319
|
+
logger.info("Keeping global configuration at ~/.mimir");
|
|
6320
|
+
}
|
|
6321
|
+
} catch (error) {
|
|
6322
|
+
result.success = false;
|
|
6323
|
+
result.errors.push(
|
|
6324
|
+
`Uninstall failed: ${error instanceof Error ? error.message : String(error)}`
|
|
6325
|
+
);
|
|
6326
|
+
if (!quiet) {
|
|
6327
|
+
logger.error("Uninstall error", { error });
|
|
6328
|
+
}
|
|
6329
|
+
} finally {
|
|
6330
|
+
if (clear) {
|
|
6331
|
+
clear();
|
|
6332
|
+
}
|
|
6333
|
+
}
|
|
6334
|
+
return result;
|
|
6335
|
+
}
|
|
6336
|
+
async detectInstallType() {
|
|
6337
|
+
try {
|
|
6338
|
+
const scriptPath = process.argv[1];
|
|
6339
|
+
if (!scriptPath) {
|
|
6340
|
+
logger.debug("No script path found in process.argv[1]");
|
|
6341
|
+
return "unknown";
|
|
6342
|
+
}
|
|
6343
|
+
logger.debug(`Detecting install type from script path: ${scriptPath}`);
|
|
6344
|
+
const normalizedPath = path8.normalize(scriptPath).toLowerCase();
|
|
6345
|
+
if (normalizedPath.includes("node_modules")) {
|
|
6346
|
+
logger.debug("Detected npm installation (node_modules in path)");
|
|
6347
|
+
return "npm";
|
|
6348
|
+
}
|
|
6349
|
+
const homeDir = os6.homedir();
|
|
6350
|
+
const mimirBinPath = path8.normalize(path8.join(homeDir, ".mimir", "bin")).toLowerCase();
|
|
6351
|
+
const localBinPath = path8.normalize(path8.join(homeDir, ".local", "bin")).toLowerCase();
|
|
6352
|
+
if (normalizedPath.includes(mimirBinPath)) {
|
|
6353
|
+
logger.debug("Detected binary installation (.mimir/bin in path)");
|
|
6354
|
+
return "binary";
|
|
6355
|
+
}
|
|
6356
|
+
if (normalizedPath.includes(localBinPath)) {
|
|
6357
|
+
logger.debug("Detected binary installation (.local/bin in path)");
|
|
6358
|
+
return "binary";
|
|
6359
|
+
}
|
|
6360
|
+
const binaryPaths = [
|
|
6361
|
+
// Unix binary locations
|
|
6362
|
+
path8.join(homeDir, ".local", "bin", "mimir"),
|
|
6363
|
+
path8.join(homeDir, ".mimir", "bin", "mimir"),
|
|
6364
|
+
// Windows binary locations (.exe, .cmd variants)
|
|
6365
|
+
path8.join(homeDir, ".local", "bin", "mimir.exe"),
|
|
6366
|
+
path8.join(homeDir, ".local", "bin", "mimir.cmd"),
|
|
6367
|
+
path8.join(homeDir, ".mimir", "bin", "mimir.exe"),
|
|
6368
|
+
path8.join(homeDir, ".mimir", "bin", "mimir.cmd")
|
|
6369
|
+
];
|
|
6370
|
+
for (const binPath of binaryPaths) {
|
|
6371
|
+
if (await this.fs.exists(binPath)) {
|
|
6372
|
+
logger.debug(`Detected binary installation (found file at ${binPath})`);
|
|
6373
|
+
return "binary";
|
|
6374
|
+
}
|
|
6375
|
+
}
|
|
6376
|
+
logger.debug("Could not detect installation type - defaulting to unknown");
|
|
6377
|
+
return "unknown";
|
|
6378
|
+
} catch (error) {
|
|
6379
|
+
logger.debug("Error detecting installation type", { error });
|
|
6380
|
+
return "unknown";
|
|
6381
|
+
}
|
|
6382
|
+
}
|
|
6383
|
+
async removeNpmInstallation(result, quiet = false) {
|
|
6384
|
+
if (!this.executor) {
|
|
6385
|
+
if (!quiet) {
|
|
6386
|
+
logger.warn("Cannot automatically uninstall npm package.");
|
|
6387
|
+
logger.info("Please run manually: npm uninstall -g @codedir/mimir-code");
|
|
6388
|
+
}
|
|
6389
|
+
return;
|
|
6390
|
+
}
|
|
6391
|
+
try {
|
|
6392
|
+
if (!quiet) {
|
|
6393
|
+
logger.info("Removing npm global package...");
|
|
6394
|
+
}
|
|
6395
|
+
const npmResult = await this.executor.execute(
|
|
6396
|
+
"npm",
|
|
6397
|
+
["uninstall", "-g", "@codedir/mimir-code"],
|
|
6398
|
+
{
|
|
6399
|
+
cwd: process.cwd()
|
|
6400
|
+
}
|
|
6401
|
+
);
|
|
6402
|
+
if (npmResult.exitCode === 0) {
|
|
6403
|
+
result.removed.push("npm global package (@codedir/mimir-code)");
|
|
6404
|
+
if (!quiet) {
|
|
6405
|
+
logger.info("Successfully uninstalled npm package");
|
|
6406
|
+
}
|
|
6407
|
+
} else {
|
|
6408
|
+
throw new Error(`npm uninstall failed: ${npmResult.stderr}`);
|
|
6409
|
+
}
|
|
6410
|
+
} catch (error) {
|
|
6411
|
+
if (!quiet) {
|
|
6412
|
+
logger.error("Failed to uninstall npm package", { error });
|
|
6413
|
+
logger.info("Please run manually: npm uninstall -g @codedir/mimir-code");
|
|
6414
|
+
}
|
|
6415
|
+
result.errors.push(
|
|
6416
|
+
`npm uninstall failed: ${error instanceof Error ? error.message : String(error)}`
|
|
6417
|
+
);
|
|
6418
|
+
}
|
|
6419
|
+
}
|
|
6420
|
+
async removeBinaryInstallation(homeDir, result, quiet = false) {
|
|
6421
|
+
const isWindows = process.platform === "win32";
|
|
6422
|
+
const localBinPath = path8.join(homeDir, ".local", "bin", "mimir");
|
|
6423
|
+
const mimirBinDir = path8.join(homeDir, ".mimir", "bin");
|
|
6424
|
+
if (isWindows) {
|
|
6425
|
+
await this.spawnWindowsCleanup(localBinPath, mimirBinDir, quiet);
|
|
6426
|
+
await this.removeFromWindowsPath(quiet);
|
|
6427
|
+
result.removed.push("Binary (scheduled for deletion after exit)");
|
|
6428
|
+
result.removed.push("PATH entry");
|
|
6429
|
+
if (!quiet) {
|
|
6430
|
+
logger.info("\u2713 Scheduled binary deletion");
|
|
6431
|
+
logger.info("\u2713 Removed from PATH");
|
|
6432
|
+
logger.warn("\u26A0 Cleanup will complete in ~3 seconds");
|
|
6433
|
+
}
|
|
6434
|
+
} else {
|
|
6435
|
+
if (await this.fs.exists(localBinPath)) {
|
|
6436
|
+
await this.fs.unlink(localBinPath);
|
|
6437
|
+
result.removed.push("~/.local/bin/mimir");
|
|
6438
|
+
if (!quiet) {
|
|
6439
|
+
logger.info("Removed binary from ~/.local/bin");
|
|
6440
|
+
}
|
|
6441
|
+
}
|
|
6442
|
+
if (await this.fs.exists(mimirBinDir)) {
|
|
6443
|
+
await this.fs.rmdir(mimirBinDir, { recursive: true });
|
|
6444
|
+
result.removed.push("~/.mimir/bin/");
|
|
6445
|
+
if (!quiet) {
|
|
6446
|
+
logger.info("Removed binary directory");
|
|
6447
|
+
}
|
|
6448
|
+
}
|
|
6449
|
+
if (!quiet) {
|
|
6450
|
+
logger.info("\u2713 Binary uninstalled");
|
|
6451
|
+
logger.warn("\u26A0 Current terminal still has mimir cached");
|
|
6452
|
+
logger.info(" Run: hash -r (to clear shell cache)");
|
|
6453
|
+
}
|
|
6454
|
+
}
|
|
6455
|
+
}
|
|
6456
|
+
async spawnWindowsCleanup(binPath, binDir, quiet) {
|
|
6457
|
+
if (!this.executor) {
|
|
6458
|
+
if (!quiet) {
|
|
6459
|
+
logger.warn("Cannot spawn cleanup process - no executor available");
|
|
6460
|
+
}
|
|
6461
|
+
return;
|
|
6462
|
+
}
|
|
6463
|
+
try {
|
|
6464
|
+
const cleanupScript = `@echo off
|
|
6465
|
+
REM Wait for parent process to exit
|
|
6466
|
+
timeout /t 3 /nobreak >nul 2>&1
|
|
6467
|
+
|
|
6468
|
+
REM Delete binary if it exists
|
|
6469
|
+
if exist "${binPath}" (
|
|
6470
|
+
del /f /q "${binPath}" >nul 2>&1
|
|
6471
|
+
)
|
|
6472
|
+
if exist "${binPath}.exe" (
|
|
6473
|
+
del /f /q "${binPath}.exe" >nul 2>&1
|
|
6474
|
+
)
|
|
6475
|
+
if exist "${binPath}.cmd" (
|
|
6476
|
+
del /f /q "${binPath}.cmd" >nul 2>&1
|
|
6477
|
+
)
|
|
6478
|
+
|
|
6479
|
+
REM Delete binary directory
|
|
6480
|
+
if exist "${binDir}" (
|
|
6481
|
+
rmdir /s /q "${binDir}" >nul 2>&1
|
|
6482
|
+
)
|
|
6483
|
+
|
|
6484
|
+
REM Delete this cleanup script
|
|
6485
|
+
del /f /q "%~f0" >nul 2>&1
|
|
6486
|
+
`;
|
|
6487
|
+
const tempDir = os6.tmpdir();
|
|
6488
|
+
const cleanupPath = path8.join(tempDir, `mimir-cleanup-${Date.now()}.bat`);
|
|
6489
|
+
await this.fs.writeFile(cleanupPath, cleanupScript);
|
|
6490
|
+
const { spawn } = await import("child_process");
|
|
6491
|
+
const child = spawn("cmd", ["/c", cleanupPath], {
|
|
6492
|
+
detached: true,
|
|
6493
|
+
stdio: "ignore",
|
|
6494
|
+
windowsHide: true
|
|
6495
|
+
});
|
|
6496
|
+
child.unref();
|
|
6497
|
+
if (!quiet) {
|
|
6498
|
+
logger.info("Spawned background cleanup process");
|
|
6499
|
+
}
|
|
6500
|
+
} catch (error) {
|
|
6501
|
+
if (!quiet) {
|
|
6502
|
+
logger.error("Failed to spawn cleanup process", { error });
|
|
6503
|
+
}
|
|
6504
|
+
}
|
|
6505
|
+
}
|
|
6506
|
+
async removeFromWindowsPath(quiet) {
|
|
6507
|
+
if (!this.executor) return;
|
|
6508
|
+
try {
|
|
6509
|
+
const result = await this.executor.execute(
|
|
6510
|
+
"powershell",
|
|
6511
|
+
["-NoProfile", "-Command", '[Environment]::GetEnvironmentVariable("Path", "User")'],
|
|
6512
|
+
{ cwd: process.cwd() }
|
|
6513
|
+
);
|
|
6514
|
+
if (result.exitCode !== 0) {
|
|
6515
|
+
throw new Error("Failed to read PATH");
|
|
6516
|
+
}
|
|
6517
|
+
const currentPath = result.stdout.trim();
|
|
6518
|
+
const pathEntries = currentPath.split(";").filter(Boolean);
|
|
6519
|
+
const filteredEntries = pathEntries.filter((entry) => {
|
|
6520
|
+
const normalizedEntry = path8.normalize(entry.trim()).toLowerCase();
|
|
6521
|
+
return !normalizedEntry.includes("mimir");
|
|
6522
|
+
});
|
|
6523
|
+
if (filteredEntries.length < pathEntries.length) {
|
|
6524
|
+
const newPath = filteredEntries.join(";");
|
|
6525
|
+
await this.executor.execute(
|
|
6526
|
+
"powershell",
|
|
6527
|
+
[
|
|
6528
|
+
"-NoProfile",
|
|
6529
|
+
"-Command",
|
|
6530
|
+
`[Environment]::SetEnvironmentVariable("Path", "${newPath}", "User")`
|
|
6531
|
+
],
|
|
6532
|
+
{ cwd: process.cwd() }
|
|
6533
|
+
);
|
|
6534
|
+
const removedCount = pathEntries.length - filteredEntries.length;
|
|
6535
|
+
if (!quiet) {
|
|
6536
|
+
logger.info(`Removed ${removedCount} PATH entry/entries containing 'mimir'`);
|
|
6537
|
+
}
|
|
6538
|
+
}
|
|
6539
|
+
} catch (error) {
|
|
6540
|
+
if (!quiet) {
|
|
6541
|
+
logger.warn("Failed to remove from PATH", { error });
|
|
6542
|
+
logger.info("You may need to manually remove from PATH");
|
|
6543
|
+
}
|
|
6544
|
+
}
|
|
6545
|
+
}
|
|
6546
|
+
async removeGlobalConfig(homeDir, result, quiet = false) {
|
|
6547
|
+
const mimirDir = path8.join(homeDir, ".mimir");
|
|
6548
|
+
if (await this.fs.exists(mimirDir)) {
|
|
6549
|
+
await this.fs.rmdir(mimirDir, { recursive: true });
|
|
6550
|
+
result.removed.push("~/.mimir/");
|
|
6551
|
+
if (!quiet) {
|
|
6552
|
+
logger.info("Removed configuration directory: ~/.mimir");
|
|
6553
|
+
logger.info("All Mimir data has been deleted.");
|
|
6554
|
+
}
|
|
6555
|
+
}
|
|
6556
|
+
}
|
|
6557
|
+
/* eslint-disable no-console */
|
|
6558
|
+
printSummary(result) {
|
|
6559
|
+
console.log("");
|
|
6560
|
+
console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
6561
|
+
if (result.success) {
|
|
6562
|
+
console.log("\u2705 Mimir has been uninstalled");
|
|
6563
|
+
} else {
|
|
6564
|
+
console.log("\u274C Uninstall completed with errors");
|
|
6565
|
+
}
|
|
6566
|
+
console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
6567
|
+
if (result.removed.length > 0) {
|
|
6568
|
+
console.log("");
|
|
6569
|
+
console.log("Removed:");
|
|
6570
|
+
result.removed.forEach((item) => console.log(` - ${item}`));
|
|
6571
|
+
}
|
|
6572
|
+
if (result.keepConfig) {
|
|
6573
|
+
console.log("");
|
|
6574
|
+
console.log("Configuration preserved:");
|
|
6575
|
+
console.log(" - ~/.mimir/ (your settings and data)");
|
|
6576
|
+
console.log("");
|
|
6577
|
+
console.log("To remove it later, run:");
|
|
6578
|
+
console.log(" mimir uninstall --yes --remove-config");
|
|
6579
|
+
console.log(" or manually: rm -rf ~/.mimir");
|
|
6580
|
+
}
|
|
6581
|
+
if (result.errors.length > 0) {
|
|
6582
|
+
console.log("");
|
|
6583
|
+
console.log("Errors:");
|
|
6584
|
+
result.errors.forEach((error) => console.log(` - ${error}`));
|
|
6585
|
+
}
|
|
6586
|
+
console.log("");
|
|
6587
|
+
console.log("Thank you for using Mimir! \u{1F44B}");
|
|
6588
|
+
console.log("");
|
|
6589
|
+
}
|
|
6590
|
+
/* eslint-enable no-console */
|
|
6591
|
+
};
|
|
6592
|
+
|
|
7044
6593
|
// src/cli.ts
|
|
7045
6594
|
var fs3 = new FileSystemAdapter();
|
|
6595
|
+
var executor = new ProcessExecutorAdapter();
|
|
7046
6596
|
var configLoader = new ConfigLoader(fs3);
|
|
7047
6597
|
var firstRunDetector = new FirstRunDetector(fs3);
|
|
7048
6598
|
var setupCommand = new SetupCommand(configLoader);
|
|
7049
6599
|
var chatCommand = new ChatCommand(configLoader, firstRunDetector, setupCommand, fs3);
|
|
7050
6600
|
var initCommand = new InitCommand(fs3, configLoader);
|
|
6601
|
+
var uninstallCommand = new UninstallCommand(fs3, executor);
|
|
7051
6602
|
var program = new Command();
|
|
7052
6603
|
program.name("mimir").description("Platform-agnostic, BYOK AI coding agent CLI").version("0.1.0");
|
|
7053
6604
|
program.command("setup").description("Run setup wizard").action(async () => {
|
|
@@ -7058,10 +6609,16 @@ program.command("chat", { isDefault: true }).description("Start interactive chat
|
|
|
7058
6609
|
await chatCommand.execute();
|
|
7059
6610
|
process.exit(0);
|
|
7060
6611
|
});
|
|
7061
|
-
program.command("init").description("Initialize Mimir in current project").action(async () => {
|
|
7062
|
-
await initCommand.execute();
|
|
6612
|
+
program.command("init").description("Initialize Mimir in current project").option("--no-interactive", "Run without interactive prompts (for automated setup)").option("-q, --quiet", "Suppress output").action(async (options) => {
|
|
6613
|
+
await initCommand.execute(void 0, options);
|
|
7063
6614
|
process.exit(0);
|
|
7064
6615
|
});
|
|
6616
|
+
program.command("uninstall").description("Uninstall Mimir from your system").option("-y, --yes", "Skip confirmation prompts").option("--keep-config", "Keep configuration directory (~/.mimir)").option("--remove-config", "Remove configuration directory (~/.mimir)").option("-q, --quiet", "Suppress output (implies --yes)").action(
|
|
6617
|
+
async (options) => {
|
|
6618
|
+
await uninstallCommand.execute(options);
|
|
6619
|
+
process.exit(0);
|
|
6620
|
+
}
|
|
6621
|
+
);
|
|
7065
6622
|
var history = program.command("history").description("Manage conversation history");
|
|
7066
6623
|
history.command("list").description("List recent conversations").action(() => {
|
|
7067
6624
|
logger.warn("Listing conversations... (not implemented yet)");
|
|
@@ -7091,15 +6648,15 @@ cost.command("compare").description("Compare provider costs").action(() => {
|
|
|
7091
6648
|
program.command("doctor").description("Run diagnostics").action(() => {
|
|
7092
6649
|
logger.warn("Running diagnostics... (not implemented yet)");
|
|
7093
6650
|
});
|
|
7094
|
-
var
|
|
7095
|
-
|
|
6651
|
+
var permissions = program.command("permissions").description("Manage command permissions");
|
|
6652
|
+
permissions.command("list").description("List allowed commands").action(() => {
|
|
7096
6653
|
logger.warn("Listing permissions... (not implemented yet)");
|
|
7097
6654
|
});
|
|
7098
|
-
|
|
6655
|
+
permissions.command("add <pattern>").description("Add command to allowlist").action((pattern) => {
|
|
7099
6656
|
logger.warn(`Adding ${pattern} to allowlist... (not implemented yet)`);
|
|
7100
6657
|
});
|
|
7101
|
-
|
|
6658
|
+
permissions.command("remove <pattern>").description("Remove command from allowlist").action((pattern) => {
|
|
7102
6659
|
logger.warn(`Removing ${pattern} from allowlist... (not implemented yet)`);
|
|
7103
6660
|
});
|
|
7104
6661
|
program.parse();
|
|
7105
|
-
//# sourceMappingURL=cli.
|
|
6662
|
+
//# sourceMappingURL=cli.mjs.map
|