omnius 1.0.603 → 1.0.604
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 +286 -129
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -703755,6 +703755,90 @@ var init_ollama_gpu_policy = __esm({
|
|
|
703755
703755
|
}
|
|
703756
703756
|
});
|
|
703757
703757
|
|
|
703758
|
+
// packages/cli/src/session-quality.ts
|
|
703759
|
+
function withoutAnsi(text2) {
|
|
703760
|
+
return String(text2 || "").replace(ANSI_RE, "");
|
|
703761
|
+
}
|
|
703762
|
+
function normalizeSessionDisplayText(text2) {
|
|
703763
|
+
return withoutAnsi(text2).trim().replace(MARKER_PREFIX_RE, "").replace(SPEAKER_RE, "").replace(/\s+/g, " ").trim();
|
|
703764
|
+
}
|
|
703765
|
+
function isSessionControlText(text2) {
|
|
703766
|
+
const raw = withoutAnsi(text2).trim().replace(/^[∙•·‹›▹▸▶►◆◇❯❮>\-=_*#|\\.\s]+/, "").replace(SPEAKER_RE, "").trim();
|
|
703767
|
+
return CONTROL_ONLY_RE.test(raw);
|
|
703768
|
+
}
|
|
703769
|
+
function isSessionNoiseText(text2) {
|
|
703770
|
+
const raw = withoutAnsi(text2).trim();
|
|
703771
|
+
if (!raw || raw.length < 3 || isSessionControlText(raw)) return true;
|
|
703772
|
+
if (BOX_OR_TOOL_CHROME_RE.test(raw)) return true;
|
|
703773
|
+
const core = normalizeSessionDisplayText(raw);
|
|
703774
|
+
if (!core || core.length < 3 || CONTROL_ONLY_RE.test(core)) return true;
|
|
703775
|
+
return STATUS_RE.test(core);
|
|
703776
|
+
}
|
|
703777
|
+
function firstMeaningfulSessionLine(transcript) {
|
|
703778
|
+
const lines = withoutAnsi(transcript).split(/\r?\n/).map((line) => line.trim());
|
|
703779
|
+
for (const line of lines) {
|
|
703780
|
+
if (USER_LINE_RE.test(line) && !isSessionNoiseText(line)) {
|
|
703781
|
+
return normalizeSessionDisplayText(line);
|
|
703782
|
+
}
|
|
703783
|
+
}
|
|
703784
|
+
for (const line of lines) {
|
|
703785
|
+
if (!isSessionNoiseText(line)) return normalizeSessionDisplayText(line);
|
|
703786
|
+
}
|
|
703787
|
+
return "";
|
|
703788
|
+
}
|
|
703789
|
+
function hasMeaningfulSessionContent(transcript) {
|
|
703790
|
+
return firstMeaningfulSessionLine(transcript).length > 0;
|
|
703791
|
+
}
|
|
703792
|
+
function normalizedSessionFingerprint(transcript) {
|
|
703793
|
+
const semantic = [];
|
|
703794
|
+
let mode = "text";
|
|
703795
|
+
let inToolBox = false;
|
|
703796
|
+
for (const raw of withoutAnsi(transcript).split(/\r?\n/)) {
|
|
703797
|
+
const line = raw.trim();
|
|
703798
|
+
if (!line) continue;
|
|
703799
|
+
if (/^[╭┌]/.test(line)) {
|
|
703800
|
+
inToolBox = true;
|
|
703801
|
+
continue;
|
|
703802
|
+
}
|
|
703803
|
+
if (/^[╰└]/.test(line)) {
|
|
703804
|
+
inToolBox = false;
|
|
703805
|
+
continue;
|
|
703806
|
+
}
|
|
703807
|
+
if (inToolBox) continue;
|
|
703808
|
+
const user = line.match(/^(?:[▹▸►❯>]\s*|(?:User|You)\s*:\s*)(.+)$/i);
|
|
703809
|
+
if (user && !isSessionNoiseText(user[1] || "")) {
|
|
703810
|
+
mode = "user";
|
|
703811
|
+
semantic.push(`user:${normalizeSessionDisplayText(user[1] || "").toLowerCase()}`);
|
|
703812
|
+
continue;
|
|
703813
|
+
}
|
|
703814
|
+
const assistant = line.match(/^(?:(?:Assistant|Open Agent|Omnius)\s*:\s*|│\s?)(.*)$/i);
|
|
703815
|
+
if (assistant) {
|
|
703816
|
+
const content2 = normalizeSessionDisplayText((assistant[1] || "").replace(/\s?│$/, ""));
|
|
703817
|
+
if (content2) {
|
|
703818
|
+
mode = "assistant";
|
|
703819
|
+
semantic.push(`assistant:${content2.toLowerCase()}`);
|
|
703820
|
+
}
|
|
703821
|
+
continue;
|
|
703822
|
+
}
|
|
703823
|
+
if (isSessionNoiseText(line)) continue;
|
|
703824
|
+
const content = normalizeSessionDisplayText(line);
|
|
703825
|
+
if (content) semantic.push(`${mode}:${content.toLowerCase()}`);
|
|
703826
|
+
}
|
|
703827
|
+
return semantic.join("\n");
|
|
703828
|
+
}
|
|
703829
|
+
var ANSI_RE, SPEAKER_RE, MARKER_PREFIX_RE, USER_LINE_RE, CONTROL_ONLY_RE, BOX_OR_TOOL_CHROME_RE, STATUS_RE;
|
|
703830
|
+
var init_session_quality = __esm({
|
|
703831
|
+
"packages/cli/src/session-quality.ts"() {
|
|
703832
|
+
ANSI_RE = /\x1B\[[0-9;]*m|\x1B\][^\x07]*(?:\x07|\x1B\\)/g;
|
|
703833
|
+
SPEAKER_RE = /^(?:User|Assistant|You|Open Agent|Omnius)\s*:\s*/i;
|
|
703834
|
+
MARKER_PREFIX_RE = /^[∙•·‹›▹▸▶►◆◇❯❮>\-=_*#|/\\.\s]+/;
|
|
703835
|
+
USER_LINE_RE = /^(?:[▹▸►❯>]\s+\S|(?:User|You)\s*:\s*\S)/i;
|
|
703836
|
+
CONTROL_ONLY_RE = /^\/?(?:q|quit|exit)$/i;
|
|
703837
|
+
BOX_OR_TOOL_CHROME_RE = /^[╭╮╰╯├┤┬┴┌┐└┘─━═╿│▌▐█▒░●○◐◖✔✖$]/;
|
|
703838
|
+
STATUS_RE = /^(?:nexus|rest api|voice feedback|clone ref|connecting to|connected|http:\/\/|https:\/\/|last task:|\(manual save\)|good morning|good evening|good afternoon|cannot reach|could not|unable to|warning:|error:|loaded tui session|session restored|restored previous|using (?:expanded )?context model|using model|tui session\b|chat tui:|previous session found|context (?:auto-)?restored|context restored|recovered session|\[?new_task_intake\b|\[imported tui session transcript\]|title:|description:|project root:|user is asking\b|\[vram|vram |model_info|kv |arch[ -]capped|no context to restore|starting fresh|use \/endpoint|general session$|knowledge graph:|zettelkasten:|episodes captured:|current omnius_host:)/i;
|
|
703839
|
+
}
|
|
703840
|
+
});
|
|
703841
|
+
|
|
703758
703842
|
// packages/cli/src/tui/omnius-directory.ts
|
|
703759
703843
|
var omnius_directory_exports = {};
|
|
703760
703844
|
__export(omnius_directory_exports, {
|
|
@@ -705130,16 +705214,18 @@ function firstMeaningfulSessionHistoryLine(lines) {
|
|
|
705130
705214
|
const trimmed = line.trimStart();
|
|
705131
705215
|
if (!trimmed || VISUAL_CHROME_LINE.test(trimmed)) continue;
|
|
705132
705216
|
const clean7 = cleanSessionHistoryDisplayLine(line);
|
|
705133
|
-
if (!clean7 || SESSION_TITLE_STATUS_LINE.test(clean7)) continue;
|
|
705217
|
+
if (!clean7 || SESSION_TITLE_STATUS_LINE.test(clean7) || isSessionNoiseText(clean7)) continue;
|
|
705134
705218
|
return clean7;
|
|
705135
705219
|
}
|
|
705136
|
-
return "";
|
|
705220
|
+
return firstMeaningfulSessionLine(lines.slice(0, 120).join("\n"));
|
|
705137
705221
|
}
|
|
705138
|
-
function sanitizeSessionHistoryEntry(repoRoot, entry) {
|
|
705139
|
-
const
|
|
705140
|
-
const
|
|
705222
|
+
function sanitizeSessionHistoryEntry(repoRoot, entry, loadedLines) {
|
|
705223
|
+
const cleanName = cleanSessionHistoryDisplayLine(entry.name);
|
|
705224
|
+
const cleanDescription = cleanSessionHistoryDisplayLine(entry.description);
|
|
705225
|
+
const nameLooksAuthored = cleanName.length > 0 && !isSessionNoiseText(cleanName);
|
|
705226
|
+
const descriptionLooksAuthored = cleanDescription.length > 0 && !isSessionNoiseText(cleanDescription);
|
|
705141
705227
|
if (nameLooksAuthored && descriptionLooksAuthored) return entry;
|
|
705142
|
-
const lines = loadSessionHistory(repoRoot, entry.id)
|
|
705228
|
+
const lines = loadedLines ?? loadSessionHistory(repoRoot, entry.id) ?? [];
|
|
705143
705229
|
const fallback = firstMeaningfulSessionHistoryLine(lines);
|
|
705144
705230
|
return {
|
|
705145
705231
|
...entry,
|
|
@@ -705166,14 +705252,16 @@ function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
|
|
|
705166
705252
|
} catch {
|
|
705167
705253
|
}
|
|
705168
705254
|
const existing = index.findIndex((s2) => s2.id === sessionId);
|
|
705255
|
+
const previous = existing >= 0 ? index[existing] : void 0;
|
|
705169
705256
|
const record = {
|
|
705257
|
+
...previous ?? {},
|
|
705170
705258
|
id: sessionId,
|
|
705171
|
-
name: autoName,
|
|
705172
|
-
description: autoDesc,
|
|
705173
|
-
createdAt:
|
|
705259
|
+
name: !isSessionNoiseText(autoName) ? autoName : previous?.name ?? autoName,
|
|
705260
|
+
description: !isSessionNoiseText(autoDesc) ? autoDesc : previous?.description ?? autoDesc,
|
|
705261
|
+
createdAt: previous?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
705174
705262
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
705175
|
-
taskCount: meta.taskCount ?? 1,
|
|
705176
|
-
model: meta.model ?? "unknown"
|
|
705263
|
+
taskCount: meta.taskCount ?? previous?.taskCount ?? 1,
|
|
705264
|
+
model: meta.model ?? previous?.model ?? "unknown"
|
|
705177
705265
|
};
|
|
705178
705266
|
if (existing >= 0) {
|
|
705179
705267
|
index[existing] = record;
|
|
@@ -705186,6 +705274,15 @@ function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
|
|
|
705186
705274
|
unlinkSync28(join141(sessDir, `${removed.id}.jsonl`));
|
|
705187
705275
|
} catch {
|
|
705188
705276
|
}
|
|
705277
|
+
try {
|
|
705278
|
+
unlinkSync28(join141(sessDir, `${removed.id}${TUI_STATE_SUFFIX}`));
|
|
705279
|
+
} catch {
|
|
705280
|
+
}
|
|
705281
|
+
try {
|
|
705282
|
+
const mirrorId = `tui:${removed.id}`.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
705283
|
+
unlinkSync28(join141(homedir45(), ".omnius", "chat-sessions", `${mirrorId}.json`));
|
|
705284
|
+
} catch {
|
|
705285
|
+
}
|
|
705189
705286
|
}
|
|
705190
705287
|
writeFileSync70(indexPath, JSON.stringify(index, null, 2), "utf-8");
|
|
705191
705288
|
}
|
|
@@ -705222,7 +705319,13 @@ function listSessions(repoRoot) {
|
|
|
705222
705319
|
try {
|
|
705223
705320
|
if (!existsSync130(indexPath)) return [];
|
|
705224
705321
|
const index = JSON.parse(readFileSync107(indexPath, "utf-8"));
|
|
705225
|
-
|
|
705322
|
+
const eligible = [];
|
|
705323
|
+
for (const entry of index) {
|
|
705324
|
+
const lines = loadSessionHistory(repoRoot, entry.id) ?? [];
|
|
705325
|
+
if (!hasMeaningfulSessionContent(lines.join("\n"))) continue;
|
|
705326
|
+
eligible.push(sanitizeSessionHistoryEntry(repoRoot, entry, lines));
|
|
705327
|
+
}
|
|
705328
|
+
return eligible.sort((a2, b) => b.updatedAt.localeCompare(a2.updatedAt));
|
|
705226
705329
|
} catch {
|
|
705227
705330
|
return [];
|
|
705228
705331
|
}
|
|
@@ -705244,6 +705347,9 @@ function deleteSession(repoRoot, sessionId) {
|
|
|
705244
705347
|
if (existsSync130(contentPath)) unlinkSync28(contentPath);
|
|
705245
705348
|
const statePath = join141(sessDir, `${sessionId}${TUI_STATE_SUFFIX}`);
|
|
705246
705349
|
if (existsSync130(statePath)) unlinkSync28(statePath);
|
|
705350
|
+
const mirrorId = `tui:${sessionId}`.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
705351
|
+
const mirrorPath = join141(homedir45(), ".omnius", "chat-sessions", `${mirrorId}.json`);
|
|
705352
|
+
if (existsSync130(mirrorPath)) unlinkSync28(mirrorPath);
|
|
705247
705353
|
if (existsSync130(indexPath)) {
|
|
705248
705354
|
let index = JSON.parse(readFileSync107(indexPath, "utf-8"));
|
|
705249
705355
|
index = index.filter((s2) => s2.id !== sessionId);
|
|
@@ -705481,6 +705587,7 @@ var init_omnius_directory = __esm({
|
|
|
705481
705587
|
"packages/cli/src/tui/omnius-directory.ts"() {
|
|
705482
705588
|
init_dist5();
|
|
705483
705589
|
init_task_complete_box();
|
|
705590
|
+
init_session_quality();
|
|
705484
705591
|
OMNIUS_DIR2 = ".omnius";
|
|
705485
705592
|
LEGACY_DIRS = [".oa", ".open-agents"];
|
|
705486
705593
|
SUBDIRS = ["memory", "index", "context", "history", "notes", "embedded", "provenance", "tools", "dreams"];
|
|
@@ -705596,29 +705703,12 @@ var init_omnius_directory = __esm({
|
|
|
705596
705703
|
});
|
|
705597
705704
|
|
|
705598
705705
|
// packages/cli/src/api/session-summary.ts
|
|
705599
|
-
function isNoiseLine(line) {
|
|
705600
|
-
const t2 = line.trim();
|
|
705601
|
-
if (t2.length < 3) return true;
|
|
705602
|
-
const core = t2.replace(TUI_MARKER_PREFIX, "").trim();
|
|
705603
|
-
if (core.length < 3) return true;
|
|
705604
|
-
return /^(nexus|rest api|voice feedback|clone ref|connecting to|connected|http:\/\/|https:\/\/|last task:|\(manual save\)|good morning|good evening|good afternoon|cannot reach|could not|unable to|warning:|error:|loaded tui session|session restored|restored previous|using (expanded )?context model|using model|tui session\b|chat tui:|previous session found|context (auto-)?restored|context restored|recovered session|\[vram|vram |model_info|kv |arch[ -]capped)/i.test(core);
|
|
705605
|
-
}
|
|
705606
|
-
function firstMeaningfulLine(transcript) {
|
|
705607
|
-
const lines = transcript.split("\n").map((r2) => r2.replace(ANSI_RE, "").trim());
|
|
705608
|
-
for (const line of lines) {
|
|
705609
|
-
if (/^[▹▸►❯>]\s+\S/.test(line) && !isNoiseLine(line)) return line;
|
|
705610
|
-
}
|
|
705611
|
-
for (const line of lines) {
|
|
705612
|
-
if (line && !isNoiseLine(line)) return line;
|
|
705613
|
-
}
|
|
705614
|
-
return "";
|
|
705615
|
-
}
|
|
705616
705706
|
function clamp9(value2, max) {
|
|
705617
705707
|
const v = value2.replace(/\s+/g, " ").trim();
|
|
705618
705708
|
return v.length > max ? v.slice(0, max - 1).trimEnd() + "…" : v;
|
|
705619
705709
|
}
|
|
705620
705710
|
function deterministicSummary(transcript) {
|
|
705621
|
-
const first2 =
|
|
705711
|
+
const first2 = firstMeaningfulSessionLine(transcript);
|
|
705622
705712
|
if (!first2) return { title: "Untitled session", summary: "Empty session." };
|
|
705623
705713
|
const cleaned = first2.replace(TUI_MARKER_PREFIX, "").replace(/^[>›$#\s]+/, "").trim();
|
|
705624
705714
|
const title = clamp9(cleaned, TITLE_MAX);
|
|
@@ -705640,7 +705730,7 @@ function parseSummaryReply(content) {
|
|
|
705640
705730
|
}
|
|
705641
705731
|
async function generateSessionSummary(args) {
|
|
705642
705732
|
const fallback = deterministicSummary(args.transcript);
|
|
705643
|
-
const transcript = (args.transcript || "").replace(
|
|
705733
|
+
const transcript = (args.transcript || "").replace(ANSI_RE2, "").trim();
|
|
705644
705734
|
if (!transcript || !args.config.model || !args.config.backendUrl) return fallback;
|
|
705645
705735
|
try {
|
|
705646
705736
|
const url = normalizeBaseUrl(args.config.backendUrl) + "/v1/chat/completions";
|
|
@@ -705673,8 +705763,9 @@ async function generateSessionSummary(args) {
|
|
|
705673
705763
|
const content = data?.choices?.[0]?.message?.content ?? "";
|
|
705674
705764
|
const parsed = parseSummaryReply(content);
|
|
705675
705765
|
if (!parsed) return fallback;
|
|
705766
|
+
const parsedTitle = clamp9(parsed.title, TITLE_MAX);
|
|
705676
705767
|
return {
|
|
705677
|
-
title:
|
|
705768
|
+
title: parsedTitle && !isSessionNoiseText(parsedTitle) ? parsedTitle : fallback.title,
|
|
705678
705769
|
summary: clamp9(parsed.summary, SUMMARY_MAX) || fallback.summary
|
|
705679
705770
|
};
|
|
705680
705771
|
} catch {
|
|
@@ -705685,7 +705776,7 @@ async function ensureSessionSummary(args) {
|
|
|
705685
705776
|
const entry = listSessions(args.repoRoot).find(
|
|
705686
705777
|
(e2) => e2.id === args.sessionId
|
|
705687
705778
|
);
|
|
705688
|
-
if (entry?.aiTitle && entry.aiSummary && !args.force) {
|
|
705779
|
+
if (entry?.aiTitle && entry.aiSummary && !isSessionNoiseText(entry.aiTitle) && !args.force) {
|
|
705689
705780
|
return { title: entry.aiTitle, summary: entry.aiSummary };
|
|
705690
705781
|
}
|
|
705691
705782
|
const lines = loadSessionHistory(args.repoRoot, args.sessionId);
|
|
@@ -705711,19 +705802,20 @@ async function ensureSessionSummary(args) {
|
|
|
705711
705802
|
_inflightSummaries.delete(key);
|
|
705712
705803
|
}
|
|
705713
705804
|
}
|
|
705714
|
-
function sessionDisplayTitle(entry) {
|
|
705715
|
-
if (entry.aiTitle && entry.aiTitle
|
|
705716
|
-
return deterministicSummary(entry.name
|
|
705805
|
+
function sessionDisplayTitle(entry, transcript = "") {
|
|
705806
|
+
if (entry.aiTitle && !isSessionNoiseText(entry.aiTitle)) return entry.aiTitle.trim();
|
|
705807
|
+
return deterministicSummary(transcript || [entry.name, entry.description].filter(Boolean).join("\n")).title;
|
|
705717
705808
|
}
|
|
705718
|
-
var TITLE_MAX, SUMMARY_MAX, TRANSCRIPT_CHARS,
|
|
705809
|
+
var TITLE_MAX, SUMMARY_MAX, TRANSCRIPT_CHARS, ANSI_RE2, TUI_MARKER_PREFIX, _inflightSummaries;
|
|
705719
705810
|
var init_session_summary = __esm({
|
|
705720
705811
|
"packages/cli/src/api/session-summary.ts"() {
|
|
705721
705812
|
init_dist6();
|
|
705722
705813
|
init_omnius_directory();
|
|
705814
|
+
init_session_quality();
|
|
705723
705815
|
TITLE_MAX = 56;
|
|
705724
705816
|
SUMMARY_MAX = 160;
|
|
705725
705817
|
TRANSCRIPT_CHARS = 6e3;
|
|
705726
|
-
|
|
705818
|
+
ANSI_RE2 = /\x1B\[[0-9;]*m|\x1B\][^\x07]*(?:\x07|\x1B\\)/g;
|
|
705727
705819
|
TUI_MARKER_PREFIX = /^[∙•·‹›▹▸▶►◆◇❯❮>\-=_*#|/\\.\s]+/;
|
|
705728
705820
|
_inflightSummaries = /* @__PURE__ */ new Set();
|
|
705729
705821
|
}
|
|
@@ -706617,7 +706709,7 @@ function paintBlockBorder(glyphs, stage2, phase, truecolor, startCol = 0) {
|
|
|
706617
706709
|
return `${out}\x1B[0m`;
|
|
706618
706710
|
}
|
|
706619
706711
|
function sanitizeSubAgentActivity(value2) {
|
|
706620
|
-
return value2.replace(
|
|
706712
|
+
return value2.replace(ANSI_RE3, "").replace(/[\x00-\x1F\x7F]/g, " ").replace(/\s+/g, " ").trim().slice(0, MAX_ACTIVITY_CHARS);
|
|
706621
706713
|
}
|
|
706622
706714
|
function appendSubAgentActivity(entry, value2, maxLines = 3) {
|
|
706623
706715
|
const line = sanitizeSubAgentActivity(value2);
|
|
@@ -706671,7 +706763,7 @@ function contentRow(value2, width, stage2, phase, truecolor) {
|
|
|
706671
706763
|
return `${left} ${fit2(value2, width)} ${right}`;
|
|
706672
706764
|
}
|
|
706673
706765
|
function fit2(value2, width) {
|
|
706674
|
-
const plain = value2.replace(
|
|
706766
|
+
const plain = value2.replace(ANSI_RE3, "").replace(/\s+$/g, "");
|
|
706675
706767
|
const chars = Array.from(plain);
|
|
706676
706768
|
if (chars.length > width) {
|
|
706677
706769
|
return `${chars.slice(0, Math.max(0, width - 1)).join("")}…`;
|
|
@@ -706691,11 +706783,11 @@ function statusIcon(status) {
|
|
|
706691
706783
|
return "●";
|
|
706692
706784
|
}
|
|
706693
706785
|
}
|
|
706694
|
-
var
|
|
706786
|
+
var ANSI_RE3, MAX_PREVIEW_AGENTS, MAX_ACTIVITY_CHARS, STAGE_FALLBACK_COLOR, BORDER_GRADIENT_SEG;
|
|
706695
706787
|
var init_sub_agent_live_block = __esm({
|
|
706696
706788
|
"packages/cli/src/tui/sub-agent-live-block.ts"() {
|
|
706697
706789
|
init_stageIndicator();
|
|
706698
|
-
|
|
706790
|
+
ANSI_RE3 = /\x1B\[[0-?]*[ -/]*[@-~]|\x1B\].*?(?:\x07|\x1B\\)/g;
|
|
706699
706791
|
MAX_PREVIEW_AGENTS = 4;
|
|
706700
706792
|
MAX_ACTIVITY_CHARS = 220;
|
|
706701
706793
|
STAGE_FALLBACK_COLOR = {
|
|
@@ -706815,19 +706907,19 @@ function row(value2, width, stage2, phase, truecolor) {
|
|
|
706815
706907
|
return `${left} ${fit3(value2, width)} ${right}`;
|
|
706816
706908
|
}
|
|
706817
706909
|
function fit3(value2, width) {
|
|
706818
|
-
const clean7 = value2.replace(
|
|
706910
|
+
const clean7 = value2.replace(ANSI_RE4, "").replace(/\s+/g, " ").trim();
|
|
706819
706911
|
const chars = Array.from(clean7);
|
|
706820
706912
|
if (chars.length > width) {
|
|
706821
706913
|
return `${chars.slice(0, Math.max(0, width - 1)).join("")}…`;
|
|
706822
706914
|
}
|
|
706823
706915
|
return clean7 + " ".repeat(Math.max(0, width - chars.length));
|
|
706824
706916
|
}
|
|
706825
|
-
var
|
|
706917
|
+
var ANSI_RE4;
|
|
706826
706918
|
var init_trajectory_live_block = __esm({
|
|
706827
706919
|
"packages/cli/src/tui/trajectory-live-block.ts"() {
|
|
706828
706920
|
init_stageIndicator();
|
|
706829
706921
|
init_sub_agent_live_block();
|
|
706830
|
-
|
|
706922
|
+
ANSI_RE4 = /\x1B\[[0-?]*[ -/]*[@-~]|\x1B\].*?(?:\x07|\x1B\\)/g;
|
|
706831
706923
|
}
|
|
706832
706924
|
});
|
|
706833
706925
|
|
|
@@ -719818,7 +719910,7 @@ export PATH="${binDir}:$PATH" # Added by omnius for nvim
|
|
|
719818
719910
|
} catch {
|
|
719819
719911
|
}
|
|
719820
719912
|
}
|
|
719821
|
-
var execAsync2, OMNIUS_FIRST_RUN_BANNER,
|
|
719913
|
+
var execAsync2, OMNIUS_FIRST_RUN_BANNER, ANSI_RE5, visibleLen2, SETUP_MODEL_VARIANTS, _toolSupportCache, EXPANDED_VARIANT_MIN_NUM_CTX, _cloudflaredInstallPromise;
|
|
719822
719914
|
var init_setup = __esm({
|
|
719823
719915
|
"packages/cli/src/tui/setup.ts"() {
|
|
719824
719916
|
init_model_picker();
|
|
@@ -719838,8 +719930,8 @@ var init_setup = __esm({
|
|
|
719838
719930
|
"░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ",
|
|
719839
719931
|
" ░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓██████▓▒░░▒▓███████▓▒░ "
|
|
719840
719932
|
].join("\n");
|
|
719841
|
-
|
|
719842
|
-
visibleLen2 = (value2) => Array.from(value2.replace(
|
|
719933
|
+
ANSI_RE5 = /\x1B\[[0-?]*[ -/]*[@-~]/g;
|
|
719934
|
+
visibleLen2 = (value2) => Array.from(value2.replace(ANSI_RE5, "")).length;
|
|
719843
719935
|
SETUP_MODEL_VARIANTS = [
|
|
719844
719936
|
{ tag: "robit/ornith:9b", sizeGB: 6.6, label: "9B params (6.6 GB) - recommended minimum", cloud: false },
|
|
719845
719937
|
{ tag: "robit/ornith:35b", sizeGB: 24, label: "35B params (24 GB) - recommended on 32GB+ unified memory/VRAM", cloud: false }
|
|
@@ -749568,21 +749660,13 @@ function stripAnsi6(text2) {
|
|
|
749568
749660
|
return String(text2 || "").replace(/\u001b\[[0-9;]*[a-zA-Z]/g, "");
|
|
749569
749661
|
}
|
|
749570
749662
|
function cleanSessionDisplayLine(line) {
|
|
749571
|
-
return stripAnsi6(line)
|
|
749663
|
+
return normalizeSessionDisplayText(stripAnsi6(line));
|
|
749572
749664
|
}
|
|
749573
749665
|
function isNoisySessionDisplayLine(line) {
|
|
749574
|
-
|
|
749575
|
-
if (!clean7) return true;
|
|
749576
|
-
return /^(?:Previous session found|REST API:|Nexus P2P network connected|No context to restore|Starting fresh|Use \/endpoint|Knowledge graph:|Zettelkasten:|Episodes captured:|Current OMNIUS_HOST:|Loaded TUI session|General session$|Chat tui:sess|\[Imported TUI session transcript\]|Title:|Description:|Project root:|i\s+)/i.test(clean7);
|
|
749666
|
+
return isSessionNoiseText(line || "") || /^(?:\[Imported TUI session transcript\]|Title:|Description:|Project root:|i\s+)/i.test(cleanSessionDisplayLine(line || ""));
|
|
749577
749667
|
}
|
|
749578
749668
|
function bestSessionDisplayLine(text2) {
|
|
749579
|
-
|
|
749580
|
-
for (const line of lines) {
|
|
749581
|
-
const clean7 = cleanSessionDisplayLine(line);
|
|
749582
|
-
if (!isNoisySessionDisplayLine(clean7)) return clean7;
|
|
749583
|
-
}
|
|
749584
|
-
const fallback = stripAnsi6(text2).replace(/\s+/g, " ").trim();
|
|
749585
|
-
return isNoisySessionDisplayLine(fallback) ? "" : fallback;
|
|
749669
|
+
return firstMeaningfulSessionLine(stripAnsi6(text2));
|
|
749586
749670
|
}
|
|
749587
749671
|
function makeTitle(text2) {
|
|
749588
749672
|
const clean7 = bestSessionDisplayLine(text2);
|
|
@@ -749796,7 +749880,7 @@ function importTranscriptSession(opts) {
|
|
|
749796
749880
|
"",
|
|
749797
749881
|
cappedTranscript || "(empty transcript)"
|
|
749798
749882
|
].filter(Boolean).join("\n");
|
|
749799
|
-
const
|
|
749883
|
+
const isImportedNotice = (message2) => message2.role === "assistant" && /^Loaded TUI session ".*"\. Its transcript is attached as context for this chat\.$/.test(message2.content);
|
|
749800
749884
|
const existing = lookupSession(id2);
|
|
749801
749885
|
if (existing) {
|
|
749802
749886
|
existing.projectRoot = projectRoot;
|
|
@@ -749806,14 +749890,12 @@ function importTranscriptSession(opts) {
|
|
|
749806
749890
|
existing.preview = preview;
|
|
749807
749891
|
existing.transcript = cappedTranscript || "(empty transcript)";
|
|
749808
749892
|
existing.lastActivity = opts.updatedAt ?? Date.now();
|
|
749893
|
+
existing.messages = existing.messages.filter((message2) => !isImportedNotice(message2));
|
|
749809
749894
|
const idx = existing.messages.findIndex(
|
|
749810
749895
|
(m2) => m2.role === "system" && m2.content.startsWith("[Imported TUI session transcript]")
|
|
749811
749896
|
);
|
|
749812
749897
|
if (idx >= 0) existing.messages[idx] = { role: "system", content: importedContext };
|
|
749813
749898
|
else existing.messages.splice(1, 0, { role: "system", content: importedContext });
|
|
749814
|
-
if (!existing.messages.some((m2) => m2.role === "assistant" && m2.content === visibleNotice)) {
|
|
749815
|
-
existing.messages.push({ role: "assistant", content: visibleNotice });
|
|
749816
|
-
}
|
|
749817
749899
|
persistSession(existing);
|
|
749818
749900
|
return existing;
|
|
749819
749901
|
}
|
|
@@ -749822,8 +749904,7 @@ function importTranscriptSession(opts) {
|
|
|
749822
749904
|
id: id2,
|
|
749823
749905
|
messages: [
|
|
749824
749906
|
{ role: "system", content: buildSystemPrompt(projectRoot) },
|
|
749825
|
-
{ role: "system", content: importedContext }
|
|
749826
|
-
{ role: "assistant", content: visibleNotice }
|
|
749907
|
+
{ role: "system", content: importedContext }
|
|
749827
749908
|
],
|
|
749828
749909
|
model: opts.model || "unknown",
|
|
749829
749910
|
createdAt: opts.createdAt ?? opts.updatedAt ?? now2,
|
|
@@ -749968,6 +750049,9 @@ function listSessions2(opts = {}) {
|
|
|
749968
750049
|
if (!root) return true;
|
|
749969
750050
|
if (!s2.projectRoot) return !!opts.includeUnscoped;
|
|
749970
750051
|
return normalizeRoot(s2.projectRoot) === root;
|
|
750052
|
+
}).filter((s2) => {
|
|
750053
|
+
const authoredTurns = s2.messages.filter((message2) => message2.role === "user").map((message2) => message2.content).join("\n");
|
|
750054
|
+
return hasMeaningfulSessionContent(authoredTurns) || hasMeaningfulSessionContent(s2.transcript || "") || !!s2.title && !isNoisySessionDisplayLine(s2.title);
|
|
749971
750055
|
}).sort((a2, b) => b.lastActivity - a2.lastActivity).map((s2) => ({
|
|
749972
750056
|
id: s2.id,
|
|
749973
750057
|
model: s2.model,
|
|
@@ -750076,6 +750160,7 @@ var sessions2, inFlight, SESSION_TTL_MS, INFERENCE_ROLES, PARTIAL_TAIL_BUDGET;
|
|
|
750076
750160
|
var init_chat_session = __esm({
|
|
750077
750161
|
"packages/cli/src/api/chat-session.ts"() {
|
|
750078
750162
|
init_secret_redactor();
|
|
750163
|
+
init_session_quality();
|
|
750079
750164
|
sessions2 = /* @__PURE__ */ new Map();
|
|
750080
750165
|
inFlight = /* @__PURE__ */ new Map();
|
|
750081
750166
|
SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -796406,8 +796491,10 @@ async function loadServerPrefs() {
|
|
|
796406
796491
|
function isNoisyChatSessionText(text) {
|
|
796407
796492
|
const clean = String(text || '').replace(/\\s+/g, ' ').trim();
|
|
796408
796493
|
if (!clean) return true;
|
|
796409
|
-
const
|
|
796410
|
-
|
|
796494
|
+
const raw = clean.replace(/^[>❯▹∙•\\-\\s]+/, '');
|
|
796495
|
+
if (/^\\/?(?:q|quit|exit)$/i.test(raw)) return true;
|
|
796496
|
+
const t = raw.replace(/^\\/+/, '');
|
|
796497
|
+
return /^(Previous session found|REST API:|Nexus P2P network connected|No context to restore|Starting fresh|Use \\/endpoint|General session$|Loaded TUI session|Chat tui:sess|Last task:|\\(manual save\\)|Using (?:expanded )?context model|Using model|TUI session\\b|\\[?NEW_TASK_INTAKE\\b|User is asking\\b|Context (?:auto-)?restored|Recovered session)/i.test(t);
|
|
796411
796498
|
}
|
|
796412
796499
|
|
|
796413
796500
|
function isGenericChatTitle(id, title) {
|
|
@@ -796424,10 +796511,11 @@ function sessionDisplayTitle(id, session) {
|
|
|
796424
796511
|
if (!isGenericChatTitle(id, candidate)) return String(candidate).trim();
|
|
796425
796512
|
}
|
|
796426
796513
|
if (Array.isArray(s.messages)) {
|
|
796427
|
-
for (
|
|
796428
|
-
const msg
|
|
796429
|
-
|
|
796430
|
-
|
|
796514
|
+
for (const preferredRole of ['user', 'assistant']) {
|
|
796515
|
+
for (const msg of s.messages) {
|
|
796516
|
+
const content = msg && msg.role === preferredRole && typeof msg.content === 'string' ? msg.content : '';
|
|
796517
|
+
if (!isGenericChatTitle(id, content)) return content.replace(/\\s+/g, ' ').trim().slice(0, 72);
|
|
796518
|
+
}
|
|
796431
796519
|
}
|
|
796432
796520
|
}
|
|
796433
796521
|
return String(id || '').startsWith('tui:') ? 'TUI session ' + String(id).slice(4, 16) : 'Chat ' + String(id || '').slice(0, 8);
|
|
@@ -796441,6 +796529,14 @@ function sessionDisplayPreview(session) {
|
|
|
796441
796529
|
return '';
|
|
796442
796530
|
}
|
|
796443
796531
|
|
|
796532
|
+
function isEligibleChatSession(id, session) {
|
|
796533
|
+
const s = session || {};
|
|
796534
|
+
if (![s.title, s.name, s.preview].every(candidate => isGenericChatTitle(id, candidate))) return true;
|
|
796535
|
+
return Array.isArray(s.messages) && s.messages.some(message =>
|
|
796536
|
+
message && message.role === 'user' && !isNoisyChatSessionText(message.content)
|
|
796537
|
+
);
|
|
796538
|
+
}
|
|
796539
|
+
|
|
796444
796540
|
async function loadServerChatSessions() {
|
|
796445
796541
|
const root = $currentProject.get()?.root || '';
|
|
796446
796542
|
if (!root) return;
|
|
@@ -796449,23 +796545,30 @@ async function loadServerChatSessions() {
|
|
|
796449
796545
|
if (!r.ok) return;
|
|
796450
796546
|
const data = await r.json();
|
|
796451
796547
|
const local = loadScopedSessions();
|
|
796452
|
-
|
|
796548
|
+
// A successful canonical load retires local TUI summaries that the server
|
|
796549
|
+
// no longer considers sessions. Keep eligible browser-native chats so an
|
|
796550
|
+
// unsent/local conversation is never lost during reconciliation.
|
|
796551
|
+
const merged = {};
|
|
796552
|
+
for (const [id, session] of Object.entries(local)) {
|
|
796553
|
+
const isTui = String(id).startsWith('tui:') || session?.source === 'tui';
|
|
796554
|
+
if (!isTui && isEligibleChatSession(id, session)) merged[id] = session;
|
|
796555
|
+
}
|
|
796453
796556
|
for (const sess of (data.sessions || [])) {
|
|
796454
796557
|
if (!sess || !sess.id) continue;
|
|
796455
|
-
const existing = merged[sess.id] || {};
|
|
796558
|
+
const existing = local[sess.id] || merged[sess.id] || {};
|
|
796456
796559
|
const serverTitle = sess.title || sess.preview || '';
|
|
796457
796560
|
const existingTitle = existing.title || existing.name || '';
|
|
796458
|
-
const title = !isGenericChatTitle(sess.id,
|
|
796459
|
-
?
|
|
796460
|
-
: (!isGenericChatTitle(sess.id,
|
|
796461
|
-
const preview = !isNoisyChatSessionText(
|
|
796462
|
-
?
|
|
796463
|
-
: (!isNoisyChatSessionText(
|
|
796561
|
+
const title = !isGenericChatTitle(sess.id, serverTitle)
|
|
796562
|
+
? serverTitle
|
|
796563
|
+
: (!isGenericChatTitle(sess.id, existingTitle) ? existingTitle : sessionDisplayTitle(sess.id, sess));
|
|
796564
|
+
const preview = !isNoisyChatSessionText(sess.preview)
|
|
796565
|
+
? sess.preview
|
|
796566
|
+
: (!isNoisyChatSessionText(existing.preview) ? existing.preview : sessionDisplayPreview(sess));
|
|
796464
796567
|
merged[sess.id] = {
|
|
796465
796568
|
...existing,
|
|
796466
796569
|
id: sess.id,
|
|
796467
796570
|
title,
|
|
796468
|
-
name:
|
|
796571
|
+
name: title,
|
|
796469
796572
|
preview,
|
|
796470
796573
|
model: existing.model || sess.model || '',
|
|
796471
796574
|
source: sess.source || existing.source || 'web',
|
|
@@ -796474,7 +796577,14 @@ async function loadServerChatSessions() {
|
|
|
796474
796577
|
messages: existing.messages || [],
|
|
796475
796578
|
};
|
|
796476
796579
|
}
|
|
796580
|
+
saveScopedSessions(merged);
|
|
796477
796581
|
$chatSessions.set(merged);
|
|
796582
|
+
if (chatSessionId && !merged[chatSessionId]) {
|
|
796583
|
+
$chatSessionId.set(null);
|
|
796584
|
+
messages = [];
|
|
796585
|
+
const conversation = document.getElementById('conversation');
|
|
796586
|
+
if (conversation) conversation.innerHTML = '';
|
|
796587
|
+
}
|
|
796478
796588
|
updateSessionSelect();
|
|
796479
796589
|
} catch {}
|
|
796480
796590
|
}
|
|
@@ -798918,7 +799028,7 @@ function chatSessionFromRouteSearch(search) {
|
|
|
798918
799028
|
}
|
|
798919
799029
|
function syncRouteForTab(tab, replace) {
|
|
798920
799030
|
const path = routePathForTab(tab);
|
|
798921
|
-
const query = tab === 'chat' && chatSessionId ? '?' + encodeURIComponent(chatSessionId) : '';
|
|
799031
|
+
const query = tab === 'chat' && chatSessionId ? '?session=' + encodeURIComponent(chatSessionId) : '';
|
|
798922
799032
|
const next = path + query;
|
|
798923
799033
|
if ((location.pathname + location.search) === next) return;
|
|
798924
799034
|
const method = replace ? 'replaceState' : 'pushState';
|
|
@@ -799519,6 +799629,7 @@ window.addEventListener('popstate', () => {
|
|
|
799519
799629
|
if (tab === 'chat') {
|
|
799520
799630
|
const sid = chatSessionFromRouteSearch(location.search);
|
|
799521
799631
|
if (sid && sid !== chatSessionId) switchSession(sid);
|
|
799632
|
+
else if (!sid && chatSessionId) switchSession('');
|
|
799522
799633
|
}
|
|
799523
799634
|
switchTab(tab, { fromRoute: true });
|
|
799524
799635
|
});
|
|
@@ -800418,6 +800529,7 @@ function updateSessionSelect() {
|
|
|
800418
800529
|
const storeSessions = ($chatSessions.get && $chatSessions.get()) || {};
|
|
800419
800530
|
const saved = { ...storeSessions, ...loadScopedSessions() };
|
|
800420
800531
|
const entries = Object.entries(saved)
|
|
800532
|
+
.filter(([id, session]) => isEligibleChatSession(id, session))
|
|
800421
800533
|
.sort((a, b) => (b[1].updatedAt || '').localeCompare(a[1].updatedAt || ''))
|
|
800422
800534
|
.slice(0, 20);
|
|
800423
800535
|
for (const sel of targets) {
|
|
@@ -800437,8 +800549,8 @@ function updateSessionSelect() {
|
|
|
800437
800549
|
// It delegates to the existing switchSession() so chat history restoration
|
|
800438
800550
|
// still works exactly as before.
|
|
800439
800551
|
function switchChatSession(id) {
|
|
800440
|
-
switchSession(id);
|
|
800441
800552
|
switchTab('chat', { replaceRoute: true });
|
|
800553
|
+
switchSession(id);
|
|
800442
800554
|
}
|
|
800443
800555
|
function newChatSession() {
|
|
800444
800556
|
switchSession('');
|
|
@@ -800615,7 +800727,8 @@ function switchSession(id) {
|
|
|
800615
800727
|
return;
|
|
800616
800728
|
}
|
|
800617
800729
|
const saved = loadScopedSessions();
|
|
800618
|
-
const
|
|
800730
|
+
const storeSessions = ($chatSessions.get && $chatSessions.get()) || {};
|
|
800731
|
+
const s = saved[id] || storeSessions[id];
|
|
800619
800732
|
if (s) {
|
|
800620
800733
|
chatSessionId = id;
|
|
800621
800734
|
messages = s.messages || [];
|
|
@@ -800667,6 +800780,9 @@ function switchSession(id) {
|
|
|
800667
800780
|
updateSessionSelect();
|
|
800668
800781
|
try { _renderSidebarChats(_lastSidebarFilter || ''); } catch {}
|
|
800669
800782
|
try { refreshTodos(id); } catch {}
|
|
800783
|
+
// Local entries are only a fast paint. Always re-fetch the canonical
|
|
800784
|
+
// session so summary-only or stale caches cannot suppress real history.
|
|
800785
|
+
void restoreChatSession();
|
|
800670
800786
|
} else {
|
|
800671
800787
|
// Server-backed sessions (including imported TUI sessions) may only be
|
|
800672
800788
|
// present in $chatSessions, not localStorage. Activate and let the daemon
|
|
@@ -800675,7 +800791,7 @@ function switchSession(id) {
|
|
|
800675
800791
|
syncRouteForTab('chat', true);
|
|
800676
800792
|
updateSessionSelect();
|
|
800677
800793
|
try { _renderSidebarChats(_lastSidebarFilter || ''); } catch {}
|
|
800678
|
-
restoreChatSession();
|
|
800794
|
+
void restoreChatSession();
|
|
800679
800795
|
}
|
|
800680
800796
|
}
|
|
800681
800797
|
|
|
@@ -802332,6 +802448,7 @@ function renderRecoveredTranscript(raw, conv, title) {
|
|
|
802332
802448
|
let mode = null; // 'user' | 'assistant'
|
|
802333
802449
|
let buf = [];
|
|
802334
802450
|
let toolCount = 0;
|
|
802451
|
+
let inToolBox = false;
|
|
802335
802452
|
const out = []; // [{role, text}] or {tools:n}
|
|
802336
802453
|
const flush = () => {
|
|
802337
802454
|
const text = buf.join(NL).trim();
|
|
@@ -802346,22 +802463,29 @@ function renderRecoveredTranscript(raw, conv, title) {
|
|
|
802346
802463
|
line = line.replace(sentRe, '');
|
|
802347
802464
|
const t = line.trim();
|
|
802348
802465
|
if (!t) continue;
|
|
802349
|
-
//
|
|
802350
|
-
|
|
802351
|
-
if (/^[
|
|
802466
|
+
// Tool/task panels also use │. Track their box boundaries so their labels,
|
|
802467
|
+
// commands, and output cannot be mistaken for assistant prose.
|
|
802468
|
+
if (/^[╭┌]/.test(t)) { flush(); inToolBox = true; continue; }
|
|
802469
|
+
if (/^[╰└]/.test(t)) { inToolBox = false; continue; }
|
|
802470
|
+
if (inToolBox) continue;
|
|
802471
|
+
if (/^[─━═╿\\s]+$/.test(t)) continue;
|
|
802472
|
+
const userMatch = t.match(/^(?:[▹❯>]\\s*|(?:User|You)\\s*:\\s*)(.+)$/i);
|
|
802473
|
+
if (userMatch) {
|
|
802474
|
+
if (isNoisyChatSessionText(userMatch[1])) { flush(); mode = null; continue; }
|
|
802352
802475
|
flush(); if (toolCount) { out.push({ tools: toolCount }); toolCount = 0; }
|
|
802353
|
-
|
|
802476
|
+
mode = 'user'; buf.push(userMatch[1]); continue;
|
|
802354
802477
|
}
|
|
802355
|
-
|
|
802478
|
+
const assistantMatch = t.match(/^(?:(?:Assistant|Open Agent|Omnius)\\s*:\\s*|│\\s?)(.*)$/i);
|
|
802479
|
+
if (assistantMatch) {
|
|
802356
802480
|
if (mode !== 'assistant') { flush(); mode = 'assistant'; }
|
|
802357
|
-
buf.push(
|
|
802481
|
+
buf.push(assistantMatch[1].replace(/\\s?│$/, '')); continue;
|
|
802358
802482
|
}
|
|
802359
|
-
if (/^[∙!]/.test(t)) continue;
|
|
802360
|
-
if (mode
|
|
802483
|
+
if (/^[∙!EW⚠]/.test(t) || isNoisyChatSessionText(t)) continue;
|
|
802484
|
+
if (mode) buf.push(t); // wrapped authored continuation
|
|
802361
802485
|
}
|
|
802362
802486
|
flush(); if (toolCount) out.push({ tools: toolCount });
|
|
802363
802487
|
|
|
802364
|
-
if (out.length === 0) return; // nothing meaningful — show nothing rather than garbage
|
|
802488
|
+
if (out.length === 0) return []; // nothing meaningful — show nothing rather than garbage
|
|
802365
802489
|
const note = document.createElement('div');
|
|
802366
802490
|
note.style.cssText = 'font-size:0.6rem;color:var(--color-fg-faint);margin:4px 0 8px;text-align:center';
|
|
802367
802491
|
note.textContent = 'recovered session' + (title ? ' — ' + title : '');
|
|
@@ -802376,6 +802500,9 @@ function renderRecoveredTranscript(raw, conv, title) {
|
|
|
802376
802500
|
addMessage(item.role, item.text);
|
|
802377
802501
|
}
|
|
802378
802502
|
}
|
|
802503
|
+
return out
|
|
802504
|
+
.filter(item => !item.tools && (item.role === 'user' || item.role === 'assistant'))
|
|
802505
|
+
.map(item => ({ role: item.role, content: item.text }));
|
|
802379
802506
|
}
|
|
802380
802507
|
window.renderRecoveredTranscript = renderRecoveredTranscript;
|
|
802381
802508
|
|
|
@@ -802389,6 +802516,7 @@ async function restoreChatSession() {
|
|
|
802389
802516
|
const root = $currentProject.get()?.root || '';
|
|
802390
802517
|
const query = root ? '?root=' + encodeURIComponent(root) : '';
|
|
802391
802518
|
const r = await fetch('/v1/chat/sessions/' + encodeURIComponent(sid) + query, { headers: headers() });
|
|
802519
|
+
if (chatSessionId !== sid) return;
|
|
802392
802520
|
if (!r.ok) {
|
|
802393
802521
|
if (r.status === 404) {
|
|
802394
802522
|
// Server lost the session (e.g. daemon restart) — clear via store
|
|
@@ -802398,16 +802526,17 @@ async function restoreChatSession() {
|
|
|
802398
802526
|
return;
|
|
802399
802527
|
}
|
|
802400
802528
|
const data = await r.json();
|
|
802529
|
+
if (chatSessionId !== sid) return;
|
|
802401
802530
|
if (!data || !data.id) return;
|
|
802402
802531
|
chatSessionId = data.id;
|
|
802403
802532
|
window.currentSessionId = data.id;
|
|
802404
802533
|
// Keep the in-memory messages array clean (only user/assistant) so
|
|
802405
802534
|
// the next inference call sees a valid conversation. Tool events
|
|
802406
802535
|
// are still rendered into the DOM via the dropdown helpers below.
|
|
802407
|
-
const allMessages = data.messages || []
|
|
802408
|
-
|
|
802409
|
-
|
|
802410
|
-
|
|
802536
|
+
const allMessages = (data.messages || []).filter(m => !(
|
|
802537
|
+
m.role === 'assistant' && /^Loaded TUI session ".*"\\. Its transcript is attached as context for this chat\\.$/.test(String(m.content || ''))
|
|
802538
|
+
));
|
|
802539
|
+
let recoveredMessages = [];
|
|
802411
802540
|
const conv = document.getElementById('conversation');
|
|
802412
802541
|
if (conv) {
|
|
802413
802542
|
conv.innerHTML = '';
|
|
@@ -802415,15 +802544,15 @@ async function restoreChatSession() {
|
|
|
802415
802544
|
// decisions, sub-agent activity — everything that scrolled past in the
|
|
802416
802545
|
// TUI) as a visible, scrollable block at the top so opening the session
|
|
802417
802546
|
// actually shows what happened, instead of just a "loaded" notice.
|
|
802418
|
-
if (data.transcript && String(data.transcript).trim()
|
|
802419
|
-
&&
|
|
802547
|
+
if (data.source === 'tui' && data.transcript && String(data.transcript).trim()
|
|
802548
|
+
&& data.transcript !== '(empty transcript)') {
|
|
802420
802549
|
// TUI/raw transcript: PARSE the rendered-TUI scrollback into real chat
|
|
802421
802550
|
// bubbles instead of dumping the raw log. The persisted log carries
|
|
802422
802551
|
// DYNBLOCK:<id> sentinels (dynamic blocks expanded only at TUI
|
|
802423
802552
|
// paint time — no content here) plus chrome (▹ user, │ assistant,
|
|
802424
802553
|
// ∙ status, ! internal). We strip the dead sentinels + noise and emit
|
|
802425
802554
|
// user/assistant messages so it reads like a GUI chat.
|
|
802426
|
-
renderRecoveredTranscript(String(data.transcript), conv, data.title || '');
|
|
802555
|
+
recoveredMessages = renderRecoveredTranscript(String(data.transcript), conv, data.title || '');
|
|
802427
802556
|
}
|
|
802428
802557
|
// WO-CHAT-RESUME-TOOLS — replay the FULL intermediate flow on
|
|
802429
802558
|
// restore: user/assistant text bubbles AND tool_call/tool_result
|
|
@@ -802471,6 +802600,12 @@ async function restoreChatSession() {
|
|
|
802471
802600
|
}
|
|
802472
802601
|
}
|
|
802473
802602
|
}
|
|
802603
|
+
messages = [
|
|
802604
|
+
...recoveredMessages,
|
|
802605
|
+
...allMessages
|
|
802606
|
+
.filter(m => m.role === 'user' || m.role === 'assistant')
|
|
802607
|
+
.map(m => ({ role: m.role, content: m.content })),
|
|
802608
|
+
];
|
|
802474
802609
|
try {
|
|
802475
802610
|
const saved = loadScopedSessions();
|
|
802476
802611
|
saved[data.id] = {
|
|
@@ -803632,7 +803767,7 @@ function _renderSidebarChats(filter) {
|
|
|
803632
803767
|
_renderSidebarFoldersToolbar();
|
|
803633
803768
|
|
|
803634
803769
|
const sessions = (typeof $chatSessions !== 'undefined' && $chatSessions.get) ? $chatSessions.get() : {};
|
|
803635
|
-
const allIds = Object.keys(sessions || {});
|
|
803770
|
+
const allIds = Object.keys(sessions || {}).filter(id => isEligibleChatSession(id, sessions[id]));
|
|
803636
803771
|
const q = (filter || '').trim().toLowerCase();
|
|
803637
803772
|
const activeId = chatSessionId || (($chatSessionId.get && $chatSessionId.get()) || null);
|
|
803638
803773
|
|
|
@@ -803644,8 +803779,8 @@ function _renderSidebarChats(filter) {
|
|
|
803644
803779
|
// Sort helper
|
|
803645
803780
|
const sortByRecency = (a, b) => {
|
|
803646
803781
|
const sa = sessions[a] || {}, sb = sessions[b] || {};
|
|
803647
|
-
const ta = sa.updated_at || sa.created_at || a;
|
|
803648
|
-
const tb = sb.updated_at || sb.created_at || b;
|
|
803782
|
+
const ta = sa.updatedAt || sa.updated_at || sa.createdAt || sa.created_at || a;
|
|
803783
|
+
const tb = sb.updatedAt || sb.updated_at || sb.createdAt || sb.created_at || b;
|
|
803649
803784
|
return String(tb).localeCompare(String(ta));
|
|
803650
803785
|
};
|
|
803651
803786
|
allIds.sort(sortByRecency);
|
|
@@ -803679,7 +803814,7 @@ function _renderSidebarChats(filter) {
|
|
|
803679
803814
|
const cls = 'sb-chat' + (id === activeId ? ' active' : '');
|
|
803680
803815
|
const safeId = String(id).replace(/'/g, "\\\\'");
|
|
803681
803816
|
const safeTitle = title.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
803682
|
-
return '<div class="' + cls + '" draggable="true" ondragstart="_onChatDragStart(event,\\'' + safeId + '\\')" onclick="
|
|
803817
|
+
return '<div class="' + cls + '" draggable="true" ondragstart="_onChatDragStart(event,\\'' + safeId + '\\')" onclick="switchChatSession(\\'' + safeId + '\\')" title="' + safeTitle + '">' +
|
|
803683
803818
|
'<span class="sb-chat-title">' + safeTitle + '</span>' +
|
|
803684
803819
|
'<button class="sb-chat-menu" onclick="_showChatRowMenu(event,\\'' + safeId + '\\')" title="More">⋮</button>' +
|
|
803685
803820
|
'</div>';
|
|
@@ -814360,17 +814495,30 @@ ${historyLines}
|
|
|
814360
814495
|
if (!checkAuth(req3, res, "read")) return;
|
|
814361
814496
|
const queriedRoot = urlObj.searchParams.get("root");
|
|
814362
814497
|
const targetRoot = queriedRoot && queriedRoot.trim() ? resolve82(queriedRoot.trim()) : getCurrentProject()?.root ?? process.cwd();
|
|
814363
|
-
const sessions3 = listSessions2({ projectRoot: targetRoot });
|
|
814364
814498
|
const includeTui = urlObj.searchParams.get("include_tui") !== "0";
|
|
814499
|
+
const tuiHistory = includeTui && targetRoot ? listSessions(targetRoot) : [];
|
|
814500
|
+
const canonicalTuiIds = new Set(tuiHistory.map((entry) => `tui:${entry.id}`));
|
|
814501
|
+
const sessions3 = listSessions2({ projectRoot: targetRoot }).filter((session) => {
|
|
814502
|
+
const isTui = session.source === "tui" || session.id.startsWith("tui:");
|
|
814503
|
+
return !isTui || includeTui && canonicalTuiIds.has(session.id);
|
|
814504
|
+
});
|
|
814365
814505
|
if (includeTui && targetRoot) {
|
|
814366
|
-
const
|
|
814506
|
+
const byId = new Map(sessions3.map((session) => [session.id, session]));
|
|
814507
|
+
const seenFingerprints = /* @__PURE__ */ new Set();
|
|
814367
814508
|
const cfg = loadConfig();
|
|
814368
814509
|
const needSummary = [];
|
|
814369
|
-
for (const t2 of
|
|
814510
|
+
for (const t2 of tuiHistory) {
|
|
814370
814511
|
const id2 = `tui:${t2.id}`;
|
|
814371
|
-
|
|
814372
|
-
|
|
814373
|
-
|
|
814512
|
+
const transcriptLines = loadSessionHistory(targetRoot, t2.id) ?? [];
|
|
814513
|
+
const transcript = transcriptLines.join("\n");
|
|
814514
|
+
const fingerprint3 = normalizedSessionFingerprint(transcript);
|
|
814515
|
+
if (fingerprint3 && seenFingerprints.has(fingerprint3)) continue;
|
|
814516
|
+
if (fingerprint3) seenFingerprints.add(fingerprint3);
|
|
814517
|
+
const fallback = deterministicSummary(transcript);
|
|
814518
|
+
const title = sessionDisplayTitle(t2, transcript);
|
|
814519
|
+
const preview = t2.aiSummary && !isSessionNoiseText(t2.aiSummary) ? t2.aiSummary : fallback.summary !== "Empty session." ? fallback.summary : t2.description;
|
|
814520
|
+
if (!t2.aiTitle || isSessionNoiseText(t2.aiTitle)) needSummary.push(t2.id);
|
|
814521
|
+
const canonical3 = {
|
|
814374
814522
|
id: id2,
|
|
814375
814523
|
model: t2.model,
|
|
814376
814524
|
messages: 0,
|
|
@@ -814379,9 +814527,15 @@ ${historyLines}
|
|
|
814379
814527
|
lastActivity: t2.updatedAt,
|
|
814380
814528
|
projectRoot: targetRoot,
|
|
814381
814529
|
source: "tui",
|
|
814382
|
-
title
|
|
814383
|
-
preview
|
|
814384
|
-
}
|
|
814530
|
+
title,
|
|
814531
|
+
preview
|
|
814532
|
+
};
|
|
814533
|
+
const existing = byId.get(id2);
|
|
814534
|
+
if (existing) Object.assign(existing, canonical3);
|
|
814535
|
+
else {
|
|
814536
|
+
sessions3.push(canonical3);
|
|
814537
|
+
byId.set(id2, canonical3);
|
|
814538
|
+
}
|
|
814385
814539
|
}
|
|
814386
814540
|
for (const sid of needSummary.slice(0, 6)) {
|
|
814387
814541
|
void ensureSessionSummary({
|
|
@@ -814559,23 +814713,23 @@ ${historyLines}
|
|
|
814559
814713
|
const sid = decodeURIComponent(chatSessionMatch[1]);
|
|
814560
814714
|
if (method === "GET") {
|
|
814561
814715
|
if (!checkAuth(req3, res, "read")) return;
|
|
814562
|
-
let session = lookupSession(sid);
|
|
814563
|
-
if (
|
|
814716
|
+
let session = sid.startsWith("tui:") ? null : lookupSession(sid);
|
|
814717
|
+
if (sid.startsWith("tui:")) {
|
|
814564
814718
|
const queriedRoot = urlObj.searchParams.get("root");
|
|
814565
814719
|
const targetRoot = queriedRoot && queriedRoot.trim() ? resolve82(queriedRoot.trim()) : getCurrentProject()?.root ?? process.cwd();
|
|
814566
814720
|
const tuiId = sid.slice("tui:".length);
|
|
814567
814721
|
const lines = loadSessionHistory(targetRoot, tuiId);
|
|
814568
|
-
|
|
814569
|
-
|
|
814722
|
+
const meta = listSessions(targetRoot).find((s2) => s2.id === tuiId);
|
|
814723
|
+
if (meta && lines && lines.length > 0) {
|
|
814570
814724
|
session = importTranscriptSession({
|
|
814571
814725
|
id: sid,
|
|
814572
814726
|
projectRoot: targetRoot,
|
|
814573
814727
|
model: meta?.model || loadConfig().model,
|
|
814574
|
-
title: meta
|
|
814575
|
-
description: meta
|
|
814728
|
+
title: sessionDisplayTitle(meta, lines.join("\n")),
|
|
814729
|
+
description: meta.aiSummary || meta.description,
|
|
814576
814730
|
transcriptLines: lines,
|
|
814577
|
-
createdAt: meta
|
|
814578
|
-
updatedAt: meta
|
|
814731
|
+
createdAt: meta.createdAt ? Date.parse(meta.createdAt) : void 0,
|
|
814732
|
+
updatedAt: meta.updatedAt ? Date.parse(meta.updatedAt) : void 0
|
|
814579
814733
|
});
|
|
814580
814734
|
}
|
|
814581
814735
|
}
|
|
@@ -817266,6 +817420,7 @@ var init_serve = __esm({
|
|
|
817266
817420
|
init_usage_tracker();
|
|
817267
817421
|
init_omnius_directory();
|
|
817268
817422
|
init_session_summary();
|
|
817423
|
+
init_session_quality();
|
|
817269
817424
|
init_chat_run_registry();
|
|
817270
817425
|
init_chat_followup();
|
|
817271
817426
|
init_omnius_directory();
|
|
@@ -822244,7 +822399,7 @@ async function startInteractive(config, repoPath2) {
|
|
|
822244
822399
|
const cleanupAndExit = (code8) => {
|
|
822245
822400
|
interactiveExiting = true;
|
|
822246
822401
|
try {
|
|
822247
|
-
saveVisualSessionSnapshotRef?.(
|
|
822402
|
+
saveVisualSessionSnapshotRef?.();
|
|
822248
822403
|
} catch {
|
|
822249
822404
|
}
|
|
822250
822405
|
if (_shellToolRef) _shellToolRef.killAll();
|
|
@@ -823931,15 +824086,16 @@ This is an independent background session started from /background.`
|
|
|
823931
824086
|
}
|
|
823932
824087
|
}
|
|
823933
824088
|
setDreamWriteContent(writeContent);
|
|
823934
|
-
function saveVisualSessionSnapshot(
|
|
824089
|
+
function saveVisualSessionSnapshot() {
|
|
823935
824090
|
try {
|
|
823936
824091
|
const historySessionId = process.env["OMNIUS_SESSION_ID"] || process.env["OMNIUS_TUI_SESSION_ID"] || `session-${Date.now().toString(36)}`;
|
|
823937
824092
|
const tuiState = statusBar.capturePersistedSessionState();
|
|
823938
824093
|
const contentLines = statusBar.capturePersistedSessionLines(100);
|
|
823939
824094
|
if (contentLines.length === 0) return;
|
|
823940
824095
|
const description = cleanPromptForDiary(
|
|
823941
|
-
lastSubmittedPrompt || lastCompletedSummary
|
|
823942
|
-
).slice(0, 240)
|
|
824096
|
+
lastSubmittedPrompt || lastCompletedSummary
|
|
824097
|
+
).slice(0, 240);
|
|
824098
|
+
if (!description || isSessionNoiseText(description)) return;
|
|
823943
824099
|
const historyTitle = description.slice(0, 80) || void 0;
|
|
823944
824100
|
saveSessionHistory(repoRoot, historySessionId, contentLines, {
|
|
823945
824101
|
name: historyTitle,
|
|
@@ -824699,7 +824855,7 @@ This is an independent background session started from /background.`
|
|
|
824699
824855
|
clearInterval(reminderDispatchTimer);
|
|
824700
824856
|
reminderDispatchTimer = null;
|
|
824701
824857
|
}
|
|
824702
|
-
saveVisualSessionSnapshot(
|
|
824858
|
+
saveVisualSessionSnapshot();
|
|
824703
824859
|
statusBar.deactivate();
|
|
824704
824860
|
if (carousel.isRunning) carousel.stop();
|
|
824705
824861
|
banner.stop();
|
|
@@ -827347,7 +827503,7 @@ ${result.content.slice(0, 2e3)}${result.content.length > 2e3 ? "\n[truncated]" :
|
|
|
827347
827503
|
const quitMatch = input.trim().replace(/^\//, "").toLowerCase();
|
|
827348
827504
|
if (quitMatch === "quit" || quitMatch === "exit" || quitMatch === "q") {
|
|
827349
827505
|
interactiveExiting = true;
|
|
827350
|
-
saveVisualSessionSnapshot(
|
|
827506
|
+
saveVisualSessionSnapshot();
|
|
827351
827507
|
if (activeTask) activeTask.runner.abort();
|
|
827352
827508
|
idleMemoryMaintenance?.stop();
|
|
827353
827509
|
taskManager.stopAll();
|
|
@@ -827365,7 +827521,7 @@ ${result.content.slice(0, 2e3)}${result.content.length > 2e3 ? "\n[truncated]" :
|
|
|
827365
827521
|
);
|
|
827366
827522
|
if (cmdResult === "exit") {
|
|
827367
827523
|
interactiveExiting = true;
|
|
827368
|
-
saveVisualSessionSnapshot(
|
|
827524
|
+
saveVisualSessionSnapshot();
|
|
827369
827525
|
if (activeTask) activeTask.runner.abort();
|
|
827370
827526
|
idleMemoryMaintenance?.stop();
|
|
827371
827527
|
taskManager.stopAll();
|
|
@@ -828237,7 +828393,7 @@ Rationale: ${proposal.rationale}${provenanceNote}${dmnDevDiscipline(proposal.cat
|
|
|
828237
828393
|
rl.on("close", () => {
|
|
828238
828394
|
if (interactiveExiting) return;
|
|
828239
828395
|
interactiveExiting = true;
|
|
828240
|
-
saveVisualSessionSnapshot(
|
|
828396
|
+
saveVisualSessionSnapshot();
|
|
828241
828397
|
if (peerMesh) {
|
|
828242
828398
|
peerMesh.stop().catch(() => {
|
|
828243
828399
|
});
|
|
@@ -828823,6 +828979,7 @@ var init_interactive = __esm({
|
|
|
828823
828979
|
init_project_context();
|
|
828824
828980
|
init_realtime();
|
|
828825
828981
|
init_chat_session();
|
|
828982
|
+
init_session_quality();
|
|
828826
828983
|
init_identity_memory_tool();
|
|
828827
828984
|
init_visual_identity_association();
|
|
828828
828985
|
init_dist();
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnius",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.604",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omnius",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.604",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"image-to-ascii"
|
|
12
12
|
],
|
package/package.json
CHANGED