switchroom 0.20.8 → 0.20.9
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/agent-scheduler/index.js +16 -13
- package/dist/auth-broker/index.js +51 -29
- package/dist/cli/autoaccept-poll.js +5 -3
- package/dist/cli/drive-write-pretool.mjs +5 -3
- package/dist/cli/ms-365-write-pretool.mjs +5 -3
- package/dist/cli/notion-write-pretool.mjs +6 -6
- package/dist/cli/switchroom.js +12 -10
- package/dist/host-control/main.js +7 -7
- package/dist/vault/approvals/kernel-server.js +6 -6
- package/dist/vault/broker/server.js +6 -6
- package/package.json +1 -1
- package/profiles/default/CLAUDE.md.hbs +12 -13
- package/telegram-plugin/ask-user.ts +6 -7
- package/telegram-plugin/dist/gateway/gateway.js +183 -66
- package/telegram-plugin/gateway/auth-broker-client.ts +1 -1
- package/telegram-plugin/gateway/auth-command.ts +4 -2
- package/telegram-plugin/gateway/checklist-fallback.ts +8 -1
- package/telegram-plugin/gateway/gateway.ts +8 -4
- package/telegram-plugin/gateway/outbound-send-path.ts +9 -1
- package/telegram-plugin/gateway/subagent-handback-inbound-builder.ts +21 -1
- package/telegram-plugin/gateway/subagent-handback-marker.ts +94 -0
- package/telegram-plugin/gateway/throttle-tier-wiring.ts +93 -18
- package/telegram-plugin/render/emphasis-guard.ts +92 -12
- package/telegram-plugin/render/line-start-guard.ts +27 -2
- package/telegram-plugin/sticker-aliases.ts +12 -14
- package/telegram-plugin/tests/ask-user.test.ts +15 -0
- package/telegram-plugin/tests/checklist-fallback.test.ts +21 -0
- package/telegram-plugin/tests/handback-tasknotif-dedup.test.ts +248 -0
- package/telegram-plugin/tests/render/emphasis-guard.test.ts +105 -6
- package/telegram-plugin/tests/render/heading-guard-blockquote-glued-hash.test.ts +123 -36
- package/telegram-plugin/tests/reply-quote-wire.test.ts +47 -0
- package/telegram-plugin/tests/sticker-aliases.test.ts +43 -0
- package/telegram-plugin/tests/throttle-tier-probe-only.test.ts +216 -0
- package/telegram-plugin/tests/throttle-tier-route-429-wiring.test.ts +92 -0
- package/telegram-plugin/tests/throttle-tier-route-429.test.ts +71 -0
- package/telegram-plugin/throttle-tier.ts +59 -0
|
@@ -12019,12 +12019,13 @@ function recordReadFailure(agentCfg, failure) {
|
|
|
12019
12019
|
writable: false
|
|
12020
12020
|
});
|
|
12021
12021
|
}
|
|
12022
|
-
function overlayReadFailures(config, agent) {
|
|
12022
|
+
function overlayReadFailures(config, agent, source) {
|
|
12023
12023
|
const agentCfg = config.agents?.[agent];
|
|
12024
12024
|
if (!agentCfg)
|
|
12025
12025
|
return [];
|
|
12026
12026
|
const list = agentCfg[OVERLAY_READ_FAILURES];
|
|
12027
|
-
|
|
12027
|
+
const all = Array.isArray(list) ? list : [];
|
|
12028
|
+
return source ? all.filter((f) => f.source === source) : all;
|
|
12028
12029
|
}
|
|
12029
12030
|
function deriveOverlayTitle(raw, fileName) {
|
|
12030
12031
|
const titleFromComment = raw.match(/^#[^\S\n]*name:[^\S\n]*(\S.*?)[^\S\n]*$/m)?.[1];
|
|
@@ -12035,7 +12036,7 @@ function deriveOverlayTitle(raw, fileName) {
|
|
|
12035
12036
|
return;
|
|
12036
12037
|
return base.length > 0 ? base : undefined;
|
|
12037
12038
|
}
|
|
12038
|
-
function readOverlayFile(agentName, file, agentCfg, warnings) {
|
|
12039
|
+
function readOverlayFile(agentName, file, agentCfg, warnings, source) {
|
|
12039
12040
|
try {
|
|
12040
12041
|
return readFileSync(file, "utf-8");
|
|
12041
12042
|
} catch (err) {
|
|
@@ -12048,7 +12049,7 @@ function readOverlayFile(agentName, file, agentCfg, warnings) {
|
|
|
12048
12049
|
reason: `read error: ${err.message}`,
|
|
12049
12050
|
code: code ?? "EUNKNOWN"
|
|
12050
12051
|
};
|
|
12051
|
-
recordReadFailure(agentCfg, { file, code: w.code });
|
|
12052
|
+
recordReadFailure(agentCfg, { file, code: w.code, source });
|
|
12052
12053
|
warnings.push(w);
|
|
12053
12054
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${file}': ${w.reason}`);
|
|
12054
12055
|
return;
|
|
@@ -12112,14 +12113,14 @@ function applyAgentOverlays(config) {
|
|
|
12112
12113
|
reason: `read error: cannot list overlay directory (${code})`,
|
|
12113
12114
|
code
|
|
12114
12115
|
};
|
|
12115
|
-
recordReadFailure(agentCfg, { file: scheduleDir, code });
|
|
12116
|
+
recordReadFailure(agentCfg, { file: scheduleDir, code, source: "schedule" });
|
|
12116
12117
|
warnings.push(w);
|
|
12117
12118
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${scheduleDir}': ${w.reason}`);
|
|
12118
12119
|
});
|
|
12119
12120
|
if (files.length > 0) {
|
|
12120
12121
|
const merged = [...agentCfg.schedule ?? []];
|
|
12121
12122
|
for (const file of files) {
|
|
12122
|
-
const raw = readOverlayFile(agentName, file, agentCfg, warnings);
|
|
12123
|
+
const raw = readOverlayFile(agentName, file, agentCfg, warnings, "schedule");
|
|
12123
12124
|
if (raw === undefined)
|
|
12124
12125
|
continue;
|
|
12125
12126
|
try {
|
|
@@ -12164,7 +12165,7 @@ function applyAgentOverlays(config) {
|
|
|
12164
12165
|
reason: `read error: cannot list overlay directory (${code})`,
|
|
12165
12166
|
code
|
|
12166
12167
|
};
|
|
12167
|
-
recordReadFailure(agentCfg, { file: skillsDir, code });
|
|
12168
|
+
recordReadFailure(agentCfg, { file: skillsDir, code, source: "skills" });
|
|
12168
12169
|
warnings.push(w);
|
|
12169
12170
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${skillsDir}': ${w.reason}`);
|
|
12170
12171
|
});
|
|
@@ -12172,7 +12173,7 @@ function applyAgentOverlays(config) {
|
|
|
12172
12173
|
const merged = [...agentCfg.skills ?? []];
|
|
12173
12174
|
const seen = new Set(merged);
|
|
12174
12175
|
for (const file of skillFiles) {
|
|
12175
|
-
const raw = readOverlayFile(agentName, file, agentCfg, warnings);
|
|
12176
|
+
const raw = readOverlayFile(agentName, file, agentCfg, warnings, "skills");
|
|
12176
12177
|
if (raw === undefined)
|
|
12177
12178
|
continue;
|
|
12178
12179
|
try {
|
|
@@ -14043,7 +14044,8 @@ var MarkThrottledRequestSchema = exports_external.object({
|
|
|
14043
14044
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
14044
14045
|
op: exports_external.literal("mark-throttled"),
|
|
14045
14046
|
id: exports_external.string().min(1),
|
|
14046
|
-
until: exports_external.number().int().positive()
|
|
14047
|
+
until: exports_external.number().int().positive(),
|
|
14048
|
+
probeOnly: exports_external.boolean().optional()
|
|
14047
14049
|
});
|
|
14048
14050
|
var RefreshAccountRequestSchema = exports_external.object({
|
|
14049
14051
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
@@ -14460,12 +14462,13 @@ class AuthBrokerClient {
|
|
|
14460
14462
|
const data = await this.send(req);
|
|
14461
14463
|
return data;
|
|
14462
14464
|
}
|
|
14463
|
-
async markThrottled(until) {
|
|
14465
|
+
async markThrottled(until, probeOnly = false) {
|
|
14464
14466
|
const data = await this.send({
|
|
14465
14467
|
v: PROTOCOL_VERSION,
|
|
14466
14468
|
id: randomUUID(),
|
|
14467
14469
|
op: "mark-throttled",
|
|
14468
|
-
until
|
|
14470
|
+
until,
|
|
14471
|
+
...probeOnly ? { probeOnly: true } : {}
|
|
14469
14472
|
});
|
|
14470
14473
|
return data;
|
|
14471
14474
|
}
|
|
@@ -15337,7 +15340,7 @@ function formatReadFailures(failures) {
|
|
|
15337
15340
|
}
|
|
15338
15341
|
function loadAgentEntriesStrict(configPath, agentName) {
|
|
15339
15342
|
const config = loadConfig(configPath);
|
|
15340
|
-
const failures = overlayReadFailures(config, agentName);
|
|
15343
|
+
const failures = overlayReadFailures(config, agentName, "schedule");
|
|
15341
15344
|
if (failures.length > 0) {
|
|
15342
15345
|
throw new Error(`schedule.d overlay unreadable — refusing a reload that may be ` + `missing entries: ${formatReadFailures(failures)}`);
|
|
15343
15346
|
}
|
|
@@ -15382,7 +15385,7 @@ async function main() {
|
|
|
15382
15385
|
const config = loadConfig(configPath);
|
|
15383
15386
|
const allEntries = collectScheduleEntries(config);
|
|
15384
15387
|
const entries = allEntries.filter((e) => e.agent === agentName);
|
|
15385
|
-
const bootReadFailures = overlayReadFailures(config, agentName);
|
|
15388
|
+
const bootReadFailures = overlayReadFailures(config, agentName, "schedule");
|
|
15386
15389
|
if (bootReadFailures.length > 0) {
|
|
15387
15390
|
process.stderr.write(`agent-scheduler: ${agentName} WARNING: ${bootReadFailures.length} ` + `schedule.d overlay file(s) unreadable at boot — their cron entries ` + `are NOT registered: ${formatReadFailures(bootReadFailures)}
|
|
15388
15391
|
`);
|
|
@@ -12053,7 +12053,7 @@ function deriveOverlayTitle(raw, fileName) {
|
|
|
12053
12053
|
return;
|
|
12054
12054
|
return base.length > 0 ? base : undefined;
|
|
12055
12055
|
}
|
|
12056
|
-
function readOverlayFile(agentName, file, agentCfg, warnings) {
|
|
12056
|
+
function readOverlayFile(agentName, file, agentCfg, warnings, source) {
|
|
12057
12057
|
try {
|
|
12058
12058
|
return readFileSync(file, "utf-8");
|
|
12059
12059
|
} catch (err) {
|
|
@@ -12066,7 +12066,7 @@ function readOverlayFile(agentName, file, agentCfg, warnings) {
|
|
|
12066
12066
|
reason: `read error: ${err.message}`,
|
|
12067
12067
|
code: code ?? "EUNKNOWN"
|
|
12068
12068
|
};
|
|
12069
|
-
recordReadFailure(agentCfg, { file, code: w.code });
|
|
12069
|
+
recordReadFailure(agentCfg, { file, code: w.code, source });
|
|
12070
12070
|
warnings.push(w);
|
|
12071
12071
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${file}': ${w.reason}`);
|
|
12072
12072
|
return;
|
|
@@ -12130,14 +12130,14 @@ function applyAgentOverlays(config) {
|
|
|
12130
12130
|
reason: `read error: cannot list overlay directory (${code})`,
|
|
12131
12131
|
code
|
|
12132
12132
|
};
|
|
12133
|
-
recordReadFailure(agentCfg, { file: scheduleDir, code });
|
|
12133
|
+
recordReadFailure(agentCfg, { file: scheduleDir, code, source: "schedule" });
|
|
12134
12134
|
warnings.push(w);
|
|
12135
12135
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${scheduleDir}': ${w.reason}`);
|
|
12136
12136
|
});
|
|
12137
12137
|
if (files.length > 0) {
|
|
12138
12138
|
const merged = [...agentCfg.schedule ?? []];
|
|
12139
12139
|
for (const file of files) {
|
|
12140
|
-
const raw = readOverlayFile(agentName, file, agentCfg, warnings);
|
|
12140
|
+
const raw = readOverlayFile(agentName, file, agentCfg, warnings, "schedule");
|
|
12141
12141
|
if (raw === undefined)
|
|
12142
12142
|
continue;
|
|
12143
12143
|
try {
|
|
@@ -12182,7 +12182,7 @@ function applyAgentOverlays(config) {
|
|
|
12182
12182
|
reason: `read error: cannot list overlay directory (${code})`,
|
|
12183
12183
|
code
|
|
12184
12184
|
};
|
|
12185
|
-
recordReadFailure(agentCfg, { file: skillsDir, code });
|
|
12185
|
+
recordReadFailure(agentCfg, { file: skillsDir, code, source: "skills" });
|
|
12186
12186
|
warnings.push(w);
|
|
12187
12187
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${skillsDir}': ${w.reason}`);
|
|
12188
12188
|
});
|
|
@@ -12190,7 +12190,7 @@ function applyAgentOverlays(config) {
|
|
|
12190
12190
|
const merged = [...agentCfg.skills ?? []];
|
|
12191
12191
|
const seen = new Set(merged);
|
|
12192
12192
|
for (const file of skillFiles) {
|
|
12193
|
-
const raw = readOverlayFile(agentName, file, agentCfg, warnings);
|
|
12193
|
+
const raw = readOverlayFile(agentName, file, agentCfg, warnings, "skills");
|
|
12194
12194
|
if (raw === undefined)
|
|
12195
12195
|
continue;
|
|
12196
12196
|
try {
|
|
@@ -21286,7 +21286,8 @@ var MarkThrottledRequestSchema = exports_external.object({
|
|
|
21286
21286
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
21287
21287
|
op: exports_external.literal("mark-throttled"),
|
|
21288
21288
|
id: exports_external.string().min(1),
|
|
21289
|
-
until: exports_external.number().int().positive()
|
|
21289
|
+
until: exports_external.number().int().positive(),
|
|
21290
|
+
probeOnly: exports_external.boolean().optional()
|
|
21290
21291
|
});
|
|
21291
21292
|
var RefreshAccountRequestSchema = exports_external.object({
|
|
21292
21293
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
@@ -21568,8 +21569,8 @@ var AUTH_BROKER_ROOT2 = "/run/switchroom/auth-broker";
|
|
|
21568
21569
|
var REFRESH_TICK_INTERVAL_MS = 60 * 1000;
|
|
21569
21570
|
var MARK_EXHAUSTED_DEFAULT_MS = 5 * 60 * 60 * 1000;
|
|
21570
21571
|
var MARK_THROTTLED_MAX_MS = 30 * 60 * 1000;
|
|
21571
|
-
var THROTTLE_ESCALATION_HITS = 3;
|
|
21572
21572
|
var THROTTLE_ESCALATION_WINDOW_MS = 10 * 60 * 1000;
|
|
21573
|
+
var THROTTLE_ESCALATION_PROBE_MIN_INTERVAL_MS = 60 * 1000;
|
|
21573
21574
|
var MARK_THROTTLED_MIN_INTERVAL_MS = 5 * 1000;
|
|
21574
21575
|
var MARK_CORROBORATION_PROBE_DELAY_MS = 90 * 1000;
|
|
21575
21576
|
var AUDIT_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
@@ -21663,6 +21664,7 @@ class AuthBroker {
|
|
|
21663
21664
|
externalSpendCache = null;
|
|
21664
21665
|
externalSpendInFlight = null;
|
|
21665
21666
|
probeInFlight = new Map;
|
|
21667
|
+
lastEscalationProbeAt = {};
|
|
21666
21668
|
shaIndex = {};
|
|
21667
21669
|
thresholdViolations = {};
|
|
21668
21670
|
notificationClaims = {};
|
|
@@ -22047,7 +22049,7 @@ class AuthBroker {
|
|
|
22047
22049
|
await this.opMarkExhausted(socket, reqId, identity, req.until);
|
|
22048
22050
|
break;
|
|
22049
22051
|
case "mark-throttled":
|
|
22050
|
-
await this.opMarkThrottled(socket, reqId, identity, req.until);
|
|
22052
|
+
await this.opMarkThrottled(socket, reqId, identity, req.until, req.probeOnly);
|
|
22051
22053
|
break;
|
|
22052
22054
|
case "refresh-account": {
|
|
22053
22055
|
const provider = req.provider ?? "anthropic";
|
|
@@ -22879,7 +22881,7 @@ class AuthBroker {
|
|
|
22879
22881
|
this.audit({ op: "mark-exhausted", identity, account, accountKind: "claude", ok: true });
|
|
22880
22882
|
socket.write(encodeSuccess(id, { account, rolled, rolledTo }));
|
|
22881
22883
|
}
|
|
22882
|
-
async opMarkThrottled(socket, id, identity, until) {
|
|
22884
|
+
async opMarkThrottled(socket, id, identity, until, probeOnly = false) {
|
|
22883
22885
|
const account = this.callerAccount(identity);
|
|
22884
22886
|
if (!account) {
|
|
22885
22887
|
this.audit({ op: "mark-throttled", identity, accountKind: "claude", ok: false, error: "no-active-account" });
|
|
@@ -22887,6 +22889,17 @@ class AuthBroker {
|
|
|
22887
22889
|
return;
|
|
22888
22890
|
}
|
|
22889
22891
|
const now = this.now();
|
|
22892
|
+
if (probeOnly) {
|
|
22893
|
+
const { escalated: escalated2, rolledTo: rolledTo2 } = await this.maybeEscalateThrottle(account, identity, now);
|
|
22894
|
+
this.audit({ op: "mark-throttled", identity, account, accountKind: "claude", ok: true });
|
|
22895
|
+
socket.write(encodeSuccess(id, {
|
|
22896
|
+
account,
|
|
22897
|
+
throttled_until: this.quota[account]?.throttled_until ?? 0,
|
|
22898
|
+
escalated: escalated2,
|
|
22899
|
+
rolledTo: escalated2 ? rolledTo2 : null
|
|
22900
|
+
}));
|
|
22901
|
+
return;
|
|
22902
|
+
}
|
|
22890
22903
|
const throttledUntil = Math.min(Math.max(until, now + 1000), now + MARK_THROTTLED_MAX_MS);
|
|
22891
22904
|
const entry = this.quota[account] ?? {};
|
|
22892
22905
|
const priorHits = entry.throttle_hits ?? [];
|
|
@@ -22908,31 +22921,19 @@ class AuthBroker {
|
|
|
22908
22921
|
}
|
|
22909
22922
|
const hits = priorHits.filter((t) => now - t < THROTTLE_ESCALATION_WINDOW_MS);
|
|
22910
22923
|
hits.push(now);
|
|
22911
|
-
const escalate = hits.length >= THROTTLE_ESCALATION_HITS;
|
|
22912
22924
|
this.quota[account] = {
|
|
22913
22925
|
...entry,
|
|
22914
22926
|
throttled_until: throttledUntil,
|
|
22915
|
-
throttle_hits:
|
|
22927
|
+
throttle_hits: hits
|
|
22916
22928
|
};
|
|
22917
22929
|
this.persistQuota();
|
|
22918
22930
|
this.audit({ op: "mark-throttled", identity, account, accountKind: "claude", ok: true });
|
|
22919
|
-
process.stdout.write(`auth-broker: mark-throttled ${account} until ${new Date(throttledUntil).toISOString()} ` + `(hit ${hits.length}
|
|
22920
|
-
`);
|
|
22921
|
-
let escalated = false;
|
|
22922
|
-
let rolledTo = null;
|
|
22923
|
-
if (escalate) {
|
|
22924
|
-
const probe = await this.probeThrottleEscalation(account);
|
|
22925
|
-
if (probe.exhausted) {
|
|
22926
|
-
escalated = true;
|
|
22927
|
-
process.stdout.write(`auth-broker: throttle-escalation probe corroborates wall on ${account} — mark-exhausted + roll
|
|
22928
|
-
`);
|
|
22929
|
-
this.audit({ op: "mark-exhausted", identity, account, accountKind: "claude", ok: true, reason: "throttle-escalation" });
|
|
22930
|
-
const roll = await this.markExhaustedAndRoll(account, probe.until ?? undefined, identity);
|
|
22931
|
-
rolledTo = roll.rolledTo;
|
|
22932
|
-
} else {
|
|
22933
|
-
process.stdout.write(`auth-broker: throttle-escalation probe on ${account} did NOT corroborate a wall — staying throttled
|
|
22931
|
+
process.stdout.write(`auth-broker: mark-throttled ${account} until ${new Date(throttledUntil).toISOString()} ` + `(hit ${hits.length} in window)
|
|
22934
22932
|
`);
|
|
22935
|
-
|
|
22933
|
+
const { escalated, rolledTo } = await this.maybeEscalateThrottle(account, identity, now);
|
|
22934
|
+
if (escalated) {
|
|
22935
|
+
this.quota[account] = { ...this.quota[account], throttle_hits: [] };
|
|
22936
|
+
this.persistQuota();
|
|
22936
22937
|
}
|
|
22937
22938
|
socket.write(encodeSuccess(id, {
|
|
22938
22939
|
account,
|
|
@@ -22941,6 +22942,27 @@ class AuthBroker {
|
|
|
22941
22942
|
rolledTo: escalated ? rolledTo : null
|
|
22942
22943
|
}));
|
|
22943
22944
|
}
|
|
22945
|
+
async maybeEscalateThrottle(account, identity, now) {
|
|
22946
|
+
const lastProbeAt = this.lastEscalationProbeAt[account];
|
|
22947
|
+
const probeAllowed = lastProbeAt === undefined || now - lastProbeAt >= THROTTLE_ESCALATION_PROBE_MIN_INTERVAL_MS;
|
|
22948
|
+
if (!probeAllowed) {
|
|
22949
|
+
process.stdout.write(`auth-broker: throttle-escalation probe on ${account} rate-bounded — skipped
|
|
22950
|
+
`);
|
|
22951
|
+
return { escalated: false, rolledTo: null };
|
|
22952
|
+
}
|
|
22953
|
+
this.lastEscalationProbeAt[account] = now;
|
|
22954
|
+
const probe = await this.probeThrottleEscalation(account);
|
|
22955
|
+
if (!probe.exhausted) {
|
|
22956
|
+
process.stdout.write(`auth-broker: throttle-escalation probe on ${account} did NOT corroborate a wall — staying put
|
|
22957
|
+
`);
|
|
22958
|
+
return { escalated: false, rolledTo: null };
|
|
22959
|
+
}
|
|
22960
|
+
process.stdout.write(`auth-broker: throttle-escalation probe corroborates wall on ${account} — mark-exhausted + roll
|
|
22961
|
+
`);
|
|
22962
|
+
this.audit({ op: "mark-exhausted", identity, account, accountKind: "claude", ok: true, reason: "throttle-escalation" });
|
|
22963
|
+
const roll = await this.markExhaustedAndRoll(account, probe.until ?? undefined, identity);
|
|
22964
|
+
return { escalated: true, rolledTo: roll.rolledTo };
|
|
22965
|
+
}
|
|
22944
22966
|
async probeThrottleEscalation(account) {
|
|
22945
22967
|
const creds = readAccountCredentials(account, this.home);
|
|
22946
22968
|
const token = creds?.claudeAiOauth?.accessToken;
|
|
@@ -22948,7 +22970,7 @@ class AuthBroker {
|
|
|
22948
22970
|
return { exhausted: false, until: null };
|
|
22949
22971
|
let result;
|
|
22950
22972
|
try {
|
|
22951
|
-
result = await this.
|
|
22973
|
+
result = await this.probeQuotaSingleFlight(account, token);
|
|
22952
22974
|
} catch (err) {
|
|
22953
22975
|
this.logErr(`throttle-escalation probe ${account}: ${err.message}`);
|
|
22954
22976
|
return { exhausted: false, until: null };
|
|
@@ -4958,7 +4958,8 @@ var MarkThrottledRequestSchema = exports_external.object({
|
|
|
4958
4958
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
4959
4959
|
op: exports_external.literal("mark-throttled"),
|
|
4960
4960
|
id: exports_external.string().min(1),
|
|
4961
|
-
until: exports_external.number().int().positive()
|
|
4961
|
+
until: exports_external.number().int().positive(),
|
|
4962
|
+
probeOnly: exports_external.boolean().optional()
|
|
4962
4963
|
});
|
|
4963
4964
|
var RefreshAccountRequestSchema = exports_external.object({
|
|
4964
4965
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
@@ -5375,12 +5376,13 @@ class AuthBrokerClient {
|
|
|
5375
5376
|
const data = await this.send(req);
|
|
5376
5377
|
return data;
|
|
5377
5378
|
}
|
|
5378
|
-
async markThrottled(until) {
|
|
5379
|
+
async markThrottled(until, probeOnly = false) {
|
|
5379
5380
|
const data = await this.send({
|
|
5380
5381
|
v: PROTOCOL_VERSION,
|
|
5381
5382
|
id: randomUUID2(),
|
|
5382
5383
|
op: "mark-throttled",
|
|
5383
|
-
until
|
|
5384
|
+
until,
|
|
5385
|
+
...probeOnly ? { probeOnly: true } : {}
|
|
5384
5386
|
});
|
|
5385
5387
|
return data;
|
|
5386
5388
|
}
|
|
@@ -4034,7 +4034,8 @@ var init_protocol = __esm(() => {
|
|
|
4034
4034
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
4035
4035
|
op: exports_external.literal("mark-throttled"),
|
|
4036
4036
|
id: exports_external.string().min(1),
|
|
4037
|
-
until: exports_external.number().int().positive()
|
|
4037
|
+
until: exports_external.number().int().positive(),
|
|
4038
|
+
probeOnly: exports_external.boolean().optional()
|
|
4038
4039
|
});
|
|
4039
4040
|
RefreshAccountRequestSchema = exports_external.object({
|
|
4040
4041
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
@@ -4430,12 +4431,13 @@ class AuthBrokerClient {
|
|
|
4430
4431
|
const data = await this.send(req);
|
|
4431
4432
|
return data;
|
|
4432
4433
|
}
|
|
4433
|
-
async markThrottled(until) {
|
|
4434
|
+
async markThrottled(until, probeOnly = false) {
|
|
4434
4435
|
const data = await this.send({
|
|
4435
4436
|
v: PROTOCOL_VERSION,
|
|
4436
4437
|
id: randomUUID(),
|
|
4437
4438
|
op: "mark-throttled",
|
|
4438
|
-
until
|
|
4439
|
+
until,
|
|
4440
|
+
...probeOnly ? { probeOnly: true } : {}
|
|
4439
4441
|
});
|
|
4440
4442
|
return data;
|
|
4441
4443
|
}
|
|
@@ -4036,7 +4036,8 @@ var init_protocol = __esm(() => {
|
|
|
4036
4036
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
4037
4037
|
op: exports_external.literal("mark-throttled"),
|
|
4038
4038
|
id: exports_external.string().min(1),
|
|
4039
|
-
until: exports_external.number().int().positive()
|
|
4039
|
+
until: exports_external.number().int().positive(),
|
|
4040
|
+
probeOnly: exports_external.boolean().optional()
|
|
4040
4041
|
});
|
|
4041
4042
|
RefreshAccountRequestSchema = exports_external.object({
|
|
4042
4043
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
@@ -4432,12 +4433,13 @@ class AuthBrokerClient {
|
|
|
4432
4433
|
const data = await this.send(req);
|
|
4433
4434
|
return data;
|
|
4434
4435
|
}
|
|
4435
|
-
async markThrottled(until) {
|
|
4436
|
+
async markThrottled(until, probeOnly = false) {
|
|
4436
4437
|
const data = await this.send({
|
|
4437
4438
|
v: PROTOCOL_VERSION,
|
|
4438
4439
|
id: randomUUID(),
|
|
4439
4440
|
op: "mark-throttled",
|
|
4440
|
-
until
|
|
4441
|
+
until,
|
|
4442
|
+
...probeOnly ? { probeOnly: true } : {}
|
|
4441
4443
|
});
|
|
4442
4444
|
return data;
|
|
4443
4445
|
}
|
|
@@ -12791,7 +12791,7 @@ function deriveOverlayTitle(raw, fileName) {
|
|
|
12791
12791
|
return;
|
|
12792
12792
|
return base.length > 0 ? base : undefined;
|
|
12793
12793
|
}
|
|
12794
|
-
function readOverlayFile(agentName, file, agentCfg, warnings) {
|
|
12794
|
+
function readOverlayFile(agentName, file, agentCfg, warnings, source) {
|
|
12795
12795
|
try {
|
|
12796
12796
|
return readFileSync(file, "utf-8");
|
|
12797
12797
|
} catch (err) {
|
|
@@ -12804,7 +12804,7 @@ function readOverlayFile(agentName, file, agentCfg, warnings) {
|
|
|
12804
12804
|
reason: `read error: ${err.message}`,
|
|
12805
12805
|
code: code ?? "EUNKNOWN"
|
|
12806
12806
|
};
|
|
12807
|
-
recordReadFailure(agentCfg, { file, code: w.code });
|
|
12807
|
+
recordReadFailure(agentCfg, { file, code: w.code, source });
|
|
12808
12808
|
warnings.push(w);
|
|
12809
12809
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${file}': ${w.reason}`);
|
|
12810
12810
|
return;
|
|
@@ -12868,14 +12868,14 @@ function applyAgentOverlays(config) {
|
|
|
12868
12868
|
reason: `read error: cannot list overlay directory (${code})`,
|
|
12869
12869
|
code
|
|
12870
12870
|
};
|
|
12871
|
-
recordReadFailure(agentCfg, { file: scheduleDir, code });
|
|
12871
|
+
recordReadFailure(agentCfg, { file: scheduleDir, code, source: "schedule" });
|
|
12872
12872
|
warnings.push(w);
|
|
12873
12873
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${scheduleDir}': ${w.reason}`);
|
|
12874
12874
|
});
|
|
12875
12875
|
if (files.length > 0) {
|
|
12876
12876
|
const merged = [...agentCfg.schedule ?? []];
|
|
12877
12877
|
for (const file of files) {
|
|
12878
|
-
const raw = readOverlayFile(agentName, file, agentCfg, warnings);
|
|
12878
|
+
const raw = readOverlayFile(agentName, file, agentCfg, warnings, "schedule");
|
|
12879
12879
|
if (raw === undefined)
|
|
12880
12880
|
continue;
|
|
12881
12881
|
try {
|
|
@@ -12920,7 +12920,7 @@ function applyAgentOverlays(config) {
|
|
|
12920
12920
|
reason: `read error: cannot list overlay directory (${code})`,
|
|
12921
12921
|
code
|
|
12922
12922
|
};
|
|
12923
|
-
recordReadFailure(agentCfg, { file: skillsDir, code });
|
|
12923
|
+
recordReadFailure(agentCfg, { file: skillsDir, code, source: "skills" });
|
|
12924
12924
|
warnings.push(w);
|
|
12925
12925
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${skillsDir}': ${w.reason}`);
|
|
12926
12926
|
});
|
|
@@ -12928,7 +12928,7 @@ function applyAgentOverlays(config) {
|
|
|
12928
12928
|
const merged = [...agentCfg.skills ?? []];
|
|
12929
12929
|
const seen = new Set(merged);
|
|
12930
12930
|
for (const file of skillFiles) {
|
|
12931
|
-
const raw = readOverlayFile(agentName, file, agentCfg, warnings);
|
|
12931
|
+
const raw = readOverlayFile(agentName, file, agentCfg, warnings, "skills");
|
|
12932
12932
|
if (raw === undefined)
|
|
12933
12933
|
continue;
|
|
12934
12934
|
try {
|
package/dist/cli/switchroom.js
CHANGED
|
@@ -2120,7 +2120,7 @@ var init_esm = __esm(() => {
|
|
|
2120
2120
|
});
|
|
2121
2121
|
|
|
2122
2122
|
// src/build-info.ts
|
|
2123
|
-
var VERSION = "0.20.
|
|
2123
|
+
var VERSION = "0.20.9", COMMIT_SHA = "63c4c44b";
|
|
2124
2124
|
|
|
2125
2125
|
// src/cli/resolve-version.ts
|
|
2126
2126
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -14664,7 +14664,7 @@ function deriveOverlayTitle(raw, fileName) {
|
|
|
14664
14664
|
return;
|
|
14665
14665
|
return base.length > 0 ? base : undefined;
|
|
14666
14666
|
}
|
|
14667
|
-
function readOverlayFile(agentName, file, agentCfg, warnings) {
|
|
14667
|
+
function readOverlayFile(agentName, file, agentCfg, warnings, source) {
|
|
14668
14668
|
try {
|
|
14669
14669
|
return readFileSync2(file, "utf-8");
|
|
14670
14670
|
} catch (err) {
|
|
@@ -14677,7 +14677,7 @@ function readOverlayFile(agentName, file, agentCfg, warnings) {
|
|
|
14677
14677
|
reason: `read error: ${err.message}`,
|
|
14678
14678
|
code: code ?? "EUNKNOWN"
|
|
14679
14679
|
};
|
|
14680
|
-
recordReadFailure(agentCfg, { file, code: w.code });
|
|
14680
|
+
recordReadFailure(agentCfg, { file, code: w.code, source });
|
|
14681
14681
|
warnings.push(w);
|
|
14682
14682
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${file}': ${w.reason}`);
|
|
14683
14683
|
return;
|
|
@@ -14741,14 +14741,14 @@ function applyAgentOverlays(config) {
|
|
|
14741
14741
|
reason: `read error: cannot list overlay directory (${code})`,
|
|
14742
14742
|
code
|
|
14743
14743
|
};
|
|
14744
|
-
recordReadFailure(agentCfg, { file: scheduleDir, code });
|
|
14744
|
+
recordReadFailure(agentCfg, { file: scheduleDir, code, source: "schedule" });
|
|
14745
14745
|
warnings.push(w);
|
|
14746
14746
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${scheduleDir}': ${w.reason}`);
|
|
14747
14747
|
});
|
|
14748
14748
|
if (files.length > 0) {
|
|
14749
14749
|
const merged = [...agentCfg.schedule ?? []];
|
|
14750
14750
|
for (const file of files) {
|
|
14751
|
-
const raw = readOverlayFile(agentName, file, agentCfg, warnings);
|
|
14751
|
+
const raw = readOverlayFile(agentName, file, agentCfg, warnings, "schedule");
|
|
14752
14752
|
if (raw === undefined)
|
|
14753
14753
|
continue;
|
|
14754
14754
|
try {
|
|
@@ -14793,7 +14793,7 @@ function applyAgentOverlays(config) {
|
|
|
14793
14793
|
reason: `read error: cannot list overlay directory (${code})`,
|
|
14794
14794
|
code
|
|
14795
14795
|
};
|
|
14796
|
-
recordReadFailure(agentCfg, { file: skillsDir, code });
|
|
14796
|
+
recordReadFailure(agentCfg, { file: skillsDir, code, source: "skills" });
|
|
14797
14797
|
warnings.push(w);
|
|
14798
14798
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${skillsDir}': ${w.reason}`);
|
|
14799
14799
|
});
|
|
@@ -14801,7 +14801,7 @@ function applyAgentOverlays(config) {
|
|
|
14801
14801
|
const merged = [...agentCfg.skills ?? []];
|
|
14802
14802
|
const seen = new Set(merged);
|
|
14803
14803
|
for (const file of skillFiles) {
|
|
14804
|
-
const raw = readOverlayFile(agentName, file, agentCfg, warnings);
|
|
14804
|
+
const raw = readOverlayFile(agentName, file, agentCfg, warnings, "skills");
|
|
14805
14805
|
if (raw === undefined)
|
|
14806
14806
|
continue;
|
|
14807
14807
|
try {
|
|
@@ -36014,7 +36014,8 @@ var init_protocol2 = __esm(() => {
|
|
|
36014
36014
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
36015
36015
|
op: exports_external.literal("mark-throttled"),
|
|
36016
36016
|
id: exports_external.string().min(1),
|
|
36017
|
-
until: exports_external.number().int().positive()
|
|
36017
|
+
until: exports_external.number().int().positive(),
|
|
36018
|
+
probeOnly: exports_external.boolean().optional()
|
|
36018
36019
|
});
|
|
36019
36020
|
RefreshAccountRequestSchema = exports_external.object({
|
|
36020
36021
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
@@ -36410,12 +36411,13 @@ class AuthBrokerClient {
|
|
|
36410
36411
|
const data = await this.send(req);
|
|
36411
36412
|
return data;
|
|
36412
36413
|
}
|
|
36413
|
-
async markThrottled(until) {
|
|
36414
|
+
async markThrottled(until, probeOnly = false) {
|
|
36414
36415
|
const data = await this.send({
|
|
36415
36416
|
v: PROTOCOL_VERSION,
|
|
36416
36417
|
id: randomUUID(),
|
|
36417
36418
|
op: "mark-throttled",
|
|
36418
|
-
until
|
|
36419
|
+
until,
|
|
36420
|
+
...probeOnly ? { probeOnly: true } : {}
|
|
36419
36421
|
});
|
|
36420
36422
|
return data;
|
|
36421
36423
|
}
|
|
@@ -12063,7 +12063,7 @@ function deriveOverlayTitle(raw, fileName) {
|
|
|
12063
12063
|
return;
|
|
12064
12064
|
return base.length > 0 ? base : undefined;
|
|
12065
12065
|
}
|
|
12066
|
-
function readOverlayFile(agentName, file, agentCfg, warnings) {
|
|
12066
|
+
function readOverlayFile(agentName, file, agentCfg, warnings, source) {
|
|
12067
12067
|
try {
|
|
12068
12068
|
return readFileSync(file, "utf-8");
|
|
12069
12069
|
} catch (err) {
|
|
@@ -12076,7 +12076,7 @@ function readOverlayFile(agentName, file, agentCfg, warnings) {
|
|
|
12076
12076
|
reason: `read error: ${err.message}`,
|
|
12077
12077
|
code: code ?? "EUNKNOWN"
|
|
12078
12078
|
};
|
|
12079
|
-
recordReadFailure(agentCfg, { file, code: w.code });
|
|
12079
|
+
recordReadFailure(agentCfg, { file, code: w.code, source });
|
|
12080
12080
|
warnings.push(w);
|
|
12081
12081
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${file}': ${w.reason}`);
|
|
12082
12082
|
return;
|
|
@@ -12140,14 +12140,14 @@ function applyAgentOverlays(config) {
|
|
|
12140
12140
|
reason: `read error: cannot list overlay directory (${code})`,
|
|
12141
12141
|
code
|
|
12142
12142
|
};
|
|
12143
|
-
recordReadFailure(agentCfg, { file: scheduleDir, code });
|
|
12143
|
+
recordReadFailure(agentCfg, { file: scheduleDir, code, source: "schedule" });
|
|
12144
12144
|
warnings.push(w);
|
|
12145
12145
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${scheduleDir}': ${w.reason}`);
|
|
12146
12146
|
});
|
|
12147
12147
|
if (files.length > 0) {
|
|
12148
12148
|
const merged = [...agentCfg.schedule ?? []];
|
|
12149
12149
|
for (const file of files) {
|
|
12150
|
-
const raw = readOverlayFile(agentName, file, agentCfg, warnings);
|
|
12150
|
+
const raw = readOverlayFile(agentName, file, agentCfg, warnings, "schedule");
|
|
12151
12151
|
if (raw === undefined)
|
|
12152
12152
|
continue;
|
|
12153
12153
|
try {
|
|
@@ -12192,7 +12192,7 @@ function applyAgentOverlays(config) {
|
|
|
12192
12192
|
reason: `read error: cannot list overlay directory (${code})`,
|
|
12193
12193
|
code
|
|
12194
12194
|
};
|
|
12195
|
-
recordReadFailure(agentCfg, { file: skillsDir, code });
|
|
12195
|
+
recordReadFailure(agentCfg, { file: skillsDir, code, source: "skills" });
|
|
12196
12196
|
warnings.push(w);
|
|
12197
12197
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${skillsDir}': ${w.reason}`);
|
|
12198
12198
|
});
|
|
@@ -12200,7 +12200,7 @@ function applyAgentOverlays(config) {
|
|
|
12200
12200
|
const merged = [...agentCfg.skills ?? []];
|
|
12201
12201
|
const seen = new Set(merged);
|
|
12202
12202
|
for (const file of skillFiles) {
|
|
12203
|
-
const raw = readOverlayFile(agentName, file, agentCfg, warnings);
|
|
12203
|
+
const raw = readOverlayFile(agentName, file, agentCfg, warnings, "skills");
|
|
12204
12204
|
if (raw === undefined)
|
|
12205
12205
|
continue;
|
|
12206
12206
|
try {
|
|
@@ -21493,7 +21493,7 @@ function allocateAgentUid(name) {
|
|
|
21493
21493
|
}
|
|
21494
21494
|
|
|
21495
21495
|
// src/build-info.ts
|
|
21496
|
-
var VERSION = "0.20.
|
|
21496
|
+
var VERSION = "0.20.9";
|
|
21497
21497
|
|
|
21498
21498
|
// src/setup/hindsight-recall-tunables.ts
|
|
21499
21499
|
var RECALL_DEADLINE_HEADROOM_SECONDS = 2;
|
|
@@ -12867,7 +12867,7 @@ function deriveOverlayTitle(raw, fileName) {
|
|
|
12867
12867
|
return;
|
|
12868
12868
|
return base.length > 0 ? base : undefined;
|
|
12869
12869
|
}
|
|
12870
|
-
function readOverlayFile(agentName, file, agentCfg, warnings) {
|
|
12870
|
+
function readOverlayFile(agentName, file, agentCfg, warnings, source) {
|
|
12871
12871
|
try {
|
|
12872
12872
|
return readFileSync2(file, "utf-8");
|
|
12873
12873
|
} catch (err) {
|
|
@@ -12880,7 +12880,7 @@ function readOverlayFile(agentName, file, agentCfg, warnings) {
|
|
|
12880
12880
|
reason: `read error: ${err.message}`,
|
|
12881
12881
|
code: code ?? "EUNKNOWN"
|
|
12882
12882
|
};
|
|
12883
|
-
recordReadFailure(agentCfg, { file, code: w.code });
|
|
12883
|
+
recordReadFailure(agentCfg, { file, code: w.code, source });
|
|
12884
12884
|
warnings.push(w);
|
|
12885
12885
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${file}': ${w.reason}`);
|
|
12886
12886
|
return;
|
|
@@ -12944,14 +12944,14 @@ function applyAgentOverlays(config) {
|
|
|
12944
12944
|
reason: `read error: cannot list overlay directory (${code})`,
|
|
12945
12945
|
code
|
|
12946
12946
|
};
|
|
12947
|
-
recordReadFailure(agentCfg, { file: scheduleDir, code });
|
|
12947
|
+
recordReadFailure(agentCfg, { file: scheduleDir, code, source: "schedule" });
|
|
12948
12948
|
warnings.push(w);
|
|
12949
12949
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${scheduleDir}': ${w.reason}`);
|
|
12950
12950
|
});
|
|
12951
12951
|
if (files.length > 0) {
|
|
12952
12952
|
const merged = [...agentCfg.schedule ?? []];
|
|
12953
12953
|
for (const file of files) {
|
|
12954
|
-
const raw = readOverlayFile(agentName, file, agentCfg, warnings);
|
|
12954
|
+
const raw = readOverlayFile(agentName, file, agentCfg, warnings, "schedule");
|
|
12955
12955
|
if (raw === undefined)
|
|
12956
12956
|
continue;
|
|
12957
12957
|
try {
|
|
@@ -12996,7 +12996,7 @@ function applyAgentOverlays(config) {
|
|
|
12996
12996
|
reason: `read error: cannot list overlay directory (${code})`,
|
|
12997
12997
|
code
|
|
12998
12998
|
};
|
|
12999
|
-
recordReadFailure(agentCfg, { file: skillsDir, code });
|
|
12999
|
+
recordReadFailure(agentCfg, { file: skillsDir, code, source: "skills" });
|
|
13000
13000
|
warnings.push(w);
|
|
13001
13001
|
console.warn(`[switchroom] overlay-loader: agent='${agentName}' file='${skillsDir}': ${w.reason}`);
|
|
13002
13002
|
});
|
|
@@ -13004,7 +13004,7 @@ function applyAgentOverlays(config) {
|
|
|
13004
13004
|
const merged = [...agentCfg.skills ?? []];
|
|
13005
13005
|
const seen = new Set(merged);
|
|
13006
13006
|
for (const file of skillFiles) {
|
|
13007
|
-
const raw = readOverlayFile(agentName, file, agentCfg, warnings);
|
|
13007
|
+
const raw = readOverlayFile(agentName, file, agentCfg, warnings, "skills");
|
|
13008
13008
|
if (raw === undefined)
|
|
13009
13009
|
continue;
|
|
13010
13010
|
try {
|