switchroom 0.20.8 → 0.20.10
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/bin/handoff-briefing.sh +57 -5
- package/bin/working-state-reload-hook.sh +262 -0
- package/dist/agent-scheduler/index.js +16 -13
- package/dist/auth-broker/index.js +70 -30
- 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 +42 -13
- 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/_base/start.sh.hbs +49 -0
- package/profiles/default/CLAUDE.md.hbs +12 -13
- package/telegram-plugin/ask-user.ts +6 -7
- package/telegram-plugin/dist/gateway/gateway.js +192 -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
- package/vendor/hindsight-memory/CHANGELOG.md +31 -0
- package/vendor/hindsight-memory/hooks/hooks.json +2 -1
- package/vendor/hindsight-memory/scripts/session_start.py +35 -8
- package/vendor/hindsight-memory/scripts/tests/test_session_start_durability.py +107 -0
|
@@ -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 {
|
|
@@ -19820,6 +19820,23 @@ function extractApiErrorMessage(bodyText) {
|
|
|
19820
19820
|
} catch {}
|
|
19821
19821
|
return bodyText.trim().slice(0, 500);
|
|
19822
19822
|
}
|
|
19823
|
+
function extractApiErrorCode(bodyText) {
|
|
19824
|
+
if (!bodyText || bodyText.trim().length === 0)
|
|
19825
|
+
return null;
|
|
19826
|
+
try {
|
|
19827
|
+
const parsed = JSON.parse(bodyText);
|
|
19828
|
+
const code = parsed?.error?.details?.error_code;
|
|
19829
|
+
if (typeof code === "string" && code.trim().length > 0)
|
|
19830
|
+
return code.trim();
|
|
19831
|
+
} catch {}
|
|
19832
|
+
return null;
|
|
19833
|
+
}
|
|
19834
|
+
var ENTITLEMENT_BLOCKED_ERROR_CODES = new Set([
|
|
19835
|
+
"oauth_not_allowed_for_organization"
|
|
19836
|
+
]);
|
|
19837
|
+
function isEntitlementBlockedErrorCode(code) {
|
|
19838
|
+
return code != null && ENTITLEMENT_BLOCKED_ERROR_CODES.has(code);
|
|
19839
|
+
}
|
|
19823
19840
|
function isEntitlementDisabledMessage(message) {
|
|
19824
19841
|
if (!message)
|
|
19825
19842
|
return false;
|
|
@@ -19877,7 +19894,8 @@ async function fetchQuota(opts) {
|
|
|
19877
19894
|
} catch {}
|
|
19878
19895
|
clearTimeout(timeout);
|
|
19879
19896
|
const apiErrorMessage = extractApiErrorMessage(bodyText);
|
|
19880
|
-
const
|
|
19897
|
+
const apiErrorCode = extractApiErrorCode(bodyText);
|
|
19898
|
+
const entitlement = resp.status === 403 && (isEntitlementBlockedErrorCode(apiErrorCode) || isEntitlementDisabledMessage(apiErrorMessage));
|
|
19881
19899
|
return {
|
|
19882
19900
|
ok: false,
|
|
19883
19901
|
reason: `HTTP ${resp.status} from Anthropic (${parsed.reason})`,
|
|
@@ -21286,7 +21304,8 @@ var MarkThrottledRequestSchema = exports_external.object({
|
|
|
21286
21304
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
21287
21305
|
op: exports_external.literal("mark-throttled"),
|
|
21288
21306
|
id: exports_external.string().min(1),
|
|
21289
|
-
until: exports_external.number().int().positive()
|
|
21307
|
+
until: exports_external.number().int().positive(),
|
|
21308
|
+
probeOnly: exports_external.boolean().optional()
|
|
21290
21309
|
});
|
|
21291
21310
|
var RefreshAccountRequestSchema = exports_external.object({
|
|
21292
21311
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
@@ -21568,8 +21587,8 @@ var AUTH_BROKER_ROOT2 = "/run/switchroom/auth-broker";
|
|
|
21568
21587
|
var REFRESH_TICK_INTERVAL_MS = 60 * 1000;
|
|
21569
21588
|
var MARK_EXHAUSTED_DEFAULT_MS = 5 * 60 * 60 * 1000;
|
|
21570
21589
|
var MARK_THROTTLED_MAX_MS = 30 * 60 * 1000;
|
|
21571
|
-
var THROTTLE_ESCALATION_HITS = 3;
|
|
21572
21590
|
var THROTTLE_ESCALATION_WINDOW_MS = 10 * 60 * 1000;
|
|
21591
|
+
var THROTTLE_ESCALATION_PROBE_MIN_INTERVAL_MS = 60 * 1000;
|
|
21573
21592
|
var MARK_THROTTLED_MIN_INTERVAL_MS = 5 * 1000;
|
|
21574
21593
|
var MARK_CORROBORATION_PROBE_DELAY_MS = 90 * 1000;
|
|
21575
21594
|
var AUDIT_ROTATE_BYTES = 10 * 1024 * 1024;
|
|
@@ -21663,6 +21682,7 @@ class AuthBroker {
|
|
|
21663
21682
|
externalSpendCache = null;
|
|
21664
21683
|
externalSpendInFlight = null;
|
|
21665
21684
|
probeInFlight = new Map;
|
|
21685
|
+
lastEscalationProbeAt = {};
|
|
21666
21686
|
shaIndex = {};
|
|
21667
21687
|
thresholdViolations = {};
|
|
21668
21688
|
notificationClaims = {};
|
|
@@ -22047,7 +22067,7 @@ class AuthBroker {
|
|
|
22047
22067
|
await this.opMarkExhausted(socket, reqId, identity, req.until);
|
|
22048
22068
|
break;
|
|
22049
22069
|
case "mark-throttled":
|
|
22050
|
-
await this.opMarkThrottled(socket, reqId, identity, req.until);
|
|
22070
|
+
await this.opMarkThrottled(socket, reqId, identity, req.until, req.probeOnly);
|
|
22051
22071
|
break;
|
|
22052
22072
|
case "refresh-account": {
|
|
22053
22073
|
const provider = req.provider ?? "anthropic";
|
|
@@ -22879,7 +22899,7 @@ class AuthBroker {
|
|
|
22879
22899
|
this.audit({ op: "mark-exhausted", identity, account, accountKind: "claude", ok: true });
|
|
22880
22900
|
socket.write(encodeSuccess(id, { account, rolled, rolledTo }));
|
|
22881
22901
|
}
|
|
22882
|
-
async opMarkThrottled(socket, id, identity, until) {
|
|
22902
|
+
async opMarkThrottled(socket, id, identity, until, probeOnly = false) {
|
|
22883
22903
|
const account = this.callerAccount(identity);
|
|
22884
22904
|
if (!account) {
|
|
22885
22905
|
this.audit({ op: "mark-throttled", identity, accountKind: "claude", ok: false, error: "no-active-account" });
|
|
@@ -22887,6 +22907,17 @@ class AuthBroker {
|
|
|
22887
22907
|
return;
|
|
22888
22908
|
}
|
|
22889
22909
|
const now = this.now();
|
|
22910
|
+
if (probeOnly) {
|
|
22911
|
+
const { escalated: escalated2, rolledTo: rolledTo2 } = await this.maybeEscalateThrottle(account, identity, now);
|
|
22912
|
+
this.audit({ op: "mark-throttled", identity, account, accountKind: "claude", ok: true });
|
|
22913
|
+
socket.write(encodeSuccess(id, {
|
|
22914
|
+
account,
|
|
22915
|
+
throttled_until: this.quota[account]?.throttled_until ?? 0,
|
|
22916
|
+
escalated: escalated2,
|
|
22917
|
+
rolledTo: escalated2 ? rolledTo2 : null
|
|
22918
|
+
}));
|
|
22919
|
+
return;
|
|
22920
|
+
}
|
|
22890
22921
|
const throttledUntil = Math.min(Math.max(until, now + 1000), now + MARK_THROTTLED_MAX_MS);
|
|
22891
22922
|
const entry = this.quota[account] ?? {};
|
|
22892
22923
|
const priorHits = entry.throttle_hits ?? [];
|
|
@@ -22908,31 +22939,19 @@ class AuthBroker {
|
|
|
22908
22939
|
}
|
|
22909
22940
|
const hits = priorHits.filter((t) => now - t < THROTTLE_ESCALATION_WINDOW_MS);
|
|
22910
22941
|
hits.push(now);
|
|
22911
|
-
const escalate = hits.length >= THROTTLE_ESCALATION_HITS;
|
|
22912
22942
|
this.quota[account] = {
|
|
22913
22943
|
...entry,
|
|
22914
22944
|
throttled_until: throttledUntil,
|
|
22915
|
-
throttle_hits:
|
|
22945
|
+
throttle_hits: hits
|
|
22916
22946
|
};
|
|
22917
22947
|
this.persistQuota();
|
|
22918
22948
|
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
|
|
22949
|
+
process.stdout.write(`auth-broker: mark-throttled ${account} until ${new Date(throttledUntil).toISOString()} ` + `(hit ${hits.length} in window)
|
|
22934
22950
|
`);
|
|
22935
|
-
|
|
22951
|
+
const { escalated, rolledTo } = await this.maybeEscalateThrottle(account, identity, now);
|
|
22952
|
+
if (escalated) {
|
|
22953
|
+
this.quota[account] = { ...this.quota[account], throttle_hits: [] };
|
|
22954
|
+
this.persistQuota();
|
|
22936
22955
|
}
|
|
22937
22956
|
socket.write(encodeSuccess(id, {
|
|
22938
22957
|
account,
|
|
@@ -22941,6 +22960,27 @@ class AuthBroker {
|
|
|
22941
22960
|
rolledTo: escalated ? rolledTo : null
|
|
22942
22961
|
}));
|
|
22943
22962
|
}
|
|
22963
|
+
async maybeEscalateThrottle(account, identity, now) {
|
|
22964
|
+
const lastProbeAt = this.lastEscalationProbeAt[account];
|
|
22965
|
+
const probeAllowed = lastProbeAt === undefined || now - lastProbeAt >= THROTTLE_ESCALATION_PROBE_MIN_INTERVAL_MS;
|
|
22966
|
+
if (!probeAllowed) {
|
|
22967
|
+
process.stdout.write(`auth-broker: throttle-escalation probe on ${account} rate-bounded — skipped
|
|
22968
|
+
`);
|
|
22969
|
+
return { escalated: false, rolledTo: null };
|
|
22970
|
+
}
|
|
22971
|
+
this.lastEscalationProbeAt[account] = now;
|
|
22972
|
+
const probe = await this.probeThrottleEscalation(account);
|
|
22973
|
+
if (!probe.exhausted) {
|
|
22974
|
+
process.stdout.write(`auth-broker: throttle-escalation probe on ${account} did NOT corroborate a wall — staying put
|
|
22975
|
+
`);
|
|
22976
|
+
return { escalated: false, rolledTo: null };
|
|
22977
|
+
}
|
|
22978
|
+
process.stdout.write(`auth-broker: throttle-escalation probe corroborates wall on ${account} — mark-exhausted + roll
|
|
22979
|
+
`);
|
|
22980
|
+
this.audit({ op: "mark-exhausted", identity, account, accountKind: "claude", ok: true, reason: "throttle-escalation" });
|
|
22981
|
+
const roll = await this.markExhaustedAndRoll(account, probe.until ?? undefined, identity);
|
|
22982
|
+
return { escalated: true, rolledTo: roll.rolledTo };
|
|
22983
|
+
}
|
|
22944
22984
|
async probeThrottleEscalation(account) {
|
|
22945
22985
|
const creds = readAccountCredentials(account, this.home);
|
|
22946
22986
|
const token = creds?.claudeAiOauth?.accessToken;
|
|
@@ -22948,7 +22988,7 @@ class AuthBroker {
|
|
|
22948
22988
|
return { exhausted: false, until: null };
|
|
22949
22989
|
let result;
|
|
22950
22990
|
try {
|
|
22951
|
-
result = await this.
|
|
22991
|
+
result = await this.probeQuotaSingleFlight(account, token);
|
|
22952
22992
|
} catch (err) {
|
|
22953
22993
|
this.logErr(`throttle-escalation probe ${account}: ${err.message}`);
|
|
22954
22994
|
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.10", COMMIT_SHA = "ebb54738";
|
|
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 {
|
|
@@ -18815,7 +18815,9 @@ function hindsightContainerEnvPairs(opts) {
|
|
|
18815
18815
|
...hindsightLlmBudgetEnv(llm),
|
|
18816
18816
|
["HINDSIGHT_API_WORKER_ID", HINDSIGHT_DEFAULT_WORKER_ID],
|
|
18817
18817
|
...hindsightPerfEnvPairs(llm, litellm, gpu, perf),
|
|
18818
|
-
...hindsightPgEnvPairs(perf)
|
|
18818
|
+
...hindsightPgEnvPairs(perf),
|
|
18819
|
+
["SWITCHROOM_HINDSIGHT_REQUEUE_DEAD_LETTERS", HINDSIGHT_DEFAULT_REQUEUE_DEAD_LETTERS],
|
|
18820
|
+
["SWITCHROOM_HINDSIGHT_REQUEUE_MAX", HINDSIGHT_DEFAULT_REQUEUE_MAX]
|
|
18819
18821
|
];
|
|
18820
18822
|
if (llmProvider === "claude-code") {
|
|
18821
18823
|
pairs.push(["ANTHROPIC_MODEL", llmModel]);
|
|
@@ -19086,6 +19088,8 @@ function generateHindsightComposeSnippet(llm, mirrorDir, litellm, gpu, perf, cpA
|
|
|
19086
19088
|
` - HINDSIGHT_API_WORKER_ID=${HINDSIGHT_DEFAULT_WORKER_ID}`,
|
|
19087
19089
|
...hindsightPerfEnvPairs(llm, litellm, gpu, perf).map(([k, v]) => ` - ${k}=${v}`),
|
|
19088
19090
|
...hindsightPgEnvPairs(perf).map(([k, v]) => ` - ${k}=${v}`),
|
|
19091
|
+
` - SWITCHROOM_HINDSIGHT_REQUEUE_DEAD_LETTERS=${HINDSIGHT_DEFAULT_REQUEUE_DEAD_LETTERS}`,
|
|
19092
|
+
` - SWITCHROOM_HINDSIGHT_REQUEUE_MAX=${HINDSIGHT_DEFAULT_REQUEUE_MAX}`,
|
|
19089
19093
|
` mem_limit: ${HINDSIGHT_DEFAULT_MEM_LIMIT}`,
|
|
19090
19094
|
` mem_reservation: ${HINDSIGHT_DEFAULT_MEM_RESERVATION}`,
|
|
19091
19095
|
` pids_limit: ${HINDSIGHT_DEFAULT_PIDS_LIMIT}`,
|
|
@@ -19184,7 +19188,7 @@ async function ensureHindsightConsumer(configPath, account, uid = HINDSIGHT_DEFA
|
|
|
19184
19188
|
atomicWriteFileSync3(configPath, tail, mode);
|
|
19185
19189
|
return { added: true, reason: "added" };
|
|
19186
19190
|
}
|
|
19187
|
-
var HINDSIGHT_DEFAULT_API_PORT = 18888, HINDSIGHT_DEFAULT_UI_PORT = 9999, HINDSIGHT_DEFAULT_MCP_URL, HINDSIGHT_DEFAULT_API_BASE_URL, HINDSIGHT_CONSUMER_NAME = "hindsight", HINDSIGHT_DEFAULT_WORKER_ID = "switchroom-hindsight", HINDSIGHT_DATA_VOLUME = "switchroom-hindsight-data", HINDSIGHT_DEFAULT_UID = 11000, HINDSIGHT_IMAGE_REPO = "ghcr.io/switchroom/switchroom-hindsight", HINDSIGHT_IMAGE, HINDSIGHT_DEFAULT_MODEL = "claude-sonnet-5", HINDSIGHT_DEFAULT_LITELLM_MODEL = "openrouter/google/gemini-3.1-flash-lite", HINDSIGHT_DEFAULT_MCP_STATELESS = true, HINDSIGHT_BROKER_SOCK_VOLUME, HINDSIGHT_CREDS_MIRROR_VOLUME, HINDSIGHT_CRED_DIR = "/run/claude-creds", HINDSIGHT_RETAIN_CHUNK_SIZE = 3000, HINDSIGHT_DEFAULT_RETAIN_MAX_COMPLETION_TOKENS = 16384, HINDSIGHT_RETAIN_MIN_TOKENS_PER_SECOND = 80.6, HINDSIGHT_RETAIN_CLIENT_DEADLINE_S, HINDSIGHT_DEFAULT_MEM_LIMIT = "16g", HINDSIGHT_DEFAULT_MEM_RESERVATION = "4g", HINDSIGHT_DEFAULT_PIDS_LIMIT = 1000, HINDSIGHT_DEFAULT_SHM_SIZE = "2g", HINDSIGHT_HEALTHCHECK_PY = 'import urllib.request,sys; sys.exit(0 if urllib.request.urlopen("http://localhost:8888/health",timeout=4).getcode()==200 else 1)', HINDSIGHT_HEALTHCHECK_CMD, DOCKER_PROBE_TIMEOUT_MS, defaultDockerProbe = (args) => {
|
|
19191
|
+
var HINDSIGHT_DEFAULT_API_PORT = 18888, HINDSIGHT_DEFAULT_UI_PORT = 9999, HINDSIGHT_DEFAULT_MCP_URL, HINDSIGHT_DEFAULT_API_BASE_URL, HINDSIGHT_CONSUMER_NAME = "hindsight", HINDSIGHT_DEFAULT_WORKER_ID = "switchroom-hindsight", HINDSIGHT_DATA_VOLUME = "switchroom-hindsight-data", HINDSIGHT_DEFAULT_UID = 11000, HINDSIGHT_IMAGE_REPO = "ghcr.io/switchroom/switchroom-hindsight", HINDSIGHT_IMAGE, HINDSIGHT_DEFAULT_MODEL = "claude-sonnet-5", HINDSIGHT_DEFAULT_LITELLM_MODEL = "openrouter/google/gemini-3.1-flash-lite", HINDSIGHT_DEFAULT_MCP_STATELESS = true, HINDSIGHT_DEFAULT_REQUEUE_DEAD_LETTERS = "1", HINDSIGHT_DEFAULT_REQUEUE_MAX = "25", HINDSIGHT_BROKER_SOCK_VOLUME, HINDSIGHT_CREDS_MIRROR_VOLUME, HINDSIGHT_CRED_DIR = "/run/claude-creds", HINDSIGHT_RETAIN_CHUNK_SIZE = 3000, HINDSIGHT_DEFAULT_RETAIN_MAX_COMPLETION_TOKENS = 16384, HINDSIGHT_RETAIN_MIN_TOKENS_PER_SECOND = 80.6, HINDSIGHT_RETAIN_CLIENT_DEADLINE_S, HINDSIGHT_DEFAULT_MEM_LIMIT = "16g", HINDSIGHT_DEFAULT_MEM_RESERVATION = "4g", HINDSIGHT_DEFAULT_PIDS_LIMIT = 1000, HINDSIGHT_DEFAULT_SHM_SIZE = "2g", HINDSIGHT_HEALTHCHECK_PY = 'import urllib.request,sys; sys.exit(0 if urllib.request.urlopen("http://localhost:8888/health",timeout=4).getcode()==200 else 1)', HINDSIGHT_HEALTHCHECK_CMD, DOCKER_PROBE_TIMEOUT_MS, defaultDockerProbe = (args) => {
|
|
19188
19192
|
try {
|
|
19189
19193
|
return execFileSync2("docker", args, {
|
|
19190
19194
|
stdio: "pipe",
|
|
@@ -31105,6 +31109,18 @@ function buildSettingsHooksBlock(p) {
|
|
|
31105
31109
|
]
|
|
31106
31110
|
}
|
|
31107
31111
|
];
|
|
31112
|
+
const switchroomSessionStart = [
|
|
31113
|
+
{
|
|
31114
|
+
matcher: "compact",
|
|
31115
|
+
hooks: [
|
|
31116
|
+
{
|
|
31117
|
+
type: "command",
|
|
31118
|
+
command: wrap("hook:working-state-reload", `bash "${join12(DOCKER_BIN_PATH, "working-state-reload-hook.sh")}"`),
|
|
31119
|
+
timeout: 8
|
|
31120
|
+
}
|
|
31121
|
+
]
|
|
31122
|
+
}
|
|
31123
|
+
];
|
|
31108
31124
|
if (userHooks) {
|
|
31109
31125
|
return {
|
|
31110
31126
|
...userHooks,
|
|
@@ -31112,6 +31128,10 @@ function buildSettingsHooksBlock(p) {
|
|
|
31112
31128
|
...userHooks.UserPromptSubmit ?? [],
|
|
31113
31129
|
...switchroomUserPromptSubmit
|
|
31114
31130
|
],
|
|
31131
|
+
SessionStart: [
|
|
31132
|
+
...userHooks.SessionStart ?? [],
|
|
31133
|
+
...switchroomSessionStart
|
|
31134
|
+
],
|
|
31115
31135
|
...switchroomPreToolUse.length > 0 ? {
|
|
31116
31136
|
PreToolUse: [
|
|
31117
31137
|
...userHooks.PreToolUse ?? [],
|
|
@@ -31134,6 +31154,7 @@ function buildSettingsHooksBlock(p) {
|
|
|
31134
31154
|
}
|
|
31135
31155
|
return {
|
|
31136
31156
|
UserPromptSubmit: switchroomUserPromptSubmit,
|
|
31157
|
+
SessionStart: switchroomSessionStart,
|
|
31137
31158
|
...switchroomPreToolUse.length > 0 ? { PreToolUse: switchroomPreToolUse } : {},
|
|
31138
31159
|
...switchroomPostToolUse.length > 0 ? { PostToolUse: switchroomPostToolUse } : {},
|
|
31139
31160
|
...switchroomStop.length > 0 ? { Stop: switchroomStop } : {}
|
|
@@ -36014,7 +36035,8 @@ var init_protocol2 = __esm(() => {
|
|
|
36014
36035
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
36015
36036
|
op: exports_external.literal("mark-throttled"),
|
|
36016
36037
|
id: exports_external.string().min(1),
|
|
36017
|
-
until: exports_external.number().int().positive()
|
|
36038
|
+
until: exports_external.number().int().positive(),
|
|
36039
|
+
probeOnly: exports_external.boolean().optional()
|
|
36018
36040
|
});
|
|
36019
36041
|
RefreshAccountRequestSchema = exports_external.object({
|
|
36020
36042
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
@@ -36410,12 +36432,13 @@ class AuthBrokerClient {
|
|
|
36410
36432
|
const data = await this.send(req);
|
|
36411
36433
|
return data;
|
|
36412
36434
|
}
|
|
36413
|
-
async markThrottled(until) {
|
|
36435
|
+
async markThrottled(until, probeOnly = false) {
|
|
36414
36436
|
const data = await this.send({
|
|
36415
36437
|
v: PROTOCOL_VERSION,
|
|
36416
36438
|
id: randomUUID(),
|
|
36417
36439
|
op: "mark-throttled",
|
|
36418
|
-
until
|
|
36440
|
+
until,
|
|
36441
|
+
...probeOnly ? { probeOnly: true } : {}
|
|
36419
36442
|
});
|
|
36420
36443
|
return data;
|
|
36421
36444
|
}
|
|
@@ -63669,7 +63692,7 @@ function checkNodeVersion() {
|
|
|
63669
63692
|
}
|
|
63670
63693
|
return { name: "Node 18+", status: "ok", detail: label };
|
|
63671
63694
|
}
|
|
63672
|
-
function findChromium(homeDir = process.env.HOME ?? "", envBrowsersPath = process.env.PLAYWRIGHT_BROWSERS_PATH) {
|
|
63695
|
+
function findChromium(homeDir = process.env.HOME ?? "", envBrowsersPath = process.env.PLAYWRIGHT_BROWSERS_PATH, bakedBrowsersPath = "/opt/playwright/browsers") {
|
|
63673
63696
|
const candidates = [
|
|
63674
63697
|
"chromium",
|
|
63675
63698
|
"chromium-browser",
|
|
@@ -63686,6 +63709,9 @@ function findChromium(homeDir = process.env.HOME ?? "", envBrowsersPath = proces
|
|
|
63686
63709
|
cacheLocations.push(envBrowsersPath);
|
|
63687
63710
|
}
|
|
63688
63711
|
cacheLocations.push(join74(homeDir, ".cache", "ms-playwright"));
|
|
63712
|
+
if (bakedBrowsersPath && bakedBrowsersPath.length > 0) {
|
|
63713
|
+
cacheLocations.push(bakedBrowsersPath);
|
|
63714
|
+
}
|
|
63689
63715
|
for (const cacheDir of cacheLocations) {
|
|
63690
63716
|
if (!existsSync69(cacheDir))
|
|
63691
63717
|
continue;
|
|
@@ -88253,6 +88279,9 @@ function refillNormalizedUtils(q, now) {
|
|
|
88253
88279
|
sevenDayRefilled
|
|
88254
88280
|
};
|
|
88255
88281
|
}
|
|
88282
|
+
var ENTITLEMENT_BLOCKED_ERROR_CODES = new Set([
|
|
88283
|
+
"oauth_not_allowed_for_organization"
|
|
88284
|
+
]);
|
|
88256
88285
|
|
|
88257
88286
|
// src/cli/auth-schedule.ts
|
|
88258
88287
|
function overageReasonBlocks(reason) {
|
|
@@ -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.10";
|
|
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 {
|