Some checks failed
CI / Typecheck & Lint (pull_request) Failing after 0s
Adds a live cost ticker (⚡ ~N sats) visible in the top-right HUD during active paid interactions. The ticker appears when a work invoice is issued with the estimated cost, updates to the final charged amount when the job completes, and auto-hides after 5s. Changes: - event-bus.ts: add CostEvent type { cost:update, jobId, sats, phase, isFinal } - events.ts: translate cost:update bus events → cost_update WS messages - jobs.ts: emit cost:update with estimated sats on invoice creation, and again with actual sats when work completes (paid jobs only) - sessions.ts: emit cost:update with debitedSats after each session request - ui.js: add showCostTicker/updateCostTicker/hideCostTicker (fixed-position HUD badge) - websocket.js: handle cost_update messages, drive the cost ticker Fixes #68 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
42 lines
1.5 KiB
TypeScript
42 lines
1.5 KiB
TypeScript
import { EventEmitter } from "events";
|
|
|
|
export type JobEvent =
|
|
| { type: "job:state"; jobId: string; state: string }
|
|
| { type: "job:paid"; jobId: string; invoiceType: "eval" | "work" }
|
|
| { type: "job:completed"; jobId: string; result: string }
|
|
| { type: "job:failed"; jobId: string; reason: string };
|
|
|
|
export type SessionEvent =
|
|
| { type: "session:state"; sessionId: string; state: string }
|
|
| { type: "session:paid"; sessionId: string; amountSats: number }
|
|
| { type: "session:balance"; sessionId: string; balanceSats: number };
|
|
|
|
export type DebateEvent =
|
|
| { type: "debate:argument"; jobId: string; agent: "Beta-A" | "Beta-B"; position: "accept" | "reject"; argument: string }
|
|
| { type: "debate:verdict"; jobId: string; accepted: boolean; reason: string };
|
|
|
|
export type CostEvent =
|
|
| { type: "cost:update"; jobId: string; sats: number; phase: "eval" | "work" | "session"; isFinal: boolean };
|
|
|
|
export type BusEvent = JobEvent | SessionEvent | DebateEvent | CostEvent;
|
|
|
|
class EventBus extends EventEmitter {
|
|
emit(event: "bus", data: BusEvent): boolean;
|
|
emit(event: string, ...args: unknown[]): boolean {
|
|
return super.emit(event, ...args);
|
|
}
|
|
|
|
on(event: "bus", listener: (data: BusEvent) => void): this;
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
on(event: string, listener: (...args: any[]) => void): this {
|
|
return super.on(event, listener);
|
|
}
|
|
|
|
publish(data: BusEvent): void {
|
|
this.emit("bus", data);
|
|
}
|
|
}
|
|
|
|
export const eventBus = new EventBus();
|
|
eventBus.setMaxListeners(256);
|