@bridge4dev/runner 0.57.0 → 0.58.2
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/dist/adapters/claude.js +23 -4
- package/dist/adapters/codex-protocol.js +6 -1
- package/dist/adapters/codex.js +11 -2
- package/dist/adapters/types.js +14 -0
- package/dist/cage-authority.d.ts +118 -0
- package/dist/cage-authority.js +241 -0
- package/dist/config.d.ts +83 -5
- package/dist/config.js +59 -1
- package/dist/daemon-lock.d.ts +43 -0
- package/dist/daemon-lock.js +107 -0
- package/dist/host-load.d.ts +9 -0
- package/dist/host-load.js +9 -0
- package/dist/index.js +222 -20
- package/dist/policy.d.ts +9 -0
- package/dist/policy.js +71 -1
- package/dist/protocol.d.ts +43 -27
- package/dist/recipe-schema.d.ts +12 -12
- package/dist/regex-guard.js +6 -6
- package/dist/self-update.js +22 -1
- package/dist/service-unit.d.ts +35 -3
- package/dist/service-unit.js +82 -5
- package/dist/session-allocator.d.ts +259 -0
- package/dist/session-allocator.js +492 -0
- package/dist/session-cage.d.ts +229 -2
- package/dist/session-cage.js +590 -40
- package/dist/session-limits.d.ts +71 -0
- package/dist/session-limits.js +93 -0
- package/dist/session-stall.d.ts +353 -0
- package/dist/session-stall.js +760 -0
- package/dist/supervisor.d.ts +223 -33
- package/dist/supervisor.js +845 -94
- package/dist/systemd-memory.js +2 -5
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/policy.js
CHANGED
|
@@ -802,7 +802,9 @@ export function evaluateGitPolicy(command, ctx) {
|
|
|
802
802
|
if (policy.pushBanned) {
|
|
803
803
|
return {
|
|
804
804
|
decision: 'deny',
|
|
805
|
-
reason:
|
|
805
|
+
reason:
|
|
806
|
+
// eslint-disable-next-line @devbridge/no-cyrillic-ui-text -- quotes the Russian NAME of a project setting; it has to match the dashboard word for word (#269 leaves it alone on purpose).
|
|
807
|
+
'git push is not allowed — a human presses «Push» in the Git panel. (This project has «Принудительно запретить push» switched on.)',
|
|
806
808
|
};
|
|
807
809
|
}
|
|
808
810
|
// Everything below exists only once pushing is permitted. With the shipped
|
|
@@ -1173,6 +1175,46 @@ export function effectiveTrust(trustMode, mode) {
|
|
|
1173
1175
|
// ask / plan — at most NORMAL, never AUTO.
|
|
1174
1176
|
return trustMode === 'AUTO' ? 'NORMAL' : trustMode;
|
|
1175
1177
|
}
|
|
1178
|
+
/**
|
|
1179
|
+
* The largest Node heap this command line asks for, in bytes — or null when it
|
|
1180
|
+
* asks for none.
|
|
1181
|
+
*
|
|
1182
|
+
* Both spellings systemd-era Node accepts (`--max-old-space-size=N` and
|
|
1183
|
+
* `--max_old_space_size N`), anywhere on the line: the flag arrives through
|
|
1184
|
+
* `NODE_OPTIONS=`, through `node --…`, and through a `pnpm` script that passes
|
|
1185
|
+
* it on, and it is the NUMBER that matters, not who wrote it.
|
|
1186
|
+
*
|
|
1187
|
+
* The unit is megabytes, which is V8's own unit for the flag — a plain number,
|
|
1188
|
+
* never a suffix.
|
|
1189
|
+
*/
|
|
1190
|
+
/**
|
|
1191
|
+
* Commands that RUN node, as opposed to commands that merely mention it.
|
|
1192
|
+
*
|
|
1193
|
+
* The gate reads the heap flag out of a shell line, and a shell line is not one
|
|
1194
|
+
* command: `sed -i 's/--max-old-space-size=8192/…=3000/' package.json` contains
|
|
1195
|
+
* the flag and asks Node for nothing at all. Denying that was worse than a
|
|
1196
|
+
* nuisance — LOWERING the flag is exactly what the refusal tells the agent to
|
|
1197
|
+
* do, so the gate forbade its own remedy (#398 S7, B10).
|
|
1198
|
+
*/
|
|
1199
|
+
const NODE_RUNNERS = /(^|[\s;&|(])(sudo\s+)?(env\s+)?([A-Za-z_][A-Za-z0-9_]*=\S*\s+)*(node|nodejs|npm|npx|pnpm|yarn|bun|deno|tsx|ts-node|vitest|jest)([\s;&|)]|$)/;
|
|
1200
|
+
export function requestedHeapBytes(command) {
|
|
1201
|
+
let largest = null;
|
|
1202
|
+
for (const segment of commandSegments(command)) {
|
|
1203
|
+
// `NODE_OPTIONS=` carries the flag into whatever the segment starts, so it
|
|
1204
|
+
// counts on its own; otherwise the segment has to actually start a runtime.
|
|
1205
|
+
if (!/NODE_OPTIONS\s*=/.test(segment) && !NODE_RUNNERS.test(segment))
|
|
1206
|
+
continue;
|
|
1207
|
+
for (const match of segment.matchAll(/--?max[-_]old[-_]space[-_]size(?:\s*=\s*|\s+)(\d+)/gi)) {
|
|
1208
|
+
const mb = Number(match[1]);
|
|
1209
|
+
if (!Number.isSafeInteger(mb) || mb <= 0)
|
|
1210
|
+
continue;
|
|
1211
|
+
const bytes = mb * 1024 * 1024;
|
|
1212
|
+
if (largest === null || bytes > largest)
|
|
1213
|
+
largest = bytes;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
return largest;
|
|
1217
|
+
}
|
|
1176
1218
|
export function evaluateToolUse(toolName, input, ctx) {
|
|
1177
1219
|
// Read ONCE, here, and never `ctx.trustMode` again below: the branches that
|
|
1178
1220
|
// follow are the whole of layer 1, and a single one still reading the raw
|
|
@@ -1227,6 +1269,34 @@ export function evaluateToolUse(toolName, input, ctx) {
|
|
|
1227
1269
|
}
|
|
1228
1270
|
if (gitAsk)
|
|
1229
1271
|
return gitAsk;
|
|
1272
|
+
/**
|
|
1273
|
+
* A heap the cage cannot honour (#398 S5).
|
|
1274
|
+
*
|
|
1275
|
+
* Same position as everything above it and for the same reason: under AUTO
|
|
1276
|
+
* the Bash branch returns `allow` two lines down, and a rule placed below
|
|
1277
|
+
* that line is dead in the one mode most sessions run in. That mistake cost
|
|
1278
|
+
* a whole release once (session 13).
|
|
1279
|
+
*
|
|
1280
|
+
* From the incident this plan comes from: the agent raised its own heap to
|
|
1281
|
+
* 4 GB, then to 6 GB, against a wall of 4296 MB, and each time made things
|
|
1282
|
+
* worse — the ceiling is enforced OUTSIDE the process, so asking for more
|
|
1283
|
+
* only means being stopped sooner. The reason is written for the model to
|
|
1284
|
+
* read: it names the number and the way out.
|
|
1285
|
+
*/
|
|
1286
|
+
if (ctx.sessionMemoryMaxBytes !== undefined && ctx.sessionMemoryMaxBytes > 0) {
|
|
1287
|
+
for (const variant of [command, dequote(command)]) {
|
|
1288
|
+
const asked = requestedHeapBytes(variant);
|
|
1289
|
+
if (asked !== null && asked > ctx.sessionMemoryMaxBytes) {
|
|
1290
|
+
const mb = (bytes) => Math.round(bytes / (1024 * 1024));
|
|
1291
|
+
return {
|
|
1292
|
+
decision: 'deny',
|
|
1293
|
+
reason: `this command asks Node for a ${mb(asked)} MB heap, and this session cannot exceed ` +
|
|
1294
|
+
`${mb(ctx.sessionMemoryMaxBytes)} MB — the ceiling is enforced outside the process, so a ` +
|
|
1295
|
+
'bigger heap only means being stopped sooner. Lower --max-old-space-size, or split the work up',
|
|
1296
|
+
};
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1230
1300
|
if (trust === 'STRICT')
|
|
1231
1301
|
return { decision: 'ask', reason: 'strict mode' };
|
|
1232
1302
|
if (trust === 'AUTO')
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { HostLoadFrame } from './host-load.js';
|
|
3
|
+
import type { SessionLimitsFrame } from './session-limits.js';
|
|
3
4
|
export declare const SessionDescriptorSchema: z.ZodObject<{
|
|
4
5
|
id: z.ZodString;
|
|
5
6
|
kind: z.ZodEnum<["TICKET", "CHAT"]>;
|
|
@@ -102,8 +103,8 @@ export declare const SessionDescriptorSchema: z.ZodObject<{
|
|
|
102
103
|
budgetMinutes: z.ZodNullable<z.ZodNumber>;
|
|
103
104
|
}, "strip", z.ZodTypeAny, {
|
|
104
105
|
path: string;
|
|
105
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
106
106
|
id: string;
|
|
107
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
107
108
|
projectId: string;
|
|
108
109
|
budgetUsd: number | null;
|
|
109
110
|
budgetMinutes: number | null;
|
|
@@ -115,8 +116,8 @@ export declare const SessionDescriptorSchema: z.ZodObject<{
|
|
|
115
116
|
agentAllowDestructiveGit?: boolean | undefined;
|
|
116
117
|
}, {
|
|
117
118
|
path: string;
|
|
118
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
119
119
|
id: string;
|
|
120
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
120
121
|
projectId: string;
|
|
121
122
|
budgetUsd: number | null;
|
|
122
123
|
budgetMinutes: number | null;
|
|
@@ -208,8 +209,8 @@ export declare const SessionDescriptorSchema: z.ZodObject<{
|
|
|
208
209
|
}, "strip", z.ZodTypeAny, {
|
|
209
210
|
mode: "ask" | "plan" | "auto" | "full";
|
|
210
211
|
agent: "CLAUDE" | "CODEX";
|
|
211
|
-
id: string;
|
|
212
212
|
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
213
|
+
id: string;
|
|
213
214
|
kind: "TICKET" | "CHAT";
|
|
214
215
|
model: string | null;
|
|
215
216
|
effort: string | null;
|
|
@@ -222,8 +223,8 @@ export declare const SessionDescriptorSchema: z.ZodObject<{
|
|
|
222
223
|
extraBudgetMinutes: number | null;
|
|
223
224
|
workspace: {
|
|
224
225
|
path: string;
|
|
225
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
226
226
|
id: string;
|
|
227
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
227
228
|
projectId: string;
|
|
228
229
|
budgetUsd: number | null;
|
|
229
230
|
budgetMinutes: number | null;
|
|
@@ -256,15 +257,15 @@ export declare const SessionDescriptorSchema: z.ZodObject<{
|
|
|
256
257
|
} | undefined;
|
|
257
258
|
}, {
|
|
258
259
|
agent: "CLAUDE" | "CODEX";
|
|
259
|
-
id: string;
|
|
260
260
|
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
261
|
+
id: string;
|
|
261
262
|
kind: "TICKET" | "CHAT";
|
|
262
263
|
prompt: string;
|
|
263
264
|
providerSessionId: string | null;
|
|
264
265
|
workspace: {
|
|
265
266
|
path: string;
|
|
266
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
267
267
|
id: string;
|
|
268
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
268
269
|
projectId: string;
|
|
269
270
|
budgetUsd: number | null;
|
|
270
271
|
budgetMinutes: number | null;
|
|
@@ -520,8 +521,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
520
521
|
budgetMinutes: z.ZodNullable<z.ZodNumber>;
|
|
521
522
|
}, "strip", z.ZodTypeAny, {
|
|
522
523
|
path: string;
|
|
523
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
524
524
|
id: string;
|
|
525
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
525
526
|
projectId: string;
|
|
526
527
|
budgetUsd: number | null;
|
|
527
528
|
budgetMinutes: number | null;
|
|
@@ -533,8 +534,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
533
534
|
agentAllowDestructiveGit?: boolean | undefined;
|
|
534
535
|
}, {
|
|
535
536
|
path: string;
|
|
536
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
537
537
|
id: string;
|
|
538
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
538
539
|
projectId: string;
|
|
539
540
|
budgetUsd: number | null;
|
|
540
541
|
budgetMinutes: number | null;
|
|
@@ -626,8 +627,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
626
627
|
}, "strip", z.ZodTypeAny, {
|
|
627
628
|
mode: "ask" | "plan" | "auto" | "full";
|
|
628
629
|
agent: "CLAUDE" | "CODEX";
|
|
629
|
-
id: string;
|
|
630
630
|
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
631
|
+
id: string;
|
|
631
632
|
kind: "TICKET" | "CHAT";
|
|
632
633
|
model: string | null;
|
|
633
634
|
effort: string | null;
|
|
@@ -640,8 +641,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
640
641
|
extraBudgetMinutes: number | null;
|
|
641
642
|
workspace: {
|
|
642
643
|
path: string;
|
|
643
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
644
644
|
id: string;
|
|
645
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
645
646
|
projectId: string;
|
|
646
647
|
budgetUsd: number | null;
|
|
647
648
|
budgetMinutes: number | null;
|
|
@@ -674,15 +675,15 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
674
675
|
} | undefined;
|
|
675
676
|
}, {
|
|
676
677
|
agent: "CLAUDE" | "CODEX";
|
|
677
|
-
id: string;
|
|
678
678
|
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
679
|
+
id: string;
|
|
679
680
|
kind: "TICKET" | "CHAT";
|
|
680
681
|
prompt: string;
|
|
681
682
|
providerSessionId: string | null;
|
|
682
683
|
workspace: {
|
|
683
684
|
path: string;
|
|
684
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
685
685
|
id: string;
|
|
686
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
686
687
|
projectId: string;
|
|
687
688
|
budgetUsd: number | null;
|
|
688
689
|
budgetMinutes: number | null;
|
|
@@ -721,8 +722,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
721
722
|
sessions: {
|
|
722
723
|
mode: "ask" | "plan" | "auto" | "full";
|
|
723
724
|
agent: "CLAUDE" | "CODEX";
|
|
724
|
-
id: string;
|
|
725
725
|
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
726
|
+
id: string;
|
|
726
727
|
kind: "TICKET" | "CHAT";
|
|
727
728
|
model: string | null;
|
|
728
729
|
effort: string | null;
|
|
@@ -735,8 +736,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
735
736
|
extraBudgetMinutes: number | null;
|
|
736
737
|
workspace: {
|
|
737
738
|
path: string;
|
|
738
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
739
739
|
id: string;
|
|
740
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
740
741
|
projectId: string;
|
|
741
742
|
budgetUsd: number | null;
|
|
742
743
|
budgetMinutes: number | null;
|
|
@@ -775,15 +776,15 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
775
776
|
}, {
|
|
776
777
|
sessions: {
|
|
777
778
|
agent: "CLAUDE" | "CODEX";
|
|
778
|
-
id: string;
|
|
779
779
|
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
780
|
+
id: string;
|
|
780
781
|
kind: "TICKET" | "CHAT";
|
|
781
782
|
prompt: string;
|
|
782
783
|
providerSessionId: string | null;
|
|
783
784
|
workspace: {
|
|
784
785
|
path: string;
|
|
785
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
786
786
|
id: string;
|
|
787
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
787
788
|
projectId: string;
|
|
788
789
|
budgetUsd: number | null;
|
|
789
790
|
budgetMinutes: number | null;
|
|
@@ -953,8 +954,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
953
954
|
budgetMinutes: z.ZodNullable<z.ZodNumber>;
|
|
954
955
|
}, "strip", z.ZodTypeAny, {
|
|
955
956
|
path: string;
|
|
956
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
957
957
|
id: string;
|
|
958
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
958
959
|
projectId: string;
|
|
959
960
|
budgetUsd: number | null;
|
|
960
961
|
budgetMinutes: number | null;
|
|
@@ -966,8 +967,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
966
967
|
agentAllowDestructiveGit?: boolean | undefined;
|
|
967
968
|
}, {
|
|
968
969
|
path: string;
|
|
969
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
970
970
|
id: string;
|
|
971
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
971
972
|
projectId: string;
|
|
972
973
|
budgetUsd: number | null;
|
|
973
974
|
budgetMinutes: number | null;
|
|
@@ -1059,8 +1060,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1059
1060
|
}, "strip", z.ZodTypeAny, {
|
|
1060
1061
|
mode: "ask" | "plan" | "auto" | "full";
|
|
1061
1062
|
agent: "CLAUDE" | "CODEX";
|
|
1062
|
-
id: string;
|
|
1063
1063
|
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
1064
|
+
id: string;
|
|
1064
1065
|
kind: "TICKET" | "CHAT";
|
|
1065
1066
|
model: string | null;
|
|
1066
1067
|
effort: string | null;
|
|
@@ -1073,8 +1074,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1073
1074
|
extraBudgetMinutes: number | null;
|
|
1074
1075
|
workspace: {
|
|
1075
1076
|
path: string;
|
|
1076
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
1077
1077
|
id: string;
|
|
1078
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
1078
1079
|
projectId: string;
|
|
1079
1080
|
budgetUsd: number | null;
|
|
1080
1081
|
budgetMinutes: number | null;
|
|
@@ -1107,15 +1108,15 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1107
1108
|
} | undefined;
|
|
1108
1109
|
}, {
|
|
1109
1110
|
agent: "CLAUDE" | "CODEX";
|
|
1110
|
-
id: string;
|
|
1111
1111
|
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
1112
|
+
id: string;
|
|
1112
1113
|
kind: "TICKET" | "CHAT";
|
|
1113
1114
|
prompt: string;
|
|
1114
1115
|
providerSessionId: string | null;
|
|
1115
1116
|
workspace: {
|
|
1116
1117
|
path: string;
|
|
1117
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
1118
1118
|
id: string;
|
|
1119
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
1119
1120
|
projectId: string;
|
|
1120
1121
|
budgetUsd: number | null;
|
|
1121
1122
|
budgetMinutes: number | null;
|
|
@@ -1154,8 +1155,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1154
1155
|
session: {
|
|
1155
1156
|
mode: "ask" | "plan" | "auto" | "full";
|
|
1156
1157
|
agent: "CLAUDE" | "CODEX";
|
|
1157
|
-
id: string;
|
|
1158
1158
|
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
1159
|
+
id: string;
|
|
1159
1160
|
kind: "TICKET" | "CHAT";
|
|
1160
1161
|
model: string | null;
|
|
1161
1162
|
effort: string | null;
|
|
@@ -1168,8 +1169,8 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1168
1169
|
extraBudgetMinutes: number | null;
|
|
1169
1170
|
workspace: {
|
|
1170
1171
|
path: string;
|
|
1171
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
1172
1172
|
id: string;
|
|
1173
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
1173
1174
|
projectId: string;
|
|
1174
1175
|
budgetUsd: number | null;
|
|
1175
1176
|
budgetMinutes: number | null;
|
|
@@ -1205,15 +1206,15 @@ export declare const GatewayFrameSchema: z.ZodDiscriminatedUnion<"type", [z.ZodO
|
|
|
1205
1206
|
}, {
|
|
1206
1207
|
session: {
|
|
1207
1208
|
agent: "CLAUDE" | "CODEX";
|
|
1208
|
-
id: string;
|
|
1209
1209
|
status: "RUNNING" | "FAILED" | "STARTING" | "WAITING_INPUT" | "WAITING_PERMISSION" | "REVIEW" | "DONE" | "STOPPED";
|
|
1210
|
+
id: string;
|
|
1210
1211
|
kind: "TICKET" | "CHAT";
|
|
1211
1212
|
prompt: string;
|
|
1212
1213
|
providerSessionId: string | null;
|
|
1213
1214
|
workspace: {
|
|
1214
1215
|
path: string;
|
|
1215
|
-
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
1216
1216
|
id: string;
|
|
1217
|
+
trustMode: "STRICT" | "NORMAL" | "AUTO";
|
|
1217
1218
|
projectId: string;
|
|
1218
1219
|
budgetUsd: number | null;
|
|
1219
1220
|
budgetMinutes: number | null;
|
|
@@ -1673,7 +1674,22 @@ export type RunnerFrame = {
|
|
|
1673
1674
|
*/
|
|
1674
1675
|
| ({
|
|
1675
1676
|
type: 'host_load';
|
|
1676
|
-
} & HostLoadFrame)
|
|
1677
|
+
} & HostLoadFrame)
|
|
1678
|
+
/**
|
|
1679
|
+
* How this machine is dividing its memory between the sessions on it, right
|
|
1680
|
+
* now (#398 S4).
|
|
1681
|
+
*
|
|
1682
|
+
* Machine-scoped with a `sessions` array rather than one frame per session:
|
|
1683
|
+
* half of what has to be shown is about the MACHINE — what is free, what is
|
|
1684
|
+
* held by things that are not DevBridge, how many guarantees fit — and a
|
|
1685
|
+
* machine with no live sessions still has to be able to say it.
|
|
1686
|
+
*
|
|
1687
|
+
* Sent only when it moved, on the same tick that recomputes it. Fields mirror
|
|
1688
|
+
* `@devbridge/shared` — see `session-limits.ts`.
|
|
1689
|
+
*/
|
|
1690
|
+
| ({
|
|
1691
|
+
type: 'session_limits';
|
|
1692
|
+
} & SessionLimitsFrame) | {
|
|
1677
1693
|
type: 'pong';
|
|
1678
1694
|
};
|
|
1679
1695
|
//# sourceMappingURL=protocol.d.ts.map
|
package/dist/recipe-schema.d.ts
CHANGED
|
@@ -134,17 +134,17 @@ export declare const ProjectRecipeSchema: z.ZodObject<{
|
|
|
134
134
|
env?: Record<string, string> | undefined;
|
|
135
135
|
timeoutSec?: number | undefined;
|
|
136
136
|
} | undefined;
|
|
137
|
-
|
|
137
|
+
test?: {
|
|
138
138
|
run: string;
|
|
139
139
|
env?: Record<string, string> | undefined;
|
|
140
140
|
timeoutSec?: number | undefined;
|
|
141
141
|
} | undefined;
|
|
142
|
-
|
|
142
|
+
verify?: {
|
|
143
143
|
run: string;
|
|
144
144
|
env?: Record<string, string> | undefined;
|
|
145
145
|
timeoutSec?: number | undefined;
|
|
146
146
|
} | undefined;
|
|
147
|
-
|
|
147
|
+
build?: {
|
|
148
148
|
run: string;
|
|
149
149
|
env?: Record<string, string> | undefined;
|
|
150
150
|
timeoutSec?: number | undefined;
|
|
@@ -160,17 +160,17 @@ export declare const ProjectRecipeSchema: z.ZodObject<{
|
|
|
160
160
|
env?: Record<string, string> | undefined;
|
|
161
161
|
timeoutSec?: number | undefined;
|
|
162
162
|
} | undefined;
|
|
163
|
-
|
|
163
|
+
test?: {
|
|
164
164
|
run: string;
|
|
165
165
|
env?: Record<string, string> | undefined;
|
|
166
166
|
timeoutSec?: number | undefined;
|
|
167
167
|
} | undefined;
|
|
168
|
-
|
|
168
|
+
verify?: {
|
|
169
169
|
run: string;
|
|
170
170
|
env?: Record<string, string> | undefined;
|
|
171
171
|
timeoutSec?: number | undefined;
|
|
172
172
|
} | undefined;
|
|
173
|
-
|
|
173
|
+
build?: {
|
|
174
174
|
run: string;
|
|
175
175
|
env?: Record<string, string> | undefined;
|
|
176
176
|
timeoutSec?: number | undefined;
|
|
@@ -219,17 +219,17 @@ export declare const ProjectRecipeSchema: z.ZodObject<{
|
|
|
219
219
|
env?: Record<string, string> | undefined;
|
|
220
220
|
timeoutSec?: number | undefined;
|
|
221
221
|
} | undefined;
|
|
222
|
-
|
|
222
|
+
test?: {
|
|
223
223
|
run: string;
|
|
224
224
|
env?: Record<string, string> | undefined;
|
|
225
225
|
timeoutSec?: number | undefined;
|
|
226
226
|
} | undefined;
|
|
227
|
-
|
|
227
|
+
verify?: {
|
|
228
228
|
run: string;
|
|
229
229
|
env?: Record<string, string> | undefined;
|
|
230
230
|
timeoutSec?: number | undefined;
|
|
231
231
|
} | undefined;
|
|
232
|
-
|
|
232
|
+
build?: {
|
|
233
233
|
run: string;
|
|
234
234
|
env?: Record<string, string> | undefined;
|
|
235
235
|
timeoutSec?: number | undefined;
|
|
@@ -268,17 +268,17 @@ export declare const ProjectRecipeSchema: z.ZodObject<{
|
|
|
268
268
|
env?: Record<string, string> | undefined;
|
|
269
269
|
timeoutSec?: number | undefined;
|
|
270
270
|
} | undefined;
|
|
271
|
-
|
|
271
|
+
test?: {
|
|
272
272
|
run: string;
|
|
273
273
|
env?: Record<string, string> | undefined;
|
|
274
274
|
timeoutSec?: number | undefined;
|
|
275
275
|
} | undefined;
|
|
276
|
-
|
|
276
|
+
verify?: {
|
|
277
277
|
run: string;
|
|
278
278
|
env?: Record<string, string> | undefined;
|
|
279
279
|
timeoutSec?: number | undefined;
|
|
280
280
|
} | undefined;
|
|
281
|
-
|
|
281
|
+
build?: {
|
|
282
282
|
run: string;
|
|
283
283
|
env?: Record<string, string> | undefined;
|
|
284
284
|
timeoutSec?: number | undefined;
|
package/dist/regex-guard.js
CHANGED
|
@@ -228,12 +228,12 @@ export function inspectPattern(pattern) {
|
|
|
228
228
|
const worst = Math.max(...heavy.map((p) => p.bound ?? 0));
|
|
229
229
|
return {
|
|
230
230
|
dangerous: true,
|
|
231
|
-
reason:
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
`(
|
|
235
|
-
|
|
236
|
-
|
|
231
|
+
reason: `Search blocked: quantifier {…,${worst}} sits next to another variable-length part. ` +
|
|
232
|
+
`On a pattern like this the engine built into Claude Code needs ~5.4 GB and ~67 seconds ` +
|
|
233
|
+
`just to parse it, and that takes the dev server down and drops every session on that ` +
|
|
234
|
+
`machine (details: docs/standards/project-gotchas.md §345). ` +
|
|
235
|
+
`Run it again with command grep: the system grep handles this pattern fine. ` +
|
|
236
|
+
`Or lower the quantifier bound below ${QUANTIFIER_DANGER_BOUND}.`,
|
|
237
237
|
};
|
|
238
238
|
}
|
|
239
239
|
/**
|
package/dist/self-update.js
CHANGED
|
@@ -5,6 +5,7 @@ import path from 'node:path';
|
|
|
5
5
|
import { promisify } from 'node:util';
|
|
6
6
|
import { findClaudeCli, USE_BUNDLED_CLAUDE } from './agent-binary.js';
|
|
7
7
|
import { systemdUserEnv } from './environment.js';
|
|
8
|
+
import { cageAuthority, CageAuthorityError } from './cage-authority.js';
|
|
8
9
|
import { log } from './log.js';
|
|
9
10
|
import { stateDir } from './paths.js';
|
|
10
11
|
import { RUNNER_VERSION } from './version.js';
|
|
@@ -386,8 +387,28 @@ function systemctlEnv() {
|
|
|
386
387
|
return env;
|
|
387
388
|
}
|
|
388
389
|
export async function selfUpdate(options) {
|
|
390
|
+
/**
|
|
391
|
+
* The default executor installs software on somebody's machine and reloads
|
|
392
|
+
* their systemd, so it asks the same door the cages ask (#403).
|
|
393
|
+
*
|
|
394
|
+
* The check is on the DEFAULT and not on the injected one: a test hands its
|
|
395
|
+
* own executor and is testing the sequence of commands, which is exactly what
|
|
396
|
+
* it should be able to do. What must not happen is a call with no executor
|
|
397
|
+
* from a process that has no business updating anything — `npm install -g`
|
|
398
|
+
* from a vitest worker would be the incident of 10.09.2026 with a much longer
|
|
399
|
+
* tail.
|
|
400
|
+
*/
|
|
389
401
|
const exec = options.exec ??
|
|
390
|
-
((file, args, opts) =>
|
|
402
|
+
((file, args, opts) => {
|
|
403
|
+
if (cageAuthority() === 'none') {
|
|
404
|
+
throw new CageAuthorityError(`this process may not run «${file}»: updating this machine's runner is the daemon's job`);
|
|
405
|
+
}
|
|
406
|
+
return execFileAsync(file, args, {
|
|
407
|
+
timeout: opts.timeout,
|
|
408
|
+
env: opts.env,
|
|
409
|
+
maxBuffer: 4_000_000,
|
|
410
|
+
});
|
|
411
|
+
});
|
|
391
412
|
const fromVersion = RUNNER_VERSION;
|
|
392
413
|
const fail = (detail, extra = {}) => ({
|
|
393
414
|
ok: false,
|
package/dist/service-unit.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ export declare function buildUnit(execStart?: string, nodeBinary?: string): stri
|
|
|
57
57
|
* which is the only way to fix the servers that already have the bad numbers
|
|
58
58
|
* baked in — and it never overwrites a unit the operator edited by hand.
|
|
59
59
|
*/
|
|
60
|
-
export declare const LIMITS_VERSION =
|
|
60
|
+
export declare const LIMITS_VERSION = 6;
|
|
61
61
|
/**
|
|
62
62
|
* Where the agent sessions live once they have a cage of their own.
|
|
63
63
|
*
|
|
@@ -239,6 +239,19 @@ export declare function managedUsageFloorBytes(facts: MemoryFacts): number;
|
|
|
239
239
|
* - cap 85 % of total: on an idle dedicated box `MemAvailable` is nearly the whole
|
|
240
240
|
* machine, and a ceiling of «everything» is the bug this function exists to fix.
|
|
241
241
|
*/
|
|
242
|
+
/**
|
|
243
|
+
* What the machine keeps for itself, whatever the agents are doing.
|
|
244
|
+
*
|
|
245
|
+
* Enough for sshd, journald, the kernel and some page cache to keep working
|
|
246
|
+
* while our cgroups sit at their ceiling. Proportional on a big machine,
|
|
247
|
+
* absolute on a small one, because 15 % of 4 GB is not enough to stay reachable.
|
|
248
|
+
*
|
|
249
|
+
* Hoisted out of {@link memoryPolicy} for #398 S3: the live allocator has to
|
|
250
|
+
* subtract exactly the same reserve when it decides how much of the machine is
|
|
251
|
+
* free right now, and a second copy of this number would drift from this one on
|
|
252
|
+
* the first machine where it mattered.
|
|
253
|
+
*/
|
|
254
|
+
export declare function machineReserveBytes(totalBytes: number): number;
|
|
242
255
|
export declare function memoryPolicy(facts: MemoryFacts, minCeilingBytes?: number): MemoryPolicy;
|
|
243
256
|
/** `SwapTotal` of this machine, or null where `/proc/meminfo` will not say. */
|
|
244
257
|
export declare function readSwapTotalBytes(): number | null;
|
|
@@ -418,7 +431,24 @@ export declare function buildLimitsOverride(cpuCount?: number, facts?: MemoryFac
|
|
|
418
431
|
* can measure one (the drift check treats a file with no
|
|
419
432
|
* `MemoryMax` as outdated).
|
|
420
433
|
*/
|
|
421
|
-
export declare function buildSessionsSliceOverride(facts?: MemoryFacts | null, sessionsUsageBytes?: number | null): string;
|
|
434
|
+
export declare function buildSessionsSliceOverride(facts?: MemoryFacts | null, sessionsUsageBytes?: number | null, maxSessions?: number): string;
|
|
435
|
+
/**
|
|
436
|
+
* Where the collective brake sits under the collective ceiling.
|
|
437
|
+
*
|
|
438
|
+
* Nine tenths: close enough that the sessions get almost the whole pot before
|
|
439
|
+
* anything is throttled, far enough that the kernel has a tenth of the pot in
|
|
440
|
+
* which to slow everyone down and reclaim, instead of arriving at the hard
|
|
441
|
+
* ceiling and choosing a victim.
|
|
442
|
+
*/
|
|
443
|
+
export declare const SLICE_BRAKE_OF_CEILING = 0.9;
|
|
444
|
+
/**
|
|
445
|
+
* Seats assumed when nobody has said otherwise.
|
|
446
|
+
*
|
|
447
|
+
* Three, which is what `DevServer.maxSessions` defaults to in the database. The
|
|
448
|
+
* runner's own config may say fewer; the slice's protection is sized for the
|
|
449
|
+
* seats the machine sells, not for the sessions that happen to be running.
|
|
450
|
+
*/
|
|
451
|
+
export declare const DEFAULT_MAX_SESSIONS = 3;
|
|
422
452
|
/**
|
|
423
453
|
* The CPU share of everything the agents run, against the daemon's own.
|
|
424
454
|
*
|
|
@@ -453,7 +483,9 @@ export declare function limitsOverrideIsOutdated(readFile?: (p: string) => strin
|
|
|
453
483
|
* arrive at the same number — otherwise a write whose floor was binding would be
|
|
454
484
|
* seen as drifted on the very next call and rewritten forever.
|
|
455
485
|
*/
|
|
456
|
-
export declare function writeLimitsOverride(force?: boolean, home?: string, facts?: MemoryFacts | null, sessionsUsageBytes?: number | null
|
|
486
|
+
export declare function writeLimitsOverride(force?: boolean, home?: string, facts?: MemoryFacts | null, sessionsUsageBytes?: number | null,
|
|
487
|
+
/** Seats this machine sells — sizes the slice's collective `MemoryLow` (#398 S3). */
|
|
488
|
+
maxSessions?: number): boolean;
|
|
457
489
|
/**
|
|
458
490
|
* Does the installed unit point at something that no longer exists?
|
|
459
491
|
*
|