first commit
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Wire protocol shared between the daemon and the web app.
|
||||
*
|
||||
* NOTE: web/src/protocol.ts is a copy of this file. Keep the two in sync — they are
|
||||
* duplicated rather than shared because the server compiles under NodeNext while the web
|
||||
* app compiles under a bundler resolution, and a single rootDir cannot span both.
|
||||
*/
|
||||
|
||||
export type EventKind =
|
||||
| "session_start"
|
||||
| "session_end"
|
||||
| "prompt"
|
||||
| "tool_start"
|
||||
| "tool_end"
|
||||
| "tool_fail"
|
||||
| "permission_denied"
|
||||
| "turn_end"
|
||||
| "turn_error"
|
||||
| "notification"
|
||||
| "subagent_start"
|
||||
| "subagent_end"
|
||||
| "compact"
|
||||
| "approval_request"
|
||||
| "approval_allowed"
|
||||
| "approval_denied"
|
||||
| "approval_expired";
|
||||
|
||||
export type SessionState = "working" | "idle" | "waiting" | "error" | "ended";
|
||||
|
||||
export interface GlanceEvent {
|
||||
id: number;
|
||||
ts: number;
|
||||
sessionId: string;
|
||||
kind: EventKind;
|
||||
/** Tool name, for tool-shaped events. */
|
||||
tool?: string;
|
||||
/** One-line human summary, already truncated and redacted. */
|
||||
title: string;
|
||||
/** Optional second line, e.g. a file path or an error message. */
|
||||
detail?: string;
|
||||
durationMs?: number;
|
||||
}
|
||||
|
||||
export interface SessionView {
|
||||
id: string;
|
||||
/** Basename of the workspace root — what you actually recognise on a phone. */
|
||||
label: string;
|
||||
cwd: string;
|
||||
state: SessionState;
|
||||
startedAt: number;
|
||||
lastActivity: number;
|
||||
lastPrompt?: string;
|
||||
currentTool?: { name: string; title: string; startedAt: number };
|
||||
counts: { tools: number; failures: number; denials: number };
|
||||
}
|
||||
|
||||
export interface PendingApproval {
|
||||
id: string;
|
||||
sessionId: string;
|
||||
sessionLabel: string;
|
||||
tool: string;
|
||||
title: string;
|
||||
detail?: string;
|
||||
createdAt: number;
|
||||
expiresAt: number;
|
||||
}
|
||||
|
||||
export type ApprovalMode = "off" | "risky" | "all";
|
||||
|
||||
export interface ApprovalSettings {
|
||||
mode: ApprovalMode;
|
||||
riskyPattern: string;
|
||||
timeoutMs: number;
|
||||
/** Skip gating entirely when no browser is streaming, so an unwatched agent never stalls. */
|
||||
requireWatcher: boolean;
|
||||
/** What to do when nobody answers in time. Allow keeps the agent moving; deny is stricter. */
|
||||
onTimeout: "allow" | "deny";
|
||||
}
|
||||
|
||||
export interface Snapshot {
|
||||
now: number;
|
||||
version: string;
|
||||
sessions: SessionView[];
|
||||
events: GlanceEvent[];
|
||||
pending: PendingApproval[];
|
||||
approval: ApprovalSettings;
|
||||
}
|
||||
|
||||
export interface DeviceInfo {
|
||||
id: string;
|
||||
label: string;
|
||||
createdAt: number;
|
||||
lastUsedAt?: number;
|
||||
}
|
||||
|
||||
/** Everything the app needs before it knows whether you are signed in. */
|
||||
export interface GateInfo {
|
||||
authenticated: boolean;
|
||||
/** False when no passkey has been enrolled yet — the app then asks for an enrolment code. */
|
||||
enrolled: boolean;
|
||||
/** True while a one-time enrolment code minted by `glance enroll` is still valid. */
|
||||
enrollmentOpen: boolean;
|
||||
version: string;
|
||||
deviceLabel?: string;
|
||||
/** The WebAuthn RP ID in force. Shown so a hostname mismatch is diagnosable from the phone. */
|
||||
rpId?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user