Esqueleto inicial: sabia-core + sabia-cli + UI local, OpenWolf
- sabia-core: descoberta de interfaces, controle de modo monitor/canal via iw (ponte até ter nl80211 nativo), captura crua 802.11 via AF_PACKET (sem libpcap), parsing de radiotap e quadros de gerenciamento (beacon/probe/EAPOL), agregação em tabela de APs/ clientes, escrita de .pcap, trilha de auditoria encadeada por hash, auto-atualização via GitHub releases (curl, sem dependências de rede extras) - sabia-cli: `sabia iface`, `sabia scan`, `sabia update`, `sabia audit-verify`, `sabia ui` (servidor local + navegador, protegido por token, mesma filosofia do Guará) - OpenWolf inicializado para memória de projeto entre agentes
This commit is contained in:
commit
e989413018
76 files changed
+8386
No files matched your search
@@ -0,0 +1,42 @@
|
||||
import { withFileLock, HOOK_LOCK_BUDGET_MS } from "./anatomy-lock.js"
|
||||
import * as fs from "node:fs"
|
||||
import * as path from "node:path"
|
||||
import * as crypto from "node:crypto"
|
||||
|
||||
/** Persist only usage metadata; never transcript text or private reasoning. */
|
||||
export function recordUsage(directory: string, info: any): void {
|
||||
if (info?.role !== "assistant" || !info.tokens || !info.id || !info.sessionID) return
|
||||
const dir = path.join(directory, ".wolf", "usage", "opencode")
|
||||
fs.mkdirSync(dir, { recursive: true })
|
||||
const id = crypto.createHash("sha256").update(`${info.sessionID}:${info.id}`).digest("hex")
|
||||
const file = path.join(dir, id + ".json")
|
||||
const tmp = file + "." + crypto.randomUUID() + ".tmp"
|
||||
const message = { id: info.id, sessionID: info.sessionID, role: info.role, providerID: info.providerID, modelID: info.modelID, tokens: info.tokens, time: info.time }
|
||||
const committed = withFileLock(file + ".lock", HOOK_LOCK_BUDGET_MS, () => {
|
||||
try {
|
||||
const previous = JSON.parse(fs.readFileSync(file,"utf8"))?.message
|
||||
if (previous?.time?.completed && !info.time?.completed) return true
|
||||
if ((previous?.time?.completed ?? 0) > (info.time?.completed ?? 0)) return true
|
||||
} catch {}
|
||||
try {
|
||||
const fd = fs.openSync(tmp, "wx", 0o600)
|
||||
try { fs.writeFileSync(fd, JSON.stringify({ version: 1, directory, message })); fs.fsyncSync(fd) } finally { fs.closeSync(fd) }
|
||||
fs.renameSync(tmp, file)
|
||||
} finally { try { fs.unlinkSync(tmp) } catch {} }
|
||||
return true
|
||||
})
|
||||
if (!committed) throw new Error("OpenCode usage busy; session reconciliation will retry")
|
||||
}
|
||||
|
||||
/** Read-only SDK backfill recovers usage from before plugin installation. */
|
||||
export async function reconcileOpenCode(directory: string, client: any, sessionId?: string): Promise<void> {
|
||||
const unwrap = (response: any) => response?.data ?? response;
|
||||
const sessions = sessionId ? [unwrap(await client.session.get({path:{id:sessionId}}))] : unwrap(await client.session.list({query:{directory}}));
|
||||
if (!Array.isArray(sessions)) throw new Error("Unsupported OpenCode session list response");
|
||||
for (const session of sessions) {
|
||||
if (typeof session?.id !== "string" || typeof session.directory !== "string" || path.resolve(session.directory) !== path.resolve(directory)) continue;
|
||||
const messages = unwrap(await client.session.messages({path:{id:session.id},query:{directory}}));
|
||||
if (!Array.isArray(messages)) throw new Error("Unsupported OpenCode messages response");
|
||||
for (const message of messages) recordUsage(directory,message.info);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user