imprnt 0.1.3-edge.59 → 0.1.3-edge.61
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/cli.js +152 -44
- package/dist/imp.js +152 -44
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -766,14 +766,9 @@ function registerVault(path, opts = {}) {
|
|
|
766
766
|
const name = opts.name ?? "personal";
|
|
767
767
|
reg.vaults[name] = path;
|
|
768
768
|
reg.default = name;
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
writeFileSync5(p, JSON.stringify(reg, null, 2) + `
|
|
773
|
-
`);
|
|
774
|
-
} catch (e) {
|
|
775
|
-
return { status: "error", current: path, error: e instanceof Error ? e.message : String(e) };
|
|
776
|
-
}
|
|
769
|
+
const w = writeRegistry(reg);
|
|
770
|
+
if (!w.ok)
|
|
771
|
+
return { status: "error", current: path, error: w.error };
|
|
777
772
|
return { status: "registered", current: path };
|
|
778
773
|
}
|
|
779
774
|
function readDefaultAgent() {
|
|
@@ -842,8 +837,9 @@ var init_registry = () => {};
|
|
|
842
837
|
// scripts/lib/launch.ts
|
|
843
838
|
import { existsSync as existsSync7, mkdtempSync as mkdtempSync2, readFileSync as readFileSync7, realpathSync, rmSync as rmSync3, statSync as statSync5, writeFileSync as writeFileSync6 } from "node:fs";
|
|
844
839
|
import { homedir as homedir2, tmpdir as tmpdir2 } from "node:os";
|
|
845
|
-
import { isAbsolute, join as join8, resolve as resolve4, sep as sep2 } from "node:path";
|
|
840
|
+
import { basename as basename2, isAbsolute, join as join8, resolve as resolve4, sep as sep2 } from "node:path";
|
|
846
841
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
842
|
+
import { createInterface } from "node:readline/promises";
|
|
847
843
|
function importPath(root, target) {
|
|
848
844
|
if (target.startsWith("~/"))
|
|
849
845
|
return join8(homedir2(), target.slice(2));
|
|
@@ -1013,7 +1009,12 @@ function claudeRenderArgs(spec) {
|
|
|
1013
1009
|
const systemPrompt = spec.insideProject ? spec.globals : joinFragments([spec.cast, spec.pointer, spec.globals]);
|
|
1014
1010
|
const harness = spec.pluginsRoot ? harnessFlags(spec.pluginsRoot) : [];
|
|
1015
1011
|
const extra = spec.addDirs.flatMap((d) => ["--add-dir", d]);
|
|
1016
|
-
const
|
|
1012
|
+
const lead = [];
|
|
1013
|
+
if (spec.skipPermissions && !spec.passthrough.includes("--dangerously-skip-permissions"))
|
|
1014
|
+
lead.push("--dangerously-skip-permissions");
|
|
1015
|
+
if (spec.model && !spec.passthrough.some((a) => a === "--model" || a.startsWith("--model=")))
|
|
1016
|
+
lead.push("--model", spec.model);
|
|
1017
|
+
const pass = lead.length ? [...lead, ...spec.passthrough] : spec.passthrough;
|
|
1017
1018
|
const body = systemPrompt ? mergeFragment(pass, systemPrompt, extra) : [...pass, ...extra];
|
|
1018
1019
|
return [...harness, ...body];
|
|
1019
1020
|
}
|
|
@@ -1023,6 +1024,19 @@ function expandGeminiModel(m) {
|
|
|
1023
1024
|
function escapeGeminiImports(text) {
|
|
1024
1025
|
return text.replaceAll("@", "\\@");
|
|
1025
1026
|
}
|
|
1027
|
+
function trackGeminiTempDir(dir) {
|
|
1028
|
+
geminiTempDirs.add(dir);
|
|
1029
|
+
if (geminiCleanupArmed)
|
|
1030
|
+
return;
|
|
1031
|
+
geminiCleanupArmed = true;
|
|
1032
|
+
process.on("exit", () => {
|
|
1033
|
+
for (const d of geminiTempDirs) {
|
|
1034
|
+
try {
|
|
1035
|
+
rmSync3(d, { recursive: true, force: true });
|
|
1036
|
+
} catch {}
|
|
1037
|
+
}
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1026
1040
|
function geminiRenderArgs(spec) {
|
|
1027
1041
|
const includes = [];
|
|
1028
1042
|
const systemPrompt = joinFragments([spec.cast, spec.pointer, spec.globals]);
|
|
@@ -1030,11 +1044,7 @@ function geminiRenderArgs(spec) {
|
|
|
1030
1044
|
const dir = mkdtempSync2(join8(tmpdir2(), "imprnt-gemini-"));
|
|
1031
1045
|
writeFileSync6(join8(dir, "GEMINI.md"), escapeGeminiImports(systemPrompt) + `
|
|
1032
1046
|
`);
|
|
1033
|
-
|
|
1034
|
-
try {
|
|
1035
|
-
rmSync3(dir, { recursive: true, force: true });
|
|
1036
|
-
} catch {}
|
|
1037
|
-
});
|
|
1047
|
+
trackGeminiTempDir(dir);
|
|
1038
1048
|
includes.push(dir);
|
|
1039
1049
|
}
|
|
1040
1050
|
includes.push(...spec.addDirs);
|
|
@@ -1049,24 +1059,117 @@ function geminiRenderArgs(spec) {
|
|
|
1049
1059
|
lead.push("--skip-trust");
|
|
1050
1060
|
}
|
|
1051
1061
|
const pass = [...spec.passthrough];
|
|
1052
|
-
const
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1062
|
+
const mTerm = pass.indexOf("--");
|
|
1063
|
+
const mEnd = mTerm < 0 ? pass.length : mTerm;
|
|
1064
|
+
const isModelFlag = (a) => a === "-m" || a === "--model" || a.startsWith("-m=") || a.startsWith("--model=");
|
|
1065
|
+
const mIdx = pass.slice(0, mEnd).findIndex(isModelFlag);
|
|
1066
|
+
if (mIdx >= 0) {
|
|
1067
|
+
const tok = pass[mIdx];
|
|
1068
|
+
const eq = tok.indexOf("=");
|
|
1069
|
+
if (eq >= 0)
|
|
1070
|
+
pass[mIdx] = tok.slice(0, eq + 1) + expandGeminiModel(tok.slice(eq + 1));
|
|
1071
|
+
else if (mIdx + 1 < mEnd && pass[mIdx + 1] !== undefined)
|
|
1072
|
+
pass[mIdx + 1] = expandGeminiModel(pass[mIdx + 1]);
|
|
1073
|
+
} else if (spec.model) {
|
|
1056
1074
|
pass.unshift("-m", expandGeminiModel(spec.model));
|
|
1057
1075
|
}
|
|
1058
|
-
const rIdx = pass
|
|
1059
|
-
if (rIdx >= 0
|
|
1076
|
+
const rIdx = valuelessResumeIndex(pass);
|
|
1077
|
+
if (rIdx >= 0)
|
|
1060
1078
|
pass.splice(rIdx + 1, 0, "latest");
|
|
1061
|
-
}
|
|
1062
1079
|
const flags = includes.length ? ["--include-directories", includes.join(",")] : [];
|
|
1063
1080
|
return [...lead, ...flags, ...pass];
|
|
1064
1081
|
}
|
|
1082
|
+
function parseGeminiSessions(stdout) {
|
|
1083
|
+
const out = [];
|
|
1084
|
+
for (const raw of stdout.split(/\r?\n/)) {
|
|
1085
|
+
const m = raw.match(/^\s*(\d+)\.\s+(.+?)\s+\(([^()]+)\)\s+\[([0-9a-fA-F-]{8,})\]\s*$/);
|
|
1086
|
+
if (m)
|
|
1087
|
+
out.push({ index: Number(m[1]), name: m[2].trim(), age: m[3].trim(), id: m[4] });
|
|
1088
|
+
}
|
|
1089
|
+
return out;
|
|
1090
|
+
}
|
|
1091
|
+
function valuelessResumeIndex(args) {
|
|
1092
|
+
const term = args.indexOf("--");
|
|
1093
|
+
const end = term < 0 ? args.length : term;
|
|
1094
|
+
let i = -1;
|
|
1095
|
+
for (let k = 0;k < end; k++) {
|
|
1096
|
+
if (args[k] === "-r" || args[k] === "--resume") {
|
|
1097
|
+
i = k;
|
|
1098
|
+
break;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
if (i < 0)
|
|
1102
|
+
return -1;
|
|
1103
|
+
const next = i + 1 < end ? args[i + 1] : undefined;
|
|
1104
|
+
return next === undefined || next.startsWith("-") ? i : -1;
|
|
1105
|
+
}
|
|
1106
|
+
function listGeminiSessions(cwd) {
|
|
1107
|
+
const r = spawnSync2("gemini", ["--list-sessions", "--skip-trust"], { cwd, encoding: "utf8" });
|
|
1108
|
+
if (r.error || r.status !== 0)
|
|
1109
|
+
return { sessions: [], ran: false };
|
|
1110
|
+
const stdout = r.stdout || "";
|
|
1111
|
+
const sessions = parseGeminiSessions(stdout);
|
|
1112
|
+
if (!sessions.length && stdout.trim() && !/\(\s*0\s*\)|no sessions/i.test(stdout)) {
|
|
1113
|
+
console.error("imp: couldn't parse gemini's session list (its format may have changed) - starting fresh");
|
|
1114
|
+
}
|
|
1115
|
+
return { sessions, ran: true };
|
|
1116
|
+
}
|
|
1117
|
+
async function pickGeminiSession(sessions, label) {
|
|
1118
|
+
const cols = process.stdout.columns || 80;
|
|
1119
|
+
const nameW = Math.max(20, Math.min(64, cols - 16));
|
|
1120
|
+
const trunc = (s) => s.length > nameW ? s.slice(0, nameW - 1) + "…" : s;
|
|
1121
|
+
process.stderr.write(`
|
|
1122
|
+
resume a chat - gemini · ${label}
|
|
1123
|
+
|
|
1124
|
+
`);
|
|
1125
|
+
sessions.forEach((s, i) => {
|
|
1126
|
+
process.stderr.write(` ${String(i + 1).padStart(2)} ${trunc(s.name).padEnd(nameW)} ${s.age.replace(/\s*ago$/, "")}
|
|
1127
|
+
`);
|
|
1128
|
+
});
|
|
1129
|
+
process.stderr.write(`
|
|
1130
|
+
`);
|
|
1131
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
1132
|
+
const answer = (await rl.question(" number to resume · enter for newest · q to cancel › ")).trim();
|
|
1133
|
+
rl.close();
|
|
1134
|
+
if (answer === "")
|
|
1135
|
+
return "latest";
|
|
1136
|
+
if (answer.toLowerCase() === "q")
|
|
1137
|
+
return null;
|
|
1138
|
+
const n = Number(answer);
|
|
1139
|
+
if (Number.isInteger(n) && n >= 1 && n <= sessions.length)
|
|
1140
|
+
return sessions[n - 1].id;
|
|
1141
|
+
process.stderr.write(` not a valid choice - starting a fresh session
|
|
1142
|
+
`);
|
|
1143
|
+
return null;
|
|
1144
|
+
}
|
|
1145
|
+
async function geminiResolveResume(passthrough, cwd) {
|
|
1146
|
+
const rIdx = valuelessResumeIndex(passthrough);
|
|
1147
|
+
if (rIdx < 0)
|
|
1148
|
+
return passthrough;
|
|
1149
|
+
if (!(process.stdin.isTTY && process.stdout.isTTY))
|
|
1150
|
+
return passthrough;
|
|
1151
|
+
const { sessions, ran } = listGeminiSessions(cwd);
|
|
1152
|
+
if (!ran)
|
|
1153
|
+
return passthrough;
|
|
1154
|
+
if (!sessions.length) {
|
|
1155
|
+
console.error("imp: no saved gemini chats for this project yet - starting fresh");
|
|
1156
|
+
return passthrough.filter((_, i) => i !== rIdx);
|
|
1157
|
+
}
|
|
1158
|
+
const chosen = await pickGeminiSession(sessions, basename2(cwd));
|
|
1159
|
+
if (chosen === null)
|
|
1160
|
+
return passthrough.filter((_, i) => i !== rIdx);
|
|
1161
|
+
const out = [...passthrough];
|
|
1162
|
+
out.splice(rIdx + 1, 0, chosen);
|
|
1163
|
+
return out;
|
|
1164
|
+
}
|
|
1065
1165
|
function resolveLaunch(passthrough, config = {}) {
|
|
1166
|
+
const term = passthrough.indexOf("--");
|
|
1167
|
+
const head = term < 0 ? passthrough : passthrough.slice(0, term);
|
|
1168
|
+
const tail = term < 0 ? [] : passthrough.slice(term);
|
|
1066
1169
|
let agentFlag;
|
|
1067
1170
|
let yoloFlag;
|
|
1068
1171
|
const rest = [];
|
|
1069
|
-
for (const a of
|
|
1172
|
+
for (const a of head) {
|
|
1070
1173
|
if (a === "--gemini")
|
|
1071
1174
|
agentFlag = agentFlag ?? "gemini";
|
|
1072
1175
|
else if (a === "--claude")
|
|
@@ -1084,9 +1187,10 @@ function resolveLaunch(passthrough, config = {}) {
|
|
|
1084
1187
|
console.error(`imp: unknown agent "${name}" - falling back to claude (valid: ${Object.keys(backends).join(", ")})`);
|
|
1085
1188
|
backend = claudeBackend;
|
|
1086
1189
|
}
|
|
1087
|
-
const
|
|
1190
|
+
const yoloEnv = process.env.IMPRNT_YOLO;
|
|
1191
|
+
const envYolo = yoloEnv === undefined ? undefined : !["0", "false", "", "off", "no"].includes(yoloEnv.toLowerCase());
|
|
1088
1192
|
const skipPermissions = yoloFlag ?? envYolo ?? config.yolo ?? false;
|
|
1089
|
-
return { backend, skipPermissions, passthrough: rest };
|
|
1193
|
+
return { backend, skipPermissions, passthrough: [...rest, ...tail] };
|
|
1090
1194
|
}
|
|
1091
1195
|
function launchBackend(backend, cwd, args, env = process.env) {
|
|
1092
1196
|
if (!isDir(cwd)) {
|
|
@@ -1101,7 +1205,7 @@ function launchBackend(backend, cwd, args, env = process.env) {
|
|
|
1101
1205
|
}
|
|
1102
1206
|
return r.status ?? 1;
|
|
1103
1207
|
}
|
|
1104
|
-
var claudeBackend, GEMINI_MODEL_ALIASES, geminiBackend, backends;
|
|
1208
|
+
var claudeBackend, GEMINI_MODEL_ALIASES, geminiTempDirs, geminiCleanupArmed = false, geminiBackend, backends;
|
|
1105
1209
|
var init_launch = __esm(() => {
|
|
1106
1210
|
init_plugins();
|
|
1107
1211
|
init_global();
|
|
@@ -1118,10 +1222,12 @@ var init_launch = __esm(() => {
|
|
|
1118
1222
|
gemma31: "gemma-4-31b-it",
|
|
1119
1223
|
gemma26: "gemma-4-26b-a4b-it"
|
|
1120
1224
|
};
|
|
1225
|
+
geminiTempDirs = new Set;
|
|
1121
1226
|
geminiBackend = {
|
|
1122
1227
|
name: "gemini",
|
|
1123
1228
|
missingHint: "Install the Gemini CLI first: npm i -g @google/gemini-cli",
|
|
1124
|
-
renderArgs: geminiRenderArgs
|
|
1229
|
+
renderArgs: geminiRenderArgs,
|
|
1230
|
+
resolveResume: geminiResolveResume
|
|
1125
1231
|
};
|
|
1126
1232
|
backends = {
|
|
1127
1233
|
claude: claudeBackend,
|
|
@@ -1164,7 +1270,7 @@ var init_manifest = () => {};
|
|
|
1164
1270
|
var exports_ingest = {};
|
|
1165
1271
|
import { readFileSync as readFileSync9, writeFileSync as writeFileSync8, mkdirSync as mkdirSync3, existsSync as existsSync9, copyFileSync, readdirSync as readdirSync5, rmSync as rmSync4, statSync as statSync6 } from "node:fs";
|
|
1166
1272
|
import { createHash } from "node:crypto";
|
|
1167
|
-
import { basename as
|
|
1273
|
+
import { basename as basename3, extname, join as join10, relative as relative3 } from "node:path";
|
|
1168
1274
|
function slugify(s) {
|
|
1169
1275
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
1170
1276
|
}
|
|
@@ -1245,7 +1351,7 @@ function applyStaged(staged, vault) {
|
|
|
1245
1351
|
return "error";
|
|
1246
1352
|
}
|
|
1247
1353
|
const title = text.match(/^#\s+(.+)$/m)?.[1]?.trim() ?? "";
|
|
1248
|
-
const slug = deriveSlug([fmScalar2(fm, "slug"), title,
|
|
1354
|
+
const slug = deriveSlug([fmScalar2(fm, "slug"), title, basename3(staged, ".md")]);
|
|
1249
1355
|
if (!slug) {
|
|
1250
1356
|
console.error(` ✗ ${staged}: can't derive a slug - slug:, the H1 title, and the filename all slugify to nothing`);
|
|
1251
1357
|
return "error";
|
|
@@ -1472,7 +1578,7 @@ ${filed} filed, ${noop} no-op, ${conflict} conflict, ${error} error.`);
|
|
|
1472
1578
|
console.log(`unchanged (hash ${hash}) — skipping ${src}. note: ${prior.note}`);
|
|
1473
1579
|
process.exit(0);
|
|
1474
1580
|
}
|
|
1475
|
-
fname =
|
|
1581
|
+
fname = basename3(src);
|
|
1476
1582
|
dateMatch = fname.match(/(\d{4}-\d{2}-\d{2})/) || text.match(/^\s*date:\s*(\d{4}-\d{2}-\d{2})/im);
|
|
1477
1583
|
date = dateMatch ? dateMatch[1] : new Date().toISOString().slice(0, 10);
|
|
1478
1584
|
lines = text.split(/\r?\n/);
|
|
@@ -1506,7 +1612,7 @@ ${filed} filed, ${noop} no-op, ${conflict} conflict, ${error} error.`);
|
|
|
1506
1612
|
}
|
|
1507
1613
|
recurringSpeaker = [...turnsBySpeaker.values()].some((n) => n >= 2);
|
|
1508
1614
|
isTranscript = isFile && looksLikeTranscript(speakers, turnCount, contentLines, recurringSpeaker);
|
|
1509
|
-
slugBasis = slugHint || subject || [...speakers].join("-") || (isFile ?
|
|
1615
|
+
slugBasis = slugHint || subject || [...speakers].join("-") || (isFile ? basename3(src, extname(src)) : text.slice(0, 60));
|
|
1510
1616
|
subjectSlug = slugify(slugBasis) || "source";
|
|
1511
1617
|
noteSlug = `${date}-${subjectSlug}`;
|
|
1512
1618
|
rawDir = join10(vault, "..", "raw", isTranscript ? "transcripts" : "adhoc");
|
|
@@ -1747,7 +1853,7 @@ var init_tags = __esm(() => {
|
|
|
1747
1853
|
// scripts/recall.ts
|
|
1748
1854
|
var exports_recall = {};
|
|
1749
1855
|
import { lstatSync as lstatSync2, readdirSync as readdirSync6, readFileSync as readFileSync11 } from "node:fs";
|
|
1750
|
-
import { basename as
|
|
1856
|
+
import { basename as basename4, join as join12, relative as relative4 } from "node:path";
|
|
1751
1857
|
function walk2(dir2) {
|
|
1752
1858
|
const out = [];
|
|
1753
1859
|
for (const entry of readdirSync6(dir2)) {
|
|
@@ -1964,7 +2070,7 @@ var init_recall = __esm(() => {
|
|
|
1964
2070
|
for (const t of tokens)
|
|
1965
2071
|
tf.set(t, (tf.get(t) ?? 0) + weight);
|
|
1966
2072
|
};
|
|
1967
|
-
add([...tokenize(titleText), ...tokenize(
|
|
2073
|
+
add([...tokenize(titleText), ...tokenize(basename4(path, ".md"))], TITLE_BOOST);
|
|
1968
2074
|
add(tokenize(aliases), TITLE_BOOST);
|
|
1969
2075
|
add(tags.flatMap(tokenize), TAG_BOOST);
|
|
1970
2076
|
add(tokenize(summary), SUMMARY_BOOST);
|
|
@@ -2029,7 +2135,7 @@ var init_recall = __esm(() => {
|
|
|
2029
2135
|
var exports_snapshot = {};
|
|
2030
2136
|
import { readdirSync as readdirSync7, readFileSync as readFileSync12, copyFileSync as copyFileSync2, mkdirSync as mkdirSync4, existsSync as existsSync11, statSync as statSync7, lstatSync as lstatSync3 } from "node:fs";
|
|
2031
2137
|
import { createHash as createHash2 } from "node:crypto";
|
|
2032
|
-
import { join as join13, relative as relative5, basename as
|
|
2138
|
+
import { join as join13, relative as relative5, basename as basename5, extname as extname2, resolve as resolve5, sep as sep3 } from "node:path";
|
|
2033
2139
|
function destWithinRaw(rawRoot, dest) {
|
|
2034
2140
|
const rootResolved = resolve5(rawRoot);
|
|
2035
2141
|
const destResolved = resolve5(rootResolved, dest);
|
|
@@ -2041,7 +2147,7 @@ function collect(p, base) {
|
|
|
2041
2147
|
let skippedLinks = 0;
|
|
2042
2148
|
const st = statSync7(p);
|
|
2043
2149
|
if (st.isFile())
|
|
2044
|
-
return { files: [{ abs: p, rel:
|
|
2150
|
+
return { files: [{ abs: p, rel: basename5(p) }], skippedLinks };
|
|
2045
2151
|
const out = [];
|
|
2046
2152
|
const walk3 = (dir2) => {
|
|
2047
2153
|
for (const entry of readdirSync7(dir2)) {
|
|
@@ -2519,10 +2625,10 @@ all plugin checks passed.`);
|
|
|
2519
2625
|
var exports_cli = {};
|
|
2520
2626
|
import { cpSync as cpSync3, mkdirSync as mkdirSync5, chmodSync, existsSync as existsSync13, readFileSync as readFileSync14, lstatSync as lstatSync4, statSync as statSync9, realpathSync as realpathSync2 } from "node:fs";
|
|
2521
2627
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
2522
|
-
import { join as join15, dirname as dirname4, resolve as resolve6, basename as
|
|
2628
|
+
import { join as join15, dirname as dirname4, resolve as resolve6, basename as basename6 } from "node:path";
|
|
2523
2629
|
import { homedir as homedir4 } from "node:os";
|
|
2524
2630
|
import { fileURLToPath } from "node:url";
|
|
2525
|
-
import { createInterface } from "node:readline/promises";
|
|
2631
|
+
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
2526
2632
|
function pluginRoot() {
|
|
2527
2633
|
const local = projectRoot();
|
|
2528
2634
|
if (process.env.IMPRNT_ROOT || process.env.IMPRINT_ROOT)
|
|
@@ -2569,7 +2675,7 @@ function physicalTarget(target) {
|
|
|
2569
2675
|
const parent = dirname4(existing);
|
|
2570
2676
|
if (parent === existing)
|
|
2571
2677
|
return target;
|
|
2572
|
-
tail.unshift(
|
|
2678
|
+
tail.unshift(basename6(existing));
|
|
2573
2679
|
existing = parent;
|
|
2574
2680
|
}
|
|
2575
2681
|
try {
|
|
@@ -2647,7 +2753,8 @@ var init_cli = __esm(async () => {
|
|
|
2647
2753
|
case "lair": {
|
|
2648
2754
|
const home = requireVaultHome();
|
|
2649
2755
|
const { backend, skipPermissions, passthrough } = resolveLaunch(rest, { agent: readDefaultAgent(), yolo: readSkipPermissions() });
|
|
2650
|
-
const
|
|
2756
|
+
const resumed = backend.resolveResume ? await backend.resolveResume(passthrough, home) : passthrough;
|
|
2757
|
+
const spec = assembleSession({ cwd: home, vaultProject: home, pkgRoot, passthrough: resumed, skipPermissions, model: readDefaultModel() });
|
|
2651
2758
|
process.exit(launchBackend(backend, home, backend.renderArgs(spec), spec.env));
|
|
2652
2759
|
}
|
|
2653
2760
|
case "context": {
|
|
@@ -2670,8 +2777,8 @@ var init_cli = __esm(async () => {
|
|
|
2670
2777
|
console.log("set: imprnt agent <claude|gemini> override one session: imp --gemini | imp --claude");
|
|
2671
2778
|
break;
|
|
2672
2779
|
}
|
|
2673
|
-
if (name
|
|
2674
|
-
console.error(`unknown agent "${name}" — valid:
|
|
2780
|
+
if (!(name in backends)) {
|
|
2781
|
+
console.error(`unknown agent "${name}" — valid: ${Object.keys(backends).join(", ")}`);
|
|
2675
2782
|
process.exit(1);
|
|
2676
2783
|
}
|
|
2677
2784
|
const r = setDefaultAgent(name);
|
|
@@ -2709,7 +2816,7 @@ var init_cli = __esm(async () => {
|
|
|
2709
2816
|
const m = readDefaultModel();
|
|
2710
2817
|
console.log(`default model: ${m ?? "(agent's own default)"}`);
|
|
2711
2818
|
console.log("set: imprnt model <alias|id> clear: imprnt model off");
|
|
2712
|
-
console.log(
|
|
2819
|
+
console.log(`gemini aliases: ${Object.entries(GEMINI_MODEL_ALIASES).map(([k, v]) => `${k}=${v}`).join(", ")}`);
|
|
2713
2820
|
break;
|
|
2714
2821
|
}
|
|
2715
2822
|
if (arg === "off" || arg === "default" || arg === "none") {
|
|
@@ -2934,7 +3041,7 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
2934
3041
|
const inPlace = isVaultProject(process.cwd());
|
|
2935
3042
|
const display = inPlace ? process.cwd() : "~/imprnt";
|
|
2936
3043
|
const fallback = inPlace ? process.cwd() : join15(homedir4(), "imprnt");
|
|
2937
|
-
const rl =
|
|
3044
|
+
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
2938
3045
|
const answer = (await rl.question(`vault location [${display}]: `)).trim();
|
|
2939
3046
|
rl.close();
|
|
2940
3047
|
target = answer ? resolvePath(answer) : fallback;
|
|
@@ -3046,7 +3153,8 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3046
3153
|
}
|
|
3047
3154
|
const raw = bare ? [] : [cmd, ...rest];
|
|
3048
3155
|
const { backend, skipPermissions, passthrough } = resolveLaunch(raw, { agent: readDefaultAgent(), yolo: readSkipPermissions() });
|
|
3049
|
-
const
|
|
3156
|
+
const resumed = backend.resolveResume ? await backend.resolveResume(passthrough, process.cwd()) : passthrough;
|
|
3157
|
+
const spec = assembleSession({ cwd: process.cwd(), vaultProject: home, pkgRoot, passthrough: resumed, skipPermissions, model: readDefaultModel() });
|
|
3050
3158
|
process.exit(launchBackend(backend, process.cwd(), backend.renderArgs(spec), spec.env));
|
|
3051
3159
|
}
|
|
3052
3160
|
console.log(`imprnt — deterministic-first markdown knowledge vault
|
package/dist/imp.js
CHANGED
|
@@ -766,14 +766,9 @@ function registerVault(path, opts = {}) {
|
|
|
766
766
|
const name = opts.name ?? "personal";
|
|
767
767
|
reg.vaults[name] = path;
|
|
768
768
|
reg.default = name;
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
writeFileSync5(p, JSON.stringify(reg, null, 2) + `
|
|
773
|
-
`);
|
|
774
|
-
} catch (e) {
|
|
775
|
-
return { status: "error", current: path, error: e instanceof Error ? e.message : String(e) };
|
|
776
|
-
}
|
|
769
|
+
const w = writeRegistry(reg);
|
|
770
|
+
if (!w.ok)
|
|
771
|
+
return { status: "error", current: path, error: w.error };
|
|
777
772
|
return { status: "registered", current: path };
|
|
778
773
|
}
|
|
779
774
|
function readDefaultAgent() {
|
|
@@ -842,8 +837,9 @@ var init_registry = () => {};
|
|
|
842
837
|
// scripts/lib/launch.ts
|
|
843
838
|
import { existsSync as existsSync7, mkdtempSync as mkdtempSync2, readFileSync as readFileSync7, realpathSync, rmSync as rmSync3, statSync as statSync5, writeFileSync as writeFileSync6 } from "node:fs";
|
|
844
839
|
import { homedir as homedir2, tmpdir as tmpdir2 } from "node:os";
|
|
845
|
-
import { isAbsolute, join as join8, resolve as resolve4, sep as sep2 } from "node:path";
|
|
840
|
+
import { basename as basename2, isAbsolute, join as join8, resolve as resolve4, sep as sep2 } from "node:path";
|
|
846
841
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
842
|
+
import { createInterface } from "node:readline/promises";
|
|
847
843
|
function importPath(root, target) {
|
|
848
844
|
if (target.startsWith("~/"))
|
|
849
845
|
return join8(homedir2(), target.slice(2));
|
|
@@ -1013,7 +1009,12 @@ function claudeRenderArgs(spec) {
|
|
|
1013
1009
|
const systemPrompt = spec.insideProject ? spec.globals : joinFragments([spec.cast, spec.pointer, spec.globals]);
|
|
1014
1010
|
const harness = spec.pluginsRoot ? harnessFlags(spec.pluginsRoot) : [];
|
|
1015
1011
|
const extra = spec.addDirs.flatMap((d) => ["--add-dir", d]);
|
|
1016
|
-
const
|
|
1012
|
+
const lead = [];
|
|
1013
|
+
if (spec.skipPermissions && !spec.passthrough.includes("--dangerously-skip-permissions"))
|
|
1014
|
+
lead.push("--dangerously-skip-permissions");
|
|
1015
|
+
if (spec.model && !spec.passthrough.some((a) => a === "--model" || a.startsWith("--model=")))
|
|
1016
|
+
lead.push("--model", spec.model);
|
|
1017
|
+
const pass = lead.length ? [...lead, ...spec.passthrough] : spec.passthrough;
|
|
1017
1018
|
const body = systemPrompt ? mergeFragment(pass, systemPrompt, extra) : [...pass, ...extra];
|
|
1018
1019
|
return [...harness, ...body];
|
|
1019
1020
|
}
|
|
@@ -1023,6 +1024,19 @@ function expandGeminiModel(m) {
|
|
|
1023
1024
|
function escapeGeminiImports(text) {
|
|
1024
1025
|
return text.replaceAll("@", "\\@");
|
|
1025
1026
|
}
|
|
1027
|
+
function trackGeminiTempDir(dir) {
|
|
1028
|
+
geminiTempDirs.add(dir);
|
|
1029
|
+
if (geminiCleanupArmed)
|
|
1030
|
+
return;
|
|
1031
|
+
geminiCleanupArmed = true;
|
|
1032
|
+
process.on("exit", () => {
|
|
1033
|
+
for (const d of geminiTempDirs) {
|
|
1034
|
+
try {
|
|
1035
|
+
rmSync3(d, { recursive: true, force: true });
|
|
1036
|
+
} catch {}
|
|
1037
|
+
}
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1026
1040
|
function geminiRenderArgs(spec) {
|
|
1027
1041
|
const includes = [];
|
|
1028
1042
|
const systemPrompt = joinFragments([spec.cast, spec.pointer, spec.globals]);
|
|
@@ -1030,11 +1044,7 @@ function geminiRenderArgs(spec) {
|
|
|
1030
1044
|
const dir = mkdtempSync2(join8(tmpdir2(), "imprnt-gemini-"));
|
|
1031
1045
|
writeFileSync6(join8(dir, "GEMINI.md"), escapeGeminiImports(systemPrompt) + `
|
|
1032
1046
|
`);
|
|
1033
|
-
|
|
1034
|
-
try {
|
|
1035
|
-
rmSync3(dir, { recursive: true, force: true });
|
|
1036
|
-
} catch {}
|
|
1037
|
-
});
|
|
1047
|
+
trackGeminiTempDir(dir);
|
|
1038
1048
|
includes.push(dir);
|
|
1039
1049
|
}
|
|
1040
1050
|
includes.push(...spec.addDirs);
|
|
@@ -1049,24 +1059,117 @@ function geminiRenderArgs(spec) {
|
|
|
1049
1059
|
lead.push("--skip-trust");
|
|
1050
1060
|
}
|
|
1051
1061
|
const pass = [...spec.passthrough];
|
|
1052
|
-
const
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1062
|
+
const mTerm = pass.indexOf("--");
|
|
1063
|
+
const mEnd = mTerm < 0 ? pass.length : mTerm;
|
|
1064
|
+
const isModelFlag = (a) => a === "-m" || a === "--model" || a.startsWith("-m=") || a.startsWith("--model=");
|
|
1065
|
+
const mIdx = pass.slice(0, mEnd).findIndex(isModelFlag);
|
|
1066
|
+
if (mIdx >= 0) {
|
|
1067
|
+
const tok = pass[mIdx];
|
|
1068
|
+
const eq = tok.indexOf("=");
|
|
1069
|
+
if (eq >= 0)
|
|
1070
|
+
pass[mIdx] = tok.slice(0, eq + 1) + expandGeminiModel(tok.slice(eq + 1));
|
|
1071
|
+
else if (mIdx + 1 < mEnd && pass[mIdx + 1] !== undefined)
|
|
1072
|
+
pass[mIdx + 1] = expandGeminiModel(pass[mIdx + 1]);
|
|
1073
|
+
} else if (spec.model) {
|
|
1056
1074
|
pass.unshift("-m", expandGeminiModel(spec.model));
|
|
1057
1075
|
}
|
|
1058
|
-
const rIdx = pass
|
|
1059
|
-
if (rIdx >= 0
|
|
1076
|
+
const rIdx = valuelessResumeIndex(pass);
|
|
1077
|
+
if (rIdx >= 0)
|
|
1060
1078
|
pass.splice(rIdx + 1, 0, "latest");
|
|
1061
|
-
}
|
|
1062
1079
|
const flags = includes.length ? ["--include-directories", includes.join(",")] : [];
|
|
1063
1080
|
return [...lead, ...flags, ...pass];
|
|
1064
1081
|
}
|
|
1082
|
+
function parseGeminiSessions(stdout) {
|
|
1083
|
+
const out = [];
|
|
1084
|
+
for (const raw of stdout.split(/\r?\n/)) {
|
|
1085
|
+
const m = raw.match(/^\s*(\d+)\.\s+(.+?)\s+\(([^()]+)\)\s+\[([0-9a-fA-F-]{8,})\]\s*$/);
|
|
1086
|
+
if (m)
|
|
1087
|
+
out.push({ index: Number(m[1]), name: m[2].trim(), age: m[3].trim(), id: m[4] });
|
|
1088
|
+
}
|
|
1089
|
+
return out;
|
|
1090
|
+
}
|
|
1091
|
+
function valuelessResumeIndex(args) {
|
|
1092
|
+
const term = args.indexOf("--");
|
|
1093
|
+
const end = term < 0 ? args.length : term;
|
|
1094
|
+
let i = -1;
|
|
1095
|
+
for (let k = 0;k < end; k++) {
|
|
1096
|
+
if (args[k] === "-r" || args[k] === "--resume") {
|
|
1097
|
+
i = k;
|
|
1098
|
+
break;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
if (i < 0)
|
|
1102
|
+
return -1;
|
|
1103
|
+
const next = i + 1 < end ? args[i + 1] : undefined;
|
|
1104
|
+
return next === undefined || next.startsWith("-") ? i : -1;
|
|
1105
|
+
}
|
|
1106
|
+
function listGeminiSessions(cwd) {
|
|
1107
|
+
const r = spawnSync2("gemini", ["--list-sessions", "--skip-trust"], { cwd, encoding: "utf8" });
|
|
1108
|
+
if (r.error || r.status !== 0)
|
|
1109
|
+
return { sessions: [], ran: false };
|
|
1110
|
+
const stdout = r.stdout || "";
|
|
1111
|
+
const sessions = parseGeminiSessions(stdout);
|
|
1112
|
+
if (!sessions.length && stdout.trim() && !/\(\s*0\s*\)|no sessions/i.test(stdout)) {
|
|
1113
|
+
console.error("imp: couldn't parse gemini's session list (its format may have changed) - starting fresh");
|
|
1114
|
+
}
|
|
1115
|
+
return { sessions, ran: true };
|
|
1116
|
+
}
|
|
1117
|
+
async function pickGeminiSession(sessions, label) {
|
|
1118
|
+
const cols = process.stdout.columns || 80;
|
|
1119
|
+
const nameW = Math.max(20, Math.min(64, cols - 16));
|
|
1120
|
+
const trunc = (s) => s.length > nameW ? s.slice(0, nameW - 1) + "…" : s;
|
|
1121
|
+
process.stderr.write(`
|
|
1122
|
+
resume a chat - gemini · ${label}
|
|
1123
|
+
|
|
1124
|
+
`);
|
|
1125
|
+
sessions.forEach((s, i) => {
|
|
1126
|
+
process.stderr.write(` ${String(i + 1).padStart(2)} ${trunc(s.name).padEnd(nameW)} ${s.age.replace(/\s*ago$/, "")}
|
|
1127
|
+
`);
|
|
1128
|
+
});
|
|
1129
|
+
process.stderr.write(`
|
|
1130
|
+
`);
|
|
1131
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
1132
|
+
const answer = (await rl.question(" number to resume · enter for newest · q to cancel › ")).trim();
|
|
1133
|
+
rl.close();
|
|
1134
|
+
if (answer === "")
|
|
1135
|
+
return "latest";
|
|
1136
|
+
if (answer.toLowerCase() === "q")
|
|
1137
|
+
return null;
|
|
1138
|
+
const n = Number(answer);
|
|
1139
|
+
if (Number.isInteger(n) && n >= 1 && n <= sessions.length)
|
|
1140
|
+
return sessions[n - 1].id;
|
|
1141
|
+
process.stderr.write(` not a valid choice - starting a fresh session
|
|
1142
|
+
`);
|
|
1143
|
+
return null;
|
|
1144
|
+
}
|
|
1145
|
+
async function geminiResolveResume(passthrough, cwd) {
|
|
1146
|
+
const rIdx = valuelessResumeIndex(passthrough);
|
|
1147
|
+
if (rIdx < 0)
|
|
1148
|
+
return passthrough;
|
|
1149
|
+
if (!(process.stdin.isTTY && process.stdout.isTTY))
|
|
1150
|
+
return passthrough;
|
|
1151
|
+
const { sessions, ran } = listGeminiSessions(cwd);
|
|
1152
|
+
if (!ran)
|
|
1153
|
+
return passthrough;
|
|
1154
|
+
if (!sessions.length) {
|
|
1155
|
+
console.error("imp: no saved gemini chats for this project yet - starting fresh");
|
|
1156
|
+
return passthrough.filter((_, i) => i !== rIdx);
|
|
1157
|
+
}
|
|
1158
|
+
const chosen = await pickGeminiSession(sessions, basename2(cwd));
|
|
1159
|
+
if (chosen === null)
|
|
1160
|
+
return passthrough.filter((_, i) => i !== rIdx);
|
|
1161
|
+
const out = [...passthrough];
|
|
1162
|
+
out.splice(rIdx + 1, 0, chosen);
|
|
1163
|
+
return out;
|
|
1164
|
+
}
|
|
1065
1165
|
function resolveLaunch(passthrough, config = {}) {
|
|
1166
|
+
const term = passthrough.indexOf("--");
|
|
1167
|
+
const head = term < 0 ? passthrough : passthrough.slice(0, term);
|
|
1168
|
+
const tail = term < 0 ? [] : passthrough.slice(term);
|
|
1066
1169
|
let agentFlag;
|
|
1067
1170
|
let yoloFlag;
|
|
1068
1171
|
const rest = [];
|
|
1069
|
-
for (const a of
|
|
1172
|
+
for (const a of head) {
|
|
1070
1173
|
if (a === "--gemini")
|
|
1071
1174
|
agentFlag = agentFlag ?? "gemini";
|
|
1072
1175
|
else if (a === "--claude")
|
|
@@ -1084,9 +1187,10 @@ function resolveLaunch(passthrough, config = {}) {
|
|
|
1084
1187
|
console.error(`imp: unknown agent "${name}" - falling back to claude (valid: ${Object.keys(backends).join(", ")})`);
|
|
1085
1188
|
backend = claudeBackend;
|
|
1086
1189
|
}
|
|
1087
|
-
const
|
|
1190
|
+
const yoloEnv = process.env.IMPRNT_YOLO;
|
|
1191
|
+
const envYolo = yoloEnv === undefined ? undefined : !["0", "false", "", "off", "no"].includes(yoloEnv.toLowerCase());
|
|
1088
1192
|
const skipPermissions = yoloFlag ?? envYolo ?? config.yolo ?? false;
|
|
1089
|
-
return { backend, skipPermissions, passthrough: rest };
|
|
1193
|
+
return { backend, skipPermissions, passthrough: [...rest, ...tail] };
|
|
1090
1194
|
}
|
|
1091
1195
|
function launchBackend(backend, cwd, args, env = process.env) {
|
|
1092
1196
|
if (!isDir(cwd)) {
|
|
@@ -1101,7 +1205,7 @@ function launchBackend(backend, cwd, args, env = process.env) {
|
|
|
1101
1205
|
}
|
|
1102
1206
|
return r.status ?? 1;
|
|
1103
1207
|
}
|
|
1104
|
-
var claudeBackend, GEMINI_MODEL_ALIASES, geminiBackend, backends;
|
|
1208
|
+
var claudeBackend, GEMINI_MODEL_ALIASES, geminiTempDirs, geminiCleanupArmed = false, geminiBackend, backends;
|
|
1105
1209
|
var init_launch = __esm(() => {
|
|
1106
1210
|
init_plugins();
|
|
1107
1211
|
init_global();
|
|
@@ -1118,10 +1222,12 @@ var init_launch = __esm(() => {
|
|
|
1118
1222
|
gemma31: "gemma-4-31b-it",
|
|
1119
1223
|
gemma26: "gemma-4-26b-a4b-it"
|
|
1120
1224
|
};
|
|
1225
|
+
geminiTempDirs = new Set;
|
|
1121
1226
|
geminiBackend = {
|
|
1122
1227
|
name: "gemini",
|
|
1123
1228
|
missingHint: "Install the Gemini CLI first: npm i -g @google/gemini-cli",
|
|
1124
|
-
renderArgs: geminiRenderArgs
|
|
1229
|
+
renderArgs: geminiRenderArgs,
|
|
1230
|
+
resolveResume: geminiResolveResume
|
|
1125
1231
|
};
|
|
1126
1232
|
backends = {
|
|
1127
1233
|
claude: claudeBackend,
|
|
@@ -1164,7 +1270,7 @@ var init_manifest = () => {};
|
|
|
1164
1270
|
var exports_ingest = {};
|
|
1165
1271
|
import { readFileSync as readFileSync9, writeFileSync as writeFileSync8, mkdirSync as mkdirSync3, existsSync as existsSync9, copyFileSync, readdirSync as readdirSync5, rmSync as rmSync4, statSync as statSync6 } from "node:fs";
|
|
1166
1272
|
import { createHash } from "node:crypto";
|
|
1167
|
-
import { basename as
|
|
1273
|
+
import { basename as basename3, extname, join as join10, relative as relative3 } from "node:path";
|
|
1168
1274
|
function slugify(s) {
|
|
1169
1275
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
1170
1276
|
}
|
|
@@ -1245,7 +1351,7 @@ function applyStaged(staged, vault) {
|
|
|
1245
1351
|
return "error";
|
|
1246
1352
|
}
|
|
1247
1353
|
const title = text.match(/^#\s+(.+)$/m)?.[1]?.trim() ?? "";
|
|
1248
|
-
const slug = deriveSlug([fmScalar2(fm, "slug"), title,
|
|
1354
|
+
const slug = deriveSlug([fmScalar2(fm, "slug"), title, basename3(staged, ".md")]);
|
|
1249
1355
|
if (!slug) {
|
|
1250
1356
|
console.error(` ✗ ${staged}: can't derive a slug - slug:, the H1 title, and the filename all slugify to nothing`);
|
|
1251
1357
|
return "error";
|
|
@@ -1472,7 +1578,7 @@ ${filed} filed, ${noop} no-op, ${conflict} conflict, ${error} error.`);
|
|
|
1472
1578
|
console.log(`unchanged (hash ${hash}) — skipping ${src}. note: ${prior.note}`);
|
|
1473
1579
|
process.exit(0);
|
|
1474
1580
|
}
|
|
1475
|
-
fname =
|
|
1581
|
+
fname = basename3(src);
|
|
1476
1582
|
dateMatch = fname.match(/(\d{4}-\d{2}-\d{2})/) || text.match(/^\s*date:\s*(\d{4}-\d{2}-\d{2})/im);
|
|
1477
1583
|
date = dateMatch ? dateMatch[1] : new Date().toISOString().slice(0, 10);
|
|
1478
1584
|
lines = text.split(/\r?\n/);
|
|
@@ -1506,7 +1612,7 @@ ${filed} filed, ${noop} no-op, ${conflict} conflict, ${error} error.`);
|
|
|
1506
1612
|
}
|
|
1507
1613
|
recurringSpeaker = [...turnsBySpeaker.values()].some((n) => n >= 2);
|
|
1508
1614
|
isTranscript = isFile && looksLikeTranscript(speakers, turnCount, contentLines, recurringSpeaker);
|
|
1509
|
-
slugBasis = slugHint || subject || [...speakers].join("-") || (isFile ?
|
|
1615
|
+
slugBasis = slugHint || subject || [...speakers].join("-") || (isFile ? basename3(src, extname(src)) : text.slice(0, 60));
|
|
1510
1616
|
subjectSlug = slugify(slugBasis) || "source";
|
|
1511
1617
|
noteSlug = `${date}-${subjectSlug}`;
|
|
1512
1618
|
rawDir = join10(vault, "..", "raw", isTranscript ? "transcripts" : "adhoc");
|
|
@@ -1747,7 +1853,7 @@ var init_tags = __esm(() => {
|
|
|
1747
1853
|
// scripts/recall.ts
|
|
1748
1854
|
var exports_recall = {};
|
|
1749
1855
|
import { lstatSync as lstatSync2, readdirSync as readdirSync6, readFileSync as readFileSync11 } from "node:fs";
|
|
1750
|
-
import { basename as
|
|
1856
|
+
import { basename as basename4, join as join12, relative as relative4 } from "node:path";
|
|
1751
1857
|
function walk2(dir2) {
|
|
1752
1858
|
const out = [];
|
|
1753
1859
|
for (const entry of readdirSync6(dir2)) {
|
|
@@ -1964,7 +2070,7 @@ var init_recall = __esm(() => {
|
|
|
1964
2070
|
for (const t of tokens)
|
|
1965
2071
|
tf.set(t, (tf.get(t) ?? 0) + weight);
|
|
1966
2072
|
};
|
|
1967
|
-
add([...tokenize(titleText), ...tokenize(
|
|
2073
|
+
add([...tokenize(titleText), ...tokenize(basename4(path, ".md"))], TITLE_BOOST);
|
|
1968
2074
|
add(tokenize(aliases), TITLE_BOOST);
|
|
1969
2075
|
add(tags.flatMap(tokenize), TAG_BOOST);
|
|
1970
2076
|
add(tokenize(summary), SUMMARY_BOOST);
|
|
@@ -2029,7 +2135,7 @@ var init_recall = __esm(() => {
|
|
|
2029
2135
|
var exports_snapshot = {};
|
|
2030
2136
|
import { readdirSync as readdirSync7, readFileSync as readFileSync12, copyFileSync as copyFileSync2, mkdirSync as mkdirSync4, existsSync as existsSync11, statSync as statSync7, lstatSync as lstatSync3 } from "node:fs";
|
|
2031
2137
|
import { createHash as createHash2 } from "node:crypto";
|
|
2032
|
-
import { join as join13, relative as relative5, basename as
|
|
2138
|
+
import { join as join13, relative as relative5, basename as basename5, extname as extname2, resolve as resolve5, sep as sep3 } from "node:path";
|
|
2033
2139
|
function destWithinRaw(rawRoot, dest) {
|
|
2034
2140
|
const rootResolved = resolve5(rawRoot);
|
|
2035
2141
|
const destResolved = resolve5(rootResolved, dest);
|
|
@@ -2041,7 +2147,7 @@ function collect(p, base) {
|
|
|
2041
2147
|
let skippedLinks = 0;
|
|
2042
2148
|
const st = statSync7(p);
|
|
2043
2149
|
if (st.isFile())
|
|
2044
|
-
return { files: [{ abs: p, rel:
|
|
2150
|
+
return { files: [{ abs: p, rel: basename5(p) }], skippedLinks };
|
|
2045
2151
|
const out = [];
|
|
2046
2152
|
const walk3 = (dir2) => {
|
|
2047
2153
|
for (const entry of readdirSync7(dir2)) {
|
|
@@ -2519,10 +2625,10 @@ all plugin checks passed.`);
|
|
|
2519
2625
|
var exports_cli = {};
|
|
2520
2626
|
import { cpSync as cpSync3, mkdirSync as mkdirSync5, chmodSync, existsSync as existsSync13, readFileSync as readFileSync14, lstatSync as lstatSync4, statSync as statSync9, realpathSync as realpathSync2 } from "node:fs";
|
|
2521
2627
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
2522
|
-
import { join as join15, dirname as dirname4, resolve as resolve6, basename as
|
|
2628
|
+
import { join as join15, dirname as dirname4, resolve as resolve6, basename as basename6 } from "node:path";
|
|
2523
2629
|
import { homedir as homedir4 } from "node:os";
|
|
2524
2630
|
import { fileURLToPath } from "node:url";
|
|
2525
|
-
import { createInterface } from "node:readline/promises";
|
|
2631
|
+
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
2526
2632
|
function pluginRoot() {
|
|
2527
2633
|
const local = projectRoot();
|
|
2528
2634
|
if (process.env.IMPRNT_ROOT || process.env.IMPRINT_ROOT)
|
|
@@ -2569,7 +2675,7 @@ function physicalTarget(target) {
|
|
|
2569
2675
|
const parent = dirname4(existing);
|
|
2570
2676
|
if (parent === existing)
|
|
2571
2677
|
return target;
|
|
2572
|
-
tail.unshift(
|
|
2678
|
+
tail.unshift(basename6(existing));
|
|
2573
2679
|
existing = parent;
|
|
2574
2680
|
}
|
|
2575
2681
|
try {
|
|
@@ -2647,7 +2753,8 @@ var init_cli = __esm(async () => {
|
|
|
2647
2753
|
case "lair": {
|
|
2648
2754
|
const home = requireVaultHome();
|
|
2649
2755
|
const { backend, skipPermissions, passthrough } = resolveLaunch(rest, { agent: readDefaultAgent(), yolo: readSkipPermissions() });
|
|
2650
|
-
const
|
|
2756
|
+
const resumed = backend.resolveResume ? await backend.resolveResume(passthrough, home) : passthrough;
|
|
2757
|
+
const spec = assembleSession({ cwd: home, vaultProject: home, pkgRoot, passthrough: resumed, skipPermissions, model: readDefaultModel() });
|
|
2651
2758
|
process.exit(launchBackend(backend, home, backend.renderArgs(spec), spec.env));
|
|
2652
2759
|
}
|
|
2653
2760
|
case "context": {
|
|
@@ -2670,8 +2777,8 @@ var init_cli = __esm(async () => {
|
|
|
2670
2777
|
console.log("set: imprnt agent <claude|gemini> override one session: imp --gemini | imp --claude");
|
|
2671
2778
|
break;
|
|
2672
2779
|
}
|
|
2673
|
-
if (name
|
|
2674
|
-
console.error(`unknown agent "${name}" — valid:
|
|
2780
|
+
if (!(name in backends)) {
|
|
2781
|
+
console.error(`unknown agent "${name}" — valid: ${Object.keys(backends).join(", ")}`);
|
|
2675
2782
|
process.exit(1);
|
|
2676
2783
|
}
|
|
2677
2784
|
const r = setDefaultAgent(name);
|
|
@@ -2709,7 +2816,7 @@ var init_cli = __esm(async () => {
|
|
|
2709
2816
|
const m = readDefaultModel();
|
|
2710
2817
|
console.log(`default model: ${m ?? "(agent's own default)"}`);
|
|
2711
2818
|
console.log("set: imprnt model <alias|id> clear: imprnt model off");
|
|
2712
|
-
console.log(
|
|
2819
|
+
console.log(`gemini aliases: ${Object.entries(GEMINI_MODEL_ALIASES).map(([k, v]) => `${k}=${v}`).join(", ")}`);
|
|
2713
2820
|
break;
|
|
2714
2821
|
}
|
|
2715
2822
|
if (arg === "off" || arg === "default" || arg === "none") {
|
|
@@ -2934,7 +3041,7 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
2934
3041
|
const inPlace = isVaultProject(process.cwd());
|
|
2935
3042
|
const display = inPlace ? process.cwd() : "~/imprnt";
|
|
2936
3043
|
const fallback = inPlace ? process.cwd() : join15(homedir4(), "imprnt");
|
|
2937
|
-
const rl =
|
|
3044
|
+
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
2938
3045
|
const answer = (await rl.question(`vault location [${display}]: `)).trim();
|
|
2939
3046
|
rl.close();
|
|
2940
3047
|
target = answer ? resolvePath(answer) : fallback;
|
|
@@ -3046,7 +3153,8 @@ enable: imprnt plugin add <name> disable: imprnt plugin rm <name> [--purge]`);
|
|
|
3046
3153
|
}
|
|
3047
3154
|
const raw = bare ? [] : [cmd, ...rest];
|
|
3048
3155
|
const { backend, skipPermissions, passthrough } = resolveLaunch(raw, { agent: readDefaultAgent(), yolo: readSkipPermissions() });
|
|
3049
|
-
const
|
|
3156
|
+
const resumed = backend.resolveResume ? await backend.resolveResume(passthrough, process.cwd()) : passthrough;
|
|
3157
|
+
const spec = assembleSession({ cwd: process.cwd(), vaultProject: home, pkgRoot, passthrough: resumed, skipPermissions, model: readDefaultModel() });
|
|
3050
3158
|
process.exit(launchBackend(backend, process.cwd(), backend.renderArgs(spec), spec.env));
|
|
3051
3159
|
}
|
|
3052
3160
|
console.log(`imprnt — deterministic-first markdown knowledge vault
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imprnt",
|
|
3
|
-
"version": "0.1.3-edge.
|
|
3
|
+
"version": "0.1.3-edge.61",
|
|
4
4
|
"description": "Deterministic-first, plain-markdown knowledge vault. Code does the bulk transform. The LLM only touches the irreducibly-semantic 20%. Native grep plus BM25 retrieval, zero MCP on the vault.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|