You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

241 lines
14 KiB

'use strict';
(function () {
var TOKEN_KEY = 'dshmem-bridge-token'
var ENABLED_KEY = 'dshmem-log-enabled'
var BASE = 'http' + ':' + '//' + '127.0.0.1' + ':' + '8766'
var CHUNK = 700
var K_RATIO = 3.1; var CONTEXT_LIMIT = 131072; var charsAccum = 0
var seen = Object.create(null)
var cfg = null
var lastAccum = null; var injectBlock = ''; var injectLoaded = false; var injectErr = ''; var injectBlock = ''; var injectLoaded = false; var injectErr = ''
var SEP = String.fromCharCode(10) + String.fromCharCode(10); try { window.addEventListener('dshmem:chat-change', function () { charsAccum = 0; lastAccum = null; seen = Object.create(null); try { loadInjectBlock() } catch (e) { } }) } catch (e) {}
function hash(s) {
var h1 = 5381
var h2 = 52711
for (var i = 0; i !== s.length; i++) {
var c = s.charCodeAt(i)
h1 = (((h1 * 33) ^ c) >>> 0)
h2 = (((h2 * 31) ^ c) >>> 0)
}
return h1.toString(36) + h2.toString(36)
}
function today() {
var d = new Date()
var m = String(d.getMonth() + 1)
var dd = String(d.getDate())
if (m.length === 1) m = '0' + m
if (dd.length === 1) dd = '0' + dd
return d.getFullYear() + '-' + m + '-' + dd
}
function chunk(text) {
var out = []
var n = Math.ceil(text.length / CHUNK) || 1
for (var i = 0; i !== n; i++) out.push(text.slice(i * CHUNK, (i + 1) * CHUNK))
return out
}
function isInj(text) {
if (text.indexOf('MEMORY_SYSTEM') !== -1) return true
if (text.indexOf('DSM:memory_calls') !== -1) return true
if (text.indexOf('DSM:memory_write') !== -1) return true
if (text.indexOf('dsmemory') !== -1) return true
return false
}
function linesFor(mid, role, text, ts) {
var cs = chunk(text)
var arr = []
for (var i = 0; i !== cs.length; i++) {
var obj = {
mid: mid,
part: i,
total: cs.length,
role: role,
ts: ts,
inj: isInj(text),
text: cs[i]
}
arr.push(JSON.stringify(obj))
}
return arr
}
function requestConfig() {
return new Promise(function (resolve) {
var done = false
function onCfg(e) {
if (done) return
done = true
try {
cfg = JSON.parse(e.detail)
} catch (err) {
cfg = null
}
window.removeEventListener('dshmem:log-config', onCfg)
resolve(cfg)
}
window.addEventListener('dshmem:log-config', onCfg)
try {
window.dispatchEvent(new CustomEvent('dshmem:log-request'))
} catch (err) {
done = true
resolve(null)
}
setTimeout(function () {
if (done) return
done = true
window.removeEventListener('dshmem:log-config', onCfg)
resolve(null)
}, 2000)
})
}
function __saveReg(d) { try { if (!cfg || !cfg.token || !d) return; var ck = 'chat' + '_session' + '_id'; var cid = d[ck] ? String(d[ck]) : ''; if (!cid) return; var SL = String.fromCharCode(47); var url = BASE + SL + 'memory' + SL + 'chats'; var hh = { 'Content-Type': 'application/json', Authorization: 'Bearer ' + cfg.token }; var ent = { injected: true, injectedAt: Date.now(), ctxChars: 0 }; var payload = { chatId: cid, entry: ent }; var rb = JSON.stringify(payload); fetch(url, { method: 'POST', headers: hh, body: rb }).then(function (r) { return r.json() }).then(function (j) { if (j && j.ok) { console.log('[chat-log] registry saved') } else { console.log('[chat-log] registry failed') } }).catch(function () { console.log('[chat-log] registry error') }) } catch (e) { } }
function loadInjectFromFile() { if (!cfg || !cfg.token) return; var SL = String.fromCharCode(47); var url = BASE + SL + 'tool'; var hh = { 'Content-Type': 'application/json', Authorization: 'Bearer ' + cfg.token }; var body = { tool: 'dsh_read', args: { path: '_ai_notes/INJECT_2026-11-02.md' } }; fetch(url, { method: 'POST', headers: hh, body: JSON.stringify(body) }).then(function (r) { return r.json() }).then(function (j) { if (j && j.ok && j.data && j.data.content) { var raw = String(j.data.content); var ls = raw.split(String.fromCharCode(10)); var out = []; for (var i = 0; i < ls.length; i++) { var L = ls[i]; var p = L.indexOf(' | '); var ok = false; if (p > 0 && p < 8) { ok = true; for (var k = 0; k < p; k++) { var c = L.charCodeAt(k); if (c !== 32 && (c < 48 || c > 57)) { ok = false; break } } } if (ok) { out.push(L.slice(p + 3)) } else { out.push(L) } } injectBlock = out.join(String.fromCharCode(10)); injectLoaded = true; console.log('[chat-log] inject from file ' + injectBlock.length) } else { injectErr = 'file_read_failed'; console.log('[chat-log] fallback file read failed') } }).catch(function () { injectErr = 'file_fetch_error'; console.log('[chat-log] fallback fetch error') }) }
function loadInjectBlock() { if (!cfg || !cfg.token) return; var SL = String.fromCharCode(47); var url = BASE + SL + 'memory' + SL + 'state'; var hh = { Authorization: 'Bearer ' + cfg.token }; fetch(url, { method: 'GET', headers: hh }).then(function (r) { return r.json() }).then(function (j) { var out = ''; try { if (j && j.ok && j.data && Array.isArray(j.data.skills) && j.data.skills.length > 0) { var parts = []; for (var k = 0; k < j.data.skills.length; k++) { var sk = j.data.skills[k]; if (sk && typeof sk.content === 'string' && sk.content) { parts.push(sk.content) } } out = parts.join(String.fromCharCode(10) + String.fromCharCode(10)) } } catch (e) { out = '' } if (out.length > 0) { injectBlock = out; injectLoaded = true; console.log('[chat-log] inject from skills ' + injectBlock.length) } else { console.log('[chat-log] skills empty, fallback to file'); loadInjectFromFile() } }).catch(function () { console.log('[chat-log] skills fetch error, fallback'); loadInjectFromFile() }) }
function sendLines(file, lines) {
if (!cfg || !cfg.token) return Promise.resolve(false)
var headers = { 'Content-Type': 'application/json' }
headers.Authorization = 'Bearer ' + cfg.token
return fetch(BASE + '/log/append', {
method: 'POST',
headers: headers,
body: JSON.stringify({ file: file, lines: lines })
}).then(function (r) { return r.ok }).catch(function () { return false })
}
function extractAssistant(sse) {
if (!sse) return ''
var out = []
var blocks = sse.split(SEP); evTotal = blocks.length
for (var i = 0; i !== blocks.length; i++) {
var block = blocks[i]
var idx = block.indexOf('data: ')
if (idx === -1) continue
var json = block.slice(idx + 6).trim()
if (!json) continue
var o = null
try { o = JSON.parse(json) } catch (e) { continue }
if (!o || typeof o !== 'object') continue
if (o.p) { evP = evP + 1; continue }
if (typeof o.v !== 'string') continue
if (Object.keys(o).length !== 1) continue
evV = evV + 1; out.push(o.v)
}
return out.join('')
}
function extractAccum(sse) {
if (!sse) return null
var idx = sse.lastIndexOf('accumulated_token_usage')
if (idx === -1) return null
var tail = sse.slice(idx, idx + 80)
var start = -1
var i = 0
while (i < tail.length) {
var ch = tail.charCodeAt(i)
if (ch >= 48 && ch <= 57) {
start = i
break
}
i++
}
if (start === -1) return null
var end = start
while (end < tail.length) {
var cd = tail.charCodeAt(end)
if (cd < 48 || cd > 57) break
end++
}
if (end === start) return null
return parseInt(tail.slice(start, end), 10)
}
function process(entry) {
if (!entry || !entry.url) return
if (entry.url.indexOf('chat/completion') === -1) return
if (!cfg) {
requestConfig().then(function () { process(entry) })
return
}
if (!cfg.enabled) return
var messages = []; var chatId = ''; var reqKeys = ''
try {
var req = JSON.parse(entry.body); if (req) reqKeys = Object.keys(req).join(','); var ck = 'chat' + '_session' + '_id'; if (req) chatId = String(req[ck] || ''); var pk = 'parent' + '_message' + '_id'; var pid = (req && req[pk] !== undefined) ? String(req[pk]) : 'absent'
if (req && Array.isArray(req.messages)) messages = req.messages
else if (req && typeof req.prompt === 'string' && req.prompt) messages = [{ role: 'user', content: req.prompt }]
} catch (e) { return }
var assistant = ''; var sseCalls = 0; var respLen = 0; var respHead = ''; var hasData = 0; var evTotal = 0; var evV = 0; var evP = 0; var fetchTotal = 0;
respLen = (entry.resp || '').length; respHead = String(entry.resp || '').slice(0, 60); hasData = (entry.resp && entry.resp.indexOf('data: ') !== -1) ? 1 : 0;
try { assistant = extractAssistant(entry.resp || '') } catch (e) { }; try { var LB1 = String.fromCharCode(10214); var RB1 = String.fromCharCode(10215); var marker = LB1 + 'DSH' + RB1; var pos = 0; while (true) { var hit = assistant.indexOf(marker, pos); if (hit === -1) break; sseCalls = sseCalls + 1; pos = hit + marker.length } } catch (e) { } var all = messages.slice()
if (assistant) all.push({ role: 'assistant', content: assistant })
var file = today() + '.jsonl'
var lines = []
for (var i = 0; i !== all.length; i++) {
var msg = all[i]
if (!msg || typeof msg.content !== 'string') continue
var text = msg.content
if (!text) continue
var role = msg.role || 'user'
var h = hash(role + ':' + text)
if (seen[h]) continue
seen[h] = true
var ls = linesFor(role + '-' + h, role, text, Date.now())
for (var j = 0; j !== ls.length; j++) lines.push(ls[j])
}
var accum = null
try { accum = extractAccum(entry.resp || '') } catch (e) { accum = null }
if (accum !== null) {
var delta = 0
if (lastAccum !== null && accum > lastAccum) delta = accum - lastAccum
lastAccum = accum
var ctxChars = 0
for (var m = 0; m !== all.length; m++) {
if (all[m] && typeof all[m].content === 'string') ctxChars += all[m].content.length
}
charsAccum += ctxChars; var meta = {
mid: 'meta-' + Date.now(),
part: 0,
total: 1,
role: 'meta',
ts: Date.now(),
inj: false,
text: 'metrics',
accum: accum,
delta: delta,
chars: ctxChars,
chat_id: chatId, parent_id: pid, sse_calls: sseCalls, sse_len: assistant.length, resp_len: respLen, has_data: hasData, resp_head: respHead, fetch_total: fetchTotal, ev_total: evTotal, ev_v: evV, ev_p: evP, sse_len: assistant.length, req_keys: reqKeys, est_tok: Math.round(ctxChars / K_RATIO), ctx_chars: charsAccum, ctx_tok: Math.round(charsAccum / K_RATIO), ctx_pct: Math.round(charsAccum / K_RATIO * 1000 / CONTEXT_LIMIT) / 10
}
lines.push(JSON.stringify(meta)); try { window.dispatchEvent(new CustomEvent('dshmem:metrics', { detail: JSON.stringify({ accum: accum, delta: delta, chars: ctxChars, est_tok: Math.round(ctxChars / K_RATIO), ctx_chars: charsAccum, ctx_tok: Math.round(charsAccum / K_RATIO), ctx_pct: Math.round(charsAccum / K_RATIO * 1000 / CONTEXT_LIMIT) / 10 }) })) } catch (e) { }
}
if (!lines.length) return
sendLines(file, lines).then(function (ok) {
if (ok) console.log('[chat-log] saved', lines.length)
})
}
try { var __ofF1 = window.fetch; window.fetch = function (u, o) { try { var __us1 = (typeof u === 'string') ? u : ((u && u.url) ? String(u.url) : ''); if (__us1.indexOf('chat/completion') !== -1) { fetchTotal = fetchTotal + 1 } } catch (e) { } return __ofF1.apply(this, arguments) } } catch (e) { }
var origOpen = XMLHttpRequest.prototype.open
var origSend = XMLHttpRequest.prototype.send
XMLHttpRequest.prototype.open = function (m, u) {
this.__chatUrl = String(u || '')
return origOpen.apply(this, arguments)
}
XMLHttpRequest.prototype.send = function (body) {
var self = this
var bodyStr = typeof body === 'string' ? body : ''; var __didInject = false; if (self.__chatUrl && self.__chatUrl.indexOf('chat/completion') !== -1) { try { var __d = JSON.parse(bodyStr); var __pk = 'parent' + '_message' + '_id'; var __raw = (__d && __d[__pk] !== undefined) ? __d[__pk] : 'absent'; var __isFirst = (__raw === null || __raw === 'absent'); if (__isFirst && injectLoaded && injectBlock.length > 0) { if (typeof __d.prompt === 'string' && __d.prompt) { __d.prompt = injectBlock + String.fromCharCode(10) + String.fromCharCode(10) + __d.prompt; bodyStr = JSON.stringify(__d); __didInject = true } else if (Array.isArray(__d.messages) && __d.messages.length > 0) { var __last = __d.messages[__d.messages.length - 1]; if (__last && typeof __last.content === 'string') { __last.content = injectBlock + String.fromCharCode(10) + String.fromCharCode(10) + __last.content; bodyStr = JSON.stringify(__d); __didInject = true } } } if (__didInject) { __saveReg(__d) } console.log('[chat-log] send diag parent=' + String(__raw) + ' block=' + injectBlock.length + ' loaded=' + injectLoaded + ' injected=' + __didInject) } catch (e) { console.log('[chat-log] inject error ' + String(e)) } }
this.addEventListener('load', function () {
try {
process({ url: self.__chatUrl, body: bodyStr, resp: self.responseText || '' })
} catch (e) {
console.warn('[chat-log] error', String(e))
}
})
if (__didInject) return origSend.call(this, bodyStr); return origSend.apply(this, arguments)
}
requestConfig(); try { var __boot = Date.now(); var __nav = ''; try { var __ne = performance.getEntriesByType('navigation'); __nav = (__ne && __ne[0] && __ne[0].type) || 'unknown' } catch (e1) { __nav = 'err' } var __path = String(location.pathname || ''); var __cid = ''; var __parts = __path.split('/'); var __si = __parts.indexOf('s'); __cid = __si !== -1 && __parts[__si + 1] ? __parts[__si + 1] : ''; var __init = { mid: 'init-' + __boot, part: 0, total: 1, role: 'init', ts: __boot, inj: false, text: 'init', boot: __boot, nav: __nav, ready: document.readyState, path: __path, chat_id: __cid }; var __cfgReady = requestConfig(); __cfgReady.then(function (c) { if (!c || !c.token) return; loadInjectBlock(); var __h = { 'Content-Type': 'application/json' }; __h.Authorization = 'Bearer ' + c.token; fetch(BASE + '/log/append', { method: 'POST', headers: __h, body: JSON.stringify({ file: today() + '.jsonl', lines: [JSON.stringify(__init)] }) }).catch(function () { }) }); } catch (e2) { }
})()