Browse Source

fix-status-indicator-and-add-scripts

master
Serge Shutov 1 week ago
parent
commit
42c864f3e3
  1. 2
      bridge/config.example.json
  2. 21
      content/content.js
  3. 3
      content/overlay.css
  4. 2
      content/panel.js
  5. 67
      scripts/pair.ps1
  6. 21
      scripts/start-dsh-memory.cmd
  7. 12
      scripts/stop-dsh-memory.cmd

2
bridge/config.json → bridge/config.example.json

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
{
"token": "6d6f58acd21d37bea9a768616b189c5c858c8da26e0faecbf219f34172b5e826",
"token": "",
"port": 8766,
"allowedRoots": [
"V:/Site"

21
content/content.js

@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
var CALL_HASH_CAP = 100; var cfgToken = ''; var execMode = 'dom'; var lastSsePid = ''; var domDebugSeen = new Set(); var domDebugCount = 0;
if (UI) {
UI.onResetLoops(function () { queue.length = 0; pending.clear(); seenHashes.clear(); pumping = false; if (UI) UI.log('loops reset'); });
UI.onStop(function () { queue.length = 0; started = false; try { obs.disconnect(); } catch (e) {} if (UI) { UI.setPhase('off'); UI.setStartEnabled(true); UI.log('stopped'); } });
UI.onStop(function () { queue.length = 0; started = false; try { obs.disconnect(); } catch (e) {} if (UI) { UI.setPhase('off'); UI.setStartEnabled(true); if (UI.setDot) UI.setDot('stopped'); UI.log('stopped'); } });
UI.onSaveToken(function (v) { chrome.storage.local.set({ 'dshmem-bridge-token': v }, function () { if (UI) UI.log('token saved, reload page'); }); });
}
if (UI) { UI.onStart(function () { if (!canStart) { if (UI.setStartEnabled) UI.setStartEnabled(true); return; } started = true; markExistingAsProcessed(); obs.observe(document.documentElement, { childList: true, subtree: true, characterData: true }); UI.setPhase('idle'); UI.setConnected(true); UI.log('started'); }); }
@ -276,7 +276,7 @@ if (parsed.calls.length === 0) { if (hasMarker) { try { var __dh = hashText(text @@ -276,7 +276,7 @@ if (parsed.calls.length === 0) { if (hasMarker) { try { var __dh = hashText(text
if (results.length > 0) {
var payload = buildResultMessage(results);
if (UI) UI.setPhase('sending');
var anyFail = results.some(function (r) { return !r || !r.ok; }); sendText(payload).then(function () { if (UI) { UI.setPhase('idle'); if (UI.setDot) UI.setDot(anyFail ? 'busy' : 'ok'); } }).catch(function (err) { console.warn('[dsh-memory] sendText failed', String(err)); if (UI) { UI.setPhase('idle'); if (UI.setDot) UI.setDot('busy'); } });
var anyFail = results.some(function (r) { return !r || !r.ok; }); sendText(payload).then(function () { if (UI) { UI.setPhase('idle'); if (UI.setDot) UI.setDot(anyFail ? 'error' : 'ok'); } }).catch(function (err) { console.warn('[dsh-memory] sendText failed', String(err)); if (UI) { UI.setPhase('idle'); if (UI.setDot) UI.setDot('error'); } });
} else { if (UI) UI.setPhase('idle'); }
return;
}
@ -354,7 +354,22 @@ if (parsed.calls.length === 0) { if (hasMarker) { try { var __dh = hashText(text @@ -354,7 +354,22 @@ if (parsed.calls.length === 0) { if (hasMarker) { try { var __dh = hashText(text
characterData: true
});
console.log("[dsh-memory] content.js active");
if (UI) { UI.setPhase('off'); UI.setConnected(true); canStart = true; UI.log('ready, press Start'); } __refreshStats();
BRIDGE.health().then(function (r) {
if (UI) {
UI.setPhase('off');
UI.setConnected(!!(r && r.ok));
if (!r || !r.ok) UI.log('bridge down: ' + ((r && r.error && r.error.message) || '?'));
else UI.log('ready, press Start');
}
canStart = true;
}).catch(function (e) {
if (UI) { UI.setPhase('off'); UI.setConnected(false); UI.log('bridge down: ' + String(e)); }
canStart = true;
});
setInterval(function () {
BRIDGE.health().then(function (r) { if (UI && UI.setConnected) UI.setConnected(!!(r && r.ok)); });
}, 30000);
__refreshStats();
});
});
function __refreshStats() { try { var SB = globalThis.STORAGE_BRIDGE; if (!SB || !UI || !UI.setStats) return; SB.getState().then(function (st) { var mN = st && st.memories ? Object.keys(st.memories).length : 0; var sN = st && st.skills && st.skills.length ? st.skills.length : 0; return SB.authHeaders().then(function (h) { return fetch(SB.BU + '/health', { headers: h }); }).then(function (r) { return r.json(); }).then(function (j) { UI.setStats((j && j.workspace) || '?', mN, sN); }); }).catch(function () { UI.setStats('?', 0, 0); }); } catch (e) { console.warn('[dsh-memory] stats ' + String(e)); } }

3
content/overlay.css

@ -36,6 +36,9 @@ @@ -36,6 +36,9 @@
.dshmem-dot.ok { background: #34c759; }
.dshmem-dot.err { background: #ff5f57; }
.dshmem-dot.busy { background: #ffcc00; animation: dshmem-blink 1s infinite; } .dshmem-dot.ok-busy { background: #34c759; animation: dshmem-blink 1s infinite; }
.dshmem-dot.off { background: #666; }
.dshmem-dot.stopped { background: #666; }
.dshmem-dot.error { background: #ff5f57; animation: dshmem-blink 1s infinite; }
@keyframes dshmem-blink { 50% { opacity: 0.35; } }
.dshmem-title { font-weight: 600; letter-spacing: 0.4px; }

2
content/panel.js

@ -75,7 +75,7 @@ @@ -75,7 +75,7 @@
}
var API = {
setPhase: function (p) { state.phase = p; if (el.phase) el.phase.textContent = p; },
setConnected: function (b) { state.connected = !!b; API._applyDot(); }, setDot: function (m) { state.dotMode = (m === 'ok') ? null : m; API._applyDot(); }, _applyDot: function () { if (!el.dot) return; var md = state.dotMode || (state.connected ? 'ok' : 'err'); var cls = 'dshmem-dot'; if (md === 'ok' || md === 'err' || md === 'busy' || md === 'ok-busy') cls += ' ' + md; el.dot.className = cls; },
setConnected: function (b) { state.connected = !!b; API._applyDot(); }, setDot: function (m) { state.dotMode = m || null; API._applyDot(); }, _applyDot: function () { if (!el.dot) return; var cls = 'dshmem-dot'; if (!state.connected) { cls += ' err'; } else { var m = state.dotMode || 'off'; if (m === 'busy' || m === 'ok-busy') cls += ' busy'; else if (m === 'error') cls += ' error'; else if (m === 'stopped') cls += ' stopped'; else if (m === 'ok') cls += ' ok'; else cls += ' off'; } el.dot.className = cls; },
setStartEnabled: function (b) { if (el.start) el.start.disabled = !b; }, setStats: function (ws, memN, skillN) { if (!el.stats) return; el.stats.textContent = 'WS: ' + (ws || '?') + ' mem: ' + (memN || 0) + ' skills: ' + (skillN || 0); }, setMetrics: function (m) { if (!el.metrics) return; if (!m) { el.metrics.textContent = 'metrics: —'; return; } state.lastMetrics = m; var __pct = 0; if (state.accLimit > 0) __pct = Math.round((m.accum || 0) * 100 / state.accLimit); var __cls = 'dshmem-acc-ok'; if (__pct > 100) __cls = 'dshmem-acc-crit'; else if (__pct >= 80) __cls = 'dshmem-acc-err'; else if (__pct >= 40) __cls = 'dshmem-acc-warn'; el.metrics.className = 'dshmem-stats ' + __cls; el.metrics.textContent = 'acc: ' + m.accum + ' · turn: ' + m.delta + ' · msg: ' + m.chars + 'ch (~' + m.est_tok + 't) ctx ' + (m.ctx_tok || 0) + 't ' + (m.ctx_pct || 0) + 'pct'; },
toggleForceInject: function () {
state.forceInject = !state.forceInject;

67
scripts/pair.ps1

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
# dsh-memory pair script
# Generates a random 64-hex token, writes it into bridge/config.json,
# copies it to the clipboard, and starts the bridge if not running.
# Usage: powershell -NoProfile -ExecutionPolicy Bypass -File pair.ps1
$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent $PSScriptRoot
$cfgPath = Join-Path $root 'bridge\config.json'
# Load or create config
if (Test-Path $cfgPath) {
$raw = Get-Content $cfgPath -Raw -Encoding UTF8
$cfg = $raw | ConvertFrom-Json
} else {
Write-Host "[dsh-memory] config.json not found, creating defaults."
$cfg = [pscustomobject]@{
token = ''
port = 8766
allowedRoots = @((Split-Path -Parent $root))
bashTimeoutMs = 20000
bashTimeoutMaxMs = 120000
handoffTimeoutMs = 300000
handoffTimeoutMaxMs = 1800000
dailySendLimit = 200
}
}
# Generate 32 random bytes -> 64 hex chars
$bytes = New-Object byte[] 32
$rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
$rng.GetBytes($bytes)
$token = -join ($bytes | ForEach-Object { $_.ToString('x2') })
$rng.Dispose()
$cfg.token = $token
if (-not $cfg.allowedRoots -or $cfg.allowedRoots.Count -eq 0) {
$cfg | Add-Member -NotePropertyName allowedRoots -NotePropertyValue @((Split-Path -Parent $root)) -Force
}
$cfg | ConvertTo-Json -Depth 5 | Set-Content $cfgPath -Encoding UTF8
Write-Host "[dsh-memory] token written to $cfgPath"
# Copy token to clipboard
try {
Set-Clipboard -Value $token
Write-Host "[dsh-memory] token copied to clipboard. Paste it into the dsh-memory panel."
} catch {
Write-Host "[dsh-memory] Could not access clipboard. Token value:"
Write-Host $token
}
# Start bridge if not already listening
$port = if ($cfg.port) { [int]$cfg.port } else { 8766 }
$listening = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue
if ($listening) {
Write-Host "[dsh-memory] bridge already running on port $port."
} else {
Write-Host "[dsh-memory] starting bridge on port $port ..."
$serverJs = Join-Path $root 'bridge\server.js'
Start-Process -FilePath 'cmd.exe' -ArgumentList '/c', "title dsh-memory bridge && node `"$serverJs`" & pause" -WorkingDirectory $root
Start-Sleep -Seconds 2
$check = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue
if ($check) {
Write-Host "[dsh-memory] bridge started."
} else {
Write-Host "[dsh-memory] bridge may have failed to start. Is node in PATH? Check the bridge window for errors."
}
}

21
scripts/start-dsh-memory.cmd

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
@echo off
rem dsh-memory - idempotent bridge starter
setlocal
set "ROOT=%~dp0.."
if not exist "%ROOT%\bridge\config.json" (
echo [dsh-memory] bridge\config.json not found. Run scripts\pair.ps1 first.
pause
exit /b 1
)
powershell -NoProfile -Command "if (Get-NetTCPConnection -LocalPort 8766 -State Listen -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }"
if %errorlevel%==0 (
echo [dsh-memory] bridge already running on port 8766.
) else (
echo [dsh-memory] starting bridge...
start "dsh-memory bridge" /D "%ROOT%" cmd /c "title dsh-memory bridge && node bridge\server.js & pause"
ping -n 3 127.0.0.1 >nul
powershell -NoProfile -Command "if (Get-NetTCPConnection -LocalPort 8766 -State Listen -ErrorAction SilentlyContinue) { Write-Host '[dsh-memory] bridge started.' } else { Write-Host '[dsh-memory] bridge NOT started. Is node in PATH? Check the bridge window.' }"
)
endlocal

12
scripts/stop-dsh-memory.cmd

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
@echo off
rem dsh-memory - stop bridge (graceful via /shutdown) and clean up leftover dsh headless processes
setlocal
set "ROOT=%~dp0.."
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
"$cfgPath = Join-Path (Split-Path -Parent '%~dp0') 'bridge\config.json';" ^
"try { $cfg = Get-Content $cfgPath -Raw -Encoding UTF8 | ConvertFrom-Json; $port = if ($cfg.port) { $cfg.port } else { 8766 }; Invoke-RestMethod -Method Post -Uri ('http://127.0.0.1:' + $port + '/shutdown') -Headers @{ Authorization = ('Bearer ' + $cfg.token) } -TimeoutSec 5 | Out-Null; Write-Host '[dsh-memory] bridge stopped.' } catch { Write-Host '[dsh-memory] bridge not reachable (already stopped?)' };" ^
"$dsh = Get-CimInstance Win32_Process -Filter \"Name='node.exe'\" | Where-Object { $_.CommandLine -like '*@deepseek-ai*dsh*bin.js*--profile headless*' };" ^
"foreach ($p in $dsh) { Write-Host ('[dsh-memory] killing leftover dsh headless pid ' + $p.ProcessId); Stop-Process -Id $p.ProcessId -Force -ErrorAction SilentlyContinue }"
endlocal
Loading…
Cancel
Save