omnius 1.0.327 → 1.0.328
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 +1132 -823
- package/docs/reference/rest-api.md +1 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1699,12 +1699,12 @@ var init_model_broker = __esm({
|
|
|
1699
1699
|
// packages/execution/dist/broker-mediated-backend.js
|
|
1700
1700
|
function wrapWithBroker(backend, options2) {
|
|
1701
1701
|
const broker = getModelBroker();
|
|
1702
|
-
const
|
|
1702
|
+
const clamp10 = options2.clampNumCtx !== false;
|
|
1703
1703
|
const wrapped = Object.create(backend);
|
|
1704
1704
|
wrapped.chatCompletion = async (request) => {
|
|
1705
1705
|
const model = backend.model || request.model || "unknown";
|
|
1706
1706
|
let effectiveRequest = request;
|
|
1707
|
-
if (
|
|
1707
|
+
if (clamp10) {
|
|
1708
1708
|
const trainCtx = await broker.getNctxTrain(model).catch(() => null);
|
|
1709
1709
|
const requestedNumCtx = request.numCtx;
|
|
1710
1710
|
if (trainCtx && trainCtx > 0) {
|
|
@@ -1738,7 +1738,7 @@ function wrapWithBroker(backend, options2) {
|
|
|
1738
1738
|
wrapped.chatCompletionStream = async function* (request) {
|
|
1739
1739
|
const model = backend.model || request.model || "unknown";
|
|
1740
1740
|
let effectiveRequest = request;
|
|
1741
|
-
if (
|
|
1741
|
+
if (clamp10) {
|
|
1742
1742
|
const trainCtx = await broker.getNctxTrain(model).catch(() => null);
|
|
1743
1743
|
const requestedNumCtx = request.numCtx;
|
|
1744
1744
|
if (trainCtx && trainCtx > 0) {
|
|
@@ -568169,7 +568169,7 @@ ${context2 ?? ""}`;
|
|
|
568169
568169
|
}
|
|
568170
568170
|
}
|
|
568171
568171
|
_applyTaskAffectFromResult(result, events) {
|
|
568172
|
-
const
|
|
568172
|
+
const clamp10 = (n2) => Math.max(0, Math.min(1, n2));
|
|
568173
568173
|
let uncertainty = this._taskAffectState.uncertainty * 0.94;
|
|
568174
568174
|
let frustration = this._taskAffectState.frustration * 0.94;
|
|
568175
568175
|
let confidence2 = this._taskAffectState.confidence * 0.94;
|
|
@@ -568202,11 +568202,11 @@ ${context2 ?? ""}`;
|
|
|
568202
568202
|
}
|
|
568203
568203
|
const level = frustration >= 0.72 || uncertainty >= 0.78 ? 4 : frustration >= 0.52 || uncertainty >= 0.58 ? 3 : frustration >= 0.32 || uncertainty >= 0.38 ? 2 : frustration >= 0.18 || uncertainty >= 0.22 ? 1 : 0;
|
|
568204
568204
|
this._taskAffectState = {
|
|
568205
|
-
uncertainty:
|
|
568206
|
-
frustration:
|
|
568207
|
-
confidence:
|
|
568208
|
-
novelty:
|
|
568209
|
-
momentum:
|
|
568205
|
+
uncertainty: clamp10(uncertainty),
|
|
568206
|
+
frustration: clamp10(frustration),
|
|
568207
|
+
confidence: clamp10(confidence2),
|
|
568208
|
+
novelty: clamp10(novelty),
|
|
568209
|
+
momentum: clamp10(momentum),
|
|
568210
568210
|
adversaryLevel: level,
|
|
568211
568211
|
lastUpdatedIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
568212
568212
|
};
|
|
@@ -596755,6 +596755,7 @@ __export(render_exports, {
|
|
|
596755
596755
|
renderBoxedBlock: () => renderBoxedBlock,
|
|
596756
596756
|
renderCompactHeader: () => renderCompactHeader,
|
|
596757
596757
|
renderConfig: () => renderConfig,
|
|
596758
|
+
renderContentBlock: () => renderContentBlock,
|
|
596758
596759
|
renderContextIntakeBox: () => renderContextIntakeBox,
|
|
596759
596760
|
renderError: () => renderError,
|
|
596760
596761
|
renderHeader: () => renderHeader,
|
|
@@ -598194,6 +598195,18 @@ ${lines.map((l2) => l2 + "\x1B[0m").join("\n")}
|
|
|
598194
598195
|
process.stdout.write(text2);
|
|
598195
598196
|
_contentWriteHook?.end();
|
|
598196
598197
|
}
|
|
598198
|
+
function renderContentBlock(text2) {
|
|
598199
|
+
breakTelegramCoalesce();
|
|
598200
|
+
const body = text2.endsWith("\n") ? text2 : text2 + "\n";
|
|
598201
|
+
const redir = _contentWriteHook?.redirect?.();
|
|
598202
|
+
if (redir) {
|
|
598203
|
+
redir(body);
|
|
598204
|
+
return;
|
|
598205
|
+
}
|
|
598206
|
+
_contentWriteHook?.begin();
|
|
598207
|
+
process.stdout.write(body);
|
|
598208
|
+
_contentWriteHook?.end();
|
|
598209
|
+
}
|
|
598197
598210
|
function renderInfo(message2) {
|
|
598198
598211
|
breakTelegramCoalesce();
|
|
598199
598212
|
const redir = _contentWriteHook?.redirect?.();
|
|
@@ -604388,623 +604401,6 @@ var init_profiles = __esm({
|
|
|
604388
604401
|
}
|
|
604389
604402
|
});
|
|
604390
604403
|
|
|
604391
|
-
// packages/cli/src/tui/cad-model-viewer.ts
|
|
604392
|
-
import { createServer as createServer7 } from "node:http";
|
|
604393
|
-
import { existsSync as existsSync107, readFileSync as readFileSync86, statSync as statSync41 } from "node:fs";
|
|
604394
|
-
import { basename as basename22, extname as extname15, resolve as resolve52 } from "node:path";
|
|
604395
|
-
function getCurrentCadModelViewer() {
|
|
604396
|
-
return currentViewer;
|
|
604397
|
-
}
|
|
604398
|
-
async function startCadModelViewer(filePath) {
|
|
604399
|
-
const resolved = filePath ? resolve52(filePath) : void 0;
|
|
604400
|
-
if (resolved && (!existsSync107(resolved) || !statSync41(resolved).isFile())) {
|
|
604401
|
-
throw new Error(`3D model file not found: ${resolved}`);
|
|
604402
|
-
}
|
|
604403
|
-
if (currentViewer) {
|
|
604404
|
-
await currentViewer.close().catch(() => {
|
|
604405
|
-
});
|
|
604406
|
-
currentViewer = null;
|
|
604407
|
-
}
|
|
604408
|
-
const server2 = createServer7((req3, res) => handleViewerRequest(req3, res, resolved));
|
|
604409
|
-
const port = await listenOnEphemeralPort(server2);
|
|
604410
|
-
const session = {
|
|
604411
|
-
url: `http://127.0.0.1:${port}/`,
|
|
604412
|
-
port,
|
|
604413
|
-
filePath: resolved,
|
|
604414
|
-
close: () => new Promise((resolveClose) => server2.close(() => resolveClose()))
|
|
604415
|
-
};
|
|
604416
|
-
currentViewer = session;
|
|
604417
|
-
server2.on("close", () => {
|
|
604418
|
-
if (currentViewer === session) currentViewer = null;
|
|
604419
|
-
});
|
|
604420
|
-
return session;
|
|
604421
|
-
}
|
|
604422
|
-
function listenOnEphemeralPort(server2) {
|
|
604423
|
-
return new Promise((resolveListen, reject) => {
|
|
604424
|
-
server2.once("error", reject);
|
|
604425
|
-
server2.listen(0, "127.0.0.1", () => {
|
|
604426
|
-
server2.off("error", reject);
|
|
604427
|
-
const addr = server2.address();
|
|
604428
|
-
if (!addr || typeof addr === "string") {
|
|
604429
|
-
reject(new Error("viewer server did not bind to a TCP port"));
|
|
604430
|
-
return;
|
|
604431
|
-
}
|
|
604432
|
-
resolveListen(addr.port);
|
|
604433
|
-
});
|
|
604434
|
-
});
|
|
604435
|
-
}
|
|
604436
|
-
function handleViewerRequest(req3, res, filePath) {
|
|
604437
|
-
const url = new URL(req3.url || "/", "http://127.0.0.1");
|
|
604438
|
-
if (url.pathname === "/health") {
|
|
604439
|
-
sendJson(res, 200, { ok: true, file: filePath ?? null });
|
|
604440
|
-
return;
|
|
604441
|
-
}
|
|
604442
|
-
if (url.pathname === "/asset") {
|
|
604443
|
-
if (!filePath) {
|
|
604444
|
-
sendText(res, 404, "No model file attached to this viewer.");
|
|
604445
|
-
return;
|
|
604446
|
-
}
|
|
604447
|
-
try {
|
|
604448
|
-
res.writeHead(200, {
|
|
604449
|
-
"Content-Type": contentTypeFor(filePath),
|
|
604450
|
-
"Content-Disposition": `inline; filename="${basename22(filePath).replace(/"/g, "")}"`,
|
|
604451
|
-
"Cache-Control": "no-store"
|
|
604452
|
-
});
|
|
604453
|
-
res.end(readFileSync86(filePath));
|
|
604454
|
-
} catch (err) {
|
|
604455
|
-
sendText(res, 500, err instanceof Error ? err.message : String(err));
|
|
604456
|
-
}
|
|
604457
|
-
return;
|
|
604458
|
-
}
|
|
604459
|
-
if (url.pathname !== "/") {
|
|
604460
|
-
sendText(res, 404, "Not found");
|
|
604461
|
-
return;
|
|
604462
|
-
}
|
|
604463
|
-
sendHtml(res, viewerHtml(filePath));
|
|
604464
|
-
}
|
|
604465
|
-
function contentTypeFor(path12) {
|
|
604466
|
-
const ext = extname15(path12).toLowerCase();
|
|
604467
|
-
if (ext === ".glb") return "model/gltf-binary";
|
|
604468
|
-
if (ext === ".gltf") return "model/gltf+json";
|
|
604469
|
-
if (ext === ".obj") return "text/plain; charset=utf-8";
|
|
604470
|
-
if (ext === ".stl") return "model/stl";
|
|
604471
|
-
if (ext === ".ply") return "application/octet-stream";
|
|
604472
|
-
return "application/octet-stream";
|
|
604473
|
-
}
|
|
604474
|
-
function sendJson(res, status, value2) {
|
|
604475
|
-
res.writeHead(status, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-store" });
|
|
604476
|
-
res.end(JSON.stringify(value2));
|
|
604477
|
-
}
|
|
604478
|
-
function sendText(res, status, text2) {
|
|
604479
|
-
res.writeHead(status, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
604480
|
-
res.end(text2);
|
|
604481
|
-
}
|
|
604482
|
-
function sendHtml(res, html) {
|
|
604483
|
-
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store" });
|
|
604484
|
-
res.end(html);
|
|
604485
|
-
}
|
|
604486
|
-
function viewerHtml(filePath) {
|
|
604487
|
-
const fileName = filePath ? basename22(filePath) : "";
|
|
604488
|
-
const ext = filePath ? extname15(filePath).toLowerCase().replace(/^\./, "") : "";
|
|
604489
|
-
return `<!doctype html>
|
|
604490
|
-
<html lang="en">
|
|
604491
|
-
<head>
|
|
604492
|
-
<meta charset="utf-8">
|
|
604493
|
-
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
604494
|
-
<title>Omnius CAD/3D Viewer</title>
|
|
604495
|
-
<style>
|
|
604496
|
-
:root { color-scheme: dark; --bg:#101214; --panel:#181b1f; --line:#2a3037; --fg:#e7edf3; --muted:#9aa7b5; --accent:#5ec6a8; }
|
|
604497
|
-
* { box-sizing: border-box; }
|
|
604498
|
-
body { margin:0; min-height:100vh; background:var(--bg); color:var(--fg); font:14px/1.4 ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; display:grid; grid-template-columns:minmax(280px,360px) 1fr; }
|
|
604499
|
-
aside { border-right:1px solid var(--line); background:var(--panel); padding:14px; display:flex; flex-direction:column; gap:12px; min-height:100vh; }
|
|
604500
|
-
main { position:relative; min-height:100vh; overflow:hidden; }
|
|
604501
|
-
h1 { margin:0; font-size:16px; font-weight:650; }
|
|
604502
|
-
.meta { color:var(--muted); font-size:12px; word-break:break-word; }
|
|
604503
|
-
textarea { width:100%; min-height:280px; resize:vertical; border:1px solid var(--line); border-radius:6px; background:#0c0e10; color:var(--fg); padding:10px; font:12px/1.45 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; }
|
|
604504
|
-
button { border:1px solid var(--line); border-radius:6px; background:#20262d; color:var(--fg); padding:8px 10px; cursor:pointer; }
|
|
604505
|
-
button:hover { border-color:var(--accent); }
|
|
604506
|
-
#status { color:var(--muted); min-height:20px; font-size:12px; }
|
|
604507
|
-
canvas { display:block; width:100%; height:100%; }
|
|
604508
|
-
.row { display:flex; gap:8px; flex-wrap:wrap; }
|
|
604509
|
-
@media (max-width: 760px) { body { grid-template-columns:1fr; grid-template-rows:auto 60vh; } aside { min-height:auto; border-right:0; border-bottom:1px solid var(--line); } }
|
|
604510
|
-
</style>
|
|
604511
|
-
</head>
|
|
604512
|
-
<body>
|
|
604513
|
-
<aside>
|
|
604514
|
-
<div>
|
|
604515
|
-
<h1>Omnius CAD/3D Viewer</h1>
|
|
604516
|
-
<div class="meta">${escapeHtml(fileName ? `Viewing ${fileName}` : "No file attached. Rendering Compact IR sample.")}</div>
|
|
604517
|
-
</div>
|
|
604518
|
-
<textarea id="ir">C 50 30 5
|
|
604519
|
-
Y 3 8
|
|
604520
|
-
T 1 -18 -10 2.5
|
|
604521
|
-
Y 3 8
|
|
604522
|
-
T 3 18 -10 2.5
|
|
604523
|
-
Y 3 8
|
|
604524
|
-
T 5 -18 10 2.5
|
|
604525
|
-
Y 3 8
|
|
604526
|
-
T 7 18 10 2.5</textarea>
|
|
604527
|
-
<div class="row">
|
|
604528
|
-
<button id="render-ir">Render Compact IR</button>
|
|
604529
|
-
<button id="reset-camera">Reset Camera</button>
|
|
604530
|
-
</div>
|
|
604531
|
-
<div id="status"></div>
|
|
604532
|
-
</aside>
|
|
604533
|
-
<main id="viewport"></main>
|
|
604534
|
-
<script type="module">
|
|
604535
|
-
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.164.1/build/three.module.js';
|
|
604536
|
-
import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/controls/OrbitControls.js';
|
|
604537
|
-
import { GLTFLoader } from 'https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/loaders/GLTFLoader.js';
|
|
604538
|
-
import { STLLoader } from 'https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/loaders/STLLoader.js';
|
|
604539
|
-
import { OBJLoader } from 'https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/loaders/OBJLoader.js';
|
|
604540
|
-
import { PLYLoader } from 'https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/loaders/PLYLoader.js';
|
|
604541
|
-
|
|
604542
|
-
const assetUrl = ${JSON.stringify(filePath ? "/asset" : "")};
|
|
604543
|
-
const assetExt = ${JSON.stringify(ext)};
|
|
604544
|
-
const viewport = document.getElementById('viewport');
|
|
604545
|
-
const status = document.getElementById('status');
|
|
604546
|
-
const scene = new THREE.Scene();
|
|
604547
|
-
scene.background = new THREE.Color(0x101214);
|
|
604548
|
-
const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 5000);
|
|
604549
|
-
const renderer = new THREE.WebGLRenderer({ antialias:true });
|
|
604550
|
-
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
|
|
604551
|
-
viewport.appendChild(renderer.domElement);
|
|
604552
|
-
const controls = new OrbitControls(camera, renderer.domElement);
|
|
604553
|
-
controls.enableDamping = true;
|
|
604554
|
-
scene.add(new THREE.HemisphereLight(0xffffff, 0x223344, 1.7));
|
|
604555
|
-
const key = new THREE.DirectionalLight(0xffffff, 2.2);
|
|
604556
|
-
key.position.set(120, 160, 100);
|
|
604557
|
-
scene.add(key);
|
|
604558
|
-
const grid = new THREE.GridHelper(160, 32, 0x31404a, 0x253039);
|
|
604559
|
-
scene.add(grid);
|
|
604560
|
-
let objectRoot = new THREE.Group();
|
|
604561
|
-
scene.add(objectRoot);
|
|
604562
|
-
|
|
604563
|
-
function setStatus(text) { status.textContent = text || ''; }
|
|
604564
|
-
function clearObject() {
|
|
604565
|
-
scene.remove(objectRoot);
|
|
604566
|
-
objectRoot.traverse((o) => {
|
|
604567
|
-
if (o.geometry) o.geometry.dispose?.();
|
|
604568
|
-
if (o.material) {
|
|
604569
|
-
if (Array.isArray(o.material)) o.material.forEach((m) => m.dispose?.());
|
|
604570
|
-
else o.material.dispose?.();
|
|
604571
|
-
}
|
|
604572
|
-
});
|
|
604573
|
-
objectRoot = new THREE.Group();
|
|
604574
|
-
scene.add(objectRoot);
|
|
604575
|
-
}
|
|
604576
|
-
function frameObject() {
|
|
604577
|
-
const box = new THREE.Box3().setFromObject(objectRoot);
|
|
604578
|
-
if (box.isEmpty()) {
|
|
604579
|
-
camera.position.set(70, 70, 70);
|
|
604580
|
-
controls.target.set(0, 0, 0);
|
|
604581
|
-
return;
|
|
604582
|
-
}
|
|
604583
|
-
const size = box.getSize(new THREE.Vector3());
|
|
604584
|
-
const center = box.getCenter(new THREE.Vector3());
|
|
604585
|
-
const max = Math.max(size.x, size.y, size.z, 1);
|
|
604586
|
-
camera.position.copy(center).add(new THREE.Vector3(max * 1.35, max * 1.05, max * 1.35));
|
|
604587
|
-
controls.target.copy(center);
|
|
604588
|
-
camera.near = Math.max(0.01, max / 1000);
|
|
604589
|
-
camera.far = Math.max(1000, max * 20);
|
|
604590
|
-
camera.updateProjectionMatrix();
|
|
604591
|
-
controls.update();
|
|
604592
|
-
}
|
|
604593
|
-
function makeMaterial(index) {
|
|
604594
|
-
const colors = [0x5ec6a8, 0xf0b35a, 0x87a8ff, 0xdc6f7e, 0xb6d96a];
|
|
604595
|
-
return new THREE.MeshStandardMaterial({ color: colors[index % colors.length], metalness:0.05, roughness:0.48 });
|
|
604596
|
-
}
|
|
604597
|
-
function renderCompactIr(text) {
|
|
604598
|
-
clearObject();
|
|
604599
|
-
const nodes = [];
|
|
604600
|
-
const lines = String(text || '').split(/\\r?\\n/).map((l) => l.trim()).filter((l) => l && !l.startsWith('#'));
|
|
604601
|
-
for (const line of lines) {
|
|
604602
|
-
const parts = line.split(/\\s+/);
|
|
604603
|
-
const op = parts[0].toUpperCase();
|
|
604604
|
-
const nums = parts.slice(1).map(Number);
|
|
604605
|
-
let mesh = null;
|
|
604606
|
-
if (op === 'C' && nums.length >= 3) {
|
|
604607
|
-
mesh = new THREE.Mesh(new THREE.BoxGeometry(nums[0], nums[1], nums[2]), makeMaterial(nodes.length));
|
|
604608
|
-
} else if (op === 'Y' && nums.length >= 2) {
|
|
604609
|
-
mesh = new THREE.Mesh(new THREE.CylinderGeometry(nums[0], nums[0], nums[1], 48), makeMaterial(nodes.length));
|
|
604610
|
-
mesh.rotation.x = Math.PI / 2;
|
|
604611
|
-
} else if (op === 'S' && nums.length >= 1) {
|
|
604612
|
-
mesh = new THREE.Mesh(new THREE.SphereGeometry(nums[0], 48, 24), makeMaterial(nodes.length));
|
|
604613
|
-
} else if (op === 'K' && nums.length >= 3) {
|
|
604614
|
-
mesh = new THREE.Mesh(new THREE.CylinderGeometry(nums[1], nums[0], nums[2], 48), makeMaterial(nodes.length));
|
|
604615
|
-
mesh.rotation.x = Math.PI / 2;
|
|
604616
|
-
} else if ((op === 'U' || op === 'D' || op === 'I') && nums.length >= 2) {
|
|
604617
|
-
const group = new THREE.Group();
|
|
604618
|
-
const a = nodes[nums[0]]?.clone();
|
|
604619
|
-
const b = nodes[nums[1]]?.clone();
|
|
604620
|
-
if (a) group.add(a);
|
|
604621
|
-
if (b) {
|
|
604622
|
-
if (op === 'D') b.traverse((o) => { if (o.material) o.material = new THREE.MeshStandardMaterial({ color:0xff5570, wireframe:true }); });
|
|
604623
|
-
group.add(b);
|
|
604624
|
-
}
|
|
604625
|
-
mesh = group;
|
|
604626
|
-
} else if ((op === 'T' || op === 'R' || op === 'X') && nums.length >= 4) {
|
|
604627
|
-
const target = nodes[nums[0]];
|
|
604628
|
-
if (target) {
|
|
604629
|
-
if (op === 'T') target.position.add(new THREE.Vector3(nums[1], nums[2], nums[3]));
|
|
604630
|
-
if (op === 'R') target.rotation.set(THREE.MathUtils.degToRad(nums[1]), THREE.MathUtils.degToRad(nums[2]), THREE.MathUtils.degToRad(nums[3]));
|
|
604631
|
-
if (op === 'X') target.scale.multiply(new THREE.Vector3(nums[1], nums[2], nums[3]));
|
|
604632
|
-
}
|
|
604633
|
-
nodes.push(target ? target.clone() : new THREE.Group());
|
|
604634
|
-
continue;
|
|
604635
|
-
} else if ((op === 'F' || op === 'CH' || op === 'SH') && nums.length >= 1) {
|
|
604636
|
-
const target = nodes[nums[0]];
|
|
604637
|
-
nodes.push(target ? target.clone() : new THREE.Group());
|
|
604638
|
-
continue;
|
|
604639
|
-
}
|
|
604640
|
-
if (mesh) {
|
|
604641
|
-
nodes.push(mesh);
|
|
604642
|
-
objectRoot.add(mesh);
|
|
604643
|
-
}
|
|
604644
|
-
}
|
|
604645
|
-
if (nodes.length === 0) setStatus('No renderable Compact IR primitives found.');
|
|
604646
|
-
else setStatus('Rendered ' + nodes.length + ' Compact IR node(s). Boolean difference is shown as wireframe preview.');
|
|
604647
|
-
frameObject();
|
|
604648
|
-
}
|
|
604649
|
-
async function loadAsset() {
|
|
604650
|
-
if (!assetUrl) {
|
|
604651
|
-
renderCompactIr(document.getElementById('ir').value);
|
|
604652
|
-
return;
|
|
604653
|
-
}
|
|
604654
|
-
setStatus('Loading attached model...');
|
|
604655
|
-
clearObject();
|
|
604656
|
-
const done = (obj) => {
|
|
604657
|
-
objectRoot.add(obj);
|
|
604658
|
-
setStatus('Loaded attached model.');
|
|
604659
|
-
frameObject();
|
|
604660
|
-
};
|
|
604661
|
-
if (assetExt === 'glb' || assetExt === 'gltf') {
|
|
604662
|
-
new GLTFLoader().load(assetUrl, (gltf) => done(gltf.scene), undefined, (e) => setStatus(e.message || String(e)));
|
|
604663
|
-
} else if (assetExt === 'stl') {
|
|
604664
|
-
new STLLoader().load(assetUrl, (geo) => done(new THREE.Mesh(geo, makeMaterial(0))), undefined, (e) => setStatus(e.message || String(e)));
|
|
604665
|
-
} else if (assetExt === 'obj') {
|
|
604666
|
-
new OBJLoader().load(assetUrl, done, undefined, (e) => setStatus(e.message || String(e)));
|
|
604667
|
-
} else if (assetExt === 'ply') {
|
|
604668
|
-
new PLYLoader().load(assetUrl, (geo) => done(new THREE.Mesh(geo, makeMaterial(0))), undefined, (e) => setStatus(e.message || String(e)));
|
|
604669
|
-
} else {
|
|
604670
|
-
setStatus('Unsupported file extension for browser preview. Use GLB, GLTF, OBJ, STL, or PLY.');
|
|
604671
|
-
renderCompactIr(document.getElementById('ir').value);
|
|
604672
|
-
}
|
|
604673
|
-
}
|
|
604674
|
-
function resize() {
|
|
604675
|
-
const rect = viewport.getBoundingClientRect();
|
|
604676
|
-
renderer.setSize(rect.width, rect.height, false);
|
|
604677
|
-
camera.aspect = Math.max(1, rect.width) / Math.max(1, rect.height);
|
|
604678
|
-
camera.updateProjectionMatrix();
|
|
604679
|
-
}
|
|
604680
|
-
window.addEventListener('resize', resize);
|
|
604681
|
-
document.getElementById('render-ir').addEventListener('click', () => renderCompactIr(document.getElementById('ir').value));
|
|
604682
|
-
document.getElementById('reset-camera').addEventListener('click', frameObject);
|
|
604683
|
-
renderer.setAnimationLoop(() => { controls.update(); renderer.render(scene, camera); });
|
|
604684
|
-
resize();
|
|
604685
|
-
loadAsset();
|
|
604686
|
-
</script>
|
|
604687
|
-
</body>
|
|
604688
|
-
</html>`;
|
|
604689
|
-
}
|
|
604690
|
-
function escapeHtml(value2) {
|
|
604691
|
-
return value2.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
604692
|
-
}
|
|
604693
|
-
var currentViewer;
|
|
604694
|
-
var init_cad_model_viewer = __esm({
|
|
604695
|
-
"packages/cli/src/tui/cad-model-viewer.ts"() {
|
|
604696
|
-
"use strict";
|
|
604697
|
-
currentViewer = null;
|
|
604698
|
-
}
|
|
604699
|
-
});
|
|
604700
|
-
|
|
604701
|
-
// packages/cli/src/tui/hf-token-prompt.ts
|
|
604702
|
-
import * as fs9 from "node:fs";
|
|
604703
|
-
import * as os8 from "node:os";
|
|
604704
|
-
import * as path10 from "node:path";
|
|
604705
|
-
function loadHfToken() {
|
|
604706
|
-
const fromEnv = process.env["HF_TOKEN"]?.trim() || process.env["HUGGING_FACE_HUB_TOKEN"]?.trim() || "";
|
|
604707
|
-
if (fromEnv) return fromEnv;
|
|
604708
|
-
try {
|
|
604709
|
-
if (fs9.existsSync(TOKEN_FILE)) {
|
|
604710
|
-
const fromFile = fs9.readFileSync(TOKEN_FILE, "utf8").trim();
|
|
604711
|
-
if (fromFile) {
|
|
604712
|
-
process.env["HF_TOKEN"] = fromFile;
|
|
604713
|
-
return fromFile;
|
|
604714
|
-
}
|
|
604715
|
-
}
|
|
604716
|
-
} catch {
|
|
604717
|
-
}
|
|
604718
|
-
return null;
|
|
604719
|
-
}
|
|
604720
|
-
function saveHfToken(token) {
|
|
604721
|
-
const trimmed = token.trim();
|
|
604722
|
-
if (!trimmed) throw new Error("HF token cannot be empty");
|
|
604723
|
-
fs9.mkdirSync(TOKEN_DIR, { recursive: true, mode: 448 });
|
|
604724
|
-
fs9.writeFileSync(TOKEN_FILE, trimmed + "\n", { mode: 384 });
|
|
604725
|
-
try {
|
|
604726
|
-
fs9.chmodSync(TOKEN_FILE, 384);
|
|
604727
|
-
} catch {
|
|
604728
|
-
}
|
|
604729
|
-
process.env["HF_TOKEN"] = trimmed;
|
|
604730
|
-
}
|
|
604731
|
-
function clearHfToken() {
|
|
604732
|
-
try {
|
|
604733
|
-
if (fs9.existsSync(TOKEN_FILE)) fs9.unlinkSync(TOKEN_FILE);
|
|
604734
|
-
} catch {
|
|
604735
|
-
}
|
|
604736
|
-
delete process.env["HF_TOKEN"];
|
|
604737
|
-
}
|
|
604738
|
-
function isHfTokenPromptPending() {
|
|
604739
|
-
return pending !== null;
|
|
604740
|
-
}
|
|
604741
|
-
function describePendingHfTokenPrompt() {
|
|
604742
|
-
if (!pending) return null;
|
|
604743
|
-
return { model: pending.model, ageMs: Date.now() - pending.startedAt };
|
|
604744
|
-
}
|
|
604745
|
-
function requestHfToken(opts) {
|
|
604746
|
-
const existing = loadHfToken();
|
|
604747
|
-
if (existing) return Promise.resolve(existing);
|
|
604748
|
-
if (pending) {
|
|
604749
|
-
opts.onMessage(
|
|
604750
|
-
`Another HF token prompt is already active (for ${pending.model}). Run \`/hf <token>\` to satisfy both, or wait for the existing prompt to time out.`
|
|
604751
|
-
);
|
|
604752
|
-
return Promise.resolve(null);
|
|
604753
|
-
}
|
|
604754
|
-
const timeoutMs = Math.max(1e3, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS4);
|
|
604755
|
-
const timeoutSec = Math.round(timeoutMs / 1e3);
|
|
604756
|
-
const fallbackBit = opts.fallbackModel ? `
|
|
604757
|
-
If you don't supply one within ${timeoutSec}s, I will fall back to ${opts.fallbackModel} (no token needed).` : `
|
|
604758
|
-
If you don't supply one within ${timeoutSec}s, I will fall back to a non-gated alternative.`;
|
|
604759
|
-
opts.onMessage(
|
|
604760
|
-
[
|
|
604761
|
-
`Hugging Face model "${opts.model}" is gated and needs an access token.`,
|
|
604762
|
-
`Get one at https://huggingface.co/settings/tokens (read-only is fine),`,
|
|
604763
|
-
`accept the model license at https://huggingface.co/${opts.model},`,
|
|
604764
|
-
`then run: /hf <your-token>`,
|
|
604765
|
-
fallbackBit.trim()
|
|
604766
|
-
].join("\n")
|
|
604767
|
-
);
|
|
604768
|
-
return new Promise((resolve71) => {
|
|
604769
|
-
const timer = setTimeout(() => {
|
|
604770
|
-
const ref = pending;
|
|
604771
|
-
pending = null;
|
|
604772
|
-
if (ref) {
|
|
604773
|
-
ref.onMessage(
|
|
604774
|
-
`No HF token supplied within ${timeoutSec}s — falling back to a non-gated alternative for ${opts.model}.`
|
|
604775
|
-
);
|
|
604776
|
-
}
|
|
604777
|
-
resolve71(null);
|
|
604778
|
-
}, timeoutMs);
|
|
604779
|
-
if (typeof timer.unref === "function") timer.unref();
|
|
604780
|
-
pending = {
|
|
604781
|
-
model: opts.model,
|
|
604782
|
-
onMessage: opts.onMessage,
|
|
604783
|
-
resolve: resolve71,
|
|
604784
|
-
timer,
|
|
604785
|
-
startedAt: Date.now()
|
|
604786
|
-
};
|
|
604787
|
-
});
|
|
604788
|
-
}
|
|
604789
|
-
function fulfillHfTokenPrompt(token) {
|
|
604790
|
-
const trimmed = token.trim();
|
|
604791
|
-
if (!trimmed) return false;
|
|
604792
|
-
saveHfToken(trimmed);
|
|
604793
|
-
if (!pending) return false;
|
|
604794
|
-
const ref = pending;
|
|
604795
|
-
pending = null;
|
|
604796
|
-
clearTimeout(ref.timer);
|
|
604797
|
-
ref.resolve(trimmed);
|
|
604798
|
-
return true;
|
|
604799
|
-
}
|
|
604800
|
-
function cancelHfTokenPrompt() {
|
|
604801
|
-
if (!pending) return false;
|
|
604802
|
-
const ref = pending;
|
|
604803
|
-
pending = null;
|
|
604804
|
-
clearTimeout(ref.timer);
|
|
604805
|
-
ref.resolve(null);
|
|
604806
|
-
return true;
|
|
604807
|
-
}
|
|
604808
|
-
function isHfGatedError(blob) {
|
|
604809
|
-
if (!blob) return false;
|
|
604810
|
-
const text2 = blob.toLowerCase();
|
|
604811
|
-
if (text2.includes("[hf_token_required")) return true;
|
|
604812
|
-
if (text2.includes("gatedrepoerror")) return true;
|
|
604813
|
-
if (text2.includes("access to model")) return true;
|
|
604814
|
-
if (text2.includes("you need to accept")) return true;
|
|
604815
|
-
if (text2.includes("you must be authenticated")) return true;
|
|
604816
|
-
if (/(401|403)/.test(text2) && /(gated|access|unauthor|forbid|auth)/.test(text2)) {
|
|
604817
|
-
return true;
|
|
604818
|
-
}
|
|
604819
|
-
return false;
|
|
604820
|
-
}
|
|
604821
|
-
function extractGatedRepoId(blob) {
|
|
604822
|
-
if (!blob) return null;
|
|
604823
|
-
const tokenMarker = blob.match(/\[HF_TOKEN_REQUIRED:([^\]\s]+)\]/);
|
|
604824
|
-
if (tokenMarker?.[1]) return tokenMarker[1].trim();
|
|
604825
|
-
const hfUrl = blob.match(/huggingface\.co\/([A-Za-z0-9._-]+\/[A-Za-z0-9._-]+)/);
|
|
604826
|
-
if (hfUrl?.[1]) return hfUrl[1];
|
|
604827
|
-
const genericRepo = blob.match(/['"`]([A-Za-z0-9._-]+\/[A-Za-z0-9._-]+)['"`]/);
|
|
604828
|
-
if (genericRepo?.[1] && /\/(.+)/.test(genericRepo[1])) return genericRepo[1];
|
|
604829
|
-
return null;
|
|
604830
|
-
}
|
|
604831
|
-
var TOKEN_DIR, TOKEN_FILE, DEFAULT_TIMEOUT_MS4, pending;
|
|
604832
|
-
var init_hf_token_prompt = __esm({
|
|
604833
|
-
"packages/cli/src/tui/hf-token-prompt.ts"() {
|
|
604834
|
-
"use strict";
|
|
604835
|
-
TOKEN_DIR = path10.join(os8.homedir(), ".omnius");
|
|
604836
|
-
TOKEN_FILE = path10.join(TOKEN_DIR, "hf_token");
|
|
604837
|
-
DEFAULT_TIMEOUT_MS4 = 3e4;
|
|
604838
|
-
pending = null;
|
|
604839
|
-
}
|
|
604840
|
-
});
|
|
604841
|
-
|
|
604842
|
-
// packages/prompts/dist/loader.js
|
|
604843
|
-
var init_loader = __esm({
|
|
604844
|
-
"packages/prompts/dist/loader.js"() {
|
|
604845
|
-
"use strict";
|
|
604846
|
-
}
|
|
604847
|
-
});
|
|
604848
|
-
|
|
604849
|
-
// packages/prompts/dist/render.js
|
|
604850
|
-
var init_render2 = __esm({
|
|
604851
|
-
"packages/prompts/dist/render.js"() {
|
|
604852
|
-
"use strict";
|
|
604853
|
-
}
|
|
604854
|
-
});
|
|
604855
|
-
|
|
604856
|
-
// packages/prompts/dist/promptLoader.js
|
|
604857
|
-
import { readFileSync as readFileSync88, existsSync as existsSync109 } from "node:fs";
|
|
604858
|
-
import { join as join123, dirname as dirname38 } from "node:path";
|
|
604859
|
-
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
604860
|
-
function loadPrompt2(promptPath, vars) {
|
|
604861
|
-
let content = cache6.get(promptPath);
|
|
604862
|
-
if (content === void 0) {
|
|
604863
|
-
const fullPath = join123(PROMPTS_DIR2, promptPath);
|
|
604864
|
-
if (!existsSync109(fullPath)) {
|
|
604865
|
-
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
604866
|
-
}
|
|
604867
|
-
content = readFileSync88(fullPath, "utf-8");
|
|
604868
|
-
cache6.set(promptPath, content);
|
|
604869
|
-
}
|
|
604870
|
-
if (!vars)
|
|
604871
|
-
return content;
|
|
604872
|
-
return content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
|
|
604873
|
-
}
|
|
604874
|
-
var __filename4, __dirname5, devPath, publishedPath, PROMPTS_DIR2, cache6;
|
|
604875
|
-
var init_promptLoader2 = __esm({
|
|
604876
|
-
"packages/prompts/dist/promptLoader.js"() {
|
|
604877
|
-
"use strict";
|
|
604878
|
-
__filename4 = fileURLToPath13(import.meta.url);
|
|
604879
|
-
__dirname5 = dirname38(__filename4);
|
|
604880
|
-
devPath = join123(__dirname5, "..", "templates");
|
|
604881
|
-
publishedPath = join123(__dirname5, "..", "prompts", "templates");
|
|
604882
|
-
PROMPTS_DIR2 = existsSync109(devPath) ? devPath : publishedPath;
|
|
604883
|
-
cache6 = /* @__PURE__ */ new Map();
|
|
604884
|
-
}
|
|
604885
|
-
});
|
|
604886
|
-
|
|
604887
|
-
// packages/prompts/dist/task-templates.js
|
|
604888
|
-
function getTaskTemplate(type) {
|
|
604889
|
-
return TEMPLATES[type];
|
|
604890
|
-
}
|
|
604891
|
-
function getTaskTypes() {
|
|
604892
|
-
return Object.keys(TEMPLATES);
|
|
604893
|
-
}
|
|
604894
|
-
function buildTaskContext(type) {
|
|
604895
|
-
const template = TEMPLATES[type];
|
|
604896
|
-
return `${template.systemPromptAddition}
|
|
604897
|
-
|
|
604898
|
-
### Output Guidance
|
|
604899
|
-
${template.outputGuidance}`;
|
|
604900
|
-
}
|
|
604901
|
-
var TEMPLATES;
|
|
604902
|
-
var init_task_templates = __esm({
|
|
604903
|
-
"packages/prompts/dist/task-templates.js"() {
|
|
604904
|
-
"use strict";
|
|
604905
|
-
init_promptLoader2();
|
|
604906
|
-
TEMPLATES = {
|
|
604907
|
-
code: {
|
|
604908
|
-
type: "code",
|
|
604909
|
-
label: "Software Development",
|
|
604910
|
-
description: "Writing, debugging, refactoring, or reviewing code.",
|
|
604911
|
-
systemPromptAddition: loadPrompt2("code.md"),
|
|
604912
|
-
recommendedTools: [
|
|
604913
|
-
"file_read",
|
|
604914
|
-
"file_write",
|
|
604915
|
-
"file_edit",
|
|
604916
|
-
"shell",
|
|
604917
|
-
"grep_search",
|
|
604918
|
-
"glob_find",
|
|
604919
|
-
"git_info",
|
|
604920
|
-
"codebase_map"
|
|
604921
|
-
],
|
|
604922
|
-
outputGuidance: "Deliver working code with tests passing. Summarize what was changed and why."
|
|
604923
|
-
},
|
|
604924
|
-
document: {
|
|
604925
|
-
type: "document",
|
|
604926
|
-
label: "Document Drafting",
|
|
604927
|
-
description: "Creating reports, specifications, guides, proposals, or other professional documents.",
|
|
604928
|
-
systemPromptAddition: loadPrompt2("document.md"),
|
|
604929
|
-
recommendedTools: [
|
|
604930
|
-
"file_read",
|
|
604931
|
-
"file_write",
|
|
604932
|
-
"web_search",
|
|
604933
|
-
"web_fetch",
|
|
604934
|
-
"create_structured_file",
|
|
604935
|
-
"memory_read"
|
|
604936
|
-
],
|
|
604937
|
-
outputGuidance: "Deliver a complete, well-structured document. Specify the output format (Markdown, PDF, etc.)."
|
|
604938
|
-
},
|
|
604939
|
-
analysis: {
|
|
604940
|
-
type: "analysis",
|
|
604941
|
-
label: "Analysis & Research",
|
|
604942
|
-
description: "Analyzing data, evaluating options, conducting research, or producing insights.",
|
|
604943
|
-
systemPromptAddition: loadPrompt2("analysis.md"),
|
|
604944
|
-
recommendedTools: [
|
|
604945
|
-
"file_read",
|
|
604946
|
-
"grep_search",
|
|
604947
|
-
"glob_find",
|
|
604948
|
-
"web_search",
|
|
604949
|
-
"web_fetch",
|
|
604950
|
-
"codebase_map",
|
|
604951
|
-
"create_structured_file",
|
|
604952
|
-
"shell"
|
|
604953
|
-
],
|
|
604954
|
-
outputGuidance: "Deliver a structured analysis with findings, data tables, and actionable recommendations."
|
|
604955
|
-
},
|
|
604956
|
-
plan: {
|
|
604957
|
-
type: "plan",
|
|
604958
|
-
label: "Planning & Design",
|
|
604959
|
-
description: "Creating project plans, system designs, architecture proposals, or roadmaps.",
|
|
604960
|
-
systemPromptAddition: loadPrompt2("plan.md"),
|
|
604961
|
-
recommendedTools: [
|
|
604962
|
-
"file_read",
|
|
604963
|
-
"grep_search",
|
|
604964
|
-
"glob_find",
|
|
604965
|
-
"codebase_map",
|
|
604966
|
-
"web_search",
|
|
604967
|
-
"create_structured_file",
|
|
604968
|
-
"file_write",
|
|
604969
|
-
"git_info"
|
|
604970
|
-
],
|
|
604971
|
-
outputGuidance: "Deliver a structured plan with phases, milestones, risks, and action items."
|
|
604972
|
-
},
|
|
604973
|
-
general: {
|
|
604974
|
-
type: "general",
|
|
604975
|
-
label: "General Task",
|
|
604976
|
-
description: "Tasks that don't clearly fit another category.",
|
|
604977
|
-
systemPromptAddition: loadPrompt2("general.md"),
|
|
604978
|
-
recommendedTools: [
|
|
604979
|
-
"file_read",
|
|
604980
|
-
"file_write",
|
|
604981
|
-
"shell",
|
|
604982
|
-
"grep_search",
|
|
604983
|
-
"web_search",
|
|
604984
|
-
"memory_read"
|
|
604985
|
-
],
|
|
604986
|
-
outputGuidance: "Deliver complete results with a clear summary of what was done."
|
|
604987
|
-
}
|
|
604988
|
-
};
|
|
604989
|
-
}
|
|
604990
|
-
});
|
|
604991
|
-
|
|
604992
|
-
// packages/prompts/dist/index.js
|
|
604993
|
-
import { join as join124, dirname as dirname39 } from "node:path";
|
|
604994
|
-
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
604995
|
-
var _dir, _packageRoot;
|
|
604996
|
-
var init_dist9 = __esm({
|
|
604997
|
-
"packages/prompts/dist/index.js"() {
|
|
604998
|
-
"use strict";
|
|
604999
|
-
init_loader();
|
|
605000
|
-
init_render2();
|
|
605001
|
-
init_task_templates();
|
|
605002
|
-
init_render2();
|
|
605003
|
-
_dir = dirname39(fileURLToPath14(import.meta.url));
|
|
605004
|
-
_packageRoot = join124(_dir, "..");
|
|
605005
|
-
}
|
|
605006
|
-
});
|
|
605007
|
-
|
|
605008
604404
|
// packages/cli/src/tui/omnius-directory.ts
|
|
605009
604405
|
var omnius_directory_exports = {};
|
|
605010
604406
|
__export(omnius_directory_exports, {
|
|
@@ -605043,24 +604439,25 @@ __export(omnius_directory_exports, {
|
|
|
605043
604439
|
saveSessionHistory: () => saveSessionHistory,
|
|
605044
604440
|
sessionContextToHistoryBoxData: () => sessionContextToHistoryBoxData,
|
|
605045
604441
|
stopOmniusGitignoreWatcher: () => stopOmniusGitignoreWatcher,
|
|
604442
|
+
updateSessionEntry: () => updateSessionEntry,
|
|
605046
604443
|
writeIndexData: () => writeIndexData,
|
|
605047
604444
|
writeIndexMeta: () => writeIndexMeta,
|
|
605048
604445
|
writeTaskHandoff: () => writeTaskHandoff2
|
|
605049
604446
|
});
|
|
605050
|
-
import { appendFileSync as appendFileSync9, cpSync as cpSync2, existsSync as
|
|
605051
|
-
import { join as
|
|
605052
|
-
import { homedir as
|
|
604447
|
+
import { appendFileSync as appendFileSync9, cpSync as cpSync2, existsSync as existsSync107, mkdirSync as mkdirSync65, readFileSync as readFileSync86, writeFileSync as writeFileSync55, readdirSync as readdirSync37, statSync as statSync41, unlinkSync as unlinkSync21, openSync as openSync2, closeSync as closeSync2, renameSync as renameSync8, watch as fsWatch2 } from "node:fs";
|
|
604448
|
+
import { join as join122, relative as relative12, basename as basename22, dirname as dirname38, resolve as resolve52 } from "node:path";
|
|
604449
|
+
import { homedir as homedir37 } from "node:os";
|
|
605053
604450
|
import { createHash as createHash34 } from "node:crypto";
|
|
605054
604451
|
function isGitRoot(dir) {
|
|
605055
|
-
const gitPath =
|
|
605056
|
-
if (!
|
|
604452
|
+
const gitPath = join122(dir, ".git");
|
|
604453
|
+
if (!existsSync107(gitPath)) return false;
|
|
605057
604454
|
try {
|
|
605058
|
-
const stat8 =
|
|
604455
|
+
const stat8 = statSync41(gitPath);
|
|
605059
604456
|
if (stat8.isFile()) {
|
|
605060
|
-
return
|
|
604457
|
+
return readFileSync86(gitPath, "utf-8").trim().startsWith("gitdir:");
|
|
605061
604458
|
}
|
|
605062
604459
|
if (!stat8.isDirectory()) return false;
|
|
605063
|
-
return
|
|
604460
|
+
return existsSync107(join122(gitPath, "HEAD")) || existsSync107(join122(gitPath, "config")) || existsSync107(join122(gitPath, "commondir"));
|
|
605064
604461
|
} catch {
|
|
605065
604462
|
return false;
|
|
605066
604463
|
}
|
|
@@ -605071,7 +604468,7 @@ function findGitRoot(startDir) {
|
|
|
605071
604468
|
while (dir && !visited.has(dir)) {
|
|
605072
604469
|
visited.add(dir);
|
|
605073
604470
|
if (isGitRoot(dir)) return dir;
|
|
605074
|
-
const parent =
|
|
604471
|
+
const parent = join122(dir, "..");
|
|
605075
604472
|
if (parent === dir) break;
|
|
605076
604473
|
dir = parent;
|
|
605077
604474
|
}
|
|
@@ -605082,10 +604479,10 @@ function findNearestExistingGitignore(startDir, gitRoot) {
|
|
|
605082
604479
|
const visited = /* @__PURE__ */ new Set();
|
|
605083
604480
|
while (dir && !visited.has(dir)) {
|
|
605084
604481
|
visited.add(dir);
|
|
605085
|
-
const candidate =
|
|
605086
|
-
if (
|
|
604482
|
+
const candidate = join122(dir, ".gitignore");
|
|
604483
|
+
if (existsSync107(candidate)) return candidate;
|
|
605087
604484
|
if (dir === gitRoot) break;
|
|
605088
|
-
const parent =
|
|
604485
|
+
const parent = join122(dir, "..");
|
|
605089
604486
|
if (parent === dir) break;
|
|
605090
604487
|
dir = parent;
|
|
605091
604488
|
}
|
|
@@ -605099,7 +604496,7 @@ function candidateGitignoreDirs(startDir, gitRoot) {
|
|
|
605099
604496
|
visited.add(dir);
|
|
605100
604497
|
dirs.push(dir);
|
|
605101
604498
|
if (dir === gitRoot) break;
|
|
605102
|
-
const parent =
|
|
604499
|
+
const parent = join122(dir, "..");
|
|
605103
604500
|
if (parent === dir) break;
|
|
605104
604501
|
dir = parent;
|
|
605105
604502
|
}
|
|
@@ -605113,10 +604510,10 @@ function ensureOmniusIgnored(repoRoot) {
|
|
|
605113
604510
|
if (!gitRoot) return;
|
|
605114
604511
|
const gitignorePath = findNearestExistingGitignore(repoRoot, gitRoot);
|
|
605115
604512
|
if (!gitignorePath) return;
|
|
605116
|
-
const gitignoreDir =
|
|
604513
|
+
const gitignoreDir = dirname38(gitignorePath);
|
|
605117
604514
|
const relDir = relative12(gitignoreDir || ".", repoRoot).replace(/\\/g, "/");
|
|
605118
604515
|
const ignorePattern = relDir && relDir !== "." ? `${relDir}/.omnius/` : ".omnius/";
|
|
605119
|
-
const content =
|
|
604516
|
+
const content = readFileSync86(gitignorePath, "utf-8");
|
|
605120
604517
|
const normalizedTarget = normalizeIgnoreRule(ignorePattern);
|
|
605121
604518
|
const alreadyIgnored = content.split(/\r?\n/).some((line) => {
|
|
605122
604519
|
const trimmed = line.trim();
|
|
@@ -605124,7 +604521,7 @@ function ensureOmniusIgnored(repoRoot) {
|
|
|
605124
604521
|
return normalizeIgnoreRule(trimmed) === normalizedTarget;
|
|
605125
604522
|
});
|
|
605126
604523
|
if (alreadyIgnored) return;
|
|
605127
|
-
|
|
604524
|
+
writeFileSync55(
|
|
605128
604525
|
gitignorePath,
|
|
605129
604526
|
(content.trimEnd() ? `${content.trimEnd()}
|
|
605130
604527
|
` : "") + `${ignorePattern}
|
|
@@ -605135,7 +604532,7 @@ function ensureOmniusIgnored(repoRoot) {
|
|
|
605135
604532
|
function watchForOmniusGitignore(repoRoot) {
|
|
605136
604533
|
const gitRoot = findGitRoot(repoRoot);
|
|
605137
604534
|
if (!gitRoot) return;
|
|
605138
|
-
const key =
|
|
604535
|
+
const key = resolve52(repoRoot);
|
|
605139
604536
|
if (gitignoreWatchers.has(key)) return;
|
|
605140
604537
|
const watchers = [];
|
|
605141
604538
|
for (const dir of candidateGitignoreDirs(repoRoot, gitRoot)) {
|
|
@@ -605161,7 +604558,7 @@ function watchForOmniusGitignore(repoRoot) {
|
|
|
605161
604558
|
if (watchers.length > 0) gitignoreWatchers.set(key, watchers);
|
|
605162
604559
|
}
|
|
605163
604560
|
function stopOmniusGitignoreWatcher(repoRoot) {
|
|
605164
|
-
const keys = repoRoot ? [
|
|
604561
|
+
const keys = repoRoot ? [resolve52(repoRoot)] : Array.from(gitignoreWatchers.keys());
|
|
605165
604562
|
for (const key of keys) {
|
|
605166
604563
|
const watchers = gitignoreWatchers.get(key) ?? [];
|
|
605167
604564
|
for (const watcher of watchers) {
|
|
@@ -605175,8 +604572,8 @@ function stopOmniusGitignoreWatcher(repoRoot) {
|
|
|
605175
604572
|
}
|
|
605176
604573
|
function migrateLegacyDirectories(repoRoot, omniusPath) {
|
|
605177
604574
|
for (const legacyDir of LEGACY_DIRS) {
|
|
605178
|
-
const legacyPath =
|
|
605179
|
-
if (!
|
|
604575
|
+
const legacyPath = join122(repoRoot, legacyDir);
|
|
604576
|
+
if (!existsSync107(legacyPath) || legacyPath === omniusPath) continue;
|
|
605180
604577
|
try {
|
|
605181
604578
|
cpSync2(legacyPath, omniusPath, {
|
|
605182
604579
|
recursive: true,
|
|
@@ -605188,11 +604585,11 @@ function migrateLegacyDirectories(repoRoot, omniusPath) {
|
|
|
605188
604585
|
}
|
|
605189
604586
|
}
|
|
605190
604587
|
function initOmniusDirectory(repoRoot) {
|
|
605191
|
-
const omniusPath =
|
|
605192
|
-
|
|
604588
|
+
const omniusPath = join122(repoRoot, OMNIUS_DIR);
|
|
604589
|
+
mkdirSync65(omniusPath, { recursive: true });
|
|
605193
604590
|
migrateLegacyDirectories(repoRoot, omniusPath);
|
|
605194
604591
|
for (const sub2 of SUBDIRS) {
|
|
605195
|
-
|
|
604592
|
+
mkdirSync65(join122(omniusPath, sub2), { recursive: true });
|
|
605196
604593
|
}
|
|
605197
604594
|
try {
|
|
605198
604595
|
ensureOmniusIgnored(repoRoot);
|
|
@@ -605205,41 +604602,41 @@ function initOmniusDirectory(repoRoot) {
|
|
|
605205
604602
|
return omniusPath;
|
|
605206
604603
|
}
|
|
605207
604604
|
function hasOmniusDirectory(repoRoot) {
|
|
605208
|
-
return
|
|
604605
|
+
return existsSync107(join122(repoRoot, OMNIUS_DIR, "index"));
|
|
605209
604606
|
}
|
|
605210
604607
|
function loadProjectSettings(repoRoot) {
|
|
605211
|
-
const settingsPath =
|
|
604608
|
+
const settingsPath = join122(repoRoot, OMNIUS_DIR, "settings.json");
|
|
605212
604609
|
try {
|
|
605213
|
-
if (
|
|
605214
|
-
return JSON.parse(
|
|
604610
|
+
if (existsSync107(settingsPath)) {
|
|
604611
|
+
return JSON.parse(readFileSync86(settingsPath, "utf-8"));
|
|
605215
604612
|
}
|
|
605216
604613
|
} catch {
|
|
605217
604614
|
}
|
|
605218
604615
|
return {};
|
|
605219
604616
|
}
|
|
605220
604617
|
function saveProjectSettings(repoRoot, settings) {
|
|
605221
|
-
const omniusPath =
|
|
605222
|
-
|
|
604618
|
+
const omniusPath = join122(repoRoot, OMNIUS_DIR);
|
|
604619
|
+
mkdirSync65(omniusPath, { recursive: true });
|
|
605223
604620
|
const existing = loadProjectSettings(repoRoot);
|
|
605224
604621
|
const merged = { ...existing, ...settings };
|
|
605225
|
-
|
|
604622
|
+
writeFileSync55(join122(omniusPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
605226
604623
|
}
|
|
605227
604624
|
function loadGlobalSettings() {
|
|
605228
|
-
const settingsPath =
|
|
604625
|
+
const settingsPath = join122(homedir37(), ".omnius", "settings.json");
|
|
605229
604626
|
try {
|
|
605230
|
-
if (
|
|
605231
|
-
return JSON.parse(
|
|
604627
|
+
if (existsSync107(settingsPath)) {
|
|
604628
|
+
return JSON.parse(readFileSync86(settingsPath, "utf-8"));
|
|
605232
604629
|
}
|
|
605233
604630
|
} catch {
|
|
605234
604631
|
}
|
|
605235
604632
|
return {};
|
|
605236
604633
|
}
|
|
605237
604634
|
function saveGlobalSettings(settings) {
|
|
605238
|
-
const dir =
|
|
605239
|
-
|
|
604635
|
+
const dir = join122(homedir37(), ".omnius");
|
|
604636
|
+
mkdirSync65(dir, { recursive: true });
|
|
605240
604637
|
const existing = loadGlobalSettings();
|
|
605241
604638
|
const merged = { ...existing, ...settings };
|
|
605242
|
-
|
|
604639
|
+
writeFileSync55(join122(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
605243
604640
|
}
|
|
605244
604641
|
function resolveSettings(repoRoot) {
|
|
605245
604642
|
const global2 = loadGlobalSettings();
|
|
@@ -605254,12 +604651,12 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
605254
604651
|
while (dir && !visited.has(dir)) {
|
|
605255
604652
|
visited.add(dir);
|
|
605256
604653
|
for (const name10 of CONTEXT_FILES) {
|
|
605257
|
-
const filePath =
|
|
604654
|
+
const filePath = join122(dir, name10);
|
|
605258
604655
|
const normalizedName = name10.toLowerCase();
|
|
605259
|
-
if (
|
|
604656
|
+
if (existsSync107(filePath) && !seen.has(filePath)) {
|
|
605260
604657
|
seen.add(filePath);
|
|
605261
604658
|
try {
|
|
605262
|
-
let content =
|
|
604659
|
+
let content = readFileSync86(filePath, "utf-8");
|
|
605263
604660
|
if (content.length > maxContentLen) {
|
|
605264
604661
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
605265
604662
|
}
|
|
@@ -605273,7 +604670,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
605273
604670
|
}
|
|
605274
604671
|
}
|
|
605275
604672
|
}
|
|
605276
|
-
const parent =
|
|
604673
|
+
const parent = join122(dir, "..");
|
|
605277
604674
|
if (parent === dir) break;
|
|
605278
604675
|
dir = parent;
|
|
605279
604676
|
}
|
|
@@ -605290,34 +604687,34 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
605290
604687
|
return found;
|
|
605291
604688
|
}
|
|
605292
604689
|
function readIndexMeta(repoRoot) {
|
|
605293
|
-
const metaPath =
|
|
604690
|
+
const metaPath = join122(repoRoot, OMNIUS_DIR, "index", "meta.json");
|
|
605294
604691
|
try {
|
|
605295
|
-
return JSON.parse(
|
|
604692
|
+
return JSON.parse(readFileSync86(metaPath, "utf-8"));
|
|
605296
604693
|
} catch {
|
|
605297
604694
|
return null;
|
|
605298
604695
|
}
|
|
605299
604696
|
}
|
|
605300
604697
|
function writeIndexMeta(repoRoot, meta) {
|
|
605301
|
-
const metaPath =
|
|
605302
|
-
|
|
605303
|
-
|
|
604698
|
+
const metaPath = join122(repoRoot, OMNIUS_DIR, "index", "meta.json");
|
|
604699
|
+
mkdirSync65(join122(repoRoot, OMNIUS_DIR, "index"), { recursive: true });
|
|
604700
|
+
writeFileSync55(metaPath, JSON.stringify(meta, null, 2), "utf-8");
|
|
605304
604701
|
}
|
|
605305
604702
|
function readIndexData(repoRoot, filename) {
|
|
605306
|
-
const filePath =
|
|
604703
|
+
const filePath = join122(repoRoot, OMNIUS_DIR, "index", filename);
|
|
605307
604704
|
try {
|
|
605308
|
-
return JSON.parse(
|
|
604705
|
+
return JSON.parse(readFileSync86(filePath, "utf-8"));
|
|
605309
604706
|
} catch {
|
|
605310
604707
|
return null;
|
|
605311
604708
|
}
|
|
605312
604709
|
}
|
|
605313
604710
|
function writeIndexData(repoRoot, filename, data) {
|
|
605314
|
-
const filePath =
|
|
605315
|
-
|
|
605316
|
-
|
|
604711
|
+
const filePath = join122(repoRoot, OMNIUS_DIR, "index", filename);
|
|
604712
|
+
mkdirSync65(join122(repoRoot, OMNIUS_DIR, "index"), { recursive: true });
|
|
604713
|
+
writeFileSync55(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
605317
604714
|
}
|
|
605318
604715
|
function generateProjectMap(repoRoot) {
|
|
605319
604716
|
const sections = [];
|
|
605320
|
-
const repoName2 =
|
|
604717
|
+
const repoName2 = basename22(repoRoot);
|
|
605321
604718
|
sections.push(`# Project Map: ${repoName2}
|
|
605322
604719
|
`);
|
|
605323
604720
|
sections.push(`> Auto-generated by omnius. Updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -605360,31 +604757,31 @@ ${tree2}\`\`\`
|
|
|
605360
604757
|
sections.push("");
|
|
605361
604758
|
}
|
|
605362
604759
|
const content = sections.join("\n");
|
|
605363
|
-
const contextDir =
|
|
605364
|
-
|
|
605365
|
-
|
|
604760
|
+
const contextDir = join122(repoRoot, OMNIUS_DIR, "context");
|
|
604761
|
+
mkdirSync65(contextDir, { recursive: true });
|
|
604762
|
+
writeFileSync55(join122(contextDir, "project-map.md"), content, "utf-8");
|
|
605366
604763
|
return content;
|
|
605367
604764
|
}
|
|
605368
604765
|
function saveSession(repoRoot, session) {
|
|
605369
|
-
const historyDir =
|
|
605370
|
-
|
|
605371
|
-
|
|
605372
|
-
|
|
604766
|
+
const historyDir = join122(repoRoot, OMNIUS_DIR, "history");
|
|
604767
|
+
mkdirSync65(historyDir, { recursive: true });
|
|
604768
|
+
writeFileSync55(
|
|
604769
|
+
join122(historyDir, `${session.id}.json`),
|
|
605373
604770
|
JSON.stringify(session, null, 2),
|
|
605374
604771
|
"utf-8"
|
|
605375
604772
|
);
|
|
605376
604773
|
}
|
|
605377
604774
|
function loadRecentSessions(repoRoot, limit = 5) {
|
|
605378
|
-
const historyDir =
|
|
605379
|
-
if (!
|
|
604775
|
+
const historyDir = join122(repoRoot, OMNIUS_DIR, "history");
|
|
604776
|
+
if (!existsSync107(historyDir)) return [];
|
|
605380
604777
|
try {
|
|
605381
604778
|
const files = readdirSync37(historyDir).filter((f2) => f2.endsWith(".json") && f2 !== "pending-task.json").map((f2) => {
|
|
605382
|
-
const stat8 =
|
|
604779
|
+
const stat8 = statSync41(join122(historyDir, f2));
|
|
605383
604780
|
return { file: f2, mtime: stat8.mtimeMs };
|
|
605384
604781
|
}).sort((a2, b) => b.mtime - a2.mtime).slice(0, limit);
|
|
605385
604782
|
return files.map((f2) => {
|
|
605386
604783
|
try {
|
|
605387
|
-
return JSON.parse(
|
|
604784
|
+
return JSON.parse(readFileSync86(join122(historyDir, f2.file), "utf-8"));
|
|
605388
604785
|
} catch {
|
|
605389
604786
|
return null;
|
|
605390
604787
|
}
|
|
@@ -605396,21 +604793,21 @@ function loadRecentSessions(repoRoot, limit = 5) {
|
|
|
605396
604793
|
}
|
|
605397
604794
|
}
|
|
605398
604795
|
function savePendingTask(repoRoot, task) {
|
|
605399
|
-
const historyDir =
|
|
605400
|
-
|
|
605401
|
-
|
|
605402
|
-
|
|
604796
|
+
const historyDir = join122(repoRoot, OMNIUS_DIR, "history");
|
|
604797
|
+
mkdirSync65(historyDir, { recursive: true });
|
|
604798
|
+
writeFileSync55(
|
|
604799
|
+
join122(historyDir, PENDING_TASK_FILE),
|
|
605403
604800
|
JSON.stringify(task, null, 2) + "\n",
|
|
605404
604801
|
"utf-8"
|
|
605405
604802
|
);
|
|
605406
604803
|
}
|
|
605407
604804
|
function loadPendingTask(repoRoot) {
|
|
605408
|
-
const filePath =
|
|
604805
|
+
const filePath = join122(repoRoot, OMNIUS_DIR, "history", PENDING_TASK_FILE);
|
|
605409
604806
|
try {
|
|
605410
|
-
if (!
|
|
605411
|
-
const data = JSON.parse(
|
|
604807
|
+
if (!existsSync107(filePath)) return null;
|
|
604808
|
+
const data = JSON.parse(readFileSync86(filePath, "utf-8"));
|
|
605412
604809
|
try {
|
|
605413
|
-
|
|
604810
|
+
unlinkSync21(filePath);
|
|
605414
604811
|
} catch {
|
|
605415
604812
|
}
|
|
605416
604813
|
return data;
|
|
@@ -605419,26 +604816,26 @@ function loadPendingTask(repoRoot) {
|
|
|
605419
604816
|
}
|
|
605420
604817
|
}
|
|
605421
604818
|
function writeTaskHandoff2(repoRoot, handoff) {
|
|
605422
|
-
const contextDir =
|
|
605423
|
-
|
|
605424
|
-
const filePath =
|
|
604819
|
+
const contextDir = join122(repoRoot, OMNIUS_DIR, "context");
|
|
604820
|
+
mkdirSync65(contextDir, { recursive: true });
|
|
604821
|
+
const filePath = join122(contextDir, HANDOFF_FILE);
|
|
605425
604822
|
const tempPath = filePath + ".tmp";
|
|
605426
|
-
|
|
604823
|
+
writeFileSync55(tempPath, JSON.stringify(handoff, null, 2) + "\n", "utf-8");
|
|
605427
604824
|
try {
|
|
605428
604825
|
renameSync8(tempPath, filePath);
|
|
605429
604826
|
} catch {
|
|
605430
|
-
|
|
604827
|
+
writeFileSync55(filePath, JSON.stringify(handoff, null, 2) + "\n", "utf-8");
|
|
605431
604828
|
try {
|
|
605432
|
-
|
|
604829
|
+
unlinkSync21(tempPath);
|
|
605433
604830
|
} catch {
|
|
605434
604831
|
}
|
|
605435
604832
|
}
|
|
605436
604833
|
}
|
|
605437
604834
|
function readTaskHandoff2(repoRoot) {
|
|
605438
|
-
const filePath =
|
|
604835
|
+
const filePath = join122(repoRoot, OMNIUS_DIR, "context", HANDOFF_FILE);
|
|
605439
604836
|
try {
|
|
605440
|
-
if (!
|
|
605441
|
-
const data = JSON.parse(
|
|
604837
|
+
if (!existsSync107(filePath)) return null;
|
|
604838
|
+
const data = JSON.parse(readFileSync86(filePath, "utf-8"));
|
|
605442
604839
|
const handoffTime = new Date(data.handoffAt).getTime();
|
|
605443
604840
|
const now2 = Date.now();
|
|
605444
604841
|
const ageMs = now2 - handoffTime;
|
|
@@ -605452,10 +604849,10 @@ function readTaskHandoff2(repoRoot) {
|
|
|
605452
604849
|
}
|
|
605453
604850
|
}
|
|
605454
604851
|
function clearTaskHandoff(repoRoot) {
|
|
605455
|
-
const filePath =
|
|
604852
|
+
const filePath = join122(repoRoot, OMNIUS_DIR, "context", HANDOFF_FILE);
|
|
605456
604853
|
try {
|
|
605457
|
-
if (
|
|
605458
|
-
|
|
604854
|
+
if (existsSync107(filePath)) {
|
|
604855
|
+
unlinkSync21(filePath);
|
|
605459
604856
|
}
|
|
605460
604857
|
} catch {
|
|
605461
604858
|
}
|
|
@@ -605518,24 +604915,24 @@ function acquireLock(lockPath) {
|
|
|
605518
604915
|
try {
|
|
605519
604916
|
const fd = openSync2(lockPath, "wx");
|
|
605520
604917
|
const lockData = JSON.stringify({ pid, acquiredAt: Date.now() });
|
|
605521
|
-
|
|
604918
|
+
writeFileSync55(fd, lockData);
|
|
605522
604919
|
closeSync2(fd);
|
|
605523
604920
|
return true;
|
|
605524
604921
|
} catch (err) {
|
|
605525
|
-
if (
|
|
604922
|
+
if (existsSync107(lockPath)) {
|
|
605526
604923
|
try {
|
|
605527
|
-
const lockContent =
|
|
604924
|
+
const lockContent = readFileSync86(lockPath, "utf-8");
|
|
605528
604925
|
const lock = JSON.parse(lockContent);
|
|
605529
604926
|
const lockAge = Date.now() - lock.acquiredAt;
|
|
605530
604927
|
if (lockAge > LOCK_TIMEOUT_MS) {
|
|
605531
604928
|
try {
|
|
605532
|
-
|
|
604929
|
+
unlinkSync21(lockPath);
|
|
605533
604930
|
} catch {
|
|
605534
604931
|
}
|
|
605535
604932
|
}
|
|
605536
604933
|
} catch {
|
|
605537
604934
|
try {
|
|
605538
|
-
|
|
604935
|
+
unlinkSync21(lockPath);
|
|
605539
604936
|
} catch {
|
|
605540
604937
|
}
|
|
605541
604938
|
}
|
|
@@ -605549,11 +604946,11 @@ function acquireLock(lockPath) {
|
|
|
605549
604946
|
}
|
|
605550
604947
|
function releaseLock(lockPath) {
|
|
605551
604948
|
try {
|
|
605552
|
-
if (
|
|
605553
|
-
const lockContent =
|
|
604949
|
+
if (existsSync107(lockPath)) {
|
|
604950
|
+
const lockContent = readFileSync86(lockPath, "utf-8");
|
|
605554
604951
|
const lock = JSON.parse(lockContent);
|
|
605555
604952
|
if (lock.pid === process.pid) {
|
|
605556
|
-
|
|
604953
|
+
unlinkSync21(lockPath);
|
|
605557
604954
|
}
|
|
605558
604955
|
}
|
|
605559
604956
|
} catch {
|
|
@@ -605639,29 +605036,29 @@ function mergeSessionContextEntry(previous, incoming) {
|
|
|
605639
605036
|
}
|
|
605640
605037
|
function pruneContextLedger(ledgerPath) {
|
|
605641
605038
|
try {
|
|
605642
|
-
if (!
|
|
605643
|
-
const st =
|
|
605039
|
+
if (!existsSync107(ledgerPath)) return;
|
|
605040
|
+
const st = statSync41(ledgerPath);
|
|
605644
605041
|
if (st.size <= MAX_CONTEXT_LEDGER_BYTES) return;
|
|
605645
|
-
const lines =
|
|
605042
|
+
const lines = readFileSync86(ledgerPath, "utf-8").split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
605646
605043
|
if (lines.length <= MAX_CONTEXT_LEDGER_LINES) return;
|
|
605647
605044
|
const kept = lines.slice(-MAX_CONTEXT_LEDGER_LINES);
|
|
605648
|
-
const archiveDir =
|
|
605649
|
-
|
|
605650
|
-
const archivePath =
|
|
605045
|
+
const archiveDir = join122(dirname38(ledgerPath), "archive");
|
|
605046
|
+
mkdirSync65(archiveDir, { recursive: true });
|
|
605047
|
+
const archivePath = join122(
|
|
605651
605048
|
archiveDir,
|
|
605652
605049
|
`session-context.events.${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.jsonl`
|
|
605653
605050
|
);
|
|
605654
|
-
|
|
605655
|
-
|
|
605051
|
+
writeFileSync55(archivePath, lines.slice(0, -MAX_CONTEXT_LEDGER_LINES).join("\n") + "\n", "utf-8");
|
|
605052
|
+
writeFileSync55(ledgerPath, kept.join("\n") + "\n", "utf-8");
|
|
605656
605053
|
} catch {
|
|
605657
605054
|
}
|
|
605658
605055
|
}
|
|
605659
605056
|
function saveSessionContext(repoRoot, entry) {
|
|
605660
|
-
const contextDir =
|
|
605661
|
-
|
|
605662
|
-
const filePath =
|
|
605663
|
-
const ledgerPath =
|
|
605664
|
-
const lockPath =
|
|
605057
|
+
const contextDir = join122(repoRoot, OMNIUS_DIR, "context");
|
|
605058
|
+
mkdirSync65(contextDir, { recursive: true });
|
|
605059
|
+
const filePath = join122(contextDir, CONTEXT_SAVE_FILE);
|
|
605060
|
+
const ledgerPath = join122(contextDir, CONTEXT_LEDGER_FILE);
|
|
605061
|
+
const lockPath = join122(contextDir, CONTEXT_SAVE_FILE + ".lock");
|
|
605665
605062
|
const locked = acquireLock(lockPath);
|
|
605666
605063
|
if (!locked) {
|
|
605667
605064
|
console.warn("[saveSessionContext] Could not acquire lock, proceeding without mutex");
|
|
@@ -605669,8 +605066,8 @@ function saveSessionContext(repoRoot, entry) {
|
|
|
605669
605066
|
try {
|
|
605670
605067
|
let ctx3;
|
|
605671
605068
|
try {
|
|
605672
|
-
if (
|
|
605673
|
-
ctx3 = JSON.parse(
|
|
605069
|
+
if (existsSync107(filePath)) {
|
|
605070
|
+
ctx3 = JSON.parse(readFileSync86(filePath, "utf-8"));
|
|
605674
605071
|
} else {
|
|
605675
605072
|
ctx3 = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
|
|
605676
605073
|
}
|
|
@@ -605733,19 +605130,19 @@ function saveSessionContext(repoRoot, entry) {
|
|
|
605733
605130
|
}
|
|
605734
605131
|
ctx3.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
605735
605132
|
const tempFilePath = filePath + ".tmp";
|
|
605736
|
-
|
|
605133
|
+
writeFileSync55(tempFilePath, JSON.stringify(ctx3, null, 2) + "\n", "utf-8");
|
|
605737
605134
|
try {
|
|
605738
605135
|
renameSync8(tempFilePath, filePath);
|
|
605739
605136
|
} catch {
|
|
605740
|
-
|
|
605137
|
+
writeFileSync55(filePath, JSON.stringify(ctx3, null, 2) + "\n", "utf-8");
|
|
605741
605138
|
try {
|
|
605742
|
-
|
|
605139
|
+
unlinkSync21(tempFilePath);
|
|
605743
605140
|
} catch {
|
|
605744
605141
|
}
|
|
605745
605142
|
}
|
|
605746
605143
|
try {
|
|
605747
|
-
|
|
605748
|
-
|
|
605144
|
+
writeFileSync55(
|
|
605145
|
+
join122(contextDir, "session-diary.md"),
|
|
605749
605146
|
renderSessionDiary(ctx3.entries.slice(-MAX_SESSION_DIARY_ENTRIES)),
|
|
605750
605147
|
"utf-8"
|
|
605751
605148
|
);
|
|
@@ -605829,10 +605226,10 @@ function renderSessionDiary(entries) {
|
|
|
605829
605226
|
return lines.join("\n");
|
|
605830
605227
|
}
|
|
605831
605228
|
function loadSessionContext(repoRoot) {
|
|
605832
|
-
const filePath =
|
|
605229
|
+
const filePath = join122(repoRoot, OMNIUS_DIR, "context", CONTEXT_SAVE_FILE);
|
|
605833
605230
|
try {
|
|
605834
|
-
if (!
|
|
605835
|
-
return JSON.parse(
|
|
605231
|
+
if (!existsSync107(filePath)) return null;
|
|
605232
|
+
return JSON.parse(readFileSync86(filePath, "utf-8"));
|
|
605836
605233
|
} catch {
|
|
605837
605234
|
return null;
|
|
605838
605235
|
}
|
|
@@ -605916,6 +605313,20 @@ function getLastTaskSummary(repoRoot) {
|
|
|
605916
605313
|
const clean5 = text2.replace(/^\[.*?\]\s*/, "").replace(/\s+/g, " ").trim();
|
|
605917
605314
|
return clean5.length > 40 ? clean5.slice(0, 37) + "..." : clean5;
|
|
605918
605315
|
}
|
|
605316
|
+
function updateSessionEntry(repoRoot, sessionId, patch) {
|
|
605317
|
+
const indexPath = join122(repoRoot, OMNIUS_DIR, SESSIONS_DIR, SESSIONS_INDEX);
|
|
605318
|
+
try {
|
|
605319
|
+
if (!existsSync107(indexPath)) return false;
|
|
605320
|
+
const index = JSON.parse(readFileSync86(indexPath, "utf-8"));
|
|
605321
|
+
const idx = index.findIndex((e2) => e2.id === sessionId);
|
|
605322
|
+
if (idx < 0) return false;
|
|
605323
|
+
index[idx] = { ...index[idx], ...patch };
|
|
605324
|
+
writeFileSync55(indexPath, JSON.stringify(index, null, 2), "utf-8");
|
|
605325
|
+
return true;
|
|
605326
|
+
} catch {
|
|
605327
|
+
return false;
|
|
605328
|
+
}
|
|
605329
|
+
}
|
|
605919
605330
|
function cleanSessionHistoryDisplayLine(line) {
|
|
605920
605331
|
return String(line || "").replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "").replace(/^[>❯▹∙•*+\-\s]+/, "").replace(/^\[.*?\]\s*/, "").replace(/^(?:User|Assistant|You|Open Agent|Omnius)\s*:\s*/i, "").replace(/\s+/g, " ").trim();
|
|
605921
605332
|
}
|
|
@@ -605942,20 +605353,20 @@ function sanitizeSessionHistoryEntry(repoRoot, entry) {
|
|
|
605942
605353
|
};
|
|
605943
605354
|
}
|
|
605944
605355
|
function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
|
|
605945
|
-
const sessDir =
|
|
605946
|
-
|
|
605356
|
+
const sessDir = join122(repoRoot, OMNIUS_DIR, SESSIONS_DIR);
|
|
605357
|
+
mkdirSync65(sessDir, { recursive: true });
|
|
605947
605358
|
const stripped = contentLines.map(
|
|
605948
605359
|
(line) => typeof line === "string" ? line.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "") : ""
|
|
605949
605360
|
);
|
|
605950
605361
|
const autoName = meta.name || generateSessionName(stripped);
|
|
605951
605362
|
const autoDesc = meta.description || generateSessionDescription(stripped);
|
|
605952
|
-
const contentPath =
|
|
605953
|
-
|
|
605954
|
-
const indexPath =
|
|
605363
|
+
const contentPath = join122(sessDir, `${sessionId}.jsonl`);
|
|
605364
|
+
writeFileSync55(contentPath, stripped.join("\n"), "utf-8");
|
|
605365
|
+
const indexPath = join122(sessDir, SESSIONS_INDEX);
|
|
605955
605366
|
let index = [];
|
|
605956
605367
|
try {
|
|
605957
|
-
if (
|
|
605958
|
-
index = JSON.parse(
|
|
605368
|
+
if (existsSync107(indexPath)) {
|
|
605369
|
+
index = JSON.parse(readFileSync86(indexPath, "utf-8"));
|
|
605959
605370
|
}
|
|
605960
605371
|
} catch {
|
|
605961
605372
|
}
|
|
@@ -605977,41 +605388,41 @@ function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
|
|
|
605977
605388
|
if (index.length > 50) {
|
|
605978
605389
|
const removed = index.shift();
|
|
605979
605390
|
try {
|
|
605980
|
-
|
|
605391
|
+
unlinkSync21(join122(sessDir, `${removed.id}.jsonl`));
|
|
605981
605392
|
} catch {
|
|
605982
605393
|
}
|
|
605983
605394
|
}
|
|
605984
|
-
|
|
605395
|
+
writeFileSync55(indexPath, JSON.stringify(index, null, 2), "utf-8");
|
|
605985
605396
|
}
|
|
605986
605397
|
function listSessions(repoRoot) {
|
|
605987
|
-
const indexPath =
|
|
605398
|
+
const indexPath = join122(repoRoot, OMNIUS_DIR, SESSIONS_DIR, SESSIONS_INDEX);
|
|
605988
605399
|
try {
|
|
605989
|
-
if (!
|
|
605990
|
-
const index = JSON.parse(
|
|
605400
|
+
if (!existsSync107(indexPath)) return [];
|
|
605401
|
+
const index = JSON.parse(readFileSync86(indexPath, "utf-8"));
|
|
605991
605402
|
return index.map((entry) => sanitizeSessionHistoryEntry(repoRoot, entry)).sort((a2, b) => b.updatedAt.localeCompare(a2.updatedAt));
|
|
605992
605403
|
} catch {
|
|
605993
605404
|
return [];
|
|
605994
605405
|
}
|
|
605995
605406
|
}
|
|
605996
605407
|
function loadSessionHistory(repoRoot, sessionId) {
|
|
605997
|
-
const contentPath =
|
|
605408
|
+
const contentPath = join122(repoRoot, OMNIUS_DIR, SESSIONS_DIR, `${sessionId}.jsonl`);
|
|
605998
605409
|
try {
|
|
605999
|
-
if (!
|
|
606000
|
-
return
|
|
605410
|
+
if (!existsSync107(contentPath)) return null;
|
|
605411
|
+
return readFileSync86(contentPath, "utf-8").split("\n");
|
|
606001
605412
|
} catch {
|
|
606002
605413
|
return null;
|
|
606003
605414
|
}
|
|
606004
605415
|
}
|
|
606005
605416
|
function deleteSession(repoRoot, sessionId) {
|
|
606006
|
-
const sessDir =
|
|
606007
|
-
const indexPath =
|
|
605417
|
+
const sessDir = join122(repoRoot, OMNIUS_DIR, SESSIONS_DIR);
|
|
605418
|
+
const indexPath = join122(sessDir, SESSIONS_INDEX);
|
|
606008
605419
|
try {
|
|
606009
|
-
const contentPath =
|
|
606010
|
-
if (
|
|
606011
|
-
if (
|
|
606012
|
-
let index = JSON.parse(
|
|
605420
|
+
const contentPath = join122(sessDir, `${sessionId}.jsonl`);
|
|
605421
|
+
if (existsSync107(contentPath)) unlinkSync21(contentPath);
|
|
605422
|
+
if (existsSync107(indexPath)) {
|
|
605423
|
+
let index = JSON.parse(readFileSync86(indexPath, "utf-8"));
|
|
606013
605424
|
index = index.filter((s2) => s2.id !== sessionId);
|
|
606014
|
-
|
|
605425
|
+
writeFileSync55(indexPath, JSON.stringify(index, null, 2), "utf-8");
|
|
606015
605426
|
}
|
|
606016
605427
|
return true;
|
|
606017
605428
|
} catch {
|
|
@@ -606061,12 +605472,12 @@ function detectManifests(repoRoot) {
|
|
|
606061
605472
|
{ file: "docker-compose.yaml", type: "Docker Compose" }
|
|
606062
605473
|
];
|
|
606063
605474
|
for (const check of checks) {
|
|
606064
|
-
const filePath =
|
|
606065
|
-
if (
|
|
605475
|
+
const filePath = join122(repoRoot, check.file);
|
|
605476
|
+
if (existsSync107(filePath)) {
|
|
606066
605477
|
let name10;
|
|
606067
605478
|
if (check.nameField) {
|
|
606068
605479
|
try {
|
|
606069
|
-
const data = JSON.parse(
|
|
605480
|
+
const data = JSON.parse(readFileSync86(filePath, "utf-8"));
|
|
606070
605481
|
name10 = data[check.nameField];
|
|
606071
605482
|
} catch {
|
|
606072
605483
|
}
|
|
@@ -606095,7 +605506,7 @@ function findKeyFiles(repoRoot) {
|
|
|
606095
605506
|
{ pattern: "CLAUDE.md", description: "Claude Code context" }
|
|
606096
605507
|
];
|
|
606097
605508
|
for (const check of checks) {
|
|
606098
|
-
if (
|
|
605509
|
+
if (existsSync107(join122(repoRoot, check.pattern))) {
|
|
606099
605510
|
keyFiles.push({ path: check.pattern, description: check.description });
|
|
606100
605511
|
}
|
|
606101
605512
|
}
|
|
@@ -606104,7 +605515,7 @@ function findKeyFiles(repoRoot) {
|
|
|
606104
605515
|
function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
606105
605516
|
if (depth > maxDepth) return "";
|
|
606106
605517
|
let result = "";
|
|
606107
|
-
const isHomeRoot = depth === 0 && root ===
|
|
605518
|
+
const isHomeRoot = depth === 0 && root === homedir37();
|
|
606108
605519
|
try {
|
|
606109
605520
|
const entries = readdirSync37(root, { withFileTypes: true }).filter((e2) => !e2.name.startsWith(".") || e2.name === ".github").filter((e2) => !SKIP_DIRS3.has(e2.name)).filter((e2) => !(isHomeRoot && HOME_SKIP_DIRS.has(e2.name))).sort((a2, b) => {
|
|
606110
605521
|
if (a2.isDirectory() && !b.isDirectory()) return -1;
|
|
@@ -606119,12 +605530,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
606119
605530
|
if (entry.isDirectory()) {
|
|
606120
605531
|
let fileCount = 0;
|
|
606121
605532
|
try {
|
|
606122
|
-
fileCount = readdirSync37(
|
|
605533
|
+
fileCount = readdirSync37(join122(root, entry.name)).filter((f2) => !f2.startsWith(".")).length;
|
|
606123
605534
|
} catch {
|
|
606124
605535
|
}
|
|
606125
605536
|
result += `${prefix}${connector}${entry.name}/ (${fileCount})
|
|
606126
605537
|
`;
|
|
606127
|
-
result += buildDirTree(
|
|
605538
|
+
result += buildDirTree(join122(root, entry.name), maxDepth, childPrefix, depth + 1);
|
|
606128
605539
|
} else if (depth < maxDepth) {
|
|
606129
605540
|
result += `${prefix}${connector}${entry.name}
|
|
606130
605541
|
`;
|
|
@@ -606136,17 +605547,17 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
606136
605547
|
}
|
|
606137
605548
|
function loadUsageFile(filePath) {
|
|
606138
605549
|
try {
|
|
606139
|
-
if (
|
|
606140
|
-
return JSON.parse(
|
|
605550
|
+
if (existsSync107(filePath)) {
|
|
605551
|
+
return JSON.parse(readFileSync86(filePath, "utf-8"));
|
|
606141
605552
|
}
|
|
606142
605553
|
} catch {
|
|
606143
605554
|
}
|
|
606144
605555
|
return { records: [] };
|
|
606145
605556
|
}
|
|
606146
605557
|
function saveUsageFile(filePath, data) {
|
|
606147
|
-
const dir =
|
|
606148
|
-
|
|
606149
|
-
|
|
605558
|
+
const dir = join122(filePath, "..");
|
|
605559
|
+
mkdirSync65(dir, { recursive: true });
|
|
605560
|
+
writeFileSync55(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
606150
605561
|
}
|
|
606151
605562
|
function recordUsage(kind, value2, opts) {
|
|
606152
605563
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -606173,15 +605584,15 @@ function recordUsage(kind, value2, opts) {
|
|
|
606173
605584
|
}
|
|
606174
605585
|
saveUsageFile(filePath, data);
|
|
606175
605586
|
};
|
|
606176
|
-
update2(
|
|
605587
|
+
update2(join122(homedir37(), ".omnius", USAGE_HISTORY_FILE));
|
|
606177
605588
|
if (opts?.repoRoot) {
|
|
606178
|
-
update2(
|
|
605589
|
+
update2(join122(opts.repoRoot, OMNIUS_DIR, USAGE_HISTORY_FILE));
|
|
606179
605590
|
}
|
|
606180
605591
|
}
|
|
606181
605592
|
function loadUsageHistory(kind, repoRoot) {
|
|
606182
|
-
const globalPath =
|
|
605593
|
+
const globalPath = join122(homedir37(), ".omnius", USAGE_HISTORY_FILE);
|
|
606183
605594
|
const globalData = loadUsageFile(globalPath);
|
|
606184
|
-
const localData = repoRoot ? loadUsageFile(
|
|
605595
|
+
const localData = repoRoot ? loadUsageFile(join122(repoRoot, OMNIUS_DIR, USAGE_HISTORY_FILE)) : { records: [] };
|
|
606185
605596
|
const map2 = /* @__PURE__ */ new Map();
|
|
606186
605597
|
for (const r2 of globalData.records) {
|
|
606187
605598
|
if (r2.kind !== kind) continue;
|
|
@@ -606210,9 +605621,9 @@ function deleteUsageRecord(kind, value2, repoRoot) {
|
|
|
606210
605621
|
saveUsageFile(filePath, data);
|
|
606211
605622
|
}
|
|
606212
605623
|
};
|
|
606213
|
-
remove(
|
|
605624
|
+
remove(join122(homedir37(), ".omnius", USAGE_HISTORY_FILE));
|
|
606214
605625
|
if (repoRoot) {
|
|
606215
|
-
remove(
|
|
605626
|
+
remove(join122(repoRoot, OMNIUS_DIR, USAGE_HISTORY_FILE));
|
|
606216
605627
|
}
|
|
606217
605628
|
}
|
|
606218
605629
|
var OMNIUS_DIR, LEGACY_DIRS, SUBDIRS, gitignoreWatchers, CONTEXT_FILES, PENDING_TASK_FILE, HANDOFF_FILE, CONTEXT_SAVE_FILE, CONTEXT_LEDGER_FILE, MAX_CONTEXT_ENTRIES, MAX_SESSION_DIARY_ENTRIES, MAX_SESSION_DIARY_DETAILED_ENTRIES, MAX_CONTEXT_LEDGER_LINES, MAX_CONTEXT_LEDGER_BYTES, SAME_TASK_REPLACE_WINDOW_MS, LOCK_TIMEOUT_MS, LOCK_RETRY_MS, LOCK_RETRY_MAX, SESSIONS_DIR, SESSIONS_INDEX, SKIP_DIRS3, HOME_SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
|
|
@@ -606298,6 +605709,757 @@ var init_omnius_directory = __esm({
|
|
|
606298
605709
|
}
|
|
606299
605710
|
});
|
|
606300
605711
|
|
|
605712
|
+
// packages/cli/src/api/session-summary.ts
|
|
605713
|
+
function isNoiseLine(line) {
|
|
605714
|
+
const t2 = line.trim();
|
|
605715
|
+
if (t2.length < 3) return true;
|
|
605716
|
+
const core = t2.replace(/^[∙•·›>\-=_*#|/\\.\s]+/, "").trim();
|
|
605717
|
+
if (core.length < 3) return true;
|
|
605718
|
+
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)/i.test(core);
|
|
605719
|
+
}
|
|
605720
|
+
function firstMeaningfulLine(transcript) {
|
|
605721
|
+
for (const raw of transcript.split("\n")) {
|
|
605722
|
+
const line = raw.replace(ANSI_RE, "").trim();
|
|
605723
|
+
if (line && !isNoiseLine(line)) return line;
|
|
605724
|
+
}
|
|
605725
|
+
for (const raw of transcript.split("\n")) {
|
|
605726
|
+
const line = raw.replace(ANSI_RE, "").trim();
|
|
605727
|
+
if (line) return line;
|
|
605728
|
+
}
|
|
605729
|
+
return "";
|
|
605730
|
+
}
|
|
605731
|
+
function clamp7(value2, max) {
|
|
605732
|
+
const v = value2.replace(/\s+/g, " ").trim();
|
|
605733
|
+
return v.length > max ? v.slice(0, max - 1).trimEnd() + "…" : v;
|
|
605734
|
+
}
|
|
605735
|
+
function deterministicSummary(transcript) {
|
|
605736
|
+
const first2 = firstMeaningfulLine(transcript);
|
|
605737
|
+
if (!first2) return { title: "Untitled session", summary: "Empty session." };
|
|
605738
|
+
const title = clamp7(first2.replace(/^[>›$#\s]+/, ""), TITLE_MAX);
|
|
605739
|
+
return { title: title || "Untitled session", summary: clamp7(first2, SUMMARY_MAX) };
|
|
605740
|
+
}
|
|
605741
|
+
function parseSummaryReply(content) {
|
|
605742
|
+
if (!content) return null;
|
|
605743
|
+
const match = content.match(/\{[\s\S]*\}/);
|
|
605744
|
+
if (!match) return null;
|
|
605745
|
+
try {
|
|
605746
|
+
const obj = JSON.parse(match[0]);
|
|
605747
|
+
const title = typeof obj.title === "string" ? obj.title.trim() : "";
|
|
605748
|
+
const summary = typeof obj.summary === "string" ? obj.summary.trim() : "";
|
|
605749
|
+
if (!title && !summary) return null;
|
|
605750
|
+
return { title, summary };
|
|
605751
|
+
} catch {
|
|
605752
|
+
return null;
|
|
605753
|
+
}
|
|
605754
|
+
}
|
|
605755
|
+
async function generateSessionSummary(args) {
|
|
605756
|
+
const fallback = deterministicSummary(args.transcript);
|
|
605757
|
+
const transcript = (args.transcript || "").replace(ANSI_RE, "").trim();
|
|
605758
|
+
if (!transcript || !args.config.model || !args.config.backendUrl) return fallback;
|
|
605759
|
+
try {
|
|
605760
|
+
const url = normalizeBaseUrl(args.config.backendUrl) + "/v1/chat/completions";
|
|
605761
|
+
const headers = { "Content-Type": "application/json" };
|
|
605762
|
+
if (args.config.apiKey) headers["Authorization"] = `Bearer ${args.config.apiKey}`;
|
|
605763
|
+
const body = {
|
|
605764
|
+
model: args.config.model,
|
|
605765
|
+
messages: [
|
|
605766
|
+
{
|
|
605767
|
+
role: "system",
|
|
605768
|
+
content: 'You name and summarize AI coding/agent terminal sessions. Reply with ONLY compact JSON and nothing else: {"title":"<3-6 word title>","summary":"<one concise sentence>"}. No markdown, no code fences, no preamble.'
|
|
605769
|
+
},
|
|
605770
|
+
{
|
|
605771
|
+
role: "user",
|
|
605772
|
+
content: "Summarize this session transcript (may include tool calls, sub-agent activity, and logs):\n\n" + transcript.slice(0, TRANSCRIPT_CHARS)
|
|
605773
|
+
}
|
|
605774
|
+
],
|
|
605775
|
+
temperature: 0.2,
|
|
605776
|
+
max_tokens: 160,
|
|
605777
|
+
stream: false
|
|
605778
|
+
};
|
|
605779
|
+
const resp = await fetch(url, {
|
|
605780
|
+
method: "POST",
|
|
605781
|
+
headers,
|
|
605782
|
+
body: JSON.stringify(body),
|
|
605783
|
+
signal: AbortSignal.timeout(args.timeoutMs ?? 25e3)
|
|
605784
|
+
});
|
|
605785
|
+
if (!resp.ok) return fallback;
|
|
605786
|
+
const data = await resp.json();
|
|
605787
|
+
const content = data?.choices?.[0]?.message?.content ?? "";
|
|
605788
|
+
const parsed = parseSummaryReply(content);
|
|
605789
|
+
if (!parsed) return fallback;
|
|
605790
|
+
return {
|
|
605791
|
+
title: clamp7(parsed.title, TITLE_MAX) || fallback.title,
|
|
605792
|
+
summary: clamp7(parsed.summary, SUMMARY_MAX) || fallback.summary
|
|
605793
|
+
};
|
|
605794
|
+
} catch {
|
|
605795
|
+
return fallback;
|
|
605796
|
+
}
|
|
605797
|
+
}
|
|
605798
|
+
async function ensureSessionSummary(args) {
|
|
605799
|
+
const entry = listSessions(args.repoRoot).find(
|
|
605800
|
+
(e2) => e2.id === args.sessionId
|
|
605801
|
+
);
|
|
605802
|
+
if (entry?.aiTitle && entry.aiSummary && !args.force) {
|
|
605803
|
+
return { title: entry.aiTitle, summary: entry.aiSummary };
|
|
605804
|
+
}
|
|
605805
|
+
const lines = loadSessionHistory(args.repoRoot, args.sessionId);
|
|
605806
|
+
const transcript = (lines ?? []).join("\n").trim();
|
|
605807
|
+
if (!transcript) return deterministicSummary("");
|
|
605808
|
+
const key = `${args.repoRoot}::${args.sessionId}`;
|
|
605809
|
+
if (_inflightSummaries.has(key) && !args.force) {
|
|
605810
|
+
return deterministicSummary(transcript);
|
|
605811
|
+
}
|
|
605812
|
+
_inflightSummaries.add(key);
|
|
605813
|
+
try {
|
|
605814
|
+
const result = await generateSessionSummary({
|
|
605815
|
+
transcript,
|
|
605816
|
+
config: args.config,
|
|
605817
|
+
timeoutMs: args.timeoutMs
|
|
605818
|
+
});
|
|
605819
|
+
updateSessionEntry(args.repoRoot, args.sessionId, {
|
|
605820
|
+
aiTitle: result.title,
|
|
605821
|
+
aiSummary: result.summary
|
|
605822
|
+
});
|
|
605823
|
+
return result;
|
|
605824
|
+
} finally {
|
|
605825
|
+
_inflightSummaries.delete(key);
|
|
605826
|
+
}
|
|
605827
|
+
}
|
|
605828
|
+
function sessionDisplayTitle(entry) {
|
|
605829
|
+
if (entry.aiTitle && entry.aiTitle.trim()) return entry.aiTitle.trim();
|
|
605830
|
+
return deterministicSummary(entry.name || "").title;
|
|
605831
|
+
}
|
|
605832
|
+
var TITLE_MAX, SUMMARY_MAX, TRANSCRIPT_CHARS, ANSI_RE, _inflightSummaries;
|
|
605833
|
+
var init_session_summary = __esm({
|
|
605834
|
+
"packages/cli/src/api/session-summary.ts"() {
|
|
605835
|
+
"use strict";
|
|
605836
|
+
init_dist6();
|
|
605837
|
+
init_omnius_directory();
|
|
605838
|
+
TITLE_MAX = 56;
|
|
605839
|
+
SUMMARY_MAX = 160;
|
|
605840
|
+
TRANSCRIPT_CHARS = 6e3;
|
|
605841
|
+
ANSI_RE = /\x1B\[[0-9;]*m|\x1B\][^\x07]*(?:\x07|\x1B\\)/g;
|
|
605842
|
+
_inflightSummaries = /* @__PURE__ */ new Set();
|
|
605843
|
+
}
|
|
605844
|
+
});
|
|
605845
|
+
|
|
605846
|
+
// packages/cli/src/tui/cad-model-viewer.ts
|
|
605847
|
+
import { createServer as createServer7 } from "node:http";
|
|
605848
|
+
import { existsSync as existsSync108, readFileSync as readFileSync87, statSync as statSync42 } from "node:fs";
|
|
605849
|
+
import { basename as basename23, extname as extname16, resolve as resolve53 } from "node:path";
|
|
605850
|
+
function getCurrentCadModelViewer() {
|
|
605851
|
+
return currentViewer;
|
|
605852
|
+
}
|
|
605853
|
+
async function startCadModelViewer(filePath) {
|
|
605854
|
+
const resolved = filePath ? resolve53(filePath) : void 0;
|
|
605855
|
+
if (resolved && (!existsSync108(resolved) || !statSync42(resolved).isFile())) {
|
|
605856
|
+
throw new Error(`3D model file not found: ${resolved}`);
|
|
605857
|
+
}
|
|
605858
|
+
if (currentViewer) {
|
|
605859
|
+
await currentViewer.close().catch(() => {
|
|
605860
|
+
});
|
|
605861
|
+
currentViewer = null;
|
|
605862
|
+
}
|
|
605863
|
+
const server2 = createServer7((req3, res) => handleViewerRequest(req3, res, resolved));
|
|
605864
|
+
const port = await listenOnEphemeralPort(server2);
|
|
605865
|
+
const session = {
|
|
605866
|
+
url: `http://127.0.0.1:${port}/`,
|
|
605867
|
+
port,
|
|
605868
|
+
filePath: resolved,
|
|
605869
|
+
close: () => new Promise((resolveClose) => server2.close(() => resolveClose()))
|
|
605870
|
+
};
|
|
605871
|
+
currentViewer = session;
|
|
605872
|
+
server2.on("close", () => {
|
|
605873
|
+
if (currentViewer === session) currentViewer = null;
|
|
605874
|
+
});
|
|
605875
|
+
return session;
|
|
605876
|
+
}
|
|
605877
|
+
function listenOnEphemeralPort(server2) {
|
|
605878
|
+
return new Promise((resolveListen, reject) => {
|
|
605879
|
+
server2.once("error", reject);
|
|
605880
|
+
server2.listen(0, "127.0.0.1", () => {
|
|
605881
|
+
server2.off("error", reject);
|
|
605882
|
+
const addr = server2.address();
|
|
605883
|
+
if (!addr || typeof addr === "string") {
|
|
605884
|
+
reject(new Error("viewer server did not bind to a TCP port"));
|
|
605885
|
+
return;
|
|
605886
|
+
}
|
|
605887
|
+
resolveListen(addr.port);
|
|
605888
|
+
});
|
|
605889
|
+
});
|
|
605890
|
+
}
|
|
605891
|
+
function handleViewerRequest(req3, res, filePath) {
|
|
605892
|
+
const url = new URL(req3.url || "/", "http://127.0.0.1");
|
|
605893
|
+
if (url.pathname === "/health") {
|
|
605894
|
+
sendJson(res, 200, { ok: true, file: filePath ?? null });
|
|
605895
|
+
return;
|
|
605896
|
+
}
|
|
605897
|
+
if (url.pathname === "/asset") {
|
|
605898
|
+
if (!filePath) {
|
|
605899
|
+
sendText(res, 404, "No model file attached to this viewer.");
|
|
605900
|
+
return;
|
|
605901
|
+
}
|
|
605902
|
+
try {
|
|
605903
|
+
res.writeHead(200, {
|
|
605904
|
+
"Content-Type": contentTypeFor(filePath),
|
|
605905
|
+
"Content-Disposition": `inline; filename="${basename23(filePath).replace(/"/g, "")}"`,
|
|
605906
|
+
"Cache-Control": "no-store"
|
|
605907
|
+
});
|
|
605908
|
+
res.end(readFileSync87(filePath));
|
|
605909
|
+
} catch (err) {
|
|
605910
|
+
sendText(res, 500, err instanceof Error ? err.message : String(err));
|
|
605911
|
+
}
|
|
605912
|
+
return;
|
|
605913
|
+
}
|
|
605914
|
+
if (url.pathname !== "/") {
|
|
605915
|
+
sendText(res, 404, "Not found");
|
|
605916
|
+
return;
|
|
605917
|
+
}
|
|
605918
|
+
sendHtml(res, viewerHtml(filePath));
|
|
605919
|
+
}
|
|
605920
|
+
function contentTypeFor(path12) {
|
|
605921
|
+
const ext = extname16(path12).toLowerCase();
|
|
605922
|
+
if (ext === ".glb") return "model/gltf-binary";
|
|
605923
|
+
if (ext === ".gltf") return "model/gltf+json";
|
|
605924
|
+
if (ext === ".obj") return "text/plain; charset=utf-8";
|
|
605925
|
+
if (ext === ".stl") return "model/stl";
|
|
605926
|
+
if (ext === ".ply") return "application/octet-stream";
|
|
605927
|
+
return "application/octet-stream";
|
|
605928
|
+
}
|
|
605929
|
+
function sendJson(res, status, value2) {
|
|
605930
|
+
res.writeHead(status, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-store" });
|
|
605931
|
+
res.end(JSON.stringify(value2));
|
|
605932
|
+
}
|
|
605933
|
+
function sendText(res, status, text2) {
|
|
605934
|
+
res.writeHead(status, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
|
|
605935
|
+
res.end(text2);
|
|
605936
|
+
}
|
|
605937
|
+
function sendHtml(res, html) {
|
|
605938
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store" });
|
|
605939
|
+
res.end(html);
|
|
605940
|
+
}
|
|
605941
|
+
function viewerHtml(filePath) {
|
|
605942
|
+
const fileName = filePath ? basename23(filePath) : "";
|
|
605943
|
+
const ext = filePath ? extname16(filePath).toLowerCase().replace(/^\./, "") : "";
|
|
605944
|
+
return `<!doctype html>
|
|
605945
|
+
<html lang="en">
|
|
605946
|
+
<head>
|
|
605947
|
+
<meta charset="utf-8">
|
|
605948
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
605949
|
+
<title>Omnius CAD/3D Viewer</title>
|
|
605950
|
+
<style>
|
|
605951
|
+
:root { color-scheme: dark; --bg:#101214; --panel:#181b1f; --line:#2a3037; --fg:#e7edf3; --muted:#9aa7b5; --accent:#5ec6a8; }
|
|
605952
|
+
* { box-sizing: border-box; }
|
|
605953
|
+
body { margin:0; min-height:100vh; background:var(--bg); color:var(--fg); font:14px/1.4 ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; display:grid; grid-template-columns:minmax(280px,360px) 1fr; }
|
|
605954
|
+
aside { border-right:1px solid var(--line); background:var(--panel); padding:14px; display:flex; flex-direction:column; gap:12px; min-height:100vh; }
|
|
605955
|
+
main { position:relative; min-height:100vh; overflow:hidden; }
|
|
605956
|
+
h1 { margin:0; font-size:16px; font-weight:650; }
|
|
605957
|
+
.meta { color:var(--muted); font-size:12px; word-break:break-word; }
|
|
605958
|
+
textarea { width:100%; min-height:280px; resize:vertical; border:1px solid var(--line); border-radius:6px; background:#0c0e10; color:var(--fg); padding:10px; font:12px/1.45 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; }
|
|
605959
|
+
button { border:1px solid var(--line); border-radius:6px; background:#20262d; color:var(--fg); padding:8px 10px; cursor:pointer; }
|
|
605960
|
+
button:hover { border-color:var(--accent); }
|
|
605961
|
+
#status { color:var(--muted); min-height:20px; font-size:12px; }
|
|
605962
|
+
canvas { display:block; width:100%; height:100%; }
|
|
605963
|
+
.row { display:flex; gap:8px; flex-wrap:wrap; }
|
|
605964
|
+
@media (max-width: 760px) { body { grid-template-columns:1fr; grid-template-rows:auto 60vh; } aside { min-height:auto; border-right:0; border-bottom:1px solid var(--line); } }
|
|
605965
|
+
</style>
|
|
605966
|
+
</head>
|
|
605967
|
+
<body>
|
|
605968
|
+
<aside>
|
|
605969
|
+
<div>
|
|
605970
|
+
<h1>Omnius CAD/3D Viewer</h1>
|
|
605971
|
+
<div class="meta">${escapeHtml(fileName ? `Viewing ${fileName}` : "No file attached. Rendering Compact IR sample.")}</div>
|
|
605972
|
+
</div>
|
|
605973
|
+
<textarea id="ir">C 50 30 5
|
|
605974
|
+
Y 3 8
|
|
605975
|
+
T 1 -18 -10 2.5
|
|
605976
|
+
Y 3 8
|
|
605977
|
+
T 3 18 -10 2.5
|
|
605978
|
+
Y 3 8
|
|
605979
|
+
T 5 -18 10 2.5
|
|
605980
|
+
Y 3 8
|
|
605981
|
+
T 7 18 10 2.5</textarea>
|
|
605982
|
+
<div class="row">
|
|
605983
|
+
<button id="render-ir">Render Compact IR</button>
|
|
605984
|
+
<button id="reset-camera">Reset Camera</button>
|
|
605985
|
+
</div>
|
|
605986
|
+
<div id="status"></div>
|
|
605987
|
+
</aside>
|
|
605988
|
+
<main id="viewport"></main>
|
|
605989
|
+
<script type="module">
|
|
605990
|
+
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.164.1/build/three.module.js';
|
|
605991
|
+
import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/controls/OrbitControls.js';
|
|
605992
|
+
import { GLTFLoader } from 'https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/loaders/GLTFLoader.js';
|
|
605993
|
+
import { STLLoader } from 'https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/loaders/STLLoader.js';
|
|
605994
|
+
import { OBJLoader } from 'https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/loaders/OBJLoader.js';
|
|
605995
|
+
import { PLYLoader } from 'https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/loaders/PLYLoader.js';
|
|
605996
|
+
|
|
605997
|
+
const assetUrl = ${JSON.stringify(filePath ? "/asset" : "")};
|
|
605998
|
+
const assetExt = ${JSON.stringify(ext)};
|
|
605999
|
+
const viewport = document.getElementById('viewport');
|
|
606000
|
+
const status = document.getElementById('status');
|
|
606001
|
+
const scene = new THREE.Scene();
|
|
606002
|
+
scene.background = new THREE.Color(0x101214);
|
|
606003
|
+
const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 5000);
|
|
606004
|
+
const renderer = new THREE.WebGLRenderer({ antialias:true });
|
|
606005
|
+
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
|
|
606006
|
+
viewport.appendChild(renderer.domElement);
|
|
606007
|
+
const controls = new OrbitControls(camera, renderer.domElement);
|
|
606008
|
+
controls.enableDamping = true;
|
|
606009
|
+
scene.add(new THREE.HemisphereLight(0xffffff, 0x223344, 1.7));
|
|
606010
|
+
const key = new THREE.DirectionalLight(0xffffff, 2.2);
|
|
606011
|
+
key.position.set(120, 160, 100);
|
|
606012
|
+
scene.add(key);
|
|
606013
|
+
const grid = new THREE.GridHelper(160, 32, 0x31404a, 0x253039);
|
|
606014
|
+
scene.add(grid);
|
|
606015
|
+
let objectRoot = new THREE.Group();
|
|
606016
|
+
scene.add(objectRoot);
|
|
606017
|
+
|
|
606018
|
+
function setStatus(text) { status.textContent = text || ''; }
|
|
606019
|
+
function clearObject() {
|
|
606020
|
+
scene.remove(objectRoot);
|
|
606021
|
+
objectRoot.traverse((o) => {
|
|
606022
|
+
if (o.geometry) o.geometry.dispose?.();
|
|
606023
|
+
if (o.material) {
|
|
606024
|
+
if (Array.isArray(o.material)) o.material.forEach((m) => m.dispose?.());
|
|
606025
|
+
else o.material.dispose?.();
|
|
606026
|
+
}
|
|
606027
|
+
});
|
|
606028
|
+
objectRoot = new THREE.Group();
|
|
606029
|
+
scene.add(objectRoot);
|
|
606030
|
+
}
|
|
606031
|
+
function frameObject() {
|
|
606032
|
+
const box = new THREE.Box3().setFromObject(objectRoot);
|
|
606033
|
+
if (box.isEmpty()) {
|
|
606034
|
+
camera.position.set(70, 70, 70);
|
|
606035
|
+
controls.target.set(0, 0, 0);
|
|
606036
|
+
return;
|
|
606037
|
+
}
|
|
606038
|
+
const size = box.getSize(new THREE.Vector3());
|
|
606039
|
+
const center = box.getCenter(new THREE.Vector3());
|
|
606040
|
+
const max = Math.max(size.x, size.y, size.z, 1);
|
|
606041
|
+
camera.position.copy(center).add(new THREE.Vector3(max * 1.35, max * 1.05, max * 1.35));
|
|
606042
|
+
controls.target.copy(center);
|
|
606043
|
+
camera.near = Math.max(0.01, max / 1000);
|
|
606044
|
+
camera.far = Math.max(1000, max * 20);
|
|
606045
|
+
camera.updateProjectionMatrix();
|
|
606046
|
+
controls.update();
|
|
606047
|
+
}
|
|
606048
|
+
function makeMaterial(index) {
|
|
606049
|
+
const colors = [0x5ec6a8, 0xf0b35a, 0x87a8ff, 0xdc6f7e, 0xb6d96a];
|
|
606050
|
+
return new THREE.MeshStandardMaterial({ color: colors[index % colors.length], metalness:0.05, roughness:0.48 });
|
|
606051
|
+
}
|
|
606052
|
+
function renderCompactIr(text) {
|
|
606053
|
+
clearObject();
|
|
606054
|
+
const nodes = [];
|
|
606055
|
+
const lines = String(text || '').split(/\\r?\\n/).map((l) => l.trim()).filter((l) => l && !l.startsWith('#'));
|
|
606056
|
+
for (const line of lines) {
|
|
606057
|
+
const parts = line.split(/\\s+/);
|
|
606058
|
+
const op = parts[0].toUpperCase();
|
|
606059
|
+
const nums = parts.slice(1).map(Number);
|
|
606060
|
+
let mesh = null;
|
|
606061
|
+
if (op === 'C' && nums.length >= 3) {
|
|
606062
|
+
mesh = new THREE.Mesh(new THREE.BoxGeometry(nums[0], nums[1], nums[2]), makeMaterial(nodes.length));
|
|
606063
|
+
} else if (op === 'Y' && nums.length >= 2) {
|
|
606064
|
+
mesh = new THREE.Mesh(new THREE.CylinderGeometry(nums[0], nums[0], nums[1], 48), makeMaterial(nodes.length));
|
|
606065
|
+
mesh.rotation.x = Math.PI / 2;
|
|
606066
|
+
} else if (op === 'S' && nums.length >= 1) {
|
|
606067
|
+
mesh = new THREE.Mesh(new THREE.SphereGeometry(nums[0], 48, 24), makeMaterial(nodes.length));
|
|
606068
|
+
} else if (op === 'K' && nums.length >= 3) {
|
|
606069
|
+
mesh = new THREE.Mesh(new THREE.CylinderGeometry(nums[1], nums[0], nums[2], 48), makeMaterial(nodes.length));
|
|
606070
|
+
mesh.rotation.x = Math.PI / 2;
|
|
606071
|
+
} else if ((op === 'U' || op === 'D' || op === 'I') && nums.length >= 2) {
|
|
606072
|
+
const group = new THREE.Group();
|
|
606073
|
+
const a = nodes[nums[0]]?.clone();
|
|
606074
|
+
const b = nodes[nums[1]]?.clone();
|
|
606075
|
+
if (a) group.add(a);
|
|
606076
|
+
if (b) {
|
|
606077
|
+
if (op === 'D') b.traverse((o) => { if (o.material) o.material = new THREE.MeshStandardMaterial({ color:0xff5570, wireframe:true }); });
|
|
606078
|
+
group.add(b);
|
|
606079
|
+
}
|
|
606080
|
+
mesh = group;
|
|
606081
|
+
} else if ((op === 'T' || op === 'R' || op === 'X') && nums.length >= 4) {
|
|
606082
|
+
const target = nodes[nums[0]];
|
|
606083
|
+
if (target) {
|
|
606084
|
+
if (op === 'T') target.position.add(new THREE.Vector3(nums[1], nums[2], nums[3]));
|
|
606085
|
+
if (op === 'R') target.rotation.set(THREE.MathUtils.degToRad(nums[1]), THREE.MathUtils.degToRad(nums[2]), THREE.MathUtils.degToRad(nums[3]));
|
|
606086
|
+
if (op === 'X') target.scale.multiply(new THREE.Vector3(nums[1], nums[2], nums[3]));
|
|
606087
|
+
}
|
|
606088
|
+
nodes.push(target ? target.clone() : new THREE.Group());
|
|
606089
|
+
continue;
|
|
606090
|
+
} else if ((op === 'F' || op === 'CH' || op === 'SH') && nums.length >= 1) {
|
|
606091
|
+
const target = nodes[nums[0]];
|
|
606092
|
+
nodes.push(target ? target.clone() : new THREE.Group());
|
|
606093
|
+
continue;
|
|
606094
|
+
}
|
|
606095
|
+
if (mesh) {
|
|
606096
|
+
nodes.push(mesh);
|
|
606097
|
+
objectRoot.add(mesh);
|
|
606098
|
+
}
|
|
606099
|
+
}
|
|
606100
|
+
if (nodes.length === 0) setStatus('No renderable Compact IR primitives found.');
|
|
606101
|
+
else setStatus('Rendered ' + nodes.length + ' Compact IR node(s). Boolean difference is shown as wireframe preview.');
|
|
606102
|
+
frameObject();
|
|
606103
|
+
}
|
|
606104
|
+
async function loadAsset() {
|
|
606105
|
+
if (!assetUrl) {
|
|
606106
|
+
renderCompactIr(document.getElementById('ir').value);
|
|
606107
|
+
return;
|
|
606108
|
+
}
|
|
606109
|
+
setStatus('Loading attached model...');
|
|
606110
|
+
clearObject();
|
|
606111
|
+
const done = (obj) => {
|
|
606112
|
+
objectRoot.add(obj);
|
|
606113
|
+
setStatus('Loaded attached model.');
|
|
606114
|
+
frameObject();
|
|
606115
|
+
};
|
|
606116
|
+
if (assetExt === 'glb' || assetExt === 'gltf') {
|
|
606117
|
+
new GLTFLoader().load(assetUrl, (gltf) => done(gltf.scene), undefined, (e) => setStatus(e.message || String(e)));
|
|
606118
|
+
} else if (assetExt === 'stl') {
|
|
606119
|
+
new STLLoader().load(assetUrl, (geo) => done(new THREE.Mesh(geo, makeMaterial(0))), undefined, (e) => setStatus(e.message || String(e)));
|
|
606120
|
+
} else if (assetExt === 'obj') {
|
|
606121
|
+
new OBJLoader().load(assetUrl, done, undefined, (e) => setStatus(e.message || String(e)));
|
|
606122
|
+
} else if (assetExt === 'ply') {
|
|
606123
|
+
new PLYLoader().load(assetUrl, (geo) => done(new THREE.Mesh(geo, makeMaterial(0))), undefined, (e) => setStatus(e.message || String(e)));
|
|
606124
|
+
} else {
|
|
606125
|
+
setStatus('Unsupported file extension for browser preview. Use GLB, GLTF, OBJ, STL, or PLY.');
|
|
606126
|
+
renderCompactIr(document.getElementById('ir').value);
|
|
606127
|
+
}
|
|
606128
|
+
}
|
|
606129
|
+
function resize() {
|
|
606130
|
+
const rect = viewport.getBoundingClientRect();
|
|
606131
|
+
renderer.setSize(rect.width, rect.height, false);
|
|
606132
|
+
camera.aspect = Math.max(1, rect.width) / Math.max(1, rect.height);
|
|
606133
|
+
camera.updateProjectionMatrix();
|
|
606134
|
+
}
|
|
606135
|
+
window.addEventListener('resize', resize);
|
|
606136
|
+
document.getElementById('render-ir').addEventListener('click', () => renderCompactIr(document.getElementById('ir').value));
|
|
606137
|
+
document.getElementById('reset-camera').addEventListener('click', frameObject);
|
|
606138
|
+
renderer.setAnimationLoop(() => { controls.update(); renderer.render(scene, camera); });
|
|
606139
|
+
resize();
|
|
606140
|
+
loadAsset();
|
|
606141
|
+
</script>
|
|
606142
|
+
</body>
|
|
606143
|
+
</html>`;
|
|
606144
|
+
}
|
|
606145
|
+
function escapeHtml(value2) {
|
|
606146
|
+
return value2.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
606147
|
+
}
|
|
606148
|
+
var currentViewer;
|
|
606149
|
+
var init_cad_model_viewer = __esm({
|
|
606150
|
+
"packages/cli/src/tui/cad-model-viewer.ts"() {
|
|
606151
|
+
"use strict";
|
|
606152
|
+
currentViewer = null;
|
|
606153
|
+
}
|
|
606154
|
+
});
|
|
606155
|
+
|
|
606156
|
+
// packages/cli/src/tui/hf-token-prompt.ts
|
|
606157
|
+
import * as fs9 from "node:fs";
|
|
606158
|
+
import * as os8 from "node:os";
|
|
606159
|
+
import * as path10 from "node:path";
|
|
606160
|
+
function loadHfToken() {
|
|
606161
|
+
const fromEnv = process.env["HF_TOKEN"]?.trim() || process.env["HUGGING_FACE_HUB_TOKEN"]?.trim() || "";
|
|
606162
|
+
if (fromEnv) return fromEnv;
|
|
606163
|
+
try {
|
|
606164
|
+
if (fs9.existsSync(TOKEN_FILE)) {
|
|
606165
|
+
const fromFile = fs9.readFileSync(TOKEN_FILE, "utf8").trim();
|
|
606166
|
+
if (fromFile) {
|
|
606167
|
+
process.env["HF_TOKEN"] = fromFile;
|
|
606168
|
+
return fromFile;
|
|
606169
|
+
}
|
|
606170
|
+
}
|
|
606171
|
+
} catch {
|
|
606172
|
+
}
|
|
606173
|
+
return null;
|
|
606174
|
+
}
|
|
606175
|
+
function saveHfToken(token) {
|
|
606176
|
+
const trimmed = token.trim();
|
|
606177
|
+
if (!trimmed) throw new Error("HF token cannot be empty");
|
|
606178
|
+
fs9.mkdirSync(TOKEN_DIR, { recursive: true, mode: 448 });
|
|
606179
|
+
fs9.writeFileSync(TOKEN_FILE, trimmed + "\n", { mode: 384 });
|
|
606180
|
+
try {
|
|
606181
|
+
fs9.chmodSync(TOKEN_FILE, 384);
|
|
606182
|
+
} catch {
|
|
606183
|
+
}
|
|
606184
|
+
process.env["HF_TOKEN"] = trimmed;
|
|
606185
|
+
}
|
|
606186
|
+
function clearHfToken() {
|
|
606187
|
+
try {
|
|
606188
|
+
if (fs9.existsSync(TOKEN_FILE)) fs9.unlinkSync(TOKEN_FILE);
|
|
606189
|
+
} catch {
|
|
606190
|
+
}
|
|
606191
|
+
delete process.env["HF_TOKEN"];
|
|
606192
|
+
}
|
|
606193
|
+
function isHfTokenPromptPending() {
|
|
606194
|
+
return pending !== null;
|
|
606195
|
+
}
|
|
606196
|
+
function describePendingHfTokenPrompt() {
|
|
606197
|
+
if (!pending) return null;
|
|
606198
|
+
return { model: pending.model, ageMs: Date.now() - pending.startedAt };
|
|
606199
|
+
}
|
|
606200
|
+
function requestHfToken(opts) {
|
|
606201
|
+
const existing = loadHfToken();
|
|
606202
|
+
if (existing) return Promise.resolve(existing);
|
|
606203
|
+
if (pending) {
|
|
606204
|
+
opts.onMessage(
|
|
606205
|
+
`Another HF token prompt is already active (for ${pending.model}). Run \`/hf <token>\` to satisfy both, or wait for the existing prompt to time out.`
|
|
606206
|
+
);
|
|
606207
|
+
return Promise.resolve(null);
|
|
606208
|
+
}
|
|
606209
|
+
const timeoutMs = Math.max(1e3, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS4);
|
|
606210
|
+
const timeoutSec = Math.round(timeoutMs / 1e3);
|
|
606211
|
+
const fallbackBit = opts.fallbackModel ? `
|
|
606212
|
+
If you don't supply one within ${timeoutSec}s, I will fall back to ${opts.fallbackModel} (no token needed).` : `
|
|
606213
|
+
If you don't supply one within ${timeoutSec}s, I will fall back to a non-gated alternative.`;
|
|
606214
|
+
opts.onMessage(
|
|
606215
|
+
[
|
|
606216
|
+
`Hugging Face model "${opts.model}" is gated and needs an access token.`,
|
|
606217
|
+
`Get one at https://huggingface.co/settings/tokens (read-only is fine),`,
|
|
606218
|
+
`accept the model license at https://huggingface.co/${opts.model},`,
|
|
606219
|
+
`then run: /hf <your-token>`,
|
|
606220
|
+
fallbackBit.trim()
|
|
606221
|
+
].join("\n")
|
|
606222
|
+
);
|
|
606223
|
+
return new Promise((resolve71) => {
|
|
606224
|
+
const timer = setTimeout(() => {
|
|
606225
|
+
const ref = pending;
|
|
606226
|
+
pending = null;
|
|
606227
|
+
if (ref) {
|
|
606228
|
+
ref.onMessage(
|
|
606229
|
+
`No HF token supplied within ${timeoutSec}s — falling back to a non-gated alternative for ${opts.model}.`
|
|
606230
|
+
);
|
|
606231
|
+
}
|
|
606232
|
+
resolve71(null);
|
|
606233
|
+
}, timeoutMs);
|
|
606234
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
606235
|
+
pending = {
|
|
606236
|
+
model: opts.model,
|
|
606237
|
+
onMessage: opts.onMessage,
|
|
606238
|
+
resolve: resolve71,
|
|
606239
|
+
timer,
|
|
606240
|
+
startedAt: Date.now()
|
|
606241
|
+
};
|
|
606242
|
+
});
|
|
606243
|
+
}
|
|
606244
|
+
function fulfillHfTokenPrompt(token) {
|
|
606245
|
+
const trimmed = token.trim();
|
|
606246
|
+
if (!trimmed) return false;
|
|
606247
|
+
saveHfToken(trimmed);
|
|
606248
|
+
if (!pending) return false;
|
|
606249
|
+
const ref = pending;
|
|
606250
|
+
pending = null;
|
|
606251
|
+
clearTimeout(ref.timer);
|
|
606252
|
+
ref.resolve(trimmed);
|
|
606253
|
+
return true;
|
|
606254
|
+
}
|
|
606255
|
+
function cancelHfTokenPrompt() {
|
|
606256
|
+
if (!pending) return false;
|
|
606257
|
+
const ref = pending;
|
|
606258
|
+
pending = null;
|
|
606259
|
+
clearTimeout(ref.timer);
|
|
606260
|
+
ref.resolve(null);
|
|
606261
|
+
return true;
|
|
606262
|
+
}
|
|
606263
|
+
function isHfGatedError(blob) {
|
|
606264
|
+
if (!blob) return false;
|
|
606265
|
+
const text2 = blob.toLowerCase();
|
|
606266
|
+
if (text2.includes("[hf_token_required")) return true;
|
|
606267
|
+
if (text2.includes("gatedrepoerror")) return true;
|
|
606268
|
+
if (text2.includes("access to model")) return true;
|
|
606269
|
+
if (text2.includes("you need to accept")) return true;
|
|
606270
|
+
if (text2.includes("you must be authenticated")) return true;
|
|
606271
|
+
if (/(401|403)/.test(text2) && /(gated|access|unauthor|forbid|auth)/.test(text2)) {
|
|
606272
|
+
return true;
|
|
606273
|
+
}
|
|
606274
|
+
return false;
|
|
606275
|
+
}
|
|
606276
|
+
function extractGatedRepoId(blob) {
|
|
606277
|
+
if (!blob) return null;
|
|
606278
|
+
const tokenMarker = blob.match(/\[HF_TOKEN_REQUIRED:([^\]\s]+)\]/);
|
|
606279
|
+
if (tokenMarker?.[1]) return tokenMarker[1].trim();
|
|
606280
|
+
const hfUrl = blob.match(/huggingface\.co\/([A-Za-z0-9._-]+\/[A-Za-z0-9._-]+)/);
|
|
606281
|
+
if (hfUrl?.[1]) return hfUrl[1];
|
|
606282
|
+
const genericRepo = blob.match(/['"`]([A-Za-z0-9._-]+\/[A-Za-z0-9._-]+)['"`]/);
|
|
606283
|
+
if (genericRepo?.[1] && /\/(.+)/.test(genericRepo[1])) return genericRepo[1];
|
|
606284
|
+
return null;
|
|
606285
|
+
}
|
|
606286
|
+
var TOKEN_DIR, TOKEN_FILE, DEFAULT_TIMEOUT_MS4, pending;
|
|
606287
|
+
var init_hf_token_prompt = __esm({
|
|
606288
|
+
"packages/cli/src/tui/hf-token-prompt.ts"() {
|
|
606289
|
+
"use strict";
|
|
606290
|
+
TOKEN_DIR = path10.join(os8.homedir(), ".omnius");
|
|
606291
|
+
TOKEN_FILE = path10.join(TOKEN_DIR, "hf_token");
|
|
606292
|
+
DEFAULT_TIMEOUT_MS4 = 3e4;
|
|
606293
|
+
pending = null;
|
|
606294
|
+
}
|
|
606295
|
+
});
|
|
606296
|
+
|
|
606297
|
+
// packages/prompts/dist/loader.js
|
|
606298
|
+
var init_loader = __esm({
|
|
606299
|
+
"packages/prompts/dist/loader.js"() {
|
|
606300
|
+
"use strict";
|
|
606301
|
+
}
|
|
606302
|
+
});
|
|
606303
|
+
|
|
606304
|
+
// packages/prompts/dist/render.js
|
|
606305
|
+
var init_render2 = __esm({
|
|
606306
|
+
"packages/prompts/dist/render.js"() {
|
|
606307
|
+
"use strict";
|
|
606308
|
+
}
|
|
606309
|
+
});
|
|
606310
|
+
|
|
606311
|
+
// packages/prompts/dist/promptLoader.js
|
|
606312
|
+
import { readFileSync as readFileSync89, existsSync as existsSync110 } from "node:fs";
|
|
606313
|
+
import { join as join124, dirname as dirname39 } from "node:path";
|
|
606314
|
+
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
606315
|
+
function loadPrompt2(promptPath, vars) {
|
|
606316
|
+
let content = cache6.get(promptPath);
|
|
606317
|
+
if (content === void 0) {
|
|
606318
|
+
const fullPath = join124(PROMPTS_DIR2, promptPath);
|
|
606319
|
+
if (!existsSync110(fullPath)) {
|
|
606320
|
+
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
606321
|
+
}
|
|
606322
|
+
content = readFileSync89(fullPath, "utf-8");
|
|
606323
|
+
cache6.set(promptPath, content);
|
|
606324
|
+
}
|
|
606325
|
+
if (!vars)
|
|
606326
|
+
return content;
|
|
606327
|
+
return content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
|
|
606328
|
+
}
|
|
606329
|
+
var __filename4, __dirname5, devPath, publishedPath, PROMPTS_DIR2, cache6;
|
|
606330
|
+
var init_promptLoader2 = __esm({
|
|
606331
|
+
"packages/prompts/dist/promptLoader.js"() {
|
|
606332
|
+
"use strict";
|
|
606333
|
+
__filename4 = fileURLToPath13(import.meta.url);
|
|
606334
|
+
__dirname5 = dirname39(__filename4);
|
|
606335
|
+
devPath = join124(__dirname5, "..", "templates");
|
|
606336
|
+
publishedPath = join124(__dirname5, "..", "prompts", "templates");
|
|
606337
|
+
PROMPTS_DIR2 = existsSync110(devPath) ? devPath : publishedPath;
|
|
606338
|
+
cache6 = /* @__PURE__ */ new Map();
|
|
606339
|
+
}
|
|
606340
|
+
});
|
|
606341
|
+
|
|
606342
|
+
// packages/prompts/dist/task-templates.js
|
|
606343
|
+
function getTaskTemplate(type) {
|
|
606344
|
+
return TEMPLATES[type];
|
|
606345
|
+
}
|
|
606346
|
+
function getTaskTypes() {
|
|
606347
|
+
return Object.keys(TEMPLATES);
|
|
606348
|
+
}
|
|
606349
|
+
function buildTaskContext(type) {
|
|
606350
|
+
const template = TEMPLATES[type];
|
|
606351
|
+
return `${template.systemPromptAddition}
|
|
606352
|
+
|
|
606353
|
+
### Output Guidance
|
|
606354
|
+
${template.outputGuidance}`;
|
|
606355
|
+
}
|
|
606356
|
+
var TEMPLATES;
|
|
606357
|
+
var init_task_templates = __esm({
|
|
606358
|
+
"packages/prompts/dist/task-templates.js"() {
|
|
606359
|
+
"use strict";
|
|
606360
|
+
init_promptLoader2();
|
|
606361
|
+
TEMPLATES = {
|
|
606362
|
+
code: {
|
|
606363
|
+
type: "code",
|
|
606364
|
+
label: "Software Development",
|
|
606365
|
+
description: "Writing, debugging, refactoring, or reviewing code.",
|
|
606366
|
+
systemPromptAddition: loadPrompt2("code.md"),
|
|
606367
|
+
recommendedTools: [
|
|
606368
|
+
"file_read",
|
|
606369
|
+
"file_write",
|
|
606370
|
+
"file_edit",
|
|
606371
|
+
"shell",
|
|
606372
|
+
"grep_search",
|
|
606373
|
+
"glob_find",
|
|
606374
|
+
"git_info",
|
|
606375
|
+
"codebase_map"
|
|
606376
|
+
],
|
|
606377
|
+
outputGuidance: "Deliver working code with tests passing. Summarize what was changed and why."
|
|
606378
|
+
},
|
|
606379
|
+
document: {
|
|
606380
|
+
type: "document",
|
|
606381
|
+
label: "Document Drafting",
|
|
606382
|
+
description: "Creating reports, specifications, guides, proposals, or other professional documents.",
|
|
606383
|
+
systemPromptAddition: loadPrompt2("document.md"),
|
|
606384
|
+
recommendedTools: [
|
|
606385
|
+
"file_read",
|
|
606386
|
+
"file_write",
|
|
606387
|
+
"web_search",
|
|
606388
|
+
"web_fetch",
|
|
606389
|
+
"create_structured_file",
|
|
606390
|
+
"memory_read"
|
|
606391
|
+
],
|
|
606392
|
+
outputGuidance: "Deliver a complete, well-structured document. Specify the output format (Markdown, PDF, etc.)."
|
|
606393
|
+
},
|
|
606394
|
+
analysis: {
|
|
606395
|
+
type: "analysis",
|
|
606396
|
+
label: "Analysis & Research",
|
|
606397
|
+
description: "Analyzing data, evaluating options, conducting research, or producing insights.",
|
|
606398
|
+
systemPromptAddition: loadPrompt2("analysis.md"),
|
|
606399
|
+
recommendedTools: [
|
|
606400
|
+
"file_read",
|
|
606401
|
+
"grep_search",
|
|
606402
|
+
"glob_find",
|
|
606403
|
+
"web_search",
|
|
606404
|
+
"web_fetch",
|
|
606405
|
+
"codebase_map",
|
|
606406
|
+
"create_structured_file",
|
|
606407
|
+
"shell"
|
|
606408
|
+
],
|
|
606409
|
+
outputGuidance: "Deliver a structured analysis with findings, data tables, and actionable recommendations."
|
|
606410
|
+
},
|
|
606411
|
+
plan: {
|
|
606412
|
+
type: "plan",
|
|
606413
|
+
label: "Planning & Design",
|
|
606414
|
+
description: "Creating project plans, system designs, architecture proposals, or roadmaps.",
|
|
606415
|
+
systemPromptAddition: loadPrompt2("plan.md"),
|
|
606416
|
+
recommendedTools: [
|
|
606417
|
+
"file_read",
|
|
606418
|
+
"grep_search",
|
|
606419
|
+
"glob_find",
|
|
606420
|
+
"codebase_map",
|
|
606421
|
+
"web_search",
|
|
606422
|
+
"create_structured_file",
|
|
606423
|
+
"file_write",
|
|
606424
|
+
"git_info"
|
|
606425
|
+
],
|
|
606426
|
+
outputGuidance: "Deliver a structured plan with phases, milestones, risks, and action items."
|
|
606427
|
+
},
|
|
606428
|
+
general: {
|
|
606429
|
+
type: "general",
|
|
606430
|
+
label: "General Task",
|
|
606431
|
+
description: "Tasks that don't clearly fit another category.",
|
|
606432
|
+
systemPromptAddition: loadPrompt2("general.md"),
|
|
606433
|
+
recommendedTools: [
|
|
606434
|
+
"file_read",
|
|
606435
|
+
"file_write",
|
|
606436
|
+
"shell",
|
|
606437
|
+
"grep_search",
|
|
606438
|
+
"web_search",
|
|
606439
|
+
"memory_read"
|
|
606440
|
+
],
|
|
606441
|
+
outputGuidance: "Deliver complete results with a clear summary of what was done."
|
|
606442
|
+
}
|
|
606443
|
+
};
|
|
606444
|
+
}
|
|
606445
|
+
});
|
|
606446
|
+
|
|
606447
|
+
// packages/prompts/dist/index.js
|
|
606448
|
+
import { join as join125, dirname as dirname40 } from "node:path";
|
|
606449
|
+
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
606450
|
+
var _dir, _packageRoot;
|
|
606451
|
+
var init_dist9 = __esm({
|
|
606452
|
+
"packages/prompts/dist/index.js"() {
|
|
606453
|
+
"use strict";
|
|
606454
|
+
init_loader();
|
|
606455
|
+
init_render2();
|
|
606456
|
+
init_task_templates();
|
|
606457
|
+
init_render2();
|
|
606458
|
+
_dir = dirname40(fileURLToPath14(import.meta.url));
|
|
606459
|
+
_packageRoot = join125(_dir, "..");
|
|
606460
|
+
}
|
|
606461
|
+
});
|
|
606462
|
+
|
|
606301
606463
|
// packages/cli/src/tui/braille-spinner.ts
|
|
606302
606464
|
function buildColorRamp(ramp) {
|
|
606303
606465
|
return [...ramp, ...ramp.slice(1, -1).reverse()];
|
|
@@ -616701,7 +616863,7 @@ export PATH="${binDir}:$PATH" # Added by omnius for nvim
|
|
|
616701
616863
|
} catch {
|
|
616702
616864
|
}
|
|
616703
616865
|
}
|
|
616704
|
-
var execAsync2, OMNIUS_FIRST_RUN_BANNER,
|
|
616866
|
+
var execAsync2, OMNIUS_FIRST_RUN_BANNER, ANSI_RE2, visibleLen2, QWEN_VARIANTS, _toolSupportCache, EXPANDED_VARIANT_MIN_NUM_CTX, _cloudflaredInstallPromise;
|
|
616705
616867
|
var init_setup = __esm({
|
|
616706
616868
|
"packages/cli/src/tui/setup.ts"() {
|
|
616707
616869
|
"use strict";
|
|
@@ -616721,8 +616883,8 @@ var init_setup = __esm({
|
|
|
616721
616883
|
"░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ",
|
|
616722
616884
|
" ░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓██████▓▒░░▒▓███████▓▒░ "
|
|
616723
616885
|
].join("\n");
|
|
616724
|
-
|
|
616725
|
-
visibleLen2 = (value2) => Array.from(value2.replace(
|
|
616886
|
+
ANSI_RE2 = /\x1B\[[0-?]*[ -/]*[@-~]/g;
|
|
616887
|
+
visibleLen2 = (value2) => Array.from(value2.replace(ANSI_RE2, "")).length;
|
|
616726
616888
|
QWEN_VARIANTS = [
|
|
616727
616889
|
{ tag: "qwen3.5:0.8b", sizeGB: 1, label: "0.8B params (1.0 GB)", cloud: false },
|
|
616728
616890
|
{ tag: "qwen3.5:2b", sizeGB: 2.7, label: "2B params (2.7 GB)", cloud: false },
|
|
@@ -623929,16 +624091,16 @@ import { execFileSync as execFileSync8 } from "node:child_process";
|
|
|
623929
624091
|
import { createRequire as createRequire6 } from "node:module";
|
|
623930
624092
|
import { existsSync as existsSync125, readFileSync as readFileSync101, statSync as statSync46 } from "node:fs";
|
|
623931
624093
|
import { resolve as resolve56 } from "node:path";
|
|
623932
|
-
function
|
|
624094
|
+
function clamp8(n2, min, max) {
|
|
623933
624095
|
if (!Number.isFinite(n2)) return min;
|
|
623934
624096
|
return Math.max(min, Math.min(max, Math.floor(n2)));
|
|
623935
624097
|
}
|
|
623936
624098
|
function defaultAsciiPreviewSize(dimensions) {
|
|
623937
624099
|
const columns = process.stdout.columns || 100;
|
|
623938
624100
|
const rows = process.stdout.rows || 32;
|
|
623939
|
-
const width =
|
|
624101
|
+
const width = clamp8(columns - 14, 42, 96);
|
|
623940
624102
|
const imageAspect = dimensions && dimensions.width > 0 && dimensions.height > 0 ? dimensions.height / dimensions.width : 1;
|
|
623941
|
-
const height =
|
|
624103
|
+
const height = clamp8(Math.min(Math.round(width * imageAspect * TERMINAL_CELL_ASPECT), rows - 10), 8, 42);
|
|
623942
624104
|
return { width, height };
|
|
623943
624105
|
}
|
|
623944
624106
|
function readImageDimensions2(imagePath) {
|
|
@@ -624034,10 +624196,10 @@ function normalizeAscii(ascii2, width, height, options2 = {}) {
|
|
|
624034
624196
|
}
|
|
624035
624197
|
function byte(value2, fallback) {
|
|
624036
624198
|
const n2 = Number(value2);
|
|
624037
|
-
return Number.isFinite(n2) ?
|
|
624199
|
+
return Number.isFinite(n2) ? clamp8(n2, 0, 255) : fallback;
|
|
624038
624200
|
}
|
|
624039
624201
|
function luminance(r2, g, b) {
|
|
624040
|
-
return
|
|
624202
|
+
return clamp8(Math.round(0.2126 * r2 + 0.7152 * g + 0.0722 * b), 0, 255);
|
|
624041
624203
|
}
|
|
624042
624204
|
function matrixPixel(cell) {
|
|
624043
624205
|
if (cell && typeof cell === "object") {
|
|
@@ -624201,9 +624363,9 @@ async function buildImageAsciiPreview(inputPath, options2 = {}) {
|
|
|
624201
624363
|
}
|
|
624202
624364
|
const dimensions = readImageDimensions2(imagePath);
|
|
624203
624365
|
const defaults3 = defaultAsciiPreviewSize(dimensions);
|
|
624204
|
-
const width =
|
|
624205
|
-
const height =
|
|
624206
|
-
const timeoutMs =
|
|
624366
|
+
const width = clamp8(options2.width ?? defaults3.width, 24, 140);
|
|
624367
|
+
const height = clamp8(options2.height ?? defaults3.height, 6, 60);
|
|
624368
|
+
const timeoutMs = clamp8(options2.timeoutMs ?? 5e3, 500, 3e4);
|
|
624207
624369
|
if (options2.preferPackage !== false) {
|
|
624208
624370
|
const result = await convertWithImageToAscii(imagePath, width, height, timeoutMs);
|
|
624209
624371
|
if (result.ascii) {
|
|
@@ -634702,7 +634864,7 @@ sleep 1
|
|
|
634702
634864
|
return "handled";
|
|
634703
634865
|
}
|
|
634704
634866
|
if (arg.trim()) {
|
|
634705
|
-
restoreNamedSession(ctx3, arg.trim());
|
|
634867
|
+
await restoreNamedSession(ctx3, arg.trim());
|
|
634706
634868
|
return "handled";
|
|
634707
634869
|
}
|
|
634708
634870
|
const resumed = ctx3.resumeTask?.() ?? false;
|
|
@@ -635866,10 +636028,12 @@ async function showSessionsMenu(ctx3) {
|
|
|
635866
636028
|
const items = sessions3.map((s2) => {
|
|
635867
636029
|
const date = s2.updatedAt.slice(0, 16).replace("T", " ");
|
|
635868
636030
|
const tasks = s2.taskCount > 1 ? `${s2.taskCount} tasks` : "1 task";
|
|
636031
|
+
const title = sessionDisplayTitle(s2);
|
|
636032
|
+
const summary = s2.aiSummary ? ` ${s2.aiSummary}` : "";
|
|
635869
636033
|
return {
|
|
635870
636034
|
key: s2.id,
|
|
635871
|
-
label:
|
|
635872
|
-
detail: `${date} | ${tasks} | ${s2.model}`
|
|
636035
|
+
label: title,
|
|
636036
|
+
detail: `${date} | ${tasks} | ${s2.model}${summary}`
|
|
635873
636037
|
};
|
|
635874
636038
|
});
|
|
635875
636039
|
items.push({
|
|
@@ -635891,45 +636055,59 @@ async function showSessionsMenu(ctx3) {
|
|
|
635891
636055
|
else ctx3.clearScreen();
|
|
635892
636056
|
return;
|
|
635893
636057
|
}
|
|
635894
|
-
|
|
636058
|
+
await replaySession(ctx3, result.key);
|
|
636059
|
+
}
|
|
636060
|
+
async function replaySession(ctx3, sessionId) {
|
|
636061
|
+
const content = loadSessionHistory(ctx3.repoRoot, sessionId);
|
|
635895
636062
|
if (!content || content.length === 0) {
|
|
635896
636063
|
renderWarning("Session content not found or empty.");
|
|
635897
636064
|
return;
|
|
635898
636065
|
}
|
|
635899
|
-
const
|
|
635900
|
-
|
|
635901
|
-
|
|
635902
|
-
|
|
635903
|
-
|
|
635904
|
-
|
|
635905
|
-
|
|
636066
|
+
const sessions3 = listSessions(ctx3.repoRoot);
|
|
636067
|
+
const session = sessions3.find((s2) => s2.id === sessionId);
|
|
636068
|
+
let title = session ? sessionDisplayTitle(session) : sessionId;
|
|
636069
|
+
let summary = session?.aiSummary ?? "";
|
|
636070
|
+
if (session && !session.aiTitle) {
|
|
636071
|
+
try {
|
|
636072
|
+
const gen = await ensureSessionSummary({
|
|
636073
|
+
repoRoot: ctx3.repoRoot,
|
|
636074
|
+
sessionId,
|
|
636075
|
+
config: {
|
|
636076
|
+
backendUrl: ctx3.config.backendUrl,
|
|
636077
|
+
model: ctx3.config.model,
|
|
636078
|
+
apiKey: ctx3.config.apiKey
|
|
636079
|
+
},
|
|
636080
|
+
timeoutMs: 2e4
|
|
636081
|
+
});
|
|
636082
|
+
title = gen.title;
|
|
636083
|
+
summary = gen.summary;
|
|
636084
|
+
} catch {
|
|
636085
|
+
}
|
|
635906
636086
|
}
|
|
635907
|
-
|
|
636087
|
+
renderContentBlock(
|
|
636088
|
+
`
|
|
636089
|
+
${c3.dim("╭─")} ${c3.bold("Recovered session")} ${c3.dim("·")} ${title} ${c3.dim(`(${content.length} lines)`)}
|
|
636090
|
+
` + (summary ? `${c3.dim("│")} ${c3.dim(summary)}
|
|
636091
|
+
` : "") + `${c3.dim("╰" + "─".repeat(40))}`
|
|
636092
|
+
);
|
|
636093
|
+
renderContentBlock(content.map((line) => ` ${line}`).join("\n"));
|
|
636094
|
+
renderContentBlock(
|
|
636095
|
+
`${c3.dim("─".repeat(20))} ${c3.dim("end of recovered session")} ${c3.dim("─".repeat(20))}`
|
|
636096
|
+
);
|
|
636097
|
+
renderInfo("Previous session fully restored above. Scroll up to review.");
|
|
635908
636098
|
}
|
|
635909
|
-
function restoreNamedSession(ctx3, query) {
|
|
636099
|
+
async function restoreNamedSession(ctx3, query) {
|
|
635910
636100
|
const normalized = query.toLowerCase();
|
|
635911
636101
|
const sessions3 = listSessions(ctx3.repoRoot);
|
|
635912
|
-
const session = sessions3.find((s2) => s2.id === query) ?? sessions3.find((s2) => s2.name.toLowerCase() === normalized) ?? sessions3.find((s2) => s2.name.toLowerCase().includes(normalized));
|
|
636102
|
+
const session = sessions3.find((s2) => s2.id === query) ?? sessions3.find((s2) => sessionDisplayTitle(s2).toLowerCase() === normalized) ?? sessions3.find((s2) => s2.name.toLowerCase() === normalized) ?? sessions3.find((s2) => sessionDisplayTitle(s2).toLowerCase().includes(normalized)) ?? sessions3.find((s2) => s2.name.toLowerCase().includes(normalized));
|
|
635913
636103
|
if (!session) {
|
|
635914
636104
|
renderWarning(
|
|
635915
636105
|
`No saved session matches "${query}". Use /sessions to browse.`
|
|
635916
636106
|
);
|
|
635917
636107
|
return;
|
|
635918
636108
|
}
|
|
635919
|
-
const content = loadSessionHistory(ctx3.repoRoot, session.id);
|
|
635920
|
-
if (!content || content.length === 0) {
|
|
635921
|
-
renderWarning(`Saved session "${session.name}" has no replayable history.`);
|
|
635922
|
-
return;
|
|
635923
|
-
}
|
|
635924
636109
|
ctx3.clearScreen();
|
|
635925
|
-
|
|
635926
|
-
for (const line of content) {
|
|
635927
|
-
process.stdout.write(` ${line}
|
|
635928
|
-
`);
|
|
635929
|
-
}
|
|
635930
|
-
renderInfo(
|
|
635931
|
-
"Session history loaded. New prompts continue in the current runtime session."
|
|
635932
|
-
);
|
|
636110
|
+
await replaySession(ctx3, session.id);
|
|
635933
636111
|
}
|
|
635934
636112
|
async function showColorMenu(ctx3) {
|
|
635935
636113
|
const currentConfig = getThemeConfig();
|
|
@@ -644215,6 +644393,7 @@ var init_commands = __esm({
|
|
|
644215
644393
|
"use strict";
|
|
644216
644394
|
init_model_picker();
|
|
644217
644395
|
init_render();
|
|
644396
|
+
init_session_summary();
|
|
644218
644397
|
init_generative_progress();
|
|
644219
644398
|
init_cad_model_viewer();
|
|
644220
644399
|
init_command_registry();
|
|
@@ -645892,6 +646071,7 @@ function importTranscriptSession(opts) {
|
|
|
645892
646071
|
existing.model = opts.model || existing.model;
|
|
645893
646072
|
existing.title = title;
|
|
645894
646073
|
existing.preview = preview;
|
|
646074
|
+
existing.transcript = cappedTranscript || "(empty transcript)";
|
|
645895
646075
|
existing.lastActivity = opts.updatedAt ?? Date.now();
|
|
645896
646076
|
const idx = existing.messages.findIndex(
|
|
645897
646077
|
(m2) => m2.role === "system" && m2.content.startsWith("[Imported TUI session transcript]")
|
|
@@ -645920,7 +646100,8 @@ function importTranscriptSession(opts) {
|
|
|
645920
646100
|
projectRoot,
|
|
645921
646101
|
source: "tui",
|
|
645922
646102
|
title,
|
|
645923
|
-
preview
|
|
646103
|
+
preview,
|
|
646104
|
+
transcript: cappedTranscript || "(empty transcript)"
|
|
645924
646105
|
};
|
|
645925
646106
|
sessions2.set(id, session);
|
|
645926
646107
|
persistSession(session);
|
|
@@ -652363,7 +652544,7 @@ function appraiseEvent(event) {
|
|
|
652363
652544
|
return null;
|
|
652364
652545
|
}
|
|
652365
652546
|
}
|
|
652366
|
-
function
|
|
652547
|
+
function clamp9(value2, min, max) {
|
|
652367
652548
|
return Math.max(min, Math.min(max, value2));
|
|
652368
652549
|
}
|
|
652369
652550
|
var BASELINE_VALENCE, BASELINE_AROUSAL, DECAY_HALF_LIFE_MS, LABEL_UPDATE_INTERVAL_MS, DISTRESS_THRESHOLD, REFLECTION_COOLDOWN_MS, REFLECTION_MIN_EVENTS, LABEL_REGEN_THRESHOLD, EmotionEngine;
|
|
@@ -652502,8 +652683,8 @@ var init_emotion_engine = __esm({
|
|
|
652502
652683
|
if (this.consecutiveFailures >= 2) {
|
|
652503
652684
|
momentum = 1 + (this.consecutiveFailures - 1) * 0.25;
|
|
652504
652685
|
}
|
|
652505
|
-
this.state.valence =
|
|
652506
|
-
this.state.arousal =
|
|
652686
|
+
this.state.valence = clamp9(this.state.valence + delta.valence * momentum, -1, 1);
|
|
652687
|
+
this.state.arousal = clamp9(this.state.arousal + delta.arousal * momentum, 0, 1);
|
|
652507
652688
|
this.state.updatedAt = Date.now();
|
|
652508
652689
|
const deterministicLabel = labelFromCoordinates(this.state.valence, this.state.arousal);
|
|
652509
652690
|
this.state.label = deterministicLabel.label;
|
|
@@ -685556,6 +685737,10 @@ body { display:flex; flex-direction:column; height:100vh; margin:0; overflow:hid
|
|
|
685556
685737
|
</div>
|
|
685557
685738
|
<h3 style="color:var(--color-brand);font-size:0.7rem;margin:16px 0 8px">Inference Provider</h3>
|
|
685558
685739
|
<div id="config-endpoint" style="font-size:0.78rem;color:var(--color-fg-muted);margin-bottom:8px"></div>
|
|
685740
|
+
<div id="config-recent-providers-section" style="display:none;margin-bottom:12px">
|
|
685741
|
+
<div style="font-size:0.66rem;color:var(--color-fg-muted);margin-bottom:6px;font-weight:500">Previously connected</div>
|
|
685742
|
+
<div id="config-recent-providers" class="settings-provider-module-grid"></div>
|
|
685743
|
+
</div>
|
|
685559
685744
|
<div style="font-size:0.66rem;color:var(--color-fg-faint);margin-bottom:6px">Pick a provider to pre-fill the endpoint, then add your key and press <strong>set</strong>.</div>
|
|
685560
685745
|
<div id="config-provider-modules" style="margin-bottom:10px"></div>
|
|
685561
685746
|
<form onsubmit="event.preventDefault(); switchEndpoint();" autocomplete="off" style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:4px">
|
|
@@ -688902,6 +689087,21 @@ async function loadConfig() {
|
|
|
688902
689087
|
const pm = document.getElementById('config-provider-modules');
|
|
688903
689088
|
if (pm) pm.innerHTML = renderSettingsProviderModules(settingsProviderIdForUrl(ep.url), ep.url, 'selectConfigProviderModule');
|
|
688904
689089
|
} catch {}
|
|
689090
|
+
// Previously-connected providers — like the TUI /endpoint history, shown as
|
|
689091
|
+
// cards above the full provider list. Populated from endpoint usage history.
|
|
689092
|
+
try {
|
|
689093
|
+
const histR = await fetch('/v1/config/endpoint/history', { headers: headers() }).then(r => r.json()).catch(() => ({}));
|
|
689094
|
+
const history = (histR && Array.isArray(histR.endpoints)) ? histR.endpoints : [];
|
|
689095
|
+
const sect = document.getElementById('config-recent-providers-section');
|
|
689096
|
+
const grid = document.getElementById('config-recent-providers');
|
|
689097
|
+
if (grid && history.length > 0) {
|
|
689098
|
+
window.__omniusRecentEndpoints = history;
|
|
689099
|
+
grid.innerHTML = renderRecentProviderCards(history, ep.url);
|
|
689100
|
+
if (sect) sect.style.display = 'block';
|
|
689101
|
+
} else if (sect) {
|
|
689102
|
+
sect.style.display = 'none';
|
|
689103
|
+
}
|
|
689104
|
+
} catch {}
|
|
688905
689105
|
// Populate model switcher
|
|
688906
689106
|
const sel = document.getElementById('config-model-select');
|
|
688907
689107
|
sel.innerHTML = '';
|
|
@@ -688973,6 +689173,54 @@ function selectConfigProviderModule(providerId) {
|
|
|
688973
689173
|
}
|
|
688974
689174
|
window.selectConfigProviderModule = selectConfigProviderModule;
|
|
688975
689175
|
|
|
689176
|
+
// Render "previously connected" provider cards from endpoint usage history.
|
|
689177
|
+
// Each card resolves to a known provider (for the favicon + label) and carries
|
|
689178
|
+
// its actual URL so clicking re-selects that exact endpoint.
|
|
689179
|
+
function renderRecentProviderCards(history, activeUrl) {
|
|
689180
|
+
const seen = new Set();
|
|
689181
|
+
return history.map(h => {
|
|
689182
|
+
const url = String(h.url || '');
|
|
689183
|
+
if (!url || seen.has(url)) return '';
|
|
689184
|
+
seen.add(url);
|
|
689185
|
+
const providerId = settingsProviderIdForUrl(url);
|
|
689186
|
+
const provider = settingsProviderById(providerId) || { id: providerId, label: providerId, domain: '' };
|
|
689187
|
+
const active = url === activeUrl;
|
|
689188
|
+
const cls = 'settings-provider-module' + (active ? ' active' : '');
|
|
689189
|
+
let host = url; try { host = new URL(url).host || url; } catch {}
|
|
689190
|
+
const label = (h.meta && h.meta.provider) ? h.meta.provider : provider.label;
|
|
689191
|
+
const uses = (h.useCount ? h.useCount + (h.useCount === 1 ? ' use' : ' uses') : '');
|
|
689192
|
+
const meta = [host, uses, h.authSet ? '🔑' : ''].filter(Boolean).join(' · ');
|
|
689193
|
+
return '<button type="button" class="' + cls + '" data-recent-url="' + escapeHtml(url) + '" onclick="selectRecentProvider(\\'' + escapeHtml(url).replace(/'/g, "'") + '\\')" title="' + escapeHtml(url) + '">' +
|
|
689194
|
+
settingsProviderIcon(provider) +
|
|
689195
|
+
'<strong>' + escapeHtml(label) + '</strong>' +
|
|
689196
|
+
'<small>' + escapeHtml(meta) + '</small>' +
|
|
689197
|
+
'</button>';
|
|
689198
|
+
}).join('');
|
|
689199
|
+
}
|
|
689200
|
+
|
|
689201
|
+
// Click handler for a previously-connected provider card: fill the form with
|
|
689202
|
+
// that exact endpoint URL + detected backend type and focus the key field.
|
|
689203
|
+
function selectRecentProvider(url) {
|
|
689204
|
+
const urlInput = document.getElementById('config-ep-url');
|
|
689205
|
+
const typeSel = document.getElementById('config-ep-type');
|
|
689206
|
+
const keyInput = document.getElementById('config-ep-key');
|
|
689207
|
+
if (urlInput) urlInput.value = url;
|
|
689208
|
+
const providerId = settingsProviderIdForUrl(url);
|
|
689209
|
+
const provider = settingsProviderById(providerId);
|
|
689210
|
+
const bt = (provider && provider.backendType) ? provider.backendType : (url.includes('11434') ? 'ollama' : 'vllm');
|
|
689211
|
+
if (typeSel) {
|
|
689212
|
+
if (!Array.from(typeSel.options).some(o => o.value === bt)) {
|
|
689213
|
+
const opt = document.createElement('option'); opt.value = bt; opt.textContent = bt; typeSel.appendChild(opt);
|
|
689214
|
+
}
|
|
689215
|
+
typeSel.value = bt;
|
|
689216
|
+
}
|
|
689217
|
+
document.querySelectorAll('#config-recent-providers .settings-provider-module').forEach(btn => {
|
|
689218
|
+
btn.classList.toggle('active', btn.getAttribute('data-recent-url') === url);
|
|
689219
|
+
});
|
|
689220
|
+
if (keyInput) { try { keyInput.focus(); } catch {} }
|
|
689221
|
+
}
|
|
689222
|
+
window.selectRecentProvider = selectRecentProvider;
|
|
689223
|
+
|
|
688976
689224
|
async function switchModel() {
|
|
688977
689225
|
const model = document.getElementById('config-model-select').value;
|
|
688978
689226
|
if (!model) return;
|
|
@@ -691288,6 +691536,23 @@ async function restoreChatSession() {
|
|
|
691288
691536
|
const conv = document.getElementById('conversation');
|
|
691289
691537
|
if (conv) {
|
|
691290
691538
|
conv.innerHTML = '';
|
|
691539
|
+
// Imported TUI session: render its FULL recorded transcript (tool calls,
|
|
691540
|
+
// decisions, sub-agent activity — everything that scrolled past in the
|
|
691541
|
+
// TUI) as a visible, scrollable block at the top so opening the session
|
|
691542
|
+
// actually shows what happened, instead of just a "loaded" notice.
|
|
691543
|
+
if (data.transcript && String(data.transcript).trim() && data.transcript !== '(empty transcript)') {
|
|
691544
|
+
const wrap = document.createElement('div');
|
|
691545
|
+
wrap.style.cssText = 'margin:6px 0 14px';
|
|
691546
|
+
const head = document.createElement('div');
|
|
691547
|
+
head.style.cssText = 'font-size:0.66rem;color:var(--color-fg-muted);margin-bottom:4px;display:flex;justify-content:space-between;align-items:center';
|
|
691548
|
+
head.innerHTML = '<span>Recovered session transcript' + (data.title ? ' — ' + escapeHtml(data.title) : '') + '</span>';
|
|
691549
|
+
const pre = document.createElement('pre');
|
|
691550
|
+
pre.style.cssText = 'max-height:380px;overflow:auto;background:var(--color-bg-elevated);border:1px solid var(--color-border);border-radius:var(--radius-sm);padding:10px 12px;font-size:0.7rem;line-height:1.35;white-space:pre-wrap;word-break:break-word;color:var(--color-fg-muted);margin:0';
|
|
691551
|
+
pre.textContent = String(data.transcript);
|
|
691552
|
+
wrap.appendChild(head);
|
|
691553
|
+
wrap.appendChild(pre);
|
|
691554
|
+
conv.appendChild(wrap);
|
|
691555
|
+
}
|
|
691291
691556
|
// WO-CHAT-RESUME-TOOLS — replay the FULL intermediate flow on
|
|
691292
691557
|
// restore: user/assistant text bubbles AND tool_call/tool_result
|
|
691293
691558
|
// dropdowns interleaved in original order. We track the current
|
|
@@ -693817,6 +694082,7 @@ function getOpenApiSpec() {
|
|
|
693817
694082
|
}
|
|
693818
694083
|
},
|
|
693819
694084
|
"/v1/chat/sessions": { get: { summary: "List active chat sessions", tags: ["Chat"], responses: { 200: { description: "Session list" } } } },
|
|
694085
|
+
"/v1/chat/sessions/{id}/summarize": { post: { summary: "Generate + cache an inference-based title/summary for a session — body {force?, root?}", tags: ["Chat"], responses: { 200: { description: "Title + summary" }, 500: { description: "Generation failed" } } } },
|
|
693820
694086
|
// ───── AIWG cascade ─────
|
|
693821
694087
|
"/v1/aiwg": { get: { summary: "AIWG installation root + control map", tags: ["AIWG"], responses: { 200: { description: "AIWG installation summary" } } } },
|
|
693822
694088
|
"/v1/aiwg/frameworks": { get: { summary: "List AIWG frameworks (paginated)", tags: ["AIWG"], responses: { 200: { description: "Framework list" } } } },
|
|
@@ -702645,9 +702911,12 @@ ${historyLines}
|
|
|
702645
702911
|
const includeTui = urlObj.searchParams.get("include_tui") !== "0";
|
|
702646
702912
|
if (includeTui && targetRoot) {
|
|
702647
702913
|
const seen = new Set(sessions3.map((s2) => s2.id));
|
|
702914
|
+
const cfg = loadConfig();
|
|
702915
|
+
const needSummary = [];
|
|
702648
702916
|
for (const t2 of listSessions(targetRoot)) {
|
|
702649
702917
|
const id = `tui:${t2.id}`;
|
|
702650
702918
|
if (seen.has(id)) continue;
|
|
702919
|
+
if (!t2.aiTitle) needSummary.push(t2.id);
|
|
702651
702920
|
sessions3.push({
|
|
702652
702921
|
id,
|
|
702653
702922
|
model: t2.model,
|
|
@@ -702657,8 +702926,16 @@ ${historyLines}
|
|
|
702657
702926
|
lastActivity: t2.updatedAt,
|
|
702658
702927
|
projectRoot: targetRoot,
|
|
702659
702928
|
source: "tui",
|
|
702660
|
-
title: t2
|
|
702661
|
-
preview: t2.description
|
|
702929
|
+
title: sessionDisplayTitle(t2),
|
|
702930
|
+
preview: t2.aiSummary || t2.description
|
|
702931
|
+
});
|
|
702932
|
+
}
|
|
702933
|
+
for (const sid of needSummary.slice(0, 6)) {
|
|
702934
|
+
void ensureSessionSummary({
|
|
702935
|
+
repoRoot: targetRoot,
|
|
702936
|
+
sessionId: sid,
|
|
702937
|
+
config: { backendUrl: cfg.backendUrl, model: cfg.model, apiKey: cfg.apiKey }
|
|
702938
|
+
}).catch(() => {
|
|
702662
702939
|
});
|
|
702663
702940
|
}
|
|
702664
702941
|
sessions3.sort((a2, b) => String(b.lastActivity).localeCompare(String(a2.lastActivity)));
|
|
@@ -702822,6 +703099,7 @@ ${historyLines}
|
|
|
702822
703099
|
preview: session.preview ?? null,
|
|
702823
703100
|
source: session.source ?? "web",
|
|
702824
703101
|
projectRoot: session.projectRoot ?? null,
|
|
703102
|
+
transcript: session.transcript ?? null,
|
|
702825
703103
|
messages: publicMessages,
|
|
702826
703104
|
message_count: publicMessages.length,
|
|
702827
703105
|
tokens_in: session.tokensIn,
|
|
@@ -702861,6 +703139,36 @@ ${historyLines}
|
|
|
702861
703139
|
return;
|
|
702862
703140
|
}
|
|
702863
703141
|
}
|
|
703142
|
+
const summarizeMatch = pathname.match(
|
|
703143
|
+
/^\/v1\/chat\/sessions\/([^/]+)\/summarize$/
|
|
703144
|
+
);
|
|
703145
|
+
if (summarizeMatch && method === "POST") {
|
|
703146
|
+
if (!checkAuth(req3, res, "run")) {
|
|
703147
|
+
status = 401;
|
|
703148
|
+
return;
|
|
703149
|
+
}
|
|
703150
|
+
const sid = decodeURIComponent(summarizeMatch[1]);
|
|
703151
|
+
const body = await parseJsonBody(req3).catch(() => ({}));
|
|
703152
|
+
const queriedRoot = body.root || urlObj.searchParams.get("root");
|
|
703153
|
+
const targetRoot = queriedRoot && String(queriedRoot).trim() ? resolve66(String(queriedRoot).trim()) : getCurrentProject()?.root ?? process.cwd();
|
|
703154
|
+
const tuiId = sid.startsWith("tui:") ? sid.slice("tui:".length) : sid;
|
|
703155
|
+
const cfg = loadConfig();
|
|
703156
|
+
try {
|
|
703157
|
+
const result = await ensureSessionSummary({
|
|
703158
|
+
repoRoot: targetRoot,
|
|
703159
|
+
sessionId: tuiId,
|
|
703160
|
+
config: { backendUrl: cfg.backendUrl, model: cfg.model, apiKey: cfg.apiKey },
|
|
703161
|
+
force: body.force === true
|
|
703162
|
+
});
|
|
703163
|
+
jsonResponse(res, 200, { session_id: sid, title: result.title, summary: result.summary });
|
|
703164
|
+
} catch (err) {
|
|
703165
|
+
jsonResponse(res, 500, {
|
|
703166
|
+
error: err instanceof Error ? err.message : String(err),
|
|
703167
|
+
session_id: sid
|
|
703168
|
+
});
|
|
703169
|
+
}
|
|
703170
|
+
return;
|
|
703171
|
+
}
|
|
702864
703172
|
if (pathname === "/v1/models" && method === "GET") {
|
|
702865
703173
|
await handleV1Models(res, ollamaUrl);
|
|
702866
703174
|
return;
|
|
@@ -705367,6 +705675,7 @@ var init_serve = __esm({
|
|
|
705367
705675
|
init_chat_session();
|
|
705368
705676
|
init_usage_tracker();
|
|
705369
705677
|
init_omnius_directory();
|
|
705678
|
+
init_session_summary();
|
|
705370
705679
|
init_omnius_directory();
|
|
705371
705680
|
init_command_registry();
|
|
705372
705681
|
init_profiles();
|