conare 0.4.3 → 0.4.5
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/dist/index.js +467 -210
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -34,6 +34,27 @@ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync
|
|
|
34
34
|
import { createHash } from "node:crypto";
|
|
35
35
|
import { join as join2 } from "node:path";
|
|
36
36
|
import { homedir as homedir2 } from "node:os";
|
|
37
|
+
function fitContent(header, rounds) {
|
|
38
|
+
const buildContent = (maxUser) => {
|
|
39
|
+
const body = rounds.map((r) => {
|
|
40
|
+
const user = maxUser > 0 && r.user.length > maxUser ? r.user.slice(0, maxUser) + "..." : r.user;
|
|
41
|
+
return `## Q: ${user}
|
|
42
|
+
|
|
43
|
+
${r.assistant}`;
|
|
44
|
+
}).join(`
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
`);
|
|
49
|
+
return `${header}
|
|
50
|
+
|
|
51
|
+
${body}`;
|
|
52
|
+
};
|
|
53
|
+
const full = buildContent(0);
|
|
54
|
+
if (full.length <= MAX_MEMORY_CONTENT)
|
|
55
|
+
return full;
|
|
56
|
+
return buildContent(TRUNCATED_USER_MSG);
|
|
57
|
+
}
|
|
37
58
|
function isNarration(text) {
|
|
38
59
|
const stripped = text.trim();
|
|
39
60
|
if (stripped.length < MIN_SUBSTANTIVE)
|
|
@@ -97,7 +118,7 @@ function clearIngested(source) {
|
|
|
97
118
|
mkdirSync(dir, { recursive: true });
|
|
98
119
|
writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2));
|
|
99
120
|
}
|
|
100
|
-
var MANIFEST_PATH, MIN_SUBSTANTIVE = 200, NARRATION_RE;
|
|
121
|
+
var MANIFEST_PATH, MAX_MEMORY_CONTENT = 200000, TRUNCATED_USER_MSG = 3000, MIN_SUBSTANTIVE = 200, NARRATION_RE;
|
|
101
122
|
var init_shared = __esm(() => {
|
|
102
123
|
MANIFEST_PATH = join2(homedir2(), ".conare", "ingested.json");
|
|
103
124
|
NARRATION_RE = /^[\s\n]*(Let me |Now let me |Now I['\u2019]|Now add |Now fix |Now replace |Now integrate |Now update |Now pass |Now clean |Now build|Update the |Builds clean|Deployed\.|Wait, I |Let['\u2019]s test |Good —|Great\.|Perfect\.|Alright|OK,? let me|I[''\u2019]ll |Starting |I need to |Need |I found |I read |I[''\u2019]ve (loaded|confirmed|verified)|Context loaded|Next (I[''\u2019]|step)|Deps confirm|Diff check|Still missing|I[''\u2019]ll (do|check|inspect|trace|run|grab|pull|read|verify))/;
|
|
@@ -817,6 +838,21 @@ function Y(e, u, t) {
|
|
|
817
838
|
`).map((F) => lD(F, u, t)).join(`
|
|
818
839
|
`);
|
|
819
840
|
}
|
|
841
|
+
function cD(e) {
|
|
842
|
+
for (const u in e) {
|
|
843
|
+
const t = u;
|
|
844
|
+
if (!Object.hasOwn(e, t))
|
|
845
|
+
continue;
|
|
846
|
+
const F = e[t];
|
|
847
|
+
switch (t) {
|
|
848
|
+
case "aliases": {
|
|
849
|
+
for (const s in F)
|
|
850
|
+
Object.hasOwn(F, s) && (B.aliases.has(s) || B.aliases.set(s, F[s]));
|
|
851
|
+
break;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
820
856
|
function $(e, u) {
|
|
821
857
|
if (typeof e == "string")
|
|
822
858
|
return B.aliases.get(e) === u;
|
|
@@ -1024,7 +1060,14 @@ var import_sisteransi, import_picocolors, uD, W, tD, eD, FD = function() {
|
|
|
1024
1060
|
` && (s && o && (F += z(s)), i && (F += K(i)));
|
|
1025
1061
|
}
|
|
1026
1062
|
return F;
|
|
1027
|
-
}, xD, B, AD, S, gD, vD = (e, u, t) => (u in e) ? gD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, h = (e, u, t) => (vD(e, typeof u != "symbol" ? u + "" : u, t), t), dD,
|
|
1063
|
+
}, xD, B, AD, S, gD, vD = (e, u, t) => (u in e) ? gD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, h = (e, u, t) => (vD(e, typeof u != "symbol" ? u + "" : u, t), t), dD, mD, bD = (e, u, t) => (u in e) ? mD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, Z = (e, u, t) => (bD(e, typeof u != "symbol" ? u + "" : u, t), t), q = (e, u, t) => {
|
|
1064
|
+
if (!u.has(e))
|
|
1065
|
+
throw TypeError("Cannot " + t);
|
|
1066
|
+
}, T = (e, u, t) => (q(e, u, "read from private field"), t ? t.call(e) : u.get(e)), wD = (e, u, t) => {
|
|
1067
|
+
if (u.has(e))
|
|
1068
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
1069
|
+
u instanceof WeakSet ? u.add(e) : u.set(e, t);
|
|
1070
|
+
}, yD = (e, u, t, F) => (q(e, u, "write to private field"), F ? F.call(e, t) : u.set(e, t), t), A, _D, kD, $D = (e, u, t) => (u in e) ? kD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, H = (e, u, t) => ($D(e, typeof u != "symbol" ? u + "" : u, t), t), SD, TD, jD = (e, u, t) => (u in e) ? TD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, U = (e, u, t) => (jD(e, typeof u != "symbol" ? u + "" : u, t), t), MD, OD, PD = (e, u, t) => (u in e) ? OD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, J = (e, u, t) => (PD(e, typeof u != "symbol" ? u + "" : u, t), t), LD, WD, ND = (e, u, t) => (u in e) ? WD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t, Q = (e, u, t) => (ND(e, typeof u != "symbol" ? u + "" : u, t), t), ID, RD;
|
|
1028
1071
|
var init_dist = __esm(() => {
|
|
1029
1072
|
import_sisteransi = __toESM(require_src(), 1);
|
|
1030
1073
|
import_picocolors = __toESM(require_picocolors(), 1);
|
|
@@ -1093,6 +1136,50 @@ var init_dist = __esm(() => {
|
|
|
1093
1136
|
});
|
|
1094
1137
|
}
|
|
1095
1138
|
};
|
|
1139
|
+
mD = Object.defineProperty;
|
|
1140
|
+
_D = class extends x {
|
|
1141
|
+
constructor(u) {
|
|
1142
|
+
super(u, false), Z(this, "options"), Z(this, "cursor", 0), wD(this, A, undefined);
|
|
1143
|
+
const { options: t } = u;
|
|
1144
|
+
yD(this, A, u.selectableGroups !== false), this.options = Object.entries(t).flatMap(([F, s]) => [{ value: F, group: true, label: F }, ...s.map((i) => ({ ...i, group: F }))]), this.value = [...u.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: F }) => F === u.cursorAt), T(this, A) ? 0 : 1), this.on("cursor", (F) => {
|
|
1145
|
+
switch (F) {
|
|
1146
|
+
case "left":
|
|
1147
|
+
case "up": {
|
|
1148
|
+
this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
|
|
1149
|
+
const s = this.options[this.cursor]?.group === true;
|
|
1150
|
+
!T(this, A) && s && (this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1);
|
|
1151
|
+
break;
|
|
1152
|
+
}
|
|
1153
|
+
case "down":
|
|
1154
|
+
case "right": {
|
|
1155
|
+
this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
|
|
1156
|
+
const s = this.options[this.cursor]?.group === true;
|
|
1157
|
+
!T(this, A) && s && (this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1);
|
|
1158
|
+
break;
|
|
1159
|
+
}
|
|
1160
|
+
case "space":
|
|
1161
|
+
this.toggleValue();
|
|
1162
|
+
break;
|
|
1163
|
+
}
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
getGroupItems(u) {
|
|
1167
|
+
return this.options.filter((t) => t.group === u);
|
|
1168
|
+
}
|
|
1169
|
+
isGroupSelected(u) {
|
|
1170
|
+
return this.getGroupItems(u).every((t) => this.value.includes(t.value));
|
|
1171
|
+
}
|
|
1172
|
+
toggleValue() {
|
|
1173
|
+
const u = this.options[this.cursor];
|
|
1174
|
+
if (u.group === true) {
|
|
1175
|
+
const t = u.value, F = this.getGroupItems(t);
|
|
1176
|
+
this.isGroupSelected(t) ? this.value = this.value.filter((s) => F.findIndex((i) => i.value === s) === -1) : this.value = [...this.value, ...F.map((s) => s.value)], this.value = Array.from(new Set(this.value));
|
|
1177
|
+
} else {
|
|
1178
|
+
const t = this.value.includes(u.value);
|
|
1179
|
+
this.value = t ? this.value.filter((F) => F !== u.value) : [...this.value, u.value];
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
};
|
|
1096
1183
|
A = new WeakMap;
|
|
1097
1184
|
kD = Object.defineProperty;
|
|
1098
1185
|
SD = class extends x {
|
|
@@ -1172,15 +1259,67 @@ var init_dist = __esm(() => {
|
|
|
1172
1259
|
this.value = this._value.value;
|
|
1173
1260
|
}
|
|
1174
1261
|
};
|
|
1262
|
+
WD = Object.defineProperty;
|
|
1263
|
+
ID = class ID extends x {
|
|
1264
|
+
constructor(u) {
|
|
1265
|
+
super(u, false), Q(this, "options"), Q(this, "cursor", 0), this.options = u.options;
|
|
1266
|
+
const t = this.options.map(({ value: [F] }) => F?.toLowerCase());
|
|
1267
|
+
this.cursor = Math.max(t.indexOf(u.initialValue), 0), this.on("key", (F) => {
|
|
1268
|
+
if (!t.includes(F))
|
|
1269
|
+
return;
|
|
1270
|
+
const s = this.options.find(({ value: [i] }) => i?.toLowerCase() === F);
|
|
1271
|
+
s && (this.value = s.value, this.state = "submit", this.emit("submit"));
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
RD = class RD extends x {
|
|
1276
|
+
get valueWithCursor() {
|
|
1277
|
+
if (this.state === "submit")
|
|
1278
|
+
return this.value;
|
|
1279
|
+
if (this.cursor >= this.value.length)
|
|
1280
|
+
return `${this.value}█`;
|
|
1281
|
+
const u = this.value.slice(0, this.cursor), [t, ...F] = this.value.slice(this.cursor);
|
|
1282
|
+
return `${u}${import_picocolors.default.inverse(t)}${F.join("")}`;
|
|
1283
|
+
}
|
|
1284
|
+
get cursor() {
|
|
1285
|
+
return this._cursor;
|
|
1286
|
+
}
|
|
1287
|
+
constructor(u) {
|
|
1288
|
+
super(u), this.on("finalize", () => {
|
|
1289
|
+
this.value || (this.value = u.defaultValue);
|
|
1290
|
+
});
|
|
1291
|
+
}
|
|
1292
|
+
};
|
|
1175
1293
|
});
|
|
1176
1294
|
|
|
1177
1295
|
// node_modules/@clack/prompts/dist/index.mjs
|
|
1296
|
+
var exports_dist = {};
|
|
1297
|
+
__export(exports_dist, {
|
|
1298
|
+
updateSettings: () => cD,
|
|
1299
|
+
text: () => he,
|
|
1300
|
+
tasks: () => Te,
|
|
1301
|
+
stream: () => x2,
|
|
1302
|
+
spinner: () => Y2,
|
|
1303
|
+
selectKey: () => we,
|
|
1304
|
+
select: () => ve,
|
|
1305
|
+
password: () => ge,
|
|
1306
|
+
outro: () => Se,
|
|
1307
|
+
note: () => Me,
|
|
1308
|
+
multiselect: () => fe,
|
|
1309
|
+
log: () => M2,
|
|
1310
|
+
isCancel: () => pD,
|
|
1311
|
+
intro: () => Ie,
|
|
1312
|
+
groupMultiselect: () => be,
|
|
1313
|
+
group: () => Ce,
|
|
1314
|
+
confirm: () => ye,
|
|
1315
|
+
cancel: () => xe
|
|
1316
|
+
});
|
|
1178
1317
|
import { stripVTControlCharacters as S2 } from "node:util";
|
|
1179
1318
|
import y2 from "node:process";
|
|
1180
1319
|
function ce() {
|
|
1181
1320
|
return y2.platform !== "win32" ? y2.env.TERM !== "linux" : !!y2.env.CI || !!y2.env.WT_SESSION || !!y2.env.TERMINUS_SUBLIME || y2.env.ConEmuTask === "{cmd::Cmder}" || y2.env.TERM_PROGRAM === "Terminus-Sublime" || y2.env.TERM_PROGRAM === "vscode" || y2.env.TERM === "xterm-256color" || y2.env.TERM === "alacritty" || y2.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
1182
1321
|
}
|
|
1183
|
-
var import_picocolors2, import_sisteransi2, V2, u = (t, n) => V2 ? t : n, le, L2, W2, C, ue, o, d2, k2, P2, A2,
|
|
1322
|
+
var import_picocolors2, import_sisteransi2, V2, u = (t, n) => V2 ? t : n, le, L2, W2, C, ue, o, d2, k2, P2, A2, T2, F, $e, _2, me, de, pe, q2, D, U2, K2, b2 = (t) => {
|
|
1184
1323
|
switch (t) {
|
|
1185
1324
|
case "initial":
|
|
1186
1325
|
case "active":
|
|
@@ -1201,7 +1340,27 @@ var import_picocolors2, import_sisteransi2, V2, u = (t, n) => V2 ? t : n, le, L2
|
|
|
1201
1340
|
const j2 = v2 === 0 && $2, E = v2 === f.length - 1 && g2;
|
|
1202
1341
|
return j2 || E ? import_picocolors2.default.dim("...") : i(p2, v2 + l2 === n);
|
|
1203
1342
|
});
|
|
1204
|
-
},
|
|
1343
|
+
}, he = (t) => new RD({ validate: t.validate, placeholder: t.placeholder, defaultValue: t.defaultValue, initialValue: t.initialValue, render() {
|
|
1344
|
+
const n = `${import_picocolors2.default.gray(o)}
|
|
1345
|
+
${b2(this.state)} ${t.message}
|
|
1346
|
+
`, r2 = t.placeholder ? import_picocolors2.default.inverse(t.placeholder[0]) + import_picocolors2.default.dim(t.placeholder.slice(1)) : import_picocolors2.default.inverse(import_picocolors2.default.hidden("_")), i = this.value ? this.valueWithCursor : r2;
|
|
1347
|
+
switch (this.state) {
|
|
1348
|
+
case "error":
|
|
1349
|
+
return `${n.trim()}
|
|
1350
|
+
${import_picocolors2.default.yellow(o)} ${i}
|
|
1351
|
+
${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(this.error)}
|
|
1352
|
+
`;
|
|
1353
|
+
case "submit":
|
|
1354
|
+
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(this.value || t.placeholder)}`;
|
|
1355
|
+
case "cancel":
|
|
1356
|
+
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(this.value ?? ""))}${this.value?.trim() ? `
|
|
1357
|
+
${import_picocolors2.default.gray(o)}` : ""}`;
|
|
1358
|
+
default:
|
|
1359
|
+
return `${n}${import_picocolors2.default.cyan(o)} ${i}
|
|
1360
|
+
${import_picocolors2.default.cyan(d2)}
|
|
1361
|
+
`;
|
|
1362
|
+
}
|
|
1363
|
+
} }).prompt(), ge = (t) => new MD({ validate: t.validate, mask: t.mask ?? $e, render() {
|
|
1205
1364
|
const n = `${import_picocolors2.default.gray(o)}
|
|
1206
1365
|
${b2(this.state)} ${t.message}
|
|
1207
1366
|
`, r2 = this.valueWithCursor, i = this.masked;
|
|
@@ -1267,13 +1426,35 @@ ${import_picocolors2.default.gray(o)}`;
|
|
|
1267
1426
|
return `${r2}${import_picocolors2.default.cyan(o)} ${G2({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (i, s) => n(i, s ? "active" : "inactive") }).join(`
|
|
1268
1427
|
${import_picocolors2.default.cyan(o)} `)}
|
|
1269
1428
|
${import_picocolors2.default.cyan(d2)}
|
|
1429
|
+
`;
|
|
1430
|
+
}
|
|
1431
|
+
} }).prompt();
|
|
1432
|
+
}, we = (t) => {
|
|
1433
|
+
const n = (r2, i = "inactive") => {
|
|
1434
|
+
const s = r2.label ?? String(r2.value);
|
|
1435
|
+
return i === "selected" ? `${import_picocolors2.default.dim(s)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}` : i === "active" ? `${import_picocolors2.default.bgCyan(import_picocolors2.default.gray(` ${r2.value} `))} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : `${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(` ${r2.value} `)))} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}`;
|
|
1436
|
+
};
|
|
1437
|
+
return new ID({ options: t.options, initialValue: t.initialValue, render() {
|
|
1438
|
+
const r2 = `${import_picocolors2.default.gray(o)}
|
|
1439
|
+
${b2(this.state)} ${t.message}
|
|
1440
|
+
`;
|
|
1441
|
+
switch (this.state) {
|
|
1442
|
+
case "submit":
|
|
1443
|
+
return `${r2}${import_picocolors2.default.gray(o)} ${n(this.options.find((i) => i.value === this.value) ?? t.options[0], "selected")}`;
|
|
1444
|
+
case "cancel":
|
|
1445
|
+
return `${r2}${import_picocolors2.default.gray(o)} ${n(this.options[0], "cancelled")}
|
|
1446
|
+
${import_picocolors2.default.gray(o)}`;
|
|
1447
|
+
default:
|
|
1448
|
+
return `${r2}${import_picocolors2.default.cyan(o)} ${this.options.map((i, s) => n(i, s === this.cursor ? "active" : "inactive")).join(`
|
|
1449
|
+
${import_picocolors2.default.cyan(o)} `)}
|
|
1450
|
+
${import_picocolors2.default.cyan(d2)}
|
|
1270
1451
|
`;
|
|
1271
1452
|
}
|
|
1272
1453
|
} }).prompt();
|
|
1273
1454
|
}, fe = (t) => {
|
|
1274
1455
|
const n = (r2, i) => {
|
|
1275
1456
|
const s = r2.label ?? String(r2.value);
|
|
1276
|
-
return i === "active" ? `${import_picocolors2.default.cyan(A2)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(
|
|
1457
|
+
return i === "active" ? `${import_picocolors2.default.cyan(A2)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(T2)} ${import_picocolors2.default.dim(s)} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}` : i === "active-selected" ? `${import_picocolors2.default.green(T2)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(s)}` : `${import_picocolors2.default.dim(F)} ${import_picocolors2.default.dim(s)}`;
|
|
1277
1458
|
};
|
|
1278
1459
|
return new SD({ options: t.options, initialValues: t.initialValues, required: t.required ?? true, cursorAt: t.cursorAt, validate(r2) {
|
|
1279
1460
|
if (this.required && r2.length === 0)
|
|
@@ -1307,6 +1488,66 @@ ${s}
|
|
|
1307
1488
|
return `${r2}${import_picocolors2.default.cyan(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
|
|
1308
1489
|
${import_picocolors2.default.cyan(o)} `)}
|
|
1309
1490
|
${import_picocolors2.default.cyan(d2)}
|
|
1491
|
+
`;
|
|
1492
|
+
}
|
|
1493
|
+
} }).prompt();
|
|
1494
|
+
}, be = (t) => {
|
|
1495
|
+
const { selectableGroups: n = true } = t, r2 = (i, s, c = []) => {
|
|
1496
|
+
const a = i.label ?? String(i.value), l2 = typeof i.group == "string", $2 = l2 && (c[c.indexOf(i) + 1] ?? { group: true }), g2 = l2 && $2.group === true, p2 = l2 ? n ? `${g2 ? d2 : o} ` : " " : "";
|
|
1497
|
+
if (s === "active")
|
|
1498
|
+
return `${import_picocolors2.default.dim(p2)}${import_picocolors2.default.cyan(A2)} ${a} ${i.hint ? import_picocolors2.default.dim(`(${i.hint})`) : ""}`;
|
|
1499
|
+
if (s === "group-active")
|
|
1500
|
+
return `${p2}${import_picocolors2.default.cyan(A2)} ${import_picocolors2.default.dim(a)}`;
|
|
1501
|
+
if (s === "group-active-selected")
|
|
1502
|
+
return `${p2}${import_picocolors2.default.green(T2)} ${import_picocolors2.default.dim(a)}`;
|
|
1503
|
+
if (s === "selected") {
|
|
1504
|
+
const f = l2 || n ? import_picocolors2.default.green(T2) : "";
|
|
1505
|
+
return `${import_picocolors2.default.dim(p2)}${f} ${import_picocolors2.default.dim(a)} ${i.hint ? import_picocolors2.default.dim(`(${i.hint})`) : ""}`;
|
|
1506
|
+
}
|
|
1507
|
+
if (s === "cancelled")
|
|
1508
|
+
return `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(a))}`;
|
|
1509
|
+
if (s === "active-selected")
|
|
1510
|
+
return `${import_picocolors2.default.dim(p2)}${import_picocolors2.default.green(T2)} ${a} ${i.hint ? import_picocolors2.default.dim(`(${i.hint})`) : ""}`;
|
|
1511
|
+
if (s === "submitted")
|
|
1512
|
+
return `${import_picocolors2.default.dim(a)}`;
|
|
1513
|
+
const v2 = l2 || n ? import_picocolors2.default.dim(F) : "";
|
|
1514
|
+
return `${import_picocolors2.default.dim(p2)}${v2} ${import_picocolors2.default.dim(a)}`;
|
|
1515
|
+
};
|
|
1516
|
+
return new _D({ options: t.options, initialValues: t.initialValues, required: t.required ?? true, cursorAt: t.cursorAt, selectableGroups: n, validate(i) {
|
|
1517
|
+
if (this.required && i.length === 0)
|
|
1518
|
+
return `Please select at least one option.
|
|
1519
|
+
${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" space ")))} to select, ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" enter ")))} to submit`))}`;
|
|
1520
|
+
}, render() {
|
|
1521
|
+
const i = `${import_picocolors2.default.gray(o)}
|
|
1522
|
+
${b2(this.state)} ${t.message}
|
|
1523
|
+
`;
|
|
1524
|
+
switch (this.state) {
|
|
1525
|
+
case "submit":
|
|
1526
|
+
return `${i}${import_picocolors2.default.gray(o)} ${this.options.filter(({ value: s }) => this.value.includes(s)).map((s) => r2(s, "submitted")).join(import_picocolors2.default.dim(", "))}`;
|
|
1527
|
+
case "cancel": {
|
|
1528
|
+
const s = this.options.filter(({ value: c }) => this.value.includes(c)).map((c) => r2(c, "cancelled")).join(import_picocolors2.default.dim(", "));
|
|
1529
|
+
return `${i}${import_picocolors2.default.gray(o)} ${s.trim() ? `${s}
|
|
1530
|
+
${import_picocolors2.default.gray(o)}` : ""}`;
|
|
1531
|
+
}
|
|
1532
|
+
case "error": {
|
|
1533
|
+
const s = this.error.split(`
|
|
1534
|
+
`).map((c, a) => a === 0 ? `${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(c)}` : ` ${c}`).join(`
|
|
1535
|
+
`);
|
|
1536
|
+
return `${i}${import_picocolors2.default.yellow(o)} ${this.options.map((c, a, l2) => {
|
|
1537
|
+
const $2 = this.value.includes(c.value) || c.group === true && this.isGroupSelected(`${c.value}`), g2 = a === this.cursor;
|
|
1538
|
+
return !g2 && typeof c.group == "string" && this.options[this.cursor].value === c.group ? r2(c, $2 ? "group-active-selected" : "group-active", l2) : g2 && $2 ? r2(c, "active-selected", l2) : $2 ? r2(c, "selected", l2) : r2(c, g2 ? "active" : "inactive", l2);
|
|
1539
|
+
}).join(`
|
|
1540
|
+
${import_picocolors2.default.yellow(o)} `)}
|
|
1541
|
+
${s}
|
|
1542
|
+
`;
|
|
1543
|
+
}
|
|
1544
|
+
default:
|
|
1545
|
+
return `${i}${import_picocolors2.default.cyan(o)} ${this.options.map((s, c, a) => {
|
|
1546
|
+
const l2 = this.value.includes(s.value) || s.group === true && this.isGroupSelected(`${s.value}`), $2 = c === this.cursor;
|
|
1547
|
+
return !$2 && typeof s.group == "string" && this.options[this.cursor].value === s.group ? r2(s, l2 ? "group-active-selected" : "group-active", a) : $2 && l2 ? r2(s, "active-selected", a) : l2 ? r2(s, "selected", a) : r2(s, $2 ? "active" : "inactive", a);
|
|
1548
|
+
}).join(`
|
|
1549
|
+
${import_picocolors2.default.cyan(o)} `)}
|
|
1550
|
+
${import_picocolors2.default.cyan(d2)}
|
|
1310
1551
|
`;
|
|
1311
1552
|
}
|
|
1312
1553
|
} }).prompt();
|
|
@@ -1336,7 +1577,7 @@ ${import_picocolors2.default.gray(de + _2.repeat(s + 2) + pe)}
|
|
|
1336
1577
|
${import_picocolors2.default.gray(d2)} ${t}
|
|
1337
1578
|
|
|
1338
1579
|
`);
|
|
1339
|
-
}, J2, Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
1580
|
+
}, M2, J2, x2, Y2 = ({ indicator: t = "dots" } = {}) => {
|
|
1340
1581
|
const n = V2 ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"], r2 = V2 ? 80 : 120, i = process.env.CI === "true";
|
|
1341
1582
|
let s, c, a = false, l2 = "", $2, g2 = performance.now();
|
|
1342
1583
|
const p2 = (m2) => {
|
|
@@ -1386,6 +1627,28 @@ ${import_picocolors2.default.gray(d2)} ${t}
|
|
|
1386
1627
|
return { start: H2, stop: N2, message: (m2 = "") => {
|
|
1387
1628
|
l2 = R2(m2 ?? l2);
|
|
1388
1629
|
} };
|
|
1630
|
+
}, Ce = async (t, n) => {
|
|
1631
|
+
const r2 = {}, i = Object.keys(t);
|
|
1632
|
+
for (const s of i) {
|
|
1633
|
+
const c = t[s], a = await c({ results: r2 })?.catch((l2) => {
|
|
1634
|
+
throw l2;
|
|
1635
|
+
});
|
|
1636
|
+
if (typeof n?.onCancel == "function" && pD(a)) {
|
|
1637
|
+
r2[s] = "canceled", n.onCancel({ results: r2 });
|
|
1638
|
+
continue;
|
|
1639
|
+
}
|
|
1640
|
+
r2[s] = a;
|
|
1641
|
+
}
|
|
1642
|
+
return r2;
|
|
1643
|
+
}, Te = async (t) => {
|
|
1644
|
+
for (const n of t) {
|
|
1645
|
+
if (n.enabled === false)
|
|
1646
|
+
continue;
|
|
1647
|
+
const r2 = Y2();
|
|
1648
|
+
r2.start(n.title);
|
|
1649
|
+
const i = await n.task(r2.message);
|
|
1650
|
+
r2.stop(i || n.title);
|
|
1651
|
+
}
|
|
1389
1652
|
};
|
|
1390
1653
|
var init_dist2 = __esm(() => {
|
|
1391
1654
|
init_dist();
|
|
@@ -1403,18 +1666,57 @@ var init_dist2 = __esm(() => {
|
|
|
1403
1666
|
k2 = u("●", ">");
|
|
1404
1667
|
P2 = u("○", " ");
|
|
1405
1668
|
A2 = u("◻", "[•]");
|
|
1406
|
-
|
|
1669
|
+
T2 = u("◼", "[+]");
|
|
1407
1670
|
F = u("◻", "[ ]");
|
|
1408
1671
|
$e = u("▪", "•");
|
|
1409
1672
|
_2 = u("─", "-");
|
|
1410
1673
|
me = u("╮", "+");
|
|
1411
1674
|
de = u("├", "+");
|
|
1412
1675
|
pe = u("╯", "+");
|
|
1413
|
-
|
|
1676
|
+
q2 = u("●", "•");
|
|
1414
1677
|
D = u("◆", "*");
|
|
1415
1678
|
U2 = u("▲", "!");
|
|
1416
1679
|
K2 = u("■", "x");
|
|
1680
|
+
M2 = { message: (t = "", { symbol: n = import_picocolors2.default.gray(o) } = {}) => {
|
|
1681
|
+
const r2 = [`${import_picocolors2.default.gray(o)}`];
|
|
1682
|
+
if (t) {
|
|
1683
|
+
const [i, ...s] = t.split(`
|
|
1684
|
+
`);
|
|
1685
|
+
r2.push(`${n} ${i}`, ...s.map((c) => `${import_picocolors2.default.gray(o)} ${c}`));
|
|
1686
|
+
}
|
|
1687
|
+
process.stdout.write(`${r2.join(`
|
|
1688
|
+
`)}
|
|
1689
|
+
`);
|
|
1690
|
+
}, info: (t) => {
|
|
1691
|
+
M2.message(t, { symbol: import_picocolors2.default.blue(q2) });
|
|
1692
|
+
}, success: (t) => {
|
|
1693
|
+
M2.message(t, { symbol: import_picocolors2.default.green(D) });
|
|
1694
|
+
}, step: (t) => {
|
|
1695
|
+
M2.message(t, { symbol: import_picocolors2.default.green(C) });
|
|
1696
|
+
}, warn: (t) => {
|
|
1697
|
+
M2.message(t, { symbol: import_picocolors2.default.yellow(U2) });
|
|
1698
|
+
}, warning: (t) => {
|
|
1699
|
+
M2.warn(t);
|
|
1700
|
+
}, error: (t) => {
|
|
1701
|
+
M2.message(t, { symbol: import_picocolors2.default.red(K2) });
|
|
1702
|
+
} };
|
|
1417
1703
|
J2 = `${import_picocolors2.default.gray(o)} `;
|
|
1704
|
+
x2 = { message: async (t, { symbol: n = import_picocolors2.default.gray(o) } = {}) => {
|
|
1705
|
+
process.stdout.write(`${import_picocolors2.default.gray(o)}
|
|
1706
|
+
${n} `);
|
|
1707
|
+
let r2 = 3;
|
|
1708
|
+
for await (let i of t) {
|
|
1709
|
+
i = i.replace(/\n/g, `
|
|
1710
|
+
${J2}`), i.includes(`
|
|
1711
|
+
`) && (r2 = 3 + S2(i.slice(i.lastIndexOf(`
|
|
1712
|
+
`))).length);
|
|
1713
|
+
const s = S2(i).length;
|
|
1714
|
+
r2 + s < process.stdout.columns ? (r2 += s, process.stdout.write(i)) : (process.stdout.write(`
|
|
1715
|
+
${J2}${i.trimStart()}`), r2 = 3 + S2(i.trimStart()).length);
|
|
1716
|
+
}
|
|
1717
|
+
process.stdout.write(`
|
|
1718
|
+
`);
|
|
1719
|
+
}, info: (t) => x2.message(t, { symbol: import_picocolors2.default.blue(q2) }), success: (t) => x2.message(t, { symbol: import_picocolors2.default.green(D) }), step: (t) => x2.message(t, { symbol: import_picocolors2.default.green(C) }), warn: (t) => x2.message(t, { symbol: import_picocolors2.default.yellow(U2) }), warning: (t) => x2.warn(t), error: (t) => x2.message(t, { symbol: import_picocolors2.default.red(K2) }) };
|
|
1418
1720
|
});
|
|
1419
1721
|
|
|
1420
1722
|
// src/interactive.ts
|
|
@@ -1428,7 +1730,6 @@ __export(exports_interactive, {
|
|
|
1428
1730
|
promptAuth: () => promptAuth,
|
|
1429
1731
|
promptApiKey: () => promptApiKey,
|
|
1430
1732
|
finishSetup: () => finishSetup,
|
|
1431
|
-
confirmIndexCodebase: () => confirmIndexCodebase,
|
|
1432
1733
|
confirmBackgroundSync: () => confirmBackgroundSync
|
|
1433
1734
|
});
|
|
1434
1735
|
function formatDetectedCount(count) {
|
|
@@ -1531,12 +1832,6 @@ async function selectMcpTargets(targets) {
|
|
|
1531
1832
|
}))
|
|
1532
1833
|
}));
|
|
1533
1834
|
}
|
|
1534
|
-
async function confirmIndexCodebase() {
|
|
1535
|
-
return ensureValue(await ye({
|
|
1536
|
-
message: "Index this codebase too?",
|
|
1537
|
-
initialValue: false
|
|
1538
|
-
}));
|
|
1539
|
-
}
|
|
1540
1835
|
async function confirmBackgroundSync() {
|
|
1541
1836
|
const value = ensureValue(await ve({
|
|
1542
1837
|
message: "Auto-ingest new chats every 10 minutes?",
|
|
@@ -1712,6 +2007,21 @@ async function detect() {
|
|
|
1712
2007
|
path: join(openclawDir, "openclaw.json"),
|
|
1713
2008
|
sessionCount: 0
|
|
1714
2009
|
});
|
|
2010
|
+
const antigravityDir = join(home, ".gemini", "antigravity");
|
|
2011
|
+
const antigravityConvDir = join(antigravityDir, "conversations");
|
|
2012
|
+
let antigravityCount = 0;
|
|
2013
|
+
if (existsSync(antigravityConvDir)) {
|
|
2014
|
+
try {
|
|
2015
|
+
antigravityCount = readdirSync(antigravityConvDir).filter((f) => f.endsWith(".pb")).length;
|
|
2016
|
+
} catch {}
|
|
2017
|
+
}
|
|
2018
|
+
tools.push({
|
|
2019
|
+
name: "Antigravity",
|
|
2020
|
+
id: "antigravity",
|
|
2021
|
+
available: existsSync(antigravityDir),
|
|
2022
|
+
path: join(antigravityDir, "mcp_config.json"),
|
|
2023
|
+
sessionCount: antigravityCount
|
|
2024
|
+
});
|
|
1715
2025
|
return tools;
|
|
1716
2026
|
}
|
|
1717
2027
|
|
|
@@ -1799,7 +2109,6 @@ init_shared();
|
|
|
1799
2109
|
import { readdirSync as readdirSync2, readFileSync as readFileSync3, existsSync as existsSync3 } from "node:fs";
|
|
1800
2110
|
import { join as join3, basename } from "node:path";
|
|
1801
2111
|
import { homedir as homedir3, platform as platform3 } from "node:os";
|
|
1802
|
-
var MAX_CONTENT = 48000;
|
|
1803
2112
|
var MIN_TURN_LEN = 50;
|
|
1804
2113
|
function resolveProjectName(dirName) {
|
|
1805
2114
|
const segments = dirName.replace(/^-/, "").split("-");
|
|
@@ -1942,22 +2251,7 @@ function ingestClaude() {
|
|
|
1942
2251
|
continue;
|
|
1943
2252
|
}
|
|
1944
2253
|
const header = `# Chat: ${project}${date ? ` | ${date}` : ""}`;
|
|
1945
|
-
const
|
|
1946
|
-
return `## Q: ${t.user}
|
|
1947
|
-
|
|
1948
|
-
${t.assistant}`;
|
|
1949
|
-
}).join(`
|
|
1950
|
-
|
|
1951
|
-
---
|
|
1952
|
-
|
|
1953
|
-
`);
|
|
1954
|
-
let content = `${header}
|
|
1955
|
-
|
|
1956
|
-
${body}`;
|
|
1957
|
-
if (content.length > MAX_CONTENT)
|
|
1958
|
-
content = content.slice(0, MAX_CONTENT) + `
|
|
1959
|
-
|
|
1960
|
-
[truncated]`;
|
|
2254
|
+
const content = fitContent(header, turns);
|
|
1961
2255
|
const contentHash = createContentHash(content);
|
|
1962
2256
|
const dedupKey = `claude:${sessionId}`;
|
|
1963
2257
|
const fingerprint = `${dedupKey}:${contentHash}`;
|
|
@@ -1988,7 +2282,6 @@ init_shared();
|
|
|
1988
2282
|
import { existsSync as existsSync4, readFileSync as readFileSync4, readdirSync as readdirSync3 } from "node:fs";
|
|
1989
2283
|
import { join as join4, basename as basename2 } from "node:path";
|
|
1990
2284
|
import { homedir as homedir4 } from "node:os";
|
|
1991
|
-
var MAX_CONTENT2 = 48000;
|
|
1992
2285
|
function isCodexBoilerplate(text) {
|
|
1993
2286
|
return text.startsWith("# AGENTS.md instructions for") || text.startsWith("<INSTRUCTIONS>") || text.startsWith("<user_instructions>") || text.startsWith("<user_action>");
|
|
1994
2287
|
}
|
|
@@ -2096,25 +2389,14 @@ function walkCodexSessions(dir, memories, sessionIds, stats) {
|
|
|
2096
2389
|
stats.filtered++;
|
|
2097
2390
|
continue;
|
|
2098
2391
|
}
|
|
2099
|
-
const
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
`
|
|
2103
|
-
return `## Q: ${r.user}
|
|
2104
|
-
|
|
2105
|
-
${assistant}`;
|
|
2106
|
-
}).join(`
|
|
2107
|
-
|
|
2108
|
-
---
|
|
2392
|
+
const header = `# Codex Session${project ? `: ${project}` : ""} | ${date || "unknown"}`;
|
|
2393
|
+
const turns = rounds.map((r) => ({
|
|
2394
|
+
user: r.user,
|
|
2395
|
+
assistant: r.assistantParts.join(`
|
|
2109
2396
|
|
|
2110
|
-
`)
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
${body}`;
|
|
2114
|
-
if (content.length > MAX_CONTENT2)
|
|
2115
|
-
content = content.slice(0, MAX_CONTENT2) + `
|
|
2116
|
-
|
|
2117
|
-
[truncated]`;
|
|
2397
|
+
`)
|
|
2398
|
+
}));
|
|
2399
|
+
const content = fitContent(header, turns);
|
|
2118
2400
|
const contentHash = createContentHash(content);
|
|
2119
2401
|
const dedupKey = `codex:${sessionId}`;
|
|
2120
2402
|
const fingerprint = `${dedupKey}:${contentHash}`;
|
|
@@ -2146,7 +2428,6 @@ init_shared();
|
|
|
2146
2428
|
import { readFileSync as readFileSync5, statSync } from "node:fs";
|
|
2147
2429
|
import { join as join5 } from "node:path";
|
|
2148
2430
|
import { createRequire as createRequire3 } from "node:module";
|
|
2149
|
-
var MAX_CONTENT3 = 48000;
|
|
2150
2431
|
var MAX_DB_SIZE = 2 * 1024 * 1024 * 1024;
|
|
2151
2432
|
var WARN_DB_SIZE = 500 * 1024 * 1024;
|
|
2152
2433
|
var MIN_TURN_LEN2 = 50;
|
|
@@ -2262,22 +2543,7 @@ async function ingestCursor(dbPath, wasmDir) {
|
|
|
2262
2543
|
const sessionName = parsed.name || "Cursor Chat";
|
|
2263
2544
|
const date = parsed.createdAt ? new Date(parsed.createdAt).toISOString().slice(0, 10) : "unknown";
|
|
2264
2545
|
const header = `# ${sessionName} | ${date}`;
|
|
2265
|
-
const
|
|
2266
|
-
return `## Q: ${t.user}
|
|
2267
|
-
|
|
2268
|
-
${t.assistant}`;
|
|
2269
|
-
}).join(`
|
|
2270
|
-
|
|
2271
|
-
---
|
|
2272
|
-
|
|
2273
|
-
`);
|
|
2274
|
-
let content = `${header}
|
|
2275
|
-
|
|
2276
|
-
${body}`;
|
|
2277
|
-
if (content.length > MAX_CONTENT3)
|
|
2278
|
-
content = content.slice(0, MAX_CONTENT3) + `
|
|
2279
|
-
|
|
2280
|
-
[truncated]`;
|
|
2546
|
+
const content = fitContent(header, turns);
|
|
2281
2547
|
const contentHash = createContentHash(content);
|
|
2282
2548
|
const dedupKey = `cursor:${composerId}`;
|
|
2283
2549
|
const fingerprint = `${dedupKey}:${contentHash}`;
|
|
@@ -2327,7 +2593,8 @@ var MCP_TARGETS = [
|
|
|
2327
2593
|
{ id: "vscode", label: "VS Code Copilot", defaultSelected: false },
|
|
2328
2594
|
{ id: "cline", label: "Cline", defaultSelected: false },
|
|
2329
2595
|
{ id: "zed", label: "Zed", defaultSelected: false },
|
|
2330
|
-
{ id: "openclaw", label: "OpenClaw", defaultSelected: false }
|
|
2596
|
+
{ id: "openclaw", label: "OpenClaw", defaultSelected: false },
|
|
2597
|
+
{ id: "antigravity", label: "Antigravity", defaultSelected: false }
|
|
2331
2598
|
];
|
|
2332
2599
|
function readJsonFile(path) {
|
|
2333
2600
|
try {
|
|
@@ -2536,6 +2803,19 @@ function configureOpenclaw(apiKey) {
|
|
|
2536
2803
|
writeJsonFile(configPath, config);
|
|
2537
2804
|
return "\x1B[32m✓\x1B[0m OpenClaw";
|
|
2538
2805
|
}
|
|
2806
|
+
function configureAntigravity(apiKey) {
|
|
2807
|
+
const configPath = join7(homedir5(), ".gemini", "antigravity", "mcp_config.json");
|
|
2808
|
+
const config = readJsonFile(configPath);
|
|
2809
|
+
if (!config.mcpServers || typeof config.mcpServers !== "object") {
|
|
2810
|
+
config.mcpServers = {};
|
|
2811
|
+
}
|
|
2812
|
+
config.mcpServers[SERVER_NAME] = {
|
|
2813
|
+
serverUrl: `${CONARE_URL}/mcp`,
|
|
2814
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
2815
|
+
};
|
|
2816
|
+
writeJsonFile(configPath, config);
|
|
2817
|
+
return "\x1B[32m✓\x1B[0m Antigravity";
|
|
2818
|
+
}
|
|
2539
2819
|
var CLIENT_CONFIGURATORS = {
|
|
2540
2820
|
claude: configureClaude,
|
|
2541
2821
|
codex: configureCodex,
|
|
@@ -2544,7 +2824,8 @@ var CLIENT_CONFIGURATORS = {
|
|
|
2544
2824
|
vscode: configureVscode,
|
|
2545
2825
|
cline: configureCline,
|
|
2546
2826
|
zed: configureZed,
|
|
2547
|
-
openclaw: configureOpenclaw
|
|
2827
|
+
openclaw: configureOpenclaw,
|
|
2828
|
+
antigravity: configureAntigravity
|
|
2548
2829
|
};
|
|
2549
2830
|
var SKILL_MD = `---
|
|
2550
2831
|
name: conare
|
|
@@ -2697,16 +2978,6 @@ function saveApiKey(apiKey) {
|
|
|
2697
2978
|
function getSavedApiKey() {
|
|
2698
2979
|
return readConfig().apiKey;
|
|
2699
2980
|
}
|
|
2700
|
-
function addIndexedPath(absPath) {
|
|
2701
|
-
const config = readConfig();
|
|
2702
|
-
const paths = new Set(config.indexedPaths || []);
|
|
2703
|
-
paths.add(absPath);
|
|
2704
|
-
config.indexedPaths = [...paths];
|
|
2705
|
-
writeConfig(config);
|
|
2706
|
-
}
|
|
2707
|
-
function getIndexedPaths() {
|
|
2708
|
-
return readConfig().indexedPaths || [];
|
|
2709
|
-
}
|
|
2710
2981
|
|
|
2711
2982
|
// src/sync.ts
|
|
2712
2983
|
import { existsSync as existsSync8, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4, unlinkSync, readFileSync as readFileSync9, chmodSync, cpSync, rmSync as rmSync2, symlinkSync as symlinkSync2, readlinkSync as readlinkSync2, appendFileSync } from "node:fs";
|
|
@@ -2821,31 +3092,6 @@ echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) START sync" >> "$LOG"
|
|
|
2821
3092
|
2>> "$LOG"
|
|
2822
3093
|
echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) DONE sync (exit $?)" >> "$LOG"
|
|
2823
3094
|
`;
|
|
2824
|
-
function makePlist(intervalMinutes) {
|
|
2825
|
-
const home = homedir7();
|
|
2826
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
2827
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
2828
|
-
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
2829
|
-
<plist version="1.0">
|
|
2830
|
-
<dict>
|
|
2831
|
-
<key>Label</key>
|
|
2832
|
-
<string>${PLIST_LABEL}</string>
|
|
2833
|
-
<key>ProgramArguments</key>
|
|
2834
|
-
<array>
|
|
2835
|
-
<string>/bin/bash</string>
|
|
2836
|
-
<string>${home}/.conare/bin/run.sh</string>
|
|
2837
|
-
</array>
|
|
2838
|
-
<key>StartInterval</key>
|
|
2839
|
-
<integer>${intervalMinutes * 60}</integer>
|
|
2840
|
-
<key>StandardOutPath</key>
|
|
2841
|
-
<string>${home}/.conare/ingest.log</string>
|
|
2842
|
-
<key>StandardErrorPath</key>
|
|
2843
|
-
<string>${home}/.conare/ingest.log</string>
|
|
2844
|
-
<key>RunAtLoad</key>
|
|
2845
|
-
<true/>
|
|
2846
|
-
</dict>
|
|
2847
|
-
</plist>`;
|
|
2848
|
-
}
|
|
2849
3095
|
var SYSTEMD_SERVICE_CONTENT = `[Unit]
|
|
2850
3096
|
Description=Conare Memory — background sync
|
|
2851
3097
|
|
|
@@ -2947,22 +3193,12 @@ function findSqlJs() {
|
|
|
2947
3193
|
}
|
|
2948
3194
|
return null;
|
|
2949
3195
|
}
|
|
2950
|
-
function
|
|
2951
|
-
const plistDir = dirname2(PLIST_PATH);
|
|
2952
|
-
mkdirSync4(plistDir, { recursive: true });
|
|
2953
|
-
writeFileSync4(PLIST_PATH, makePlist(intervalMinutes));
|
|
2954
|
-
const id = uid();
|
|
3196
|
+
function cleanupOldLaunchAgent() {
|
|
2955
3197
|
try {
|
|
2956
|
-
execSync3(`launchctl bootout gui/${
|
|
3198
|
+
execSync3(`launchctl bootout gui/${uid()} "${PLIST_PATH}" 2>/dev/null`, { stdio: "ignore" });
|
|
2957
3199
|
} catch {}
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
} catch {
|
|
2961
|
-
try {
|
|
2962
|
-
execSync3(`launchctl load "${PLIST_PATH}"`, { stdio: "ignore" });
|
|
2963
|
-
} catch {
|
|
2964
|
-
throw new Error("Failed to load launchd agent. Try manually: launchctl load " + PLIST_PATH);
|
|
2965
|
-
}
|
|
3200
|
+
if (existsSync8(PLIST_PATH)) {
|
|
3201
|
+
unlinkSync(PLIST_PATH);
|
|
2966
3202
|
}
|
|
2967
3203
|
}
|
|
2968
3204
|
function setupLinuxSystemd(intervalMinutes) {
|
|
@@ -2972,13 +3208,30 @@ function setupLinuxSystemd(intervalMinutes) {
|
|
|
2972
3208
|
execSync3("systemctl --user daemon-reload", { stdio: "ignore" });
|
|
2973
3209
|
execSync3("systemctl --user enable --now conare-sync.timer", { stdio: "ignore" });
|
|
2974
3210
|
}
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
const
|
|
3211
|
+
var CRON_SAFE_INTERVALS = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30];
|
|
3212
|
+
function clampCronInterval(intervalMinutes) {
|
|
3213
|
+
const n = Number.isFinite(intervalMinutes) ? Math.round(intervalMinutes) : 10;
|
|
3214
|
+
if (n <= 0)
|
|
3215
|
+
return 10;
|
|
3216
|
+
let best = 10;
|
|
3217
|
+
let bestDist = Infinity;
|
|
3218
|
+
for (const safe of CRON_SAFE_INTERVALS) {
|
|
3219
|
+
const dist = Math.abs(n - safe);
|
|
3220
|
+
if (dist < bestDist) {
|
|
3221
|
+
bestDist = dist;
|
|
3222
|
+
best = safe;
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
return best;
|
|
3226
|
+
}
|
|
3227
|
+
function setupCron(intervalMinutes) {
|
|
3228
|
+
const clamped = clampCronInterval(intervalMinutes);
|
|
3229
|
+
const cronCmd = `"${homedir7()}/.conare/bin/run.sh"`;
|
|
3230
|
+
const cronLine = `*/${clamped} * * * * ${cronCmd} # conare-sync`;
|
|
2978
3231
|
try {
|
|
2979
3232
|
const existing = execSync3("crontab -l 2>/dev/null", { encoding: "utf-8" });
|
|
2980
3233
|
const filtered = existing.split(`
|
|
2981
|
-
`).filter((l) => !l.includes("conare")).join(`
|
|
3234
|
+
`).filter((l) => !l.endsWith("# conare-sync") && !l.includes(".conare/bin/run.sh")).join(`
|
|
2982
3235
|
`);
|
|
2983
3236
|
const newCrontab = (filtered.trim() ? filtered.trim() + `
|
|
2984
3237
|
` : "") + cronLine + `
|
|
@@ -2989,6 +3242,47 @@ function setupLinuxCron(intervalMinutes) {
|
|
|
2989
3242
|
`, stdio: ["pipe", "ignore", "ignore"] });
|
|
2990
3243
|
}
|
|
2991
3244
|
}
|
|
3245
|
+
function removeCronEntry() {
|
|
3246
|
+
try {
|
|
3247
|
+
const existing = execSync3("crontab -l 2>/dev/null", { encoding: "utf-8" });
|
|
3248
|
+
const lines = existing.split(`
|
|
3249
|
+
`);
|
|
3250
|
+
const filtered = lines.filter((l) => !l.endsWith("# conare-sync") && !l.includes(".conare/bin/run.sh"));
|
|
3251
|
+
if (filtered.length === lines.length)
|
|
3252
|
+
return false;
|
|
3253
|
+
const newCrontab = filtered.join(`
|
|
3254
|
+
`).trim();
|
|
3255
|
+
if (newCrontab) {
|
|
3256
|
+
execSync3("crontab -", { input: newCrontab + `
|
|
3257
|
+
`, stdio: ["pipe", "ignore", "ignore"] });
|
|
3258
|
+
} else {
|
|
3259
|
+
execSync3("crontab -", { input: `
|
|
3260
|
+
`, stdio: ["pipe", "ignore", "ignore"] });
|
|
3261
|
+
}
|
|
3262
|
+
return true;
|
|
3263
|
+
} catch {
|
|
3264
|
+
return false;
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
function runSyncNow() {
|
|
3268
|
+
const os = platform6();
|
|
3269
|
+
try {
|
|
3270
|
+
if (os === "win32") {
|
|
3271
|
+
const runCmd = join9(BIN_DIR, "run.cmd");
|
|
3272
|
+
if (existsSync8(runCmd)) {
|
|
3273
|
+
execSync3(`"${runCmd}"`, { stdio: "ignore", timeout: 60000 });
|
|
3274
|
+
return true;
|
|
3275
|
+
}
|
|
3276
|
+
} else {
|
|
3277
|
+
const runSh = join9(BIN_DIR, "run.sh");
|
|
3278
|
+
if (existsSync8(runSh)) {
|
|
3279
|
+
execSync3(`/bin/bash "${runSh}"`, { stdio: "ignore", timeout: 60000 });
|
|
3280
|
+
return true;
|
|
3281
|
+
}
|
|
3282
|
+
}
|
|
3283
|
+
} catch {}
|
|
3284
|
+
return false;
|
|
3285
|
+
}
|
|
2992
3286
|
function installGlobalCommand() {
|
|
2993
3287
|
const isWindows = platform6() === "win32";
|
|
2994
3288
|
if (isWindows) {
|
|
@@ -3104,13 +3398,20 @@ function persistAndInstallGlobal(apiKey) {
|
|
|
3104
3398
|
messages.push(globalMsg);
|
|
3105
3399
|
return messages;
|
|
3106
3400
|
}
|
|
3401
|
+
function sanitizeInterval(n) {
|
|
3402
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
3403
|
+
return 10;
|
|
3404
|
+
return Math.max(1, Math.round(n));
|
|
3405
|
+
}
|
|
3107
3406
|
function installSync(apiKey, intervalMinutes = 10) {
|
|
3108
3407
|
const messages = persistAndInstallGlobal(apiKey);
|
|
3109
3408
|
const os = platform6();
|
|
3409
|
+
intervalMinutes = sanitizeInterval(intervalMinutes);
|
|
3110
3410
|
if (os === "darwin") {
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3411
|
+
cleanupOldLaunchAgent();
|
|
3412
|
+
const actual = clampCronInterval(intervalMinutes);
|
|
3413
|
+
setupCron(intervalMinutes);
|
|
3414
|
+
messages.push(`Installed cron job (every ${actual} min)`);
|
|
3114
3415
|
} else if (os === "win32") {
|
|
3115
3416
|
setupWindows(intervalMinutes);
|
|
3116
3417
|
messages.push(`Installed Windows Task Scheduler (every ${intervalMinutes} min)`);
|
|
@@ -3119,25 +3420,23 @@ function installSync(apiKey, intervalMinutes = 10) {
|
|
|
3119
3420
|
setupLinuxSystemd(intervalMinutes);
|
|
3120
3421
|
messages.push(`Installed systemd timer (every ${intervalMinutes} min)`);
|
|
3121
3422
|
} else {
|
|
3122
|
-
|
|
3123
|
-
|
|
3423
|
+
const actual = clampCronInterval(intervalMinutes);
|
|
3424
|
+
setupCron(intervalMinutes);
|
|
3425
|
+
messages.push(`Installed cron job (every ${actual} min)`);
|
|
3124
3426
|
}
|
|
3125
3427
|
} else {
|
|
3126
3428
|
messages.push(`Unsupported platform: ${os}. Run manually: ~/.conare/bin/run.sh`);
|
|
3127
3429
|
}
|
|
3430
|
+
const syncOk = runSyncNow();
|
|
3431
|
+
messages.push(syncOk ? "First sync completed" : "First sync deferred to next timer tick");
|
|
3128
3432
|
return messages;
|
|
3129
3433
|
}
|
|
3130
3434
|
function uninstallSync() {
|
|
3131
3435
|
const messages = [];
|
|
3132
3436
|
const os = platform6();
|
|
3133
3437
|
if (os === "darwin") {
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
} catch {}
|
|
3137
|
-
if (existsSync8(PLIST_PATH)) {
|
|
3138
|
-
unlinkSync(PLIST_PATH);
|
|
3139
|
-
messages.push("Removed launchd agent");
|
|
3140
|
-
}
|
|
3438
|
+
removeCronEntry() && messages.push("Removed cron job");
|
|
3439
|
+
cleanupOldLaunchAgent();
|
|
3141
3440
|
} else if (os === "win32") {
|
|
3142
3441
|
try {
|
|
3143
3442
|
execSync3(`schtasks /Delete /TN "${TASK_NAME}" /F`, { stdio: "ignore" });
|
|
@@ -3157,25 +3456,18 @@ function uninstallSync() {
|
|
|
3157
3456
|
} catch {}
|
|
3158
3457
|
messages.push("Removed systemd timer");
|
|
3159
3458
|
} else {
|
|
3160
|
-
|
|
3161
|
-
const existing = execSync3("crontab -l 2>/dev/null", { encoding: "utf-8" });
|
|
3162
|
-
const filtered = existing.split(`
|
|
3163
|
-
`).filter((l) => !l.includes("conare")).join(`
|
|
3164
|
-
`);
|
|
3165
|
-
execSync3("crontab -", { input: filtered.trim() + `
|
|
3166
|
-
`, stdio: ["pipe", "ignore", "ignore"] });
|
|
3167
|
-
messages.push("Removed cron job");
|
|
3168
|
-
} catch {}
|
|
3459
|
+
removeCronEntry() && messages.push("Removed cron job");
|
|
3169
3460
|
}
|
|
3170
3461
|
}
|
|
3171
|
-
const
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3462
|
+
const configPath = join9(CONARE_DIR, "config.json");
|
|
3463
|
+
if (existsSync8(configPath))
|
|
3464
|
+
unlinkSync(configPath);
|
|
3465
|
+
const lockDir = join9(CONARE_DIR, "sync.lock.d");
|
|
3466
|
+
if (existsSync8(lockDir))
|
|
3467
|
+
rmSync2(lockDir, { recursive: true, force: true });
|
|
3468
|
+
const lockFile = join9(CONARE_DIR, "sync.lock");
|
|
3469
|
+
if (existsSync8(lockFile))
|
|
3470
|
+
unlinkSync(lockFile);
|
|
3179
3471
|
if (existsSync8(BIN_DIR)) {
|
|
3180
3472
|
rmSync2(BIN_DIR, { recursive: true, force: true });
|
|
3181
3473
|
messages.push("Removed ~/.conare/bin/");
|
|
@@ -3233,10 +3525,12 @@ function renderProgressSummary(success, failed, noun) {
|
|
|
3233
3525
|
return `\r \x1B[32m✓\x1B[0m [\x1B[36m${bar}\x1B[0m] ${success} ${noun}, ${failed} failed (${pct}%)${" ".repeat(12)}
|
|
3234
3526
|
`;
|
|
3235
3527
|
}
|
|
3236
|
-
function renderDiscoverySummary(discovered,
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3528
|
+
function renderDiscoverySummary(discovered, _filtered, deduped) {
|
|
3529
|
+
if (discovered === 0 && deduped === 0)
|
|
3530
|
+
return "no conversations found";
|
|
3531
|
+
if (discovered === 0 && deduped > 0)
|
|
3532
|
+
return `${deduped} already imported, nothing new`;
|
|
3533
|
+
const parts = [`${discovered} new`];
|
|
3240
3534
|
if (deduped > 0)
|
|
3241
3535
|
parts.push(`${deduped} already imported`);
|
|
3242
3536
|
return parts.join(", ");
|
|
@@ -3420,7 +3714,6 @@ async function main() {
|
|
|
3420
3714
|
let effectiveConfigOnly = opts.configOnly;
|
|
3421
3715
|
let effectiveIngestOnly = opts.ingestOnly;
|
|
3422
3716
|
let effectiveIndexPath = opts.indexPath;
|
|
3423
|
-
let postIngestIndexPath;
|
|
3424
3717
|
let selectedSources = opts.source ? [opts.source] : ["claude", "cursor", "codex"];
|
|
3425
3718
|
let apiKey = opts.key || configFileKey || process.env.CONARE_API_KEY || savedApiKey;
|
|
3426
3719
|
let interactiveTargets = MCP_TARGETS.map((target) => ({
|
|
@@ -3613,7 +3906,6 @@ Nothing new to index.`);
|
|
|
3613
3906
|
write(renderProgressSummary(success, failed, "indexed"));
|
|
3614
3907
|
const fileHashes = results.filter((result) => result.success).map((result) => getManifestFingerprint(memories[result.index])).filter((key) => !!key);
|
|
3615
3908
|
markIngested("codebase", fileHashes);
|
|
3616
|
-
addIndexedPath(absPath);
|
|
3617
3909
|
if (!opts.quiet)
|
|
3618
3910
|
printFailureSummary(results, memories);
|
|
3619
3911
|
}
|
|
@@ -3694,6 +3986,22 @@ Nothing new to index.`);
|
|
|
3694
3986
|
return db.localeCompare(da);
|
|
3695
3987
|
});
|
|
3696
3988
|
log();
|
|
3989
|
+
if (allMemories.length > 2000 && !opts.dryRun && !opts.quiet) {
|
|
3990
|
+
if (hasTty) {
|
|
3991
|
+
const { confirm: confirm2 } = await Promise.resolve().then(() => (init_dist2(), exports_dist));
|
|
3992
|
+
const proceed = await confirm2({
|
|
3993
|
+
message: `That's ${allMemories.length.toLocaleString()} memories — this may take a while and use significant resources. Continue?`
|
|
3994
|
+
});
|
|
3995
|
+
if (!proceed || typeof proceed === "symbol") {
|
|
3996
|
+
log("Aborted.");
|
|
3997
|
+
process.exit(0);
|
|
3998
|
+
}
|
|
3999
|
+
} else {
|
|
4000
|
+
log(`Warning: ${allMemories.length.toLocaleString()} memories detected. Skipping large upload in non-interactive mode.`);
|
|
4001
|
+
log("Re-run interactively or with --force to proceed.");
|
|
4002
|
+
process.exit(0);
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
3697
4005
|
if (allMemories.length === 0) {
|
|
3698
4006
|
log("Nothing new to upload.");
|
|
3699
4007
|
} else if (opts.dryRun) {
|
|
@@ -3747,36 +4055,14 @@ Nothing new to index.`);
|
|
|
3747
4055
|
}
|
|
3748
4056
|
}
|
|
3749
4057
|
log();
|
|
3750
|
-
if (effectiveIngestOnly && !opts.dryRun) {
|
|
3751
|
-
const savedPaths = getIndexedPaths();
|
|
3752
|
-
for (const savedPath of savedPaths) {
|
|
3753
|
-
if (!existsSync9(savedPath))
|
|
3754
|
-
continue;
|
|
3755
|
-
try {
|
|
3756
|
-
const { memories: codeMemories, project } = indexCodebase(savedPath, { changedOnly: true });
|
|
3757
|
-
if (codeMemories.length === 0)
|
|
3758
|
-
continue;
|
|
3759
|
-
log(` Re-indexing ${project}: ${codeMemories.length} changed files`);
|
|
3760
|
-
const { success, failed, results } = await uploadBulk(apiKey, codeMemories, () => {});
|
|
3761
|
-
if (!opts.quiet)
|
|
3762
|
-
log(` ${project}: ${success} indexed, ${failed} failed`);
|
|
3763
|
-
const fileHashes = results.filter((r2) => r2.success).map((r2) => getManifestFingerprint(codeMemories[r2.index])).filter((k3) => !!k3);
|
|
3764
|
-
markIngested("codebase", fileHashes);
|
|
3765
|
-
} catch {}
|
|
3766
|
-
}
|
|
3767
|
-
}
|
|
3768
4058
|
if (interactiveMode) {
|
|
3769
4059
|
selectedTargets = await selectMcpTargets(interactiveTargets);
|
|
3770
|
-
|
|
3771
|
-
if (selectedTargets.length === 0 && selectedSources.length === 0 && !shouldIndexCurrentCodebase) {
|
|
4060
|
+
if (selectedTargets.length === 0 && selectedSources.length === 0) {
|
|
3772
4061
|
effectiveConfigOnly = false;
|
|
3773
4062
|
effectiveIngestOnly = false;
|
|
3774
4063
|
} else {
|
|
3775
4064
|
effectiveIngestOnly = selectedTargets.length === 0;
|
|
3776
4065
|
}
|
|
3777
|
-
if (shouldIndexCurrentCodebase) {
|
|
3778
|
-
postIngestIndexPath = ".";
|
|
3779
|
-
}
|
|
3780
4066
|
finishSetup();
|
|
3781
4067
|
}
|
|
3782
4068
|
if (!opts.dryRun && !effectiveIngestOnly) {
|
|
@@ -3787,35 +4073,6 @@ Nothing new to index.`);
|
|
|
3787
4073
|
for (const line of mcpLines)
|
|
3788
4074
|
log(` ${line}`);
|
|
3789
4075
|
}
|
|
3790
|
-
if (postIngestIndexPath) {
|
|
3791
|
-
const { resolve: resolve2 } = await import("node:path");
|
|
3792
|
-
const absPath = resolve2(postIngestIndexPath);
|
|
3793
|
-
const idxSpinner = Y2();
|
|
3794
|
-
idxSpinner.start("Indexing codebase...");
|
|
3795
|
-
const { memories, fileCount, skipped, project } = indexCodebase(absPath, {
|
|
3796
|
-
project: opts.indexProject
|
|
3797
|
-
});
|
|
3798
|
-
idxSpinner.stop(`Codebase: ${fileCount} files found, ${skipped} skipped (project: ${project})`);
|
|
3799
|
-
if (memories.length === 0) {
|
|
3800
|
-
log(`
|
|
3801
|
-
Nothing new to index.`);
|
|
3802
|
-
} else {
|
|
3803
|
-
const barWidth = 20;
|
|
3804
|
-
const { success, failed, results } = await uploadBulk(apiKey, memories, (uploaded, total, _failed) => {
|
|
3805
|
-
const pct = (uploaded / total * 100).toFixed(1);
|
|
3806
|
-
const filled = Math.round(uploaded / total * barWidth);
|
|
3807
|
-
const bar = "█".repeat(filled) + "░".repeat(barWidth - filled);
|
|
3808
|
-
write(`\r Uploading [\x1B[36m${bar}\x1B[0m] ${uploaded}/${total} (${pct}%)`);
|
|
3809
|
-
});
|
|
3810
|
-
write(renderProgressSummary(success, failed, "indexed"));
|
|
3811
|
-
const fileHashes = results.filter((result) => result.success).map((result) => getManifestFingerprint(memories[result.index])).filter((key) => !!key);
|
|
3812
|
-
markIngested("codebase", fileHashes);
|
|
3813
|
-
addIndexedPath(absPath);
|
|
3814
|
-
if (!opts.quiet)
|
|
3815
|
-
printFailureSummary(results, memories);
|
|
3816
|
-
}
|
|
3817
|
-
log("");
|
|
3818
|
-
}
|
|
3819
4076
|
if (!opts.dryRun && !opts.quiet) {
|
|
3820
4077
|
try {
|
|
3821
4078
|
persistAndInstallGlobal(apiKey);
|