omnius 1.0.255 β†’ 1.0.257

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 CHANGED
@@ -678640,15 +678640,28 @@ body { display:flex; flex-direction:column; height:100vh; margin:0; overflow:hid
678640
678640
  <div id="activity-feed" style="font-size:0.72rem"></div>
678641
678641
  </div>
678642
678642
  <div id="projects-panel" style="display:none;flex:1;overflow-y:auto;padding:12px 16px">
678643
- <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px">
678643
+ <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px">
678644
678644
  <h3 style="color:var(--color-brand);font-size:0.7rem;margin:0">Projects</h3>
678645
- <div style="font-size:0.65rem;color:var(--color-fg-subtle)">Every folder where you have run <code style="color:var(--color-brand)">omnius</code> is registered here. Click to switch workspace.</div>
678645
+ <div style="display:flex;gap:6px;align-items:center">
678646
+ <input id="project-search" type="text" placeholder="Filter projects…" style="background:var(--color-bg);border:1px solid var(--color-border);color:var(--color-fg);padding:3px 8px;border-radius:3px;font-size:0.65rem;width:140px;font-family:inherit" oninput="filterProjects()">
678647
+ <button id="scan-btn" onclick="scanProjects()" style="background:var(--color-bg);border:1px solid var(--color-border);color:var(--color-fg-subtle);padding:3px 10px;border-radius:3px;font-size:0.65rem;cursor:pointer;font-family:inherit">πŸ” Scan</button>
678648
+ <button id="add-project-btn" onclick="showAddProject()" style="background:var(--color-bg);border:1px solid var(--color-border);color:var(--color-fg-subtle);padding:3px 10px;border-radius:3px;font-size:0.65rem;cursor:pointer;font-family:inherit">+ Add</button>
678649
+ </div>
678646
678650
  </div>
678651
+ <div style="font-size:0.65rem;color:var(--color-fg-subtle);margin-bottom:10px">Every folder where you have run <code style="color:var(--color-brand)">omnius</code> is registered here. Click to switch workspace.</div>
678647
678652
  <div id="projects-current" style="background:var(--color-bg);border-left:2px solid var(--color-brand);padding:8px 12px;margin-bottom:12px;font-size:0.72rem;color:var(--color-fg)">
678648
678653
  <span style="color:var(--color-fg-subtle)">current:</span> <span id="projects-current-name" style="color:var(--color-brand)">(none)</span>
678649
678654
  <span id="projects-current-root" style="color:var(--color-fg-subtle);margin-left:8px"></span>
678650
678655
  </div>
678651
678656
  <div id="projects-list" style="font-size:0.72rem"></div>
678657
+ <div id="add-project-form" style="display:none;margin-top:10px;padding:10px;background:var(--color-bg);border:1px solid var(--color-border);border-radius:4px">
678658
+ <div style="font-size:0.7rem;color:var(--color-brand);margin-bottom:6px">Add Project</div>
678659
+ <input id="add-project-path" type="text" placeholder="/absolute/path/to/project" style="background:var(--color-bg-input);border:1px solid var(--color-border);color:var(--color-fg);padding:4px 8px;border-radius:3px;font-size:0.65rem;width:100%;margin-bottom:6px;font-family:inherit">
678660
+ <div style="display:flex;gap:6px">
678661
+ <button onclick="addProject()" style="background:var(--color-brand);border:none;color:#fff;padding:4px 12px;border-radius:3px;font-size:0.65rem;cursor:pointer;font-family:inherit">Register</button>
678662
+ <button onclick="hideAddProject()" style="background:var(--color-bg);border:1px solid var(--color-border);color:var(--color-fg-subtle);padding:4px 12px;border-radius:3px;font-size:0.65rem;cursor:pointer;font-family:inherit">Cancel</button>
678663
+ </div>
678664
+ </div>
678652
678665
  </div>
678653
678666
 
678654
678667
  <!-- Voice tab β€” voicechat toggle + clone management. AudioWorklet drives mic capture; WebAudio handles TTS playback. -->
@@ -681442,6 +681455,127 @@ async function loadProjects() {
681442
681455
  }
681443
681456
  window.loadProjects = loadProjects;
681444
681457
 
681458
+ // ─── Scan for Omnius instances on the filesystem ───
681459
+ async function scanProjects() {
681460
+ const btn = document.getElementById('scan-btn');
681461
+ if (!btn) return;
681462
+ btn.textContent = 'Scanning…';
681463
+ btn.disabled = true;
681464
+ try {
681465
+ const resp = await fetch('/v1/projects/scan', { headers: headers() });
681466
+ if (!resp.ok) {
681467
+ alert('Scan failed: HTTP ' + resp.status);
681468
+ return;
681469
+ }
681470
+ const data = await resp.json();
681471
+ if (!data.projects || data.projects.length === 0) {
681472
+ alert('No Omnius instances found under ' + data.base);
681473
+ return;
681474
+ }
681475
+ const unregistered = data.projects.filter((p: any) => !p.registered);
681476
+ const registered = data.projects.filter((p: any) => p.registered);
681477
+ let html = '<div style="margin-bottom:8px;font-size:0.65rem;color:var(--color-fg-subtle)">Found ' + data.count + ' Omnius instance(s) under <code>' + data.base + '</code></div>';
681478
+ if (registered.length > 0) {
681479
+ html += '<div style="font-size:0.65rem;color:var(--color-fg-subtle);margin-bottom:4px">Already registered:</div>';
681480
+ registered.forEach((p: any) => {
681481
+ html += '<div style="padding:4px 8px;margin:2px 0;font-size:0.65rem;color:var(--color-fg-subtle)">βœ“ ' + p.name + ' β€” ' + p.root + '</div>';
681482
+ });
681483
+ }
681484
+ if (unregistered.length > 0) {
681485
+ html += '<div style="font-size:0.65rem;color:var(--color-fg-subtle);margin:8px 0 4px">Not registered β€” click to add:</div>';
681486
+ unregistered.forEach((p: any) => {
681487
+ html += '<div class="scan-row" data-root="' + encodeURIComponent(p.root) + '" data-name="' + encodeURIComponent(p.name) + '" style="padding:4px 8px;margin:2px 0;font-size:0.65rem;color:var(--color-brand);cursor:pointer;border:1px dashed var(--color-border);border-radius:3px">' +
681488
+ p.name + ' <span style="color:var(--color-fg-faint)">(' + p.root + ')</span>' +
681489
+ ' <span style="color:var(--color-success);font-size:0.6rem">[click to register]</span></div>';
681490
+ });
681491
+ document.querySelectorAll('.scan-row').forEach((el: any) => {
681492
+ el.addEventListener('click', async () => {
681493
+ const root = decodeURIComponent(el.getAttribute('data-root') || '');
681494
+ const name = decodeURIComponent(el.getAttribute('data-name') || '');
681495
+ if (!root) return;
681496
+ el.style.opacity = '0.5';
681497
+ try {
681498
+ const r = await fetch('/v1/projects/register', {
681499
+ method: 'POST',
681500
+ headers: { 'Content-Type': 'application/json', ...headers() },
681501
+ body: JSON.stringify({ root, name }),
681502
+ });
681503
+ if (!r.ok) {
681504
+ const err = await r.json().catch(() => ({ message: 'HTTP ' + r.status }));
681505
+ alert('Register failed: ' + (err.message || err.error || 'unknown'));
681506
+ el.style.opacity = '1';
681507
+ return;
681508
+ }
681509
+ el.textContent = 'βœ“ ' + name + ' β€” registered';
681510
+ el.style.color = 'var(--color-success)';
681511
+ el.style.cursor = 'default';
681512
+ el.style.borderColor = 'var(--color-success)';
681513
+ await loadProjects();
681514
+ } catch (e) {
681515
+ alert('Register failed: ' + (e && e.message ? e.message : String(e)));
681516
+ el.style.opacity = '1';
681517
+ }
681518
+ });
681519
+ });
681520
+ }
681521
+ document.getElementById('projects-list').innerHTML = html;
681522
+ } catch (e) {
681523
+ document.getElementById('projects-list').innerHTML =
681524
+ '<div style="color:var(--color-error)">Scan failed: ' + (e && e.message ? e.message : String(e)) + '</div>';
681525
+ } finally {
681526
+ btn.textContent = 'πŸ” Scan';
681527
+ btn.disabled = false;
681528
+ }
681529
+ }
681530
+ window.scanProjects = scanProjects;
681531
+
681532
+ // ─── Manual add project ───
681533
+ function showAddProject() {
681534
+ const form = document.getElementById('add-project-form');
681535
+ if (form) form.style.display = 'block';
681536
+ }
681537
+ function hideAddProject() {
681538
+ const form = document.getElementById('add-project-form');
681539
+ if (form) form.style.display = 'none';
681540
+ }
681541
+ async function addProject() {
681542
+ const input = document.getElementById('add-project-path');
681543
+ if (!input) return;
681544
+ const root = input.value.trim();
681545
+ if (!root) { alert('Please enter a path.'); return; }
681546
+ try {
681547
+ const r = await fetch('/v1/projects/register', {
681548
+ method: 'POST',
681549
+ headers: { 'Content-Type': 'application/json', ...headers() },
681550
+ body: JSON.stringify({ root, name: root.split('/').pop() }),
681551
+ });
681552
+ if (!r.ok) {
681553
+ const err = await r.json().catch(() => ({ message: 'HTTP ' + r.status }));
681554
+ alert('Register failed: ' + (err.message || err.error || 'unknown'));
681555
+ return;
681556
+ }
681557
+ hideAddProject();
681558
+ input.value = '';
681559
+ await loadProjects();
681560
+ } catch (e) {
681561
+ alert('Register failed: ' + (e && e.message ? e.message : String(e)));
681562
+ }
681563
+ }
681564
+ window.showAddProject = showAddProject;
681565
+ window.hideAddProject = hideAddProject;
681566
+ window.addProject = addProject;
681567
+
681568
+ // ─── Filter projects by search text ───
681569
+ function filterProjects() {
681570
+ const query = (document.getElementById('project-search') as HTMLInputElement)?.value.toLowerCase() || '';
681571
+ document.querySelectorAll('.proj-row').forEach((el: any) => {
681572
+ const root = (el.getAttribute('data-root') || '').toLowerCase();
681573
+ const name = (el.textContent || '').toLowerCase();
681574
+ el.style.display = (!query || root.includes(query) || name.includes(query)) ? '' : 'none';
681575
+ });
681576
+ }
681577
+ window.filterProjects = filterProjects;
681578
+
681445
681579
  // Token counter
681446
681580
  let totalTokens = 0;
681447
681581
  function updateTokenCounter(n) { totalTokens += n; document.getElementById('token-counter').textContent = totalTokens.toLocaleString() + ' tokens'; }
@@ -691124,7 +691258,7 @@ async function handleRequest(req3, res, ollamaUrl, verbose, runtimeDefaults = {}
691124
691258
  const dir = path12.dirname(cssEntry);
691125
691259
  const fullPath = path12.join(dir, entry.path);
691126
691260
  if (fs11.existsSync(fullPath)) {
691127
- const stat8 = fs11.statSync(fullPath);
691261
+ const stat8 = statSync52(fullPath);
691128
691262
  res.writeHead(200, {
691129
691263
  "Content-Type": entry.ct,
691130
691264
  "Content-Length": String(stat8.size),
@@ -691482,6 +691616,112 @@ async function handleRequest(req3, res, ollamaUrl, verbose, runtimeDefaults = {}
691482
691616
  jsonResponse(res, 200, entry);
691483
691617
  return;
691484
691618
  }
691619
+ if (pathname === "/v1/projects/scan" && method === "GET") {
691620
+ const scanRoot = urlObj.searchParams.get("root");
691621
+ const base3 = scanRoot && scanRoot.trim() ? resolve62(scanRoot.trim()) : homedir54();
691622
+ try {
691623
+ let walk3 = function(dir, depth) {
691624
+ if (depth > 6) return;
691625
+ let entries;
691626
+ try {
691627
+ entries = readdirSync50(dir, { withFileTypes: true });
691628
+ } catch {
691629
+ return;
691630
+ }
691631
+ for (const e2 of entries) {
691632
+ if (!e2.isDirectory()) continue;
691633
+ const child = join159(dir, e2.name);
691634
+ const omniusDir = join159(child, ".omnius");
691635
+ try {
691636
+ if (statSync52(omniusDir).isDirectory()) {
691637
+ const name10 = e2.name;
691638
+ const prefsFile = join159(omniusDir, "config.json");
691639
+ let lastSeen = 0;
691640
+ try {
691641
+ lastSeen = statSync52(prefsFile).mtimeMs;
691642
+ } catch {
691643
+ }
691644
+ if (!lastSeen) {
691645
+ try {
691646
+ lastSeen = statSync52(omniusDir).mtimeMs;
691647
+ } catch {
691648
+ }
691649
+ }
691650
+ found.push({ root: resolve62(child), name: name10, lastSeen, omniusDir });
691651
+ }
691652
+ } catch {
691653
+ }
691654
+ walk3(child, depth + 1);
691655
+ }
691656
+ };
691657
+ var walk2 = walk3;
691658
+ const found = [];
691659
+ walk3(base3, 0);
691660
+ found.sort((a2, b) => b.lastSeen - a2.lastSeen);
691661
+ const registered = listProjects().map((p2) => p2.root);
691662
+ jsonResponse(res, 200, {
691663
+ base: base3,
691664
+ count: found.length,
691665
+ projects: found.map((p2) => ({ ...p2, registered: registered.includes(p2.root) }))
691666
+ });
691667
+ } catch (e2) {
691668
+ jsonResponse(res, 500, { error: "scan_failed", message: e2.message });
691669
+ }
691670
+ return;
691671
+ }
691672
+ if (pathname === "/v1/projects/scan" && method === "GET") {
691673
+ const scanRoot = urlObj.searchParams.get("root");
691674
+ const base3 = scanRoot && scanRoot.trim() ? resolve62(scanRoot.trim()) : homedir54();
691675
+ try {
691676
+ let walk3 = function(dir, depth) {
691677
+ if (depth > 6) return;
691678
+ let entries;
691679
+ try {
691680
+ entries = readdirSync50(dir, { withFileTypes: true });
691681
+ } catch {
691682
+ return;
691683
+ }
691684
+ for (const e2 of entries) {
691685
+ if (!e2.isDirectory()) continue;
691686
+ const child = join159(dir, e2.name);
691687
+ const omniusDir = join159(child, ".omnius");
691688
+ try {
691689
+ if (statSync52(omniusDir).isDirectory()) {
691690
+ const name10 = e2.name;
691691
+ const prefsFile = join159(omniusDir, "config.json");
691692
+ let lastSeen = 0;
691693
+ try {
691694
+ lastSeen = statSync52(prefsFile).mtimeMs;
691695
+ } catch {
691696
+ }
691697
+ if (!lastSeen) {
691698
+ try {
691699
+ lastSeen = statSync52(omniusDir).mtimeMs;
691700
+ } catch {
691701
+ }
691702
+ }
691703
+ found.push({ root: resolve62(child), name: name10, lastSeen, omniusDir });
691704
+ }
691705
+ } catch {
691706
+ }
691707
+ walk3(child, depth + 1);
691708
+ }
691709
+ };
691710
+ var walk2 = walk3;
691711
+ const found = [];
691712
+ walk3(base3, 0);
691713
+ found.sort((a2, b) => b.lastSeen - a2.lastSeen);
691714
+ const registered = listProjects().map((p2) => p2.root);
691715
+ jsonResponse(res, 200, {
691716
+ base: base3,
691717
+ count: found.length,
691718
+ projects: found.map((p2) => ({ ...p2, registered: registered.includes(p2.root) }))
691719
+ });
691720
+ } catch (e2) {
691721
+ jsonResponse(res, 500, { error: "scan_failed", message: e2.message });
691722
+ }
691723
+ return;
691724
+ }
691485
691725
  if (pathname === "/v1/projects/preferences") {
691486
691726
  const queriedRoot = urlObj.searchParams.get("root");
691487
691727
  let targetRoot = null;
@@ -692421,6 +692661,197 @@ data: ${JSON.stringify(data)}
692421
692661
  jsonResponse(res, ok3 ? 200 : 500, ok3 ? { unit, action, status: "ok" } : { error: "action failed", unit, action });
692422
692662
  return;
692423
692663
  }
692664
+ if (pathname === "/v1/theme" && method === "GET") {
692665
+ const config = loadConfig();
692666
+ jsonResponse(res, 200, { theme: config.theme ?? "system", fontScale: config.fontScale ?? 1 });
692667
+ return;
692668
+ }
692669
+ if (pathname === "/v1/theme" && method === "POST") {
692670
+ const body = await parseJsonBody(req3);
692671
+ const config = loadConfig();
692672
+ if (body?.theme) config.theme = body.theme;
692673
+ if (typeof body?.fontScale === "number") config.fontScale = body.fontScale;
692674
+ try {
692675
+ require4("./config").saveConfig?.(config);
692676
+ } catch {
692677
+ }
692678
+ jsonResponse(res, 200, { ok: true, theme: config.theme, fontScale: config.fontScale });
692679
+ return;
692680
+ }
692681
+ if (pathname === "/v1/tor/status" && method === "GET") {
692682
+ const config = loadConfig();
692683
+ jsonResponse(res, 200, { enabled: config.torEnabled ?? false });
692684
+ return;
692685
+ }
692686
+ if (pathname === "/v1/tor/enable" && method === "POST") {
692687
+ const body = await parseJsonBody(req3);
692688
+ const config = loadConfig();
692689
+ config.torEnabled = Boolean(body?.enabled);
692690
+ try {
692691
+ require4("./config").saveConfig?.(config);
692692
+ } catch {
692693
+ }
692694
+ jsonResponse(res, 200, { ok: true, enabled: config.torEnabled });
692695
+ return;
692696
+ }
692697
+ if (pathname === "/v1/update" && method === "POST") {
692698
+ const config = loadConfig();
692699
+ config.updating = true;
692700
+ try {
692701
+ require4("./config").saveConfig?.(config);
692702
+ } catch {
692703
+ }
692704
+ setImmediate(() => {
692705
+ try {
692706
+ const { execSync: execSync62 } = require4("node:child_process");
692707
+ execSync62("npm update -g omnius 2>/dev/null || true", { stdio: "pipe" });
692708
+ } catch {
692709
+ }
692710
+ });
692711
+ jsonResponse(res, 200, { ok: true, message: "Update initiated" });
692712
+ return;
692713
+ }
692714
+ if (pathname === "/v1/share/generate" && method === "POST") {
692715
+ const body = await parseJsonBody(req3);
692716
+ const config = loadConfig();
692717
+ const shareDir = config.shareDir || `${require4("node:os").homedir()}/.omnius/share`;
692718
+ const fs11 = require4("node:fs");
692719
+ const path12 = require4("node:path");
692720
+ try {
692721
+ fs11.mkdirSync(shareDir, { recursive: true });
692722
+ const filename = `${Date.now()}-${(body?.title || "share").replace(/[^a-z0-9]/gi, "_")}.md`;
692723
+ const filepath = path12.join(shareDir, filename);
692724
+ fs11.writeFileSync(filepath, body?.content || "");
692725
+ jsonResponse(res, 200, { ok: true, path: filepath, filename });
692726
+ } catch (err) {
692727
+ jsonResponse(res, 500, { error: "share_failed", message: err instanceof Error ? err.message : String(err) });
692728
+ }
692729
+ return;
692730
+ }
692731
+ if (pathname === "/v1/config/endpoint/history" && method === "GET") {
692732
+ const config = loadConfig();
692733
+ const history = config.endpointHistory || [];
692734
+ jsonResponse(res, 200, { history });
692735
+ return;
692736
+ }
692737
+ if (pathname === "/v1/voice/speak" && method === "POST") {
692738
+ const body = await parseJsonBody(req3);
692739
+ const text2 = body?.text || "";
692740
+ if (!text2) {
692741
+ jsonResponse(res, 400, { error: "missing_text" });
692742
+ return;
692743
+ }
692744
+ try {
692745
+ const { execSync: execSync62 } = require4("node:child_process");
692746
+ let audioPath = null;
692747
+ const ttsCmds = [
692748
+ `espeak "${text2}" -w /tmp/tts_${Date.now()}.wav 2>/dev/null`,
692749
+ `pico2wave -w /tmp/tts_${Date.now()}.wav "text:${text2}" 2>/dev/null`,
692750
+ `say "${text2}" 2>/dev/null`
692751
+ ];
692752
+ for (const cmd of ttsCmds) {
692753
+ try {
692754
+ execSync62(cmd, { stdio: "pipe" });
692755
+ audioPath = "/tmp/tts_" + Date.now() + ".wav";
692756
+ break;
692757
+ } catch {
692758
+ continue;
692759
+ }
692760
+ }
692761
+ if (audioPath) {
692762
+ const fs11 = require4("node:fs");
692763
+ const data = fs11.readFileSync(audioPath).toString("base64");
692764
+ fs11.unlinkSync(audioPath);
692765
+ jsonResponse(res, 200, { ok: true, audio: data, format: "wav" });
692766
+ } else {
692767
+ jsonResponse(res, 500, { error: "tts_unavailable", message: "No TTS backend found" });
692768
+ }
692769
+ } catch (err) {
692770
+ jsonResponse(res, 500, { error: "tts_failed", message: err instanceof Error ? err.message : String(err) });
692771
+ }
692772
+ return;
692773
+ }
692774
+ if (pathname === "/v1/voice/supertonic-settings" && method === "GET") {
692775
+ const config = loadConfig();
692776
+ jsonResponse(res, 200, { settings: config.supertonicSettings || {} });
692777
+ return;
692778
+ }
692779
+ if (pathname === "/v1/voice/supertonic-settings" && method === "POST") {
692780
+ const body = await parseJsonBody(req3);
692781
+ const config = loadConfig();
692782
+ config.supertonicSettings = { ...config.supertonicSettings, ...body };
692783
+ try {
692784
+ require4("./config").saveConfig?.(config);
692785
+ } catch {
692786
+ }
692787
+ jsonResponse(res, 200, { ok: true, settings: config.supertonicSettings });
692788
+ return;
692789
+ }
692790
+ if (pathname === "/v1/voice/clone-refs" && method === "GET") {
692791
+ const config = loadConfig();
692792
+ const refs = config.voiceCloneRefs || [];
692793
+ jsonResponse(res, 200, { refs });
692794
+ return;
692795
+ }
692796
+ if (pathname === "/v1/voice/clone-refs" && method === "POST") {
692797
+ const body = await parseJsonBody(req3);
692798
+ const config = loadConfig();
692799
+ const refs = config.voiceCloneRefs || [];
692800
+ const newRef = { filename: body?.filename || body?.path || "", path: body?.path || body?.filename || "", active: false };
692801
+ refs.push(newRef);
692802
+ config.voiceCloneRefs = refs;
692803
+ try {
692804
+ require4("./config").saveConfig?.(config);
692805
+ } catch {
692806
+ }
692807
+ jsonResponse(res, 200, { ok: true, ref: newRef });
692808
+ return;
692809
+ }
692810
+ if (pathname?.startsWith("/v1/voice/clone-refs/") && pathname.endsWith("/activate") && method === "POST") {
692811
+ const parts = pathname.split("/");
692812
+ const filename = parts[4] || "";
692813
+ const config = loadConfig();
692814
+ const refs = config.voiceCloneRefs || [];
692815
+ const ref = refs.find((r2) => r2.filename === filename);
692816
+ if (ref) {
692817
+ ref.active = true;
692818
+ try {
692819
+ require4("./config").saveConfig?.(config);
692820
+ } catch {
692821
+ }
692822
+ }
692823
+ jsonResponse(res, 200, { ok: true, ref });
692824
+ return;
692825
+ }
692826
+ if (pathname?.startsWith("/v1/voice/clone-refs/") && pathname.endsWith("/rename") && method === "POST") {
692827
+ const parts = pathname.split("/");
692828
+ const filename = parts[4] || "";
692829
+ const body = await parseJsonBody(req3);
692830
+ const config = loadConfig();
692831
+ const refs = config.voiceCloneRefs || [];
692832
+ const ref = refs.find((r2) => r2.filename === filename);
692833
+ if (ref && body?.newFilename) {
692834
+ ref.filename = body.newFilename;
692835
+ try {
692836
+ require4("./config").saveConfig?.(config);
692837
+ } catch {
692838
+ }
692839
+ }
692840
+ jsonResponse(res, 200, { ok: true, ref });
692841
+ return;
692842
+ }
692843
+ if (pathname?.startsWith("/v1/voice/clone-refs/") && method === "DELETE") {
692844
+ const parts = pathname.split("/");
692845
+ const filename = parts[4] || "";
692846
+ const config = loadConfig();
692847
+ config.voiceCloneRefs = (config.voiceCloneRefs || []).filter((r2) => r2.filename !== filename);
692848
+ try {
692849
+ require4("./config").saveConfig?.(config);
692850
+ } catch {
692851
+ }
692852
+ jsonResponse(res, 200, { ok: true, deleted: filename });
692853
+ return;
692854
+ }
692424
692855
  if ((pathname === "/v1/chat" || pathname === "/api/chat") && method === "POST") {
692425
692856
  if (!checkAuth(req3, res, "run")) {
692426
692857
  status = 401;
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.255",
3
+ "version": "1.0.257",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.255",
9
+ "version": "1.0.257",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.255",
3
+ "version": "1.0.257",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) β€” interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",