@cesarus777/opencode-cgp 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ import { type SnapshotRpcPort } from "./snapshotserver.js";
2
+ import type { Plugin } from "@opencode/plugin";
3
+ import type { TelemetrySink } from "./types.js";
4
+ export interface Host {
5
+ rpc?: SnapshotRpcPort;
6
+ app: {
7
+ version: string;
8
+ };
9
+ options: unknown;
10
+ location: {
11
+ directory: string;
12
+ };
13
+ session: Pick<Plugin.Context["session"], "get" | "compact" | "hook">;
14
+ model: Pick<Plugin.Context["model"], "list">;
15
+ event: Plugin.Context["event"];
16
+ storage: Pick<Plugin.Context["storage"], "get" | "set">;
17
+ }
18
+ export declare function setup(ctx: Host, injectedSink?: TelemetrySink): Promise<() => Promise<void>>;
@@ -0,0 +1,2 @@
1
+ import type { Config } from "./types.js";
2
+ export declare function parseConfig(value?: unknown): Config;
@@ -0,0 +1,8 @@
1
+ export * from "./types.js";
2
+ export * from "./config.js";
3
+ export * from "./policy.js";
4
+ export * from "./monitor.js";
5
+ export * from "./scheduler.js";
6
+ export * from "./estimate.js";
7
+ export * from "./snapshot.js";
8
+ export * from "./family.js";
@@ -0,0 +1 @@
1
+ export declare function estimate(value: unknown, maxChars?: number): number | undefined;
@@ -0,0 +1,39 @@
1
+ import type { ContextSnapshot } from "./snapshot.js";
2
+ export type ExecutionStatus = "running" | "idle" | "completed" | "failed" | "unknown";
3
+ export interface SessionNode {
4
+ readonly sessionId: string;
5
+ readonly parentId?: string;
6
+ readonly agent?: string;
7
+ readonly model?: string;
8
+ readonly status: ExecutionStatus;
9
+ readonly interrupted?: boolean;
10
+ }
11
+ export interface GuardRow {
12
+ readonly node: SessionNode;
13
+ readonly snapshot?: ContextSnapshot;
14
+ readonly depth: number;
15
+ readonly current: boolean;
16
+ readonly freshness: "fresh" | "stale" | "missing" | "invalid";
17
+ readonly pressure: "normal" | "near" | "crossed" | "unknown";
18
+ readonly pressureRatio?: number;
19
+ readonly utilizationPercent?: number;
20
+ readonly triggerDeltaTokens?: number;
21
+ readonly hidden: number;
22
+ }
23
+ export declare function metric(snapshot: ContextSnapshot | undefined, now: number, staleMs: number): {
24
+ readonly triggerDeltaTokens?: number;
25
+ readonly utilizationPercent?: number;
26
+ readonly pressureRatio?: number;
27
+ readonly freshness: "fresh" | "stale" | "missing" | "invalid";
28
+ readonly pressure: "unknown" | "crossed" | "normal" | "near";
29
+ };
30
+ export declare function familyRows(nodes: readonly SessionNode[], snapshots: ReadonlyMap<string, ContextSnapshot>, current: string, now: number, staleMs: number, expanded?: ReadonlySet<string>, limit?: number, timing?: (id: string) => {
31
+ now: number;
32
+ staleMs: number;
33
+ }, stableOrder?: readonly string[]): GuardRow[];
34
+ export interface ExecutionEvidence {
35
+ readonly startedAt?: number;
36
+ readonly terminalAt?: number;
37
+ readonly outcome?: "succeeded" | "failed" | "interrupted";
38
+ }
39
+ export declare function executionStatus(known: boolean, nativeRunning: boolean, evidence: ExecutionEvidence): ExecutionStatus;
@@ -0,0 +1,3 @@
1
+ import { Plugin } from "@opencode/plugin";
2
+ declare const _default: Plugin.Plugin;
3
+ export default _default;
@@ -0,0 +1,20 @@
1
+ import { CompactionScheduler } from "./scheduler.js";
2
+ import { type BudgetController, type Config, type ContextUsage, type ContextUsageProvider, type Identity, type Measurement, type ModelLimits, type SessionState, type TelemetrySink, type Tokens } from "./types.js";
3
+ export declare function promptTokens(t: Tokens): number | undefined;
4
+ export declare class ContextMonitor implements ContextUsageProvider {
5
+ private readonly config;
6
+ readonly scheduler: CompactionScheduler;
7
+ private readonly sink;
8
+ private readonly now;
9
+ private readonly budget;
10
+ readonly sessions: Map<string, SessionState>;
11
+ private readonly resolver;
12
+ constructor(config: Config, scheduler: CompactionScheduler, sink: TelemetrySink, now?: () => number, budget?: BudgetController);
13
+ touch(identity: Identity, limits?: ModelLimits): SessionState | undefined;
14
+ accept(s: SessionState, sequence: number): boolean;
15
+ measure(s: SessionState, measurement: Measurement, cumulative?: Tokens): void;
16
+ evaluate(s: SessionState): void;
17
+ remove(id: string): void;
18
+ cleanup(): void;
19
+ getUsage(id: string): Promise<ContextUsage>;
20
+ }
@@ -0,0 +1,12 @@
1
+ import type { Config, Identity, Measurement, ModelLimits, Threshold, Decision } from "./types.js";
2
+ export declare function glob(pattern: string, text: string): boolean;
3
+ export declare class PolicyResolver {
4
+ private readonly config;
5
+ constructor(config: Config);
6
+ resolve(identity: Identity): {
7
+ threshold: Threshold;
8
+ policy: string;
9
+ };
10
+ }
11
+ export declare function usableInput(limits?: ModelLimits, reserve?: number): number | undefined;
12
+ export declare function evaluateThreshold(threshold: Threshold, measurement: Measurement | undefined, limits: ModelLimits | undefined, now: number, staleMs: number, model: string | undefined, policy: string, reserve?: number): Decision;
@@ -0,0 +1,22 @@
1
+ import type { CompactionState } from "./types.js";
2
+ export interface Recovery {
3
+ sessionId: string;
4
+ compaction: CompactionState;
5
+ sequence?: number;
6
+ }
7
+ export declare function decodeRecovery(v: unknown, max: number): Recovery[];
8
+ export declare function encodeRecovery(rows: Recovery[]): {
9
+ sessionId: string;
10
+ sequence: number;
11
+ compaction: {
12
+ requestId: string | null;
13
+ phase: import("./types.js").CompactionPhase;
14
+ armed: boolean;
15
+ count: number;
16
+ failures: number;
17
+ consecutiveFailures: number;
18
+ lastAttempt: number | null;
19
+ lastCompleted: number | null;
20
+ blockedReason: string | null;
21
+ };
22
+ }[];
@@ -0,0 +1,51 @@
1
+ import type { SnapshotBatch, SnapshotRead, SnapshotReadResult } from "./snapshot.js";
2
+ export declare const readSchema: {
3
+ type: "object";
4
+ properties: Record<string, object>;
5
+ required: string[];
6
+ additionalProperties: boolean;
7
+ };
8
+ export declare const batchSchema: {
9
+ type: "object";
10
+ properties: Record<string, object>;
11
+ required: string[];
12
+ additionalProperties: boolean;
13
+ };
14
+ export declare const resultSchema: {
15
+ type: "object";
16
+ properties: Record<string, object>;
17
+ required: string[];
18
+ additionalProperties: boolean;
19
+ };
20
+ export declare const monitorRpc: {
21
+ readonly id: "context-guard.monitor.v1";
22
+ readonly methods: {
23
+ readonly read: {
24
+ readonly input: {
25
+ type: "object";
26
+ properties: Record<string, object>;
27
+ required: string[];
28
+ additionalProperties: boolean;
29
+ };
30
+ readonly output: {
31
+ type: "object";
32
+ properties: Record<string, object>;
33
+ required: string[];
34
+ additionalProperties: boolean;
35
+ };
36
+ };
37
+ };
38
+ readonly events: {
39
+ readonly changed: {
40
+ readonly schema: {
41
+ type: "object";
42
+ properties: Record<string, object>;
43
+ required: string[];
44
+ additionalProperties: boolean;
45
+ };
46
+ };
47
+ };
48
+ };
49
+ export declare function isRead(value: unknown): value is SnapshotRead;
50
+ export declare function isBatch(value: unknown): value is SnapshotBatch;
51
+ export declare function isResult(value: unknown): value is SnapshotReadResult;
@@ -0,0 +1,18 @@
1
+ import type { CompactionPort, Config, SessionState, TelemetrySink } from "./types.js";
2
+ export declare class CompactionScheduler {
3
+ private readonly config;
4
+ private readonly port;
5
+ private readonly sink;
6
+ private readonly now;
7
+ private readonly id;
8
+ private stopped;
9
+ private readonly jobs;
10
+ constructor(config: Config, port: CompactionPort, sink: TelemetrySink, now?: () => number, id?: () => string);
11
+ consider(s: SessionState): void;
12
+ lifecycle(s: SessionState, event: "started" | "ended" | "failed", at: number): void;
13
+ measured(s: SessionState): void;
14
+ tick(s: SessionState): void;
15
+ private emit;
16
+ flush(): Promise<void>;
17
+ stop(): void;
18
+ }
@@ -0,0 +1,95 @@
1
+ import type { Config, SessionState, Measurement, ModelLimits, Threshold, Tokens, CompactionPhase } from "./types.js";
2
+ export interface ContextSnapshot {
3
+ readonly sessionId: string;
4
+ readonly revision: number;
5
+ readonly observedAt: number;
6
+ readonly parentId?: string;
7
+ readonly agent?: string;
8
+ readonly model?: string;
9
+ readonly measurement?: Readonly<Measurement>;
10
+ readonly limits?: Readonly<ModelLimits>;
11
+ readonly capacityTokens?: number;
12
+ readonly outputReserveTokens?: number;
13
+ /** Peak prompt tokens observed during monitor residency. */
14
+ readonly peakTokens?: number;
15
+ readonly policy: {
16
+ readonly id: string;
17
+ readonly configured: Readonly<Threshold>;
18
+ readonly triggerTokens?: number;
19
+ readonly comparison: ">=" | ">";
20
+ readonly reason: string;
21
+ readonly crossed: boolean;
22
+ };
23
+ readonly compaction: {
24
+ readonly phase: CompactionPhase;
25
+ /** Completed lifecycle events observed by the monitor, never admissions. */
26
+ readonly count?: number;
27
+ readonly armed: boolean;
28
+ readonly blockedReason?: string;
29
+ readonly lastAttempt?: number;
30
+ readonly lastCompleted?: number;
31
+ readonly cooldownUntil?: number;
32
+ };
33
+ readonly cumulative?: Readonly<Omit<Tokens, "cache">> & {
34
+ readonly cache: Readonly<Tokens["cache"]>;
35
+ };
36
+ readonly cumulativeScope: "session" | "unknown";
37
+ readonly lastObservedActive: boolean;
38
+ }
39
+ export interface MonitorHealth {
40
+ readonly enabled: boolean;
41
+ readonly mode: "observe" | "enforce";
42
+ readonly enforcement: "observing" | "available" | "suspended" | "disabled";
43
+ readonly reasons: readonly string[];
44
+ readonly staleMs: number;
45
+ readonly maxSessions: number;
46
+ }
47
+ export interface SnapshotBatch {
48
+ readonly schemaVersion: 1;
49
+ readonly epoch: string;
50
+ readonly sequence: number;
51
+ readonly generatedAt: number;
52
+ readonly health: MonitorHealth;
53
+ readonly upserts: readonly ContextSnapshot[];
54
+ readonly removed: readonly {
55
+ readonly sessionId: string;
56
+ readonly revision: number;
57
+ readonly reason: "deleted" | "evicted";
58
+ }[];
59
+ }
60
+ export interface SnapshotRead {
61
+ readonly schemaVersion: 1;
62
+ readonly sessionIds: readonly string[];
63
+ }
64
+ export interface SnapshotReadResult extends SnapshotBatch {
65
+ readonly unavailable: readonly {
66
+ readonly sessionId: string;
67
+ readonly reason: "not-monitored";
68
+ }[];
69
+ }
70
+ export declare function project(s: SessionState, config: Config, now: number, revision?: number): ContextSnapshot;
71
+ export declare class SnapshotStore {
72
+ private readonly config;
73
+ private readonly sessions;
74
+ private readonly now;
75
+ readonly epoch: string;
76
+ private sequence;
77
+ private revision;
78
+ private rows;
79
+ private deleted;
80
+ private dirty;
81
+ private listeners;
82
+ private healthKey;
83
+ private reasons;
84
+ constructor(config: Config, sessions: () => ReadonlyMap<string, SessionState>, now?: () => number, epoch?: string);
85
+ health(): MonitorHealth;
86
+ degrade(reason: "event-stream-gap" | "persistence-unavailable" | "capacity-exceeded" | "model-metadata-unavailable"): void;
87
+ recover(reason: "capacity-exceeded" | "model-metadata-unavailable"): void;
88
+ mark(id: string): void;
89
+ markAll(): void;
90
+ remove(id: string): void;
91
+ listen(fn: (batch: SnapshotBatch) => void): () => void;
92
+ private batch;
93
+ flush(): void;
94
+ read(input: SnapshotRead): SnapshotReadResult;
95
+ }
@@ -0,0 +1,7 @@
1
+ import type { RpcHandlers, RpcRegistration } from "@opencode/plugin/promise/rpc";
2
+ export interface SnapshotRpcPort {
3
+ register(definition: typeof monitorRpc, handlers: RpcHandlers<typeof monitorRpc>): Promise<RpcRegistration<typeof monitorRpc>>;
4
+ }
5
+ import { monitorRpc } from "./rpc.js";
6
+ import type { SnapshotStore } from "./snapshot.js";
7
+ export declare function serveSnapshots(rpc: SnapshotRpcPort | undefined, store: SnapshotStore): Promise<() => void>;
@@ -0,0 +1,17 @@
1
+ import type { Config, TelemetryEvent, TelemetrySink } from "./types.js";
2
+ export declare function defaultPath(directory: string): string;
3
+ export declare class JsonlTelemetrySink implements TelemetrySink {
4
+ readonly path: string;
5
+ private readonly config;
6
+ private pending;
7
+ private working;
8
+ private disabled;
9
+ private bytes;
10
+ private ready;
11
+ constructor(path: string, config: Config["telemetry"]);
12
+ emit(event: TelemetryEvent): void;
13
+ private kick;
14
+ private drain;
15
+ flush(): Promise<void>;
16
+ }
17
+ export declare function readJournal(path: string, maxBytes?: number): Promise<unknown[]>;
@@ -0,0 +1,10 @@
1
+ import type { Plugin } from "@opencode/plugin/tui";
2
+ import type { GuardRow } from "../family.js";
3
+ import type { GuardState } from "./state.js";
4
+ export declare function CompactSidebar(props: {
5
+ sessionID: string;
6
+ rows: readonly GuardRow[];
7
+ state: GuardState;
8
+ context: Plugin.Context;
9
+ width: number;
10
+ }): import("solid-js").JSX.Element;
@@ -0,0 +1,28 @@
1
+ import type { GuardRow } from "../family.js";
2
+ export declare function tokens(value: number | undefined): string;
3
+ export declare function columns(left: string, right: string, width: number): string[];
4
+ export declare function progress(ratio: number | undefined, width: number): string;
5
+ export interface MainSection {
6
+ readonly tone: "base" | "execution" | "pressure" | "measurement";
7
+ readonly lines: readonly string[];
8
+ }
9
+ export declare function mainSections(row: GuardRow | undefined, width: number, age: number): MainSection[];
10
+ export declare function mainLines(row: GuardRow | undefined, width: number, age: number): string[];
11
+ export declare const statusSymbol: {
12
+ readonly running: "●";
13
+ readonly idle: "◌";
14
+ readonly unknown: "◌";
15
+ readonly completed: "✓";
16
+ readonly failed: "✕";
17
+ };
18
+ export declare function agentHeading(row: GuardRow, width: number): string;
19
+ export declare function agentLines(row: GuardRow, width: number): string[];
20
+ export declare function subagentTree(rows: readonly GuardRow[], sessionID: string, collapsed: ReadonlySet<string>, hideCompleted: boolean, byPressure: boolean): {
21
+ all: GuardRow[];
22
+ visible: {
23
+ row: GuardRow;
24
+ depth: number;
25
+ hasChildren: boolean;
26
+ }[];
27
+ };
28
+ export declare function statistics(rows: readonly GuardRow[], sessionID: string, complete: boolean, width: number): string[];
@@ -0,0 +1,7 @@
1
+ import type { GuardRow } from "../family.js";
2
+ export declare function quantity(n: number | undefined): string;
3
+ export declare function cells(value: string): number;
4
+ export declare function clip(value: string, width: number): string;
5
+ export declare function rowLines(row: GuardRow, width: number): string[];
6
+ export declare function detailLines(row: GuardRow | undefined, width: number, expanded?: boolean, ageMs?: number): string[];
7
+ export declare function wrap(value: string, width: number): string[];
@@ -0,0 +1,18 @@
1
+ import type { OpenCodeClient, SessionInfo } from "@opencode/client";
2
+ interface Branch {
3
+ readonly id: string;
4
+ readonly depth: number;
5
+ readonly cursor?: string;
6
+ readonly cursors: readonly string[];
7
+ }
8
+ export interface Inventory {
9
+ readonly sessions: ReadonlyMap<string, SessionInfo>;
10
+ readonly complete: boolean;
11
+ readonly rootId: string;
12
+ readonly pages: number;
13
+ readonly pending: readonly Branch[];
14
+ readonly scanned: ReadonlySet<string>;
15
+ readonly damaged: boolean;
16
+ }
17
+ export declare function discoverFamily(client: Pick<OpenCodeClient, "session">, currentId: string, signal: AbortSignal, cached: (id: string) => SessionInfo | undefined, maxNodes?: number, previous?: Inventory): Promise<Inventory>;
18
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { Plugin } from "@opencode/plugin/tui";
2
+ import type { PanelInput } from "@opencode/plugin/tui/context";
3
+ import type { GuardState } from "./state.js";
4
+ export declare function GuardPanel(props: {
5
+ input: PanelInput;
6
+ state: GuardState;
7
+ context: Plugin.Context;
8
+ }): import("solid-js").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import type { Plugin } from "@opencode/plugin/tui";
2
+ import type { GuardState } from "./state.js";
3
+ import type { GuardRow } from "../family.js";
4
+ export declare function GuardView(props: {
5
+ sessionID: string;
6
+ state: GuardState;
7
+ context: Plugin.Context;
8
+ width: number;
9
+ expanded?: boolean;
10
+ family?: readonly GuardRow[];
11
+ selectedId?: string;
12
+ inspectId?: string | undefined;
13
+ }): import("solid-js").JSX.Element;
@@ -0,0 +1,29 @@
1
+ import type { Plugin } from "@opencode/plugin/tui";
2
+ export declare function createGuardState(context: Plugin.Context): {
3
+ version: import("solid-js").Accessor<number>;
4
+ acquire: (id: string) => {
5
+ update(next: string): void;
6
+ release(): void;
7
+ };
8
+ rows: (stableOrder?: readonly string[], allDescendants?: boolean) => import("../family.js").GuardRow[];
9
+ dispose: () => void;
10
+ age(id: string): number;
11
+ health(): import("../snapshot.js").MonitorHealth | undefined;
12
+ connection(): "unavailable" | "loading" | "live" | "reconnecting" | "incompatible";
13
+ complete(): boolean;
14
+ refresh(): void;
15
+ loadMore(): void;
16
+ expand(id: string): void;
17
+ };
18
+ export type GuardState = ReturnType<typeof createGuardState>;
19
+ export declare function locationKey(location: {
20
+ directory: string;
21
+ workspaceID?: string;
22
+ }): string;
23
+ export declare function sameLocation(a: {
24
+ directory: string;
25
+ workspaceID?: string;
26
+ }, b: {
27
+ directory: string;
28
+ workspaceID?: string;
29
+ }): boolean;
@@ -0,0 +1,40 @@
1
+ import type { ContextSnapshot, MonitorHealth } from "../snapshot.js";
2
+ export interface SnapshotTransport {
3
+ read(location: string, ids: readonly string[], signal: AbortSignal): Promise<unknown>;
4
+ subscribe(location: string, signal: AbortSignal): AsyncIterable<unknown>;
5
+ }
6
+ export type Connection = "loading" | "live" | "reconnecting" | "unavailable" | "incompatible";
7
+ export declare class SnapshotClient {
8
+ private readonly transport;
9
+ private readonly changed;
10
+ private readonly elapsed;
11
+ readonly rows: Map<string, ContextSnapshot>;
12
+ health: MonitorHealth | undefined;
13
+ connection: Connection;
14
+ private epoch;
15
+ private sequence;
16
+ private revisions;
17
+ private baselines;
18
+ private controller;
19
+ private generation;
20
+ private ids;
21
+ private location;
22
+ private refreshTimer;
23
+ private reading;
24
+ private buffered;
25
+ private overflow;
26
+ private retryTimer;
27
+ private failures;
28
+ private serverAt;
29
+ private receivedAt;
30
+ private refreshAgain;
31
+ private subscriptionActive;
32
+ constructor(transport: SnapshotTransport, changed: () => void, elapsed?: () => number);
33
+ now(): number;
34
+ setIds(ids: readonly string[]): void;
35
+ start(location: string, ids: readonly string[]): void;
36
+ private merge;
37
+ refresh(): Promise<void>;
38
+ private supervise;
39
+ stop(): void;
40
+ }
@@ -0,0 +1,3 @@
1
+ import { Plugin } from "@opencode/plugin/tui";
2
+ declare const _default: Plugin.Definition;
3
+ export default _default;
@@ -0,0 +1,142 @@
1
+ export type Threshold = {
2
+ type: "tokens" | "ratio" | "remaining";
3
+ value: number;
4
+ };
5
+ export interface Match {
6
+ role?: "main" | "subagent";
7
+ model?: string;
8
+ agent?: string;
9
+ }
10
+ export interface Policy {
11
+ match: Match;
12
+ threshold: Threshold;
13
+ }
14
+ export interface Config {
15
+ enabled: boolean;
16
+ mode: "observe" | "enforce";
17
+ defaults: {
18
+ threshold: Threshold;
19
+ };
20
+ policies: Policy[];
21
+ safety: {
22
+ cooldownMs: number;
23
+ minReclaimTokens: number;
24
+ maxConsecutiveFailures: number;
25
+ pendingTimeoutMs: number;
26
+ staleMs: number;
27
+ maxSessions: number;
28
+ sessionTtlMs: number;
29
+ outputReserveTokens?: number;
30
+ };
31
+ telemetry: {
32
+ enabled: boolean;
33
+ jsonl: boolean;
34
+ path?: string;
35
+ maxBytes: number;
36
+ };
37
+ }
38
+ export interface ModelLimits {
39
+ context: number;
40
+ input?: number;
41
+ output: number;
42
+ }
43
+ export interface Identity {
44
+ sessionId: string;
45
+ parentId?: string;
46
+ agent?: string;
47
+ model?: string;
48
+ }
49
+ export interface Tokens {
50
+ input: number;
51
+ output: number;
52
+ reasoning: number;
53
+ cache: {
54
+ read: number;
55
+ write: number;
56
+ };
57
+ }
58
+ export interface Measurement {
59
+ tokens: number;
60
+ at: number;
61
+ model: string;
62
+ requestId?: string;
63
+ provenance: "provider-normalized" | "serialized-estimate";
64
+ confidence: "reported" | "approximate";
65
+ scope: "completed-request" | "prepared-request";
66
+ }
67
+ export interface ContextUsage {
68
+ current?: Measurement;
69
+ cumulative?: Tokens;
70
+ cumulativeScope: "session" | "unknown";
71
+ peak: number;
72
+ modelRequests: number;
73
+ toolCalls: number;
74
+ countersSince: number;
75
+ }
76
+ export interface ContextUsageProvider {
77
+ getUsage(sessionId: string): Promise<ContextUsage>;
78
+ }
79
+ export type CompactionPhase = "idle" | "requesting" | "accepted" | "running" | "awaiting-measurement" | "blocked" | "uncertain";
80
+ export interface CompactionState {
81
+ phase: CompactionPhase;
82
+ count: number;
83
+ failures: number;
84
+ consecutiveFailures: number;
85
+ lastAttempt?: number;
86
+ lastCompleted?: number;
87
+ before?: number | undefined;
88
+ beforeModel?: string | undefined;
89
+ beforeConfidence?: Measurement["confidence"] | undefined;
90
+ requestId?: string;
91
+ blockedReason?: string;
92
+ armed: boolean;
93
+ }
94
+ export interface Decision {
95
+ crossed: boolean;
96
+ reason: string;
97
+ policy: string;
98
+ threshold?: number;
99
+ budget?: number;
100
+ percentage?: number;
101
+ }
102
+ export interface SessionState extends Identity {
103
+ usage: ContextUsage;
104
+ compaction: CompactionState;
105
+ limits?: ModelLimits;
106
+ decision?: Decision;
107
+ lastSeen: number;
108
+ lastExecutionEnd?: number;
109
+ sequence: number;
110
+ active: boolean;
111
+ }
112
+ export type BudgetAction = {
113
+ type: "continue";
114
+ } | {
115
+ type: "warn" | "compact" | "checkpoint" | "rotate" | "stop";
116
+ reason: string;
117
+ };
118
+ export interface BudgetInput {
119
+ session: Readonly<SessionState>;
120
+ now: number;
121
+ elapsedMs: number;
122
+ depth?: number;
123
+ inheritedTokenBudget?: number;
124
+ }
125
+ export interface BudgetController {
126
+ evaluate(input: BudgetInput): BudgetAction;
127
+ }
128
+ export declare class NoopBudgetController implements BudgetController {
129
+ evaluate(_input: BudgetInput): BudgetAction;
130
+ }
131
+ export interface TelemetryEvent {
132
+ time: number;
133
+ type: string;
134
+ session?: SessionState;
135
+ detail?: string;
136
+ }
137
+ export interface TelemetrySink {
138
+ emit(event: TelemetryEvent): void;
139
+ }
140
+ export interface CompactionPort {
141
+ compact(sessionId: string, requestId: string): Promise<void>;
142
+ }