@bridge4dev/runner 0.46.1 → 0.48.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.
- package/README.md +44 -2
- package/dist/adapters/claude.js +6 -2
- package/dist/adapters/codex.js +7 -4
- package/dist/agent-auto-update.d.ts +75 -0
- package/dist/agent-auto-update.js +134 -0
- package/dist/agent-binary.d.ts +48 -0
- package/dist/agent-binary.js +55 -0
- package/dist/agent-cleanup.d.ts +78 -0
- package/dist/agent-cleanup.js +184 -0
- package/dist/agent-install.d.ts +140 -0
- package/dist/agent-install.js +475 -0
- package/dist/agent-registry.d.ts +223 -0
- package/dist/agent-registry.js +131 -0
- package/dist/agent-versions.d.ts +93 -0
- package/dist/agent-versions.js +157 -0
- package/dist/auth-relay.d.ts +9 -1
- package/dist/auth-relay.js +3 -1
- package/dist/commit-message.js +5 -0
- package/dist/config.d.ts +44 -4
- package/dist/config.js +43 -0
- package/dist/index.js +46 -12
- package/dist/levels.d.ts +49 -0
- package/dist/levels.js +51 -0
- package/dist/protocol.d.ts +155 -28
- package/dist/protocol.js +33 -1
- package/dist/recipe-schema.d.ts +12 -12
- package/dist/self-update.d.ts +14 -0
- package/dist/self-update.js +45 -13
- package/dist/supervisor.d.ts +186 -2
- package/dist/supervisor.js +503 -14
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -15,12 +15,12 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
15
15
|
name: z.ZodString;
|
|
16
16
|
token: z.ZodString;
|
|
17
17
|
}, "strip", z.ZodTypeAny, {
|
|
18
|
-
id: string;
|
|
19
18
|
name: string;
|
|
19
|
+
id: string;
|
|
20
20
|
token: string;
|
|
21
21
|
}, {
|
|
22
|
-
id: string;
|
|
23
22
|
name: string;
|
|
23
|
+
id: string;
|
|
24
24
|
token: string;
|
|
25
25
|
}>;
|
|
26
26
|
mcp: z.ZodOptional<z.ZodObject<{
|
|
@@ -83,14 +83,36 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
83
83
|
}, {
|
|
84
84
|
enabled?: boolean | undefined;
|
|
85
85
|
}>>;
|
|
86
|
+
/**
|
|
87
|
+
* #371: the machine owner's veto over installing agent CLIs.
|
|
88
|
+
*
|
|
89
|
+
* `agent_install` downloads and runs a vendor's software on this server on a
|
|
90
|
+
* word from the dashboard. The payload is not the server's to choose — the
|
|
91
|
+
* package and the installer URL are compiled into this runner — but «which
|
|
92
|
+
* version of Codex runs here» is still a decision about somebody else's
|
|
93
|
+
* machine, and its owner gets the last word on whether we may make it at all.
|
|
94
|
+
*
|
|
95
|
+
* Same shape and same rule as `[verify]` and `[checkpoints]`:
|
|
96
|
+
* `install_enabled = false` means the capability is not announced and
|
|
97
|
+
* `agent_install` is not offered as a command, so the dashboard draws no
|
|
98
|
+
* button rather than a button that answers «refused». The server cannot
|
|
99
|
+
* switch it back on: it is read from a root-owned file, here.
|
|
100
|
+
*/
|
|
101
|
+
agents: z.ZodOptional<z.ZodObject<{
|
|
102
|
+
install_enabled: z.ZodDefault<z.ZodBoolean>;
|
|
103
|
+
}, "strip", z.ZodTypeAny, {
|
|
104
|
+
install_enabled: boolean;
|
|
105
|
+
}, {
|
|
106
|
+
install_enabled?: boolean | undefined;
|
|
107
|
+
}>>;
|
|
86
108
|
}, "strip", z.ZodTypeAny, {
|
|
87
109
|
api: {
|
|
88
110
|
url: string;
|
|
89
111
|
ws_url: string;
|
|
90
112
|
};
|
|
91
113
|
server: {
|
|
92
|
-
id: string;
|
|
93
114
|
name: string;
|
|
115
|
+
id: string;
|
|
94
116
|
token: string;
|
|
95
117
|
};
|
|
96
118
|
checkpoints?: {
|
|
@@ -109,14 +131,17 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
109
131
|
verify?: {
|
|
110
132
|
enabled: boolean;
|
|
111
133
|
} | undefined;
|
|
134
|
+
agents?: {
|
|
135
|
+
install_enabled: boolean;
|
|
136
|
+
} | undefined;
|
|
112
137
|
}, {
|
|
113
138
|
api: {
|
|
114
139
|
url: string;
|
|
115
140
|
ws_url: string;
|
|
116
141
|
};
|
|
117
142
|
server: {
|
|
118
|
-
id: string;
|
|
119
143
|
name: string;
|
|
144
|
+
id: string;
|
|
120
145
|
token: string;
|
|
121
146
|
};
|
|
122
147
|
checkpoints?: {
|
|
@@ -135,10 +160,25 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
135
160
|
verify?: {
|
|
136
161
|
enabled?: boolean | undefined;
|
|
137
162
|
} | undefined;
|
|
163
|
+
agents?: {
|
|
164
|
+
install_enabled?: boolean | undefined;
|
|
165
|
+
} | undefined;
|
|
138
166
|
}>;
|
|
139
167
|
export type RunnerConfig = z.infer<typeof ConfigSchema>;
|
|
140
168
|
export declare function loadConfig(): RunnerConfig | null;
|
|
141
169
|
export declare function requireConfig(): RunnerConfig;
|
|
170
|
+
/**
|
|
171
|
+
* The config a re-pairing should write: the new server's identity, everything
|
|
172
|
+
* else as the machine's owner left it.
|
|
173
|
+
*
|
|
174
|
+
* Lives here, beside the schema, rather than inline in `cmdPair` — because the
|
|
175
|
+
* failure mode is a section that is simply not mentioned. `saveConfig` re-parses
|
|
176
|
+
* and rewrites the whole file, so a key forgotten in this merge is not «left
|
|
177
|
+
* alone», it is **deleted from disk**: re-pairing a machine would silently lift
|
|
178
|
+
* the owner's veto over installing agents, or move Codex back to a shared
|
|
179
|
+
* credential store. Every optional section of `ConfigSchema` must be listed.
|
|
180
|
+
*/
|
|
181
|
+
export declare function mergeIntoPairedConfig(existing: RunnerConfig | null, paired: Pick<RunnerConfig, 'api' | 'server'>): RunnerConfig;
|
|
142
182
|
export declare function saveConfig(config: RunnerConfig): void;
|
|
143
183
|
export {};
|
|
144
184
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.js
CHANGED
|
@@ -76,6 +76,26 @@ const ConfigSchema = z.object({
|
|
|
76
76
|
enabled: z.boolean().default(true),
|
|
77
77
|
})
|
|
78
78
|
.optional(),
|
|
79
|
+
/**
|
|
80
|
+
* #371: the machine owner's veto over installing agent CLIs.
|
|
81
|
+
*
|
|
82
|
+
* `agent_install` downloads and runs a vendor's software on this server on a
|
|
83
|
+
* word from the dashboard. The payload is not the server's to choose — the
|
|
84
|
+
* package and the installer URL are compiled into this runner — but «which
|
|
85
|
+
* version of Codex runs here» is still a decision about somebody else's
|
|
86
|
+
* machine, and its owner gets the last word on whether we may make it at all.
|
|
87
|
+
*
|
|
88
|
+
* Same shape and same rule as `[verify]` and `[checkpoints]`:
|
|
89
|
+
* `install_enabled = false` means the capability is not announced and
|
|
90
|
+
* `agent_install` is not offered as a command, so the dashboard draws no
|
|
91
|
+
* button rather than a button that answers «refused». The server cannot
|
|
92
|
+
* switch it back on: it is read from a root-owned file, here.
|
|
93
|
+
*/
|
|
94
|
+
agents: z
|
|
95
|
+
.object({
|
|
96
|
+
install_enabled: z.boolean().default(true),
|
|
97
|
+
})
|
|
98
|
+
.optional(),
|
|
79
99
|
});
|
|
80
100
|
export function loadConfig() {
|
|
81
101
|
const file = configFilePath();
|
|
@@ -91,6 +111,29 @@ export function requireConfig() {
|
|
|
91
111
|
}
|
|
92
112
|
return config;
|
|
93
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* The config a re-pairing should write: the new server's identity, everything
|
|
116
|
+
* else as the machine's owner left it.
|
|
117
|
+
*
|
|
118
|
+
* Lives here, beside the schema, rather than inline in `cmdPair` — because the
|
|
119
|
+
* failure mode is a section that is simply not mentioned. `saveConfig` re-parses
|
|
120
|
+
* and rewrites the whole file, so a key forgotten in this merge is not «left
|
|
121
|
+
* alone», it is **deleted from disk**: re-pairing a machine would silently lift
|
|
122
|
+
* the owner's veto over installing agents, or move Codex back to a shared
|
|
123
|
+
* credential store. Every optional section of `ConfigSchema` must be listed.
|
|
124
|
+
*/
|
|
125
|
+
export function mergeIntoPairedConfig(existing, paired) {
|
|
126
|
+
return {
|
|
127
|
+
api: paired.api,
|
|
128
|
+
server: paired.server,
|
|
129
|
+
...(existing?.mcp ? { mcp: existing.mcp } : {}),
|
|
130
|
+
...(existing?.codex ? { codex: existing.codex } : {}),
|
|
131
|
+
...(existing?.limits ? { limits: existing.limits } : {}),
|
|
132
|
+
...(existing?.verify ? { verify: existing.verify } : {}),
|
|
133
|
+
...(existing?.checkpoints ? { checkpoints: existing.checkpoints } : {}),
|
|
134
|
+
...(existing?.agents ? { agents: existing.agents } : {}),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
94
137
|
export function saveConfig(config) {
|
|
95
138
|
ConfigSchema.parse(config);
|
|
96
139
|
const dir = configDir();
|
package/dist/index.js
CHANGED
|
@@ -8,8 +8,8 @@ import { promisify } from 'node:util';
|
|
|
8
8
|
import { ClaudeAdapter } from './adapters/claude.js';
|
|
9
9
|
import { CodexAdapter } from './adapters/codex.js';
|
|
10
10
|
import { ensureCodexHome } from './adapters/codex-home.js';
|
|
11
|
-
import {
|
|
12
|
-
import { loadConfig, requireConfig, saveConfig } from './config.js';
|
|
11
|
+
import { sessionClaudePath } from './agent-binary.js';
|
|
12
|
+
import { loadConfig, mergeIntoPairedConfig, requireConfig, saveConfig, } from './config.js';
|
|
13
13
|
import { log } from './log.js';
|
|
14
14
|
import { installIsWritable, installPrefixFor, isSupervisedProcess, manualUpdateCommand, resolveInstalledPackageDir, } from './self-update.js';
|
|
15
15
|
import { applyStoredClaudeToken } from './agent-auth.js';
|
|
@@ -63,6 +63,11 @@ function argValue(args, flag) {
|
|
|
63
63
|
* create a session that immediately fails.
|
|
64
64
|
*/
|
|
65
65
|
function installedAgents() {
|
|
66
|
+
// #371: this list and the `agent_versions` frame answer about the same file
|
|
67
|
+
// as of C2 — `sessionClaudePath()` follows `USE_BUNDLED_CLAUDE`, so while the
|
|
68
|
+
// constant is true it still reports the SDK's bundled binary (today's
|
|
69
|
+
// behaviour, unchanged), and the moment it flips both speak about the system
|
|
70
|
+
// `claude` on PATH. One switch, not two lists drifting apart.
|
|
66
71
|
const agents = [];
|
|
67
72
|
// Claude comes with the Agent SDK — but «comes with» is a claim about THIS
|
|
68
73
|
// installation, not a law (ticket #225). The CLI is an optional platform
|
|
@@ -70,7 +75,7 @@ function installedAgents() {
|
|
|
70
75
|
// Claude, accepts Claude sessions, and cannot start a single one. Reported as
|
|
71
76
|
// measured, so the dashboard greys the agent out instead of offering a
|
|
72
77
|
// session that dies before its first word.
|
|
73
|
-
if (
|
|
78
|
+
if (sessionClaudePath())
|
|
74
79
|
agents.push('claude');
|
|
75
80
|
if (hasExecutable('codex'))
|
|
76
81
|
agents.push('codex');
|
|
@@ -138,6 +143,7 @@ function runnerCapabilities(apiUrlOverride) {
|
|
|
138
143
|
const verifyEnabled = config?.verify?.enabled !== false;
|
|
139
144
|
// Ticket #126: the same veto, for restore points. Default on.
|
|
140
145
|
const checkpointsEnabled = config?.checkpoints?.enabled !== false;
|
|
146
|
+
const agentInstallEnabled = config?.agents?.install_enabled !== false;
|
|
141
147
|
return {
|
|
142
148
|
agents: installedAgents(),
|
|
143
149
|
git: true,
|
|
@@ -186,6 +192,27 @@ function runnerCapabilities(apiUrlOverride) {
|
|
|
186
192
|
claude: hasExecutable('claude'),
|
|
187
193
|
codex: hasExecutable('codex'),
|
|
188
194
|
},
|
|
195
|
+
/**
|
|
196
|
+
* This build measures agent versions and can be told to install one (0.47.0).
|
|
197
|
+
*
|
|
198
|
+
* One flag for both halves on purpose. The dashboard needs to know whether
|
|
199
|
+
* an empty version row means «not installed» or «this runner cannot say»,
|
|
200
|
+
* and the API needs to know whether `agent_install` will be understood —
|
|
201
|
+
* and there is no build where one is true and the other is not.
|
|
202
|
+
*
|
|
203
|
+
* Kept out of the version data itself: capabilities are computed once per
|
|
204
|
+
* process and replayed on every reconnect (`ws-client.ts`), so a version
|
|
205
|
+
* put here would freeze at daemon start. Versions travel in the
|
|
206
|
+
* `agent_versions` frame.
|
|
207
|
+
*
|
|
208
|
+
* Withheld entirely when the machine owner said no (`[agents]
|
|
209
|
+
* install_enabled = false`), like `[verify]` and `[checkpoints]`: a control
|
|
210
|
+
* that is switched off must not look like a control that is broken. The
|
|
211
|
+
* measuring half keeps working — reading a version is not installing one.
|
|
212
|
+
*/
|
|
213
|
+
...(agentInstallEnabled
|
|
214
|
+
? { agentInstall: true }
|
|
215
|
+
: { agentInstallBlocked: 'disabled-by-config' }),
|
|
189
216
|
/**
|
|
190
217
|
* Where npm put this package, and the command that updates it here
|
|
191
218
|
* (0.27.0).
|
|
@@ -437,6 +464,7 @@ function runnerCapabilities(apiUrlOverride) {
|
|
|
437
464
|
...(verifyEnabled
|
|
438
465
|
? ['verify_start', 'verify_status', 'verify_cancel', 'preview_checkout', 'preview_stop']
|
|
439
466
|
: []),
|
|
467
|
+
...(agentInstallEnabled ? ['agent_install'] : []),
|
|
440
468
|
],
|
|
441
469
|
};
|
|
442
470
|
}
|
|
@@ -464,15 +492,14 @@ async function cmdPair(args) {
|
|
|
464
492
|
fail(`pairing failed (HTTP ${response.status}): ${body?.error?.message ?? 'unknown error'}. ` +
|
|
465
493
|
'The code is one-time and expires in 10 minutes — generate a fresh one in the dashboard if needed.');
|
|
466
494
|
}
|
|
467
|
-
|
|
468
|
-
|
|
495
|
+
// Everything the machine's owner wrote by hand survives the re-pairing —
|
|
496
|
+
// `saveConfig` rewrites the whole file, so a section not carried across is a
|
|
497
|
+
// section deleted. The rule lives in `config.ts` beside the schema it has to
|
|
498
|
+
// keep up with, and is tested there.
|
|
499
|
+
const config = mergeIntoPairedConfig(loadConfig(), {
|
|
469
500
|
api: { url: apiUrl, ws_url: body.data.wsUrl },
|
|
470
501
|
server: { id: body.data.serverId, name: body.data.serverName, token: body.data.token },
|
|
471
|
-
|
|
472
|
-
// Carry settings the user wrote by hand — saveConfig re-parses through the
|
|
473
|
-
// schema, so a section dropped here is a section deleted from disk.
|
|
474
|
-
...(existing?.codex ? { codex: existing.codex } : {}),
|
|
475
|
-
};
|
|
502
|
+
});
|
|
476
503
|
saveConfig(config);
|
|
477
504
|
print(`Paired as "${body.data.serverName}" (server ${body.data.serverId}).`);
|
|
478
505
|
print('Start the daemon with: devbridge-runner install-service (or: devbridge-runner daemon)');
|
|
@@ -708,6 +735,7 @@ async function cmdDaemon() {
|
|
|
708
735
|
// frame from an API that has not noticed still cannot start a run.
|
|
709
736
|
verifyEnabled: config.verify?.enabled !== false,
|
|
710
737
|
checkpointsEnabled: config.checkpoints?.enabled !== false,
|
|
738
|
+
agentInstallEnabled: config.agents?.install_enabled !== false,
|
|
711
739
|
apiUrl: config.api.url,
|
|
712
740
|
// Used to fetch the files a user attaches to a message (session 10) — the
|
|
713
741
|
// same token the WS connection authenticates with, never passed onwards.
|
|
@@ -1062,13 +1090,19 @@ async function agentChecks() {
|
|
|
1062
1090
|
checks.push({
|
|
1063
1091
|
ok: cliPresent.claude,
|
|
1064
1092
|
name: 'claude cli',
|
|
1093
|
+
// Since 0.47.0 this is not a warning about signing in — it is «no Claude
|
|
1094
|
+
// sessions on this machine at all». The bundled binary is switched off
|
|
1095
|
+
// (`USE_BUNDLED_CLAUDE`), so the CLI on PATH is the one every session runs.
|
|
1065
1096
|
detail: cliPresent.claude
|
|
1066
1097
|
? `on ${me.user}'s PATH`
|
|
1067
|
-
: `not installed for ${me.user} — sessions
|
|
1098
|
+
: `not installed for ${me.user} — Claude sessions cannot start on this server`,
|
|
1068
1099
|
...(cliPresent.claude
|
|
1069
1100
|
? {}
|
|
1070
1101
|
: {
|
|
1071
|
-
|
|
1102
|
+
// The dashboard is the way in (Р9): it picks the version, checks the
|
|
1103
|
+
// disk first and puts the old binary back if the new one will not run.
|
|
1104
|
+
// The command stays for a machine nobody can reach the dashboard from.
|
|
1105
|
+
fix: `press «Install» on the Claude row of this server's card in DevBridge — or, by hand: sudo -iu ${me.user} sh -lc 'curl -fsSL https://claude.ai/install.sh | bash'`,
|
|
1072
1106
|
}),
|
|
1073
1107
|
});
|
|
1074
1108
|
// Codex is optional: plenty of machines only ever run Claude sessions, and a
|
package/dist/levels.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mirror of the `#region level-events-mirror` block in
|
|
3
|
+
* `packages/shared/src/constants/realtime.ts` – the DevBridge side is the
|
|
4
|
+
* source of truth, exactly like `agent-registry.ts` mirrors the agent registry
|
|
5
|
+
* and `protocol.ts` mirrors the API's wire types.
|
|
6
|
+
*
|
|
7
|
+
* Copied rather than imported on purpose: this package is published to npm on
|
|
8
|
+
* its own and installed by users who have no DevBridge workspace, so a
|
|
9
|
+
* `@devbridge/shared` import would make the published tarball unresolvable.
|
|
10
|
+
*
|
|
11
|
+
* CHECKED: `levels.test.ts` reads both files and compares the region between
|
|
12
|
+
* the markers character by character. Edit the shared file first, then paste
|
|
13
|
+
* the region here – nothing but the region, and nothing of the region left out.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Level signals on the dev-session stream – frames that carry a whole current
|
|
17
|
+
* value rather than a step of the conversation (#366).
|
|
18
|
+
*
|
|
19
|
+
* `agent_tasks` (#113), `context_usage` and `rate_limits` (#279) are LEVELS:
|
|
20
|
+
* every frame replaces the previous one, so a dropped frame costs freshness and
|
|
21
|
+
* never correctness. In production they were 61 % of every Codex session's
|
|
22
|
+
* rows (57 008 + 56 591 of ~185 000, 05.09.2026) while drawing not one line in
|
|
23
|
+
* the transcript – and each one re-rendered the whole page. So they are treated
|
|
24
|
+
* differently at every hop, and this block is the one place that says how:
|
|
25
|
+
*
|
|
26
|
+
* - the runner sends one only when the value moved (the thresholds below);
|
|
27
|
+
* - the API publishes it as a META frame (no `id:`) and never stores a row;
|
|
28
|
+
* - the dashboard keeps it beside the feed, never in it.
|
|
29
|
+
*
|
|
30
|
+
* Mirrored verbatim into `packages/runner/src/levels.ts` – the runner cannot
|
|
31
|
+
* import this package (it is published to npm on its own). `levels.test.ts`
|
|
32
|
+
* compares the two regions character by character.
|
|
33
|
+
*/
|
|
34
|
+
export declare const LEVEL_EVENT_TYPES: readonly ["agent_tasks", "context_usage", "rate_limits"];
|
|
35
|
+
/**
|
|
36
|
+
* A context-meter move smaller than BOTH of these is not worth a frame. The
|
|
37
|
+
* same pair gates the API's mirror onto the session row, so the ring a reload
|
|
38
|
+
* draws from the row and the ring the live frame draws agree to the percent.
|
|
39
|
+
*/
|
|
40
|
+
export declare const CONTEXT_USAGE_MIN_DELTA_TOKENS = 2000;
|
|
41
|
+
export declare const CONTEXT_USAGE_MIN_DELTA_RATIO = 0.01;
|
|
42
|
+
/**
|
|
43
|
+
* An unchanged plan-usage snapshot is re-sent no more often than this. It is
|
|
44
|
+
* re-sent at all because the limits panel dates its figure by ARRIVAL
|
|
45
|
+
* («updated 12 min ago»): silence would read as staleness. Three minutes is
|
|
46
|
+
* the interval the Claude adapter already probes `/usage` at.
|
|
47
|
+
*/
|
|
48
|
+
export declare const RATE_LIMITS_RESEND_INTERVAL_MS: number;
|
|
49
|
+
//# sourceMappingURL=levels.d.ts.map
|
package/dist/levels.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mirror of the `#region level-events-mirror` block in
|
|
3
|
+
* `packages/shared/src/constants/realtime.ts` – the DevBridge side is the
|
|
4
|
+
* source of truth, exactly like `agent-registry.ts` mirrors the agent registry
|
|
5
|
+
* and `protocol.ts` mirrors the API's wire types.
|
|
6
|
+
*
|
|
7
|
+
* Copied rather than imported on purpose: this package is published to npm on
|
|
8
|
+
* its own and installed by users who have no DevBridge workspace, so a
|
|
9
|
+
* `@devbridge/shared` import would make the published tarball unresolvable.
|
|
10
|
+
*
|
|
11
|
+
* CHECKED: `levels.test.ts` reads both files and compares the region between
|
|
12
|
+
* the markers character by character. Edit the shared file first, then paste
|
|
13
|
+
* the region here – nothing but the region, and nothing of the region left out.
|
|
14
|
+
*/
|
|
15
|
+
// #region level-events-mirror
|
|
16
|
+
/**
|
|
17
|
+
* Level signals on the dev-session stream – frames that carry a whole current
|
|
18
|
+
* value rather than a step of the conversation (#366).
|
|
19
|
+
*
|
|
20
|
+
* `agent_tasks` (#113), `context_usage` and `rate_limits` (#279) are LEVELS:
|
|
21
|
+
* every frame replaces the previous one, so a dropped frame costs freshness and
|
|
22
|
+
* never correctness. In production they were 61 % of every Codex session's
|
|
23
|
+
* rows (57 008 + 56 591 of ~185 000, 05.09.2026) while drawing not one line in
|
|
24
|
+
* the transcript – and each one re-rendered the whole page. So they are treated
|
|
25
|
+
* differently at every hop, and this block is the one place that says how:
|
|
26
|
+
*
|
|
27
|
+
* - the runner sends one only when the value moved (the thresholds below);
|
|
28
|
+
* - the API publishes it as a META frame (no `id:`) and never stores a row;
|
|
29
|
+
* - the dashboard keeps it beside the feed, never in it.
|
|
30
|
+
*
|
|
31
|
+
* Mirrored verbatim into `packages/runner/src/levels.ts` – the runner cannot
|
|
32
|
+
* import this package (it is published to npm on its own). `levels.test.ts`
|
|
33
|
+
* compares the two regions character by character.
|
|
34
|
+
*/
|
|
35
|
+
export const LEVEL_EVENT_TYPES = ['agent_tasks', 'context_usage', 'rate_limits'];
|
|
36
|
+
/**
|
|
37
|
+
* A context-meter move smaller than BOTH of these is not worth a frame. The
|
|
38
|
+
* same pair gates the API's mirror onto the session row, so the ring a reload
|
|
39
|
+
* draws from the row and the ring the live frame draws agree to the percent.
|
|
40
|
+
*/
|
|
41
|
+
export const CONTEXT_USAGE_MIN_DELTA_TOKENS = 2_000;
|
|
42
|
+
export const CONTEXT_USAGE_MIN_DELTA_RATIO = 0.01;
|
|
43
|
+
/**
|
|
44
|
+
* An unchanged plan-usage snapshot is re-sent no more often than this. It is
|
|
45
|
+
* re-sent at all because the limits panel dates its figure by ARRIVAL
|
|
46
|
+
* («updated 12 min ago»): silence would read as staleness. Three minutes is
|
|
47
|
+
* the interval the Claude adapter already probes `/usage` at.
|
|
48
|
+
*/
|
|
49
|
+
export const RATE_LIMITS_RESEND_INTERVAL_MS = 3 * 60 * 1000;
|
|
50
|
+
// #endregion level-events-mirror
|
|
51
|
+
//# sourceMappingURL=levels.js.map
|