switchroom 0.19.43 → 0.19.44
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 +4 -1
- package/dist/auth-broker/index.js +254 -119
- package/dist/cli/notion-write-pretool.mjs +4 -1
- package/dist/cli/switchroom.js +3281 -2416
- package/dist/host-control/main.js +270 -130
- package/dist/vault/approvals/kernel-server.js +201 -66
- package/dist/vault/broker/server.js +263 -128
- package/package.json +1 -1
- package/profiles/_base/start.sh.hbs +11 -4
- package/telegram-plugin/dist/gateway/gateway.js +463 -328
- package/vendor/hindsight-memory/scripts/lib/config.py +15 -0
- package/vendor/hindsight-memory/scripts/tests/test_retain_provenance_tag.py +135 -0
- package/vendor/hindsight-memory/settings.json +1 -1
|
@@ -21547,7 +21547,7 @@ var init_observation_scopes = __esm(() => {
|
|
|
21547
21547
|
});
|
|
21548
21548
|
|
|
21549
21549
|
// ../src/config/schema.ts
|
|
21550
|
-
var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleWorkspaceConfigSchema, LiteLLMConfigSchema, HindsightPerOpLlmSchema, HindsightConfigSchema, MicrosoftWorkspaceConfigSchema, NotionWorkspaceConfigSchema, AgentGoogleWorkspaceConfigSchema, MicrosoftAccountEmailSchema, MicrosoftToolTokenSchema, MicrosoftAccountBindingSchema, AgentMicrosoftWorkspaceConfigSchema, AgentNotionWorkspaceConfigSchema, ReactionsSchema, ReactionDispatchSchema, releaseBlockFields, ReleaseBlock, RootReleaseBlock, NetworkIsolationSchema, servesField, knowsField, profileFields, ProfileSchema, _omitExtends, defaultsFields, AgentDefaultsSchema, AgentSchema, TelegramConfigSchema, MemoryBackendConfigSchema, VaultConfigSchema, QuotaConfigSchema, AutoReleaseCheckSchema, HostControlConfigSchema, WebServiceConfigSchema, FleetHealthConfigSchema, HostdConfigSchema, CronEgressSchema, CronConfigSchema, UserSchema, SwitchroomConfigSchema;
|
|
21550
|
+
var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AntiConfabulationDirectiveSchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleWorkspaceConfigSchema, LiteLLMConfigSchema, HindsightPerOpLlmSchema, HindsightConfigSchema, MicrosoftWorkspaceConfigSchema, NotionWorkspaceConfigSchema, AgentGoogleWorkspaceConfigSchema, MicrosoftAccountEmailSchema, MicrosoftToolTokenSchema, MicrosoftAccountBindingSchema, AgentMicrosoftWorkspaceConfigSchema, AgentNotionWorkspaceConfigSchema, ReactionsSchema, ReactionDispatchSchema, releaseBlockFields, ReleaseBlock, RootReleaseBlock, NetworkIsolationSchema, servesField, knowsField, profileFields, ProfileSchema, _omitExtends, defaultsFields, AgentDefaultsSchema, AgentSchema, TelegramConfigSchema, MemoryBackendConfigSchema, VaultConfigSchema, QuotaConfigSchema, AutoReleaseCheckSchema, HostControlConfigSchema, WebServiceConfigSchema, FleetHealthConfigSchema, HostdConfigSchema, CronEgressSchema, CronConfigSchema, UserSchema, SwitchroomConfigSchema;
|
|
21551
21551
|
var init_schema = __esm(() => {
|
|
21552
21552
|
init_zod();
|
|
21553
21553
|
init_observation_scopes();
|
|
@@ -21664,6 +21664,7 @@ var init_schema = __esm(() => {
|
|
|
21664
21664
|
}).optional();
|
|
21665
21665
|
ObservationScopesSchema = exports_external.enum(OBSERVATION_SCOPES).optional().describe("Operator PIN for the per-row observation scope, overriding the " + 'default `curated` strategy (see docs/configuration.md). "shared" ' + "forces Hindsight's consolidation to write EVERY observation into ONE " + "global untagged scope \u2014 what several agents pooling one bank want so " + "their observations merge rather than sitting in parallel silos. " + '"combined" is the pin form of opting out (restores the pre-#4035 ' + "engine default). UNSET does NOT mean 'nothing on the wire': the " + "`curated` strategy still computes a scope per retain. Applies to " + "every retain path (Stop hook, " + "sidechain, boot reconcile, queue drain, backfill, session-handoff " + "mirror) and is carried on the queued payload, so a retain that fails " + "now and drains later still lands in this scope. Accepted values: " + `${OBSERVATION_SCOPES.join(", ")}. ` + "Cascade: override (per-agent wins over default).");
|
|
21666
21666
|
ObservationScopeStrategySchema = exports_external.enum(OBSERVATION_SCOPE_STRATEGIES).optional().describe("Per-retain strategy that decides how the observation scope is " + 'computed when no `observation_scopes` pin is set. "curated" ' + "(the default since #4035) strips volatile per-session provenance " + "tags from each retain's consolidation scope \u2014 keeping the stable " + "semantic ones on the source fact \u2014 so an agent's observations dedup " + "and merge across sessions instead of pocketing one-per-session. " + '"shared" sends every retain to the one global untagged scope. ' + '"combined" / "off" opt OUT: no per-row scope goes on the wire, ' + "restoring the pre-feature engine default (byte-identical to an " + "unconfigured client). OMITTED BY DEFAULT: unset leaves the plugin's " + "own default (`curated`) in force. A manual `observation_scopes` pin " + "wins over this strategy. Accepted values: " + `${OBSERVATION_SCOPE_STRATEGIES.join(", ")}. ` + "Cascade: override (per-agent wins over default).");
|
|
21667
|
+
AntiConfabulationDirectiveSchema = exports_external.union([exports_external.boolean(), exports_external.string().min(1)]).optional().describe("The seeded anti-confabulation directive: reflect has no relevance " + "floor (`min_scores` is a /recall-only parameter), so a bank holding " + "nothing relevant still yields a confident answer, and a question that " + "presupposes a decision reliably produces one. Directives ARE applied " + "during reflect, so this is the lever. Unset or true (the default) " + "seeds and maintains switchroom's own text; false disables seeding and " + "leaves any existing directive untouched; a string is operator-authored " + "text that wins outright. Switchroom only ever upgrades directive text " + "byte-equal to a default it shipped, so editing the directive in the " + "bank is also a permanent override. " + "Cascade: override (per-agent wins over default).");
|
|
21667
21668
|
AgentMemorySchema = exports_external.object({
|
|
21668
21669
|
collection: exports_external.string().describe("Hindsight collection name for this agent"),
|
|
21669
21670
|
auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
|
|
@@ -21699,6 +21700,7 @@ var init_schema = __esm(() => {
|
|
|
21699
21700
|
empathy: exports_external.number().int().min(1).max(5).optional().describe("How much the bank weights emotional/relational context (1-5; engine default 3).")
|
|
21700
21701
|
}).optional().describe("Personality traits (1-5 each) steering how this bank frames recall, " + "reflect, and observation synthesis \u2014 a coach leans empathy-high, a " + "lawyer/analyst leans skepticism/literalism-high. Maps to the engine's " + "flat `disposition_skepticism`/`_literalism`/`_empathy` fields. " + "Cascade: per-key merge (an agent overrides individual traits and " + "inherits the rest, matching `recall`)."),
|
|
21701
21702
|
directive_capture_nudge: exports_external.boolean().optional().describe("Deterministic directive-capture nudge (issue #2848 Stage B). When " + "on (switchroom default true \u2014 Stage A measured a ~55% miss rate on " + "durable corrections), the auto-recall hook regex-detects correction " + '/ standing-rule-shaped inbound ("always/never \u2026", "from now on \u2026", ' + `"stop doing \u2026", a stated preference, "that's wrong, it's \u2026") and ` + "appends a terse advisory to the turn's context telling the model to " + "persist the rule with mcp__hindsight__create_directive if it IS " + "durable. Detection is pure regex \u2014 the model does the judgment " + "in-session and calls create_directive itself (no model callsite, no " + "silent hook-side write). Set false to disable per-agent. " + "Cascade: override (per-agent wins over default)."),
|
|
21703
|
+
anti_confabulation_directive: AntiConfabulationDirectiveSchema,
|
|
21702
21704
|
observation_scopes: ObservationScopesSchema,
|
|
21703
21705
|
observation_scope_strategy: ObservationScopeStrategySchema,
|
|
21704
21706
|
recall: exports_external.object({
|
|
@@ -21969,7 +21971,7 @@ var init_schema = __esm(() => {
|
|
|
21969
21971
|
reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent \u2192 uses global."),
|
|
21970
21972
|
consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent \u2192 global.")
|
|
21971
21973
|
}).optional().describe("LLM knob for the hindsight container. The flat `provider`/`model` set " + "the global default (backward-compatible); optional `retain`/`reflect`/" + "`consolidation` blocks override individual ops. All fields optional; " + "unset fields fall back to the hard-coded defaults."),
|
|
21972
|
-
env: exports_external.record(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional().describe("Operator overrides for switchroom's capability-gated Hindsight " + "performance defaults. Only the keys switchroom actually manages are " + "honoured (`HINDSIGHT_PERF_ENV_KEYS` in " + "src/setup/hindsight-perf-defaults.ts: RERANKER_LOCAL_FP16, " + "RERANKER_LOCAL_BATCH_SIZE, LLM_MAX_CONCURRENT, " + "RETAIN/CONSOLIDATION_LLM_MAX_CONCURRENT, LLM_STRICT_SCHEMA, " + "LLM_MAX_RETRIES, CONSOLIDATION_LLM_PARALLELISM, " + "MAX_OBSERVATIONS_PER_SCOPE, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT, " + "RERANKER_LOCAL_BUCKET_BATCHING, RERANKER_MAX_CANDIDATES, " + "RERANKER_LOCAL_MAX_CONCURRENT, RECALL_MAX_CONCURRENT, " + "REFLECT_WALL_TIMEOUT, WORKER_CONSOLIDATION_RESERVED_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND, GRAPH_SEED_MIN_SIMILARITY, " + "LLM_SUPPORTS_MAX_ITEMS, RECENCY_DECAY_FUNCTION, " + "RECENCY_DECAY_HALFLIFE_DAYS \u2014 switchroom defaults recall's recency " + "curve to `exponential` with a 30-day half-life so a fact retained " + "today outranks a stale one, instead of upstream's near-flat " + "linear/365-day window), the override-only keys " + "switchroom manages but ships NO default for " + "(`HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS`: " + "HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY \u2014 a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP \u2014 the rollback knob for " + "switchroom's CE-saturation damping patch, a float; >= ~0.65 backs the " + "damping out entirely, unset means the patch's own derived gap; and " + "HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS \u2014 only read when the " + "decay function is `linear`, so switchroom ships no default for it but " + "still honours an operator who flips the function back; and " + "HINDSIGHT_API_WORKER_MAX_SLOTS \u2014 the worker poller's TOTAL in-flight " + "task budget, the pool WORKER_CONSOLIDATION_RESERVED_SLOTS reserves out of; " + "unset means upstream's own default; and " + "HINDSIGHT_API_WORKER_RETAIN_RESERVED_SLOTS \u2014 the reserved slot FLOOR for the " + "retain (memory write) lane, carved from that same total; unset means " + "upstream's own 0, i.e. no floor and retain competes for the shared " + "pool; and " + "the pre-0.8.6 name HINDSIGHT_API_WORKER_<TYPE>_MAX_SLOTS is still " + "accepted for every operation type and normalised to " + "..._RESERVED_SLOTS on the way in, because setting both names for " + "one type is a hard boot failure in the engine and switchroom " + "therefore emits only the canonical name; and " + "HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY \u2014 the cosine-similarity floor a " + "candidate must reach to be returned by the semantic retrieval arm at " + "all (0..1); unset means upstream's own 0.3, and where it should sit " + "depends on the bank's embedding model and phrasing diversity, so " + "switchroom ships no opinion; and " + "HINDSIGHT_MCP_RECALL_BUDGET_MODE \u2014 the rollback knob for switchroom's " + "mcp-recall-token-budget image patch; `legacy` restores upstream's " + "exact pre-patch recall returns, anything else or unset is the " + "honest-envelope mode; and " + "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT \u2014 upstream's own per-op reflect " + "temperature knob, made live by switchroom's reflect-temperature image " + "patch; a float, or `none` to omit the kwarg (provider default, " + "upstream's accidental pre-patch behaviour); unset means the image's " + "baked default 0.1), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS \u2014 a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED \u2014 a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
|
|
21974
|
+
env: exports_external.record(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional().describe("Operator overrides for switchroom's capability-gated Hindsight " + "performance defaults. Only the keys switchroom actually manages are " + "honoured (`HINDSIGHT_PERF_ENV_KEYS` in " + "src/setup/hindsight-perf-defaults.ts: RERANKER_LOCAL_FP16, " + "RERANKER_LOCAL_BATCH_SIZE, LLM_MAX_CONCURRENT, " + "RETAIN/CONSOLIDATION_LLM_MAX_CONCURRENT, LLM_STRICT_SCHEMA, " + "LLM_MAX_RETRIES, CONSOLIDATION_LLM_PARALLELISM, " + "MAX_OBSERVATIONS_PER_SCOPE, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT, " + "RERANKER_LOCAL_BUCKET_BATCHING, RERANKER_MAX_CANDIDATES, " + "RERANKER_LOCAL_MAX_CONCURRENT, RECALL_MAX_CONCURRENT, " + "REFLECT_WALL_TIMEOUT, WORKER_CONSOLIDATION_RESERVED_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND, GRAPH_SEED_MIN_SIMILARITY, " + "LLM_SUPPORTS_MAX_ITEMS, RECENCY_DECAY_FUNCTION, " + "RECENCY_DECAY_HALFLIFE_DAYS \u2014 switchroom defaults recall's recency " + "curve to `exponential` with a 30-day half-life so a fact retained " + "today outranks a stale one, instead of upstream's near-flat " + "linear/365-day window), the override-only keys " + "switchroom manages but ships NO default for " + "(`HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS`: " + "HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY \u2014 a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP \u2014 the rollback knob for " + "switchroom's CE-saturation damping patch, a float; >= ~0.65 backs the " + "damping out entirely, unset means the patch's own derived gap; and " + "HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS \u2014 only read when the " + "decay function is `linear`, so switchroom ships no default for it but " + "still honours an operator who flips the function back; and " + "HINDSIGHT_API_WORKER_MAX_SLOTS \u2014 the worker poller's TOTAL in-flight " + "task budget, the pool WORKER_CONSOLIDATION_RESERVED_SLOTS reserves out of; " + "unset means upstream's own default; and " + "HINDSIGHT_API_WORKER_RETAIN_RESERVED_SLOTS \u2014 the reserved slot FLOOR for the " + "retain (memory write) lane, carved from that same total; unset means " + "upstream's own 0, i.e. no floor and retain competes for the shared " + "pool; and " + "the pre-0.8.6 name HINDSIGHT_API_WORKER_<TYPE>_MAX_SLOTS is still " + "accepted for every operation type and normalised to " + "..._RESERVED_SLOTS on the way in, because setting both names for " + "one type is a hard boot failure in the engine and switchroom " + "therefore emits only the canonical name; and " + "HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY \u2014 the cosine-similarity floor a " + "candidate must reach to be returned by the semantic retrieval arm at " + "all (0..1); unset means upstream's own 0.3, and where it should sit " + "depends on the bank's embedding model and phrasing diversity, so " + "switchroom ships no opinion; and " + "HINDSIGHT_MCP_RECALL_BUDGET_MODE \u2014 the rollback knob for switchroom's " + "mcp-recall-token-budget image patch; `legacy` restores upstream's " + "exact pre-patch recall returns, anything else or unset is the " + "honest-envelope mode; and " + "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT \u2014 upstream's own per-op reflect " + "temperature knob, made live by switchroom's reflect-temperature image " + "patch; a float, or `none` to omit the kwarg (provider default, " + "upstream's accidental pre-patch behaviour); unset means the image's " + "baked default 0.1; and " + "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT \u2014 the background " + "half of switchroom's recall-admission split (#3660): of the " + "RECALL_MAX_CONCURRENT admission slots, at most this many may be held " + "by background consolidation recalls at once, so foreground per-turn " + "recall always keeps the remainder; must be >= 1 and strictly less " + "than RECALL_MAX_CONCURRENT or the engine refuses to boot; unset " + "means the image's derived default min(2, RECALL_MAX_CONCURRENT - 1); " + "1 biases hard toward the interactive lane while a consolidation " + "backlog drains), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS \u2014 a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED \u2014 a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
|
|
21973
21975
|
});
|
|
21974
21976
|
MicrosoftWorkspaceConfigSchema = exports_external.object({
|
|
21975
21977
|
microsoft_client_id: exports_external.string().min(1).optional().describe("Microsoft OAuth application (client) ID from Entra portal " + "(literal string or vault reference e.g. " + "'vault:microsoft-oauth-client-id'). OPTIONAL \u2014 omit it to use " + "switchroom's shipped default Microsoft app (zero-config). " + "Set it only to bring your own Entra app (BYO)."),
|
|
@@ -22103,6 +22105,7 @@ var init_schema = __esm(() => {
|
|
|
22103
22105
|
isolation: exports_external.enum(["default", "strict"]).optional(),
|
|
22104
22106
|
profile: exports_external.string().optional(),
|
|
22105
22107
|
directive_capture_nudge: exports_external.boolean().optional(),
|
|
22108
|
+
anti_confabulation_directive: AntiConfabulationDirectiveSchema,
|
|
22106
22109
|
observation_scopes: ObservationScopesSchema,
|
|
22107
22110
|
observation_scope_strategy: ObservationScopeStrategySchema,
|
|
22108
22111
|
recall: exports_external.object({
|
|
@@ -30147,7 +30150,7 @@ var init_turn_flush_suppression = () => {};
|
|
|
30147
30150
|
|
|
30148
30151
|
// ../src/agents/generation-stamp.ts
|
|
30149
30152
|
import { createHash as createHash6 } from "node:crypto";
|
|
30150
|
-
import { existsSync as
|
|
30153
|
+
import { existsSync as existsSync33, readFileSync as readFileSync32, writeFileSync as writeFileSync28 } from "node:fs";
|
|
30151
30154
|
import { join as join41 } from "node:path";
|
|
30152
30155
|
function sha256Text(s) {
|
|
30153
30156
|
return createHash6("sha256").update(s, "utf-8").digest("hex");
|
|
@@ -30159,11 +30162,11 @@ function hashManagedClaudeMd(content3) {
|
|
|
30159
30162
|
}
|
|
30160
30163
|
function hashStampedFileOnDisk(agentDir, rel) {
|
|
30161
30164
|
const p = join41(agentDir, rel);
|
|
30162
|
-
if (!
|
|
30165
|
+
if (!existsSync33(p))
|
|
30163
30166
|
return null;
|
|
30164
30167
|
let content3;
|
|
30165
30168
|
try {
|
|
30166
|
-
content3 =
|
|
30169
|
+
content3 = readFileSync32(p, "utf-8");
|
|
30167
30170
|
} catch {
|
|
30168
30171
|
return null;
|
|
30169
30172
|
}
|
|
@@ -30171,10 +30174,10 @@ function hashStampedFileOnDisk(agentDir, rel) {
|
|
|
30171
30174
|
}
|
|
30172
30175
|
function readGenerationStamp(agentDir) {
|
|
30173
30176
|
const p = join41(agentDir, GENERATION_STAMP_FILE);
|
|
30174
|
-
if (!
|
|
30177
|
+
if (!existsSync33(p))
|
|
30175
30178
|
return null;
|
|
30176
30179
|
try {
|
|
30177
|
-
const parsed = JSON.parse(
|
|
30180
|
+
const parsed = JSON.parse(readFileSync32(p, "utf-8"));
|
|
30178
30181
|
if (parsed?.version !== 1 || typeof parsed.files !== "object" || parsed.files === null || Array.isArray(parsed.files)) {
|
|
30179
30182
|
return null;
|
|
30180
30183
|
}
|
|
@@ -35984,19 +35987,19 @@ function renderAuthLine(state7, agentName3, now = Date.now()) {
|
|
|
35984
35987
|
}
|
|
35985
35988
|
|
|
35986
35989
|
// gateway/quota-cache.ts
|
|
35987
|
-
import { existsSync as
|
|
35988
|
-
import { join as
|
|
35990
|
+
import { existsSync as existsSync45, readFileSync as readFileSync45, writeFileSync as writeFileSync37, mkdirSync as mkdirSync39 } from "fs";
|
|
35991
|
+
import { join as join53, dirname as dirname22 } from "path";
|
|
35989
35992
|
function defaultCachePath() {
|
|
35990
|
-
return process.env.SWITCHROOM_QUOTA_CACHE_PATH ??
|
|
35993
|
+
return process.env.SWITCHROOM_QUOTA_CACHE_PATH ?? join53(process.env.HOME ?? "/tmp", ".switchroom", "quota-cache.json");
|
|
35991
35994
|
}
|
|
35992
35995
|
function readQuotaCache(opts = {}) {
|
|
35993
35996
|
const path3 = opts.path ?? defaultCachePath();
|
|
35994
35997
|
const now = opts.now ?? Date.now();
|
|
35995
|
-
if (!
|
|
35998
|
+
if (!existsSync45(path3))
|
|
35996
35999
|
return null;
|
|
35997
36000
|
let entry;
|
|
35998
36001
|
try {
|
|
35999
|
-
entry = JSON.parse(
|
|
36002
|
+
entry = JSON.parse(readFileSync45(path3, "utf8"));
|
|
36000
36003
|
} catch {
|
|
36001
36004
|
return null;
|
|
36002
36005
|
}
|
|
@@ -36033,8 +36036,8 @@ var init_quota_cache = __esm(() => {
|
|
|
36033
36036
|
});
|
|
36034
36037
|
|
|
36035
36038
|
// gateway/boot-probes.ts
|
|
36036
|
-
import { readFileSync as
|
|
36037
|
-
import { join as
|
|
36039
|
+
import { readFileSync as readFileSync46, readdirSync as readdirSync12, existsSync as existsSync46 } from "fs";
|
|
36040
|
+
import { join as join54 } from "path";
|
|
36038
36041
|
import { execFile as execFileCb } from "child_process";
|
|
36039
36042
|
import { promisify } from "util";
|
|
36040
36043
|
async function withTimeout(label, p, timeoutMs = PROBE_TIMEOUT_MS) {
|
|
@@ -36076,11 +36079,11 @@ function mapPlan(billingType, hasExtra) {
|
|
|
36076
36079
|
}
|
|
36077
36080
|
async function probeAccount(agentDir) {
|
|
36078
36081
|
return withTimeout("Account", (async () => {
|
|
36079
|
-
const claudeDir =
|
|
36080
|
-
const claudeJsonPath =
|
|
36082
|
+
const claudeDir = join54(agentDir, ".claude");
|
|
36083
|
+
const claudeJsonPath = join54(claudeDir, ".claude.json");
|
|
36081
36084
|
let cfg = {};
|
|
36082
36085
|
try {
|
|
36083
|
-
const raw =
|
|
36086
|
+
const raw = readFileSync46(claudeJsonPath, "utf8");
|
|
36084
36087
|
cfg = JSON.parse(raw);
|
|
36085
36088
|
} catch {
|
|
36086
36089
|
return { status: "fail", label: "Account", detail: "no .claude.json" };
|
|
@@ -36098,12 +36101,12 @@ async function probeAccount(agentDir) {
|
|
|
36098
36101
|
let tokenStr = "";
|
|
36099
36102
|
let status = "ok";
|
|
36100
36103
|
for (const candidate of [
|
|
36101
|
-
|
|
36102
|
-
|
|
36104
|
+
join54(claudeDir, ".oauth-token.meta.json"),
|
|
36105
|
+
join54(claudeDir, "accounts", "default", ".oauth-token.meta.json")
|
|
36103
36106
|
]) {
|
|
36104
|
-
if (
|
|
36107
|
+
if (existsSync46(candidate)) {
|
|
36105
36108
|
try {
|
|
36106
|
-
const meta = JSON.parse(
|
|
36109
|
+
const meta = JSON.parse(readFileSync46(candidate, "utf8"));
|
|
36107
36110
|
if (meta.expiresAt) {
|
|
36108
36111
|
tokenStr = " \u00b7 " + formatDaysFromNow(meta.expiresAt);
|
|
36109
36112
|
const daysLeft = Math.round((meta.expiresAt - Date.now()) / 86400000);
|
|
@@ -36278,9 +36281,9 @@ async function resolveTmuxSupervisorPid(agentName3, execFileImpl) {
|
|
|
36278
36281
|
if (!cgroup)
|
|
36279
36282
|
return null;
|
|
36280
36283
|
const procsPath = `/sys/fs/cgroup${cgroup}/cgroup.procs`;
|
|
36281
|
-
if (!
|
|
36284
|
+
if (!existsSync46(procsPath))
|
|
36282
36285
|
return null;
|
|
36283
|
-
const pidsRaw =
|
|
36286
|
+
const pidsRaw = readFileSync46(procsPath, "utf-8");
|
|
36284
36287
|
const pids = pidsRaw.split(`
|
|
36285
36288
|
`).map((s) => s.trim()).filter(Boolean);
|
|
36286
36289
|
if (pids.length === 0)
|
|
@@ -36293,7 +36296,7 @@ async function resolveTmuxSupervisorPid(agentName3, execFileImpl) {
|
|
|
36293
36296
|
let rss = 0;
|
|
36294
36297
|
let comm = "";
|
|
36295
36298
|
try {
|
|
36296
|
-
const status =
|
|
36299
|
+
const status = readFileSync46(`/proc/${pid}/status`, "utf-8");
|
|
36297
36300
|
const rssLine = status.split(`
|
|
36298
36301
|
`).find((l) => l.startsWith("VmRSS:"));
|
|
36299
36302
|
if (rssLine) {
|
|
@@ -36305,7 +36308,7 @@ async function resolveTmuxSupervisorPid(agentName3, execFileImpl) {
|
|
|
36305
36308
|
continue;
|
|
36306
36309
|
}
|
|
36307
36310
|
try {
|
|
36308
|
-
comm =
|
|
36311
|
+
comm = readFileSync46(`/proc/${pid}/comm`, "utf-8").trim();
|
|
36309
36312
|
} catch {}
|
|
36310
36313
|
candidates.push({ pid, rss, comm });
|
|
36311
36314
|
}
|
|
@@ -36485,9 +36488,9 @@ async function probeQuota(claudeConfigDir, _agentDir, fetchImpl = fetch, opts =
|
|
|
36485
36488
|
let claudeDirForProbe = null;
|
|
36486
36489
|
for (const candidate of [
|
|
36487
36490
|
claudeConfigDir,
|
|
36488
|
-
|
|
36491
|
+
join54(claudeConfigDir, "accounts", "default")
|
|
36489
36492
|
]) {
|
|
36490
|
-
if (
|
|
36493
|
+
if (existsSync46(join54(candidate, ".oauth-token"))) {
|
|
36491
36494
|
claudeDirForProbe = candidate;
|
|
36492
36495
|
break;
|
|
36493
36496
|
}
|
|
@@ -36552,7 +36555,7 @@ async function probeHindsight(bankName, fetchImpl = fetch) {
|
|
|
36552
36555
|
}
|
|
36553
36556
|
function readContainerBootTimeMsForProbe() {
|
|
36554
36557
|
try {
|
|
36555
|
-
const stat1 =
|
|
36558
|
+
const stat1 = readFileSync46("/proc/1/stat", "utf8");
|
|
36556
36559
|
const lastParen = stat1.lastIndexOf(")");
|
|
36557
36560
|
if (lastParen < 0)
|
|
36558
36561
|
return null;
|
|
@@ -36560,7 +36563,7 @@ function readContainerBootTimeMsForProbe() {
|
|
|
36560
36563
|
const starttimeTicks = Number(after[19]);
|
|
36561
36564
|
if (!Number.isFinite(starttimeTicks))
|
|
36562
36565
|
return null;
|
|
36563
|
-
const procStat =
|
|
36566
|
+
const procStat = readFileSync46("/proc/stat", "utf8");
|
|
36564
36567
|
const btimeLine = procStat.split(`
|
|
36565
36568
|
`).find((l) => l.startsWith("btime "));
|
|
36566
36569
|
if (!btimeLine)
|
|
@@ -36658,7 +36661,7 @@ async function probeUds(label, socketPath, opts = {}) {
|
|
|
36658
36661
|
}
|
|
36659
36662
|
return withTimeout(label, (async () => {
|
|
36660
36663
|
if (!opts.connectImpl) {
|
|
36661
|
-
if (!
|
|
36664
|
+
if (!existsSync46(socketPath)) {
|
|
36662
36665
|
return {
|
|
36663
36666
|
status: "fail",
|
|
36664
36667
|
label,
|
|
@@ -36722,7 +36725,7 @@ async function probeSkills(agentDir, opts = {}) {
|
|
|
36722
36725
|
return withTimeout("Skills", (async () => {
|
|
36723
36726
|
const fs3 = opts.fs ?? realSkillsFs;
|
|
36724
36727
|
const max = opts.maxNamesShown ?? 3;
|
|
36725
|
-
const skillsDir =
|
|
36728
|
+
const skillsDir = join54(agentDir, ".claude", "skills");
|
|
36726
36729
|
if (!fs3.exists(skillsDir)) {
|
|
36727
36730
|
return { status: "ok", label: "Skills", detail: "no skills dir" };
|
|
36728
36731
|
}
|
|
@@ -36737,17 +36740,17 @@ async function probeSkills(agentDir, opts = {}) {
|
|
|
36737
36740
|
}
|
|
36738
36741
|
const dangling = [];
|
|
36739
36742
|
for (const name of entries) {
|
|
36740
|
-
const skillPath =
|
|
36743
|
+
const skillPath = join54(skillsDir, name);
|
|
36741
36744
|
if (!fs3.exists(skillPath)) {
|
|
36742
36745
|
dangling.push(name);
|
|
36743
36746
|
continue;
|
|
36744
36747
|
}
|
|
36745
|
-
const skillMd =
|
|
36748
|
+
const skillMd = join54(skillPath, "SKILL.md");
|
|
36746
36749
|
if (!fs3.exists(skillMd) && !fs3.exists(skillPath + ".md")) {
|
|
36747
36750
|
continue;
|
|
36748
36751
|
}
|
|
36749
36752
|
}
|
|
36750
|
-
const overlayDir = opts.overlaySkillsDir ??
|
|
36753
|
+
const overlayDir = opts.overlaySkillsDir ?? join54(agentDir, "skills.d");
|
|
36751
36754
|
const overlaySlugs = new Set;
|
|
36752
36755
|
if (fs3.exists(overlayDir)) {
|
|
36753
36756
|
let overlayEntries = [];
|
|
@@ -36789,8 +36792,8 @@ function renderBucketedSkills(switchroom, agent) {
|
|
|
36789
36792
|
}
|
|
36790
36793
|
async function probeConnections(agentDir, opts = {}) {
|
|
36791
36794
|
return withTimeout("Connections", (async () => {
|
|
36792
|
-
const path3 =
|
|
36793
|
-
const read = opts.readFileImpl ?? ((p) =>
|
|
36795
|
+
const path3 = join54(agentDir, ".claude", "connection-health.json");
|
|
36796
|
+
const read = opts.readFileImpl ?? ((p) => readFileSync46(p, "utf8"));
|
|
36794
36797
|
let issues = [];
|
|
36795
36798
|
try {
|
|
36796
36799
|
const parsed = JSON.parse(read(path3));
|
|
@@ -36830,7 +36833,7 @@ async function probeDrift(agentDir, opts = {}) {
|
|
|
36830
36833
|
}
|
|
36831
36834
|
} catch {}
|
|
36832
36835
|
try {
|
|
36833
|
-
const raw =
|
|
36836
|
+
const raw = readFileSync46(join54(agentDir, ".switchroom-drift.json"), "utf8");
|
|
36834
36837
|
const report = JSON.parse(raw);
|
|
36835
36838
|
if (report?.version === 1 && Array.isArray(report.findings)) {
|
|
36836
36839
|
const gen = report.generatedAt ? Date.parse(report.generatedAt) : NaN;
|
|
@@ -36877,24 +36880,24 @@ var init_boot_probes = __esm(() => {
|
|
|
36877
36880
|
execFile = promisify(execFileCb);
|
|
36878
36881
|
realProcFs = {
|
|
36879
36882
|
readdir: (p) => readdirSync12(p),
|
|
36880
|
-
readFile: (p) =>
|
|
36883
|
+
readFile: (p) => readFileSync46(p, "utf-8")
|
|
36881
36884
|
};
|
|
36882
36885
|
realSchedulerFs = {
|
|
36883
|
-
readFile: (p) =>
|
|
36886
|
+
readFile: (p) => readFileSync46(p, "utf-8"),
|
|
36884
36887
|
mtimeMs: (p) => {
|
|
36885
36888
|
const { statSync: statSync17 } = __require("fs");
|
|
36886
36889
|
return statSync17(p).mtimeMs;
|
|
36887
36890
|
},
|
|
36888
|
-
exists: (p) =>
|
|
36891
|
+
exists: (p) => existsSync46(p)
|
|
36889
36892
|
};
|
|
36890
36893
|
realSkillsFs = {
|
|
36891
36894
|
readdir: (p) => readdirSync12(p),
|
|
36892
|
-
exists: (p) =>
|
|
36895
|
+
exists: (p) => existsSync46(p)
|
|
36893
36896
|
};
|
|
36894
36897
|
});
|
|
36895
36898
|
|
|
36896
36899
|
// gateway/boot-issue-cache.ts
|
|
36897
|
-
import { existsSync as
|
|
36900
|
+
import { existsSync as existsSync47, readFileSync as readFileSync47, writeFileSync as writeFileSync38, mkdirSync as mkdirSync40, renameSync as renameSync22 } from "fs";
|
|
36898
36901
|
import { dirname as dirname23 } from "path";
|
|
36899
36902
|
function fingerprintProbe(key, r) {
|
|
36900
36903
|
if (r.status === "ok")
|
|
@@ -36974,11 +36977,11 @@ function diffProbes(probes, cache, opts = {}) {
|
|
|
36974
36977
|
return out;
|
|
36975
36978
|
}
|
|
36976
36979
|
function loadCache(path3, now = Date.now) {
|
|
36977
|
-
if (!
|
|
36980
|
+
if (!existsSync47(path3))
|
|
36978
36981
|
return { ...EMPTY_CACHE, probes: {} };
|
|
36979
36982
|
let raw;
|
|
36980
36983
|
try {
|
|
36981
|
-
raw =
|
|
36984
|
+
raw = readFileSync47(path3, "utf-8");
|
|
36982
36985
|
} catch {
|
|
36983
36986
|
return { ...EMPTY_CACHE, probes: {} };
|
|
36984
36987
|
}
|
|
@@ -37037,7 +37040,7 @@ var init_boot_issue_cache = __esm(() => {
|
|
|
37037
37040
|
|
|
37038
37041
|
// gateway/config-snapshot.ts
|
|
37039
37042
|
import { createHash as createHash7 } from "crypto";
|
|
37040
|
-
import { existsSync as
|
|
37043
|
+
import { existsSync as existsSync48, readFileSync as readFileSync48, writeFileSync as writeFileSync39, mkdirSync as mkdirSync41, renameSync as renameSync23 } from "fs";
|
|
37041
37044
|
import { dirname as dirname24 } from "path";
|
|
37042
37045
|
function hashStringArray(items) {
|
|
37043
37046
|
if (!items || items.length === 0)
|
|
@@ -37102,11 +37105,11 @@ function renderConfigChangeDim(dim) {
|
|
|
37102
37105
|
}
|
|
37103
37106
|
}
|
|
37104
37107
|
function loadSnapshot(path3, now = Date.now) {
|
|
37105
|
-
if (!
|
|
37108
|
+
if (!existsSync48(path3))
|
|
37106
37109
|
return null;
|
|
37107
37110
|
let raw;
|
|
37108
37111
|
try {
|
|
37109
|
-
raw =
|
|
37112
|
+
raw = readFileSync48(path3, "utf-8");
|
|
37110
37113
|
} catch {
|
|
37111
37114
|
return null;
|
|
37112
37115
|
}
|
|
@@ -37147,13 +37150,13 @@ var init_config_snapshot = __esm(() => {
|
|
|
37147
37150
|
});
|
|
37148
37151
|
|
|
37149
37152
|
// gateway/boot-card-msgid.ts
|
|
37150
|
-
import { readFileSync as
|
|
37153
|
+
import { readFileSync as readFileSync49, writeFileSync as writeFileSync40 } from "node:fs";
|
|
37151
37154
|
function bootCardChatKey(chatId, threadId) {
|
|
37152
37155
|
return `${chatId}:${threadId ?? ""}`;
|
|
37153
37156
|
}
|
|
37154
37157
|
function readStore(path3) {
|
|
37155
37158
|
try {
|
|
37156
|
-
const parsed = JSON.parse(
|
|
37159
|
+
const parsed = JSON.parse(readFileSync49(path3, "utf8"));
|
|
37157
37160
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
37158
37161
|
return parsed;
|
|
37159
37162
|
}
|
|
@@ -37190,8 +37193,8 @@ __export(exports_boot_card, {
|
|
|
37190
37193
|
readRoutingMode: () => readRoutingMode,
|
|
37191
37194
|
containerBootStartMs: () => containerBootStartMs
|
|
37192
37195
|
});
|
|
37193
|
-
import { join as
|
|
37194
|
-
import { readFileSync as
|
|
37196
|
+
import { join as join55 } from "path";
|
|
37197
|
+
import { readFileSync as readFileSync50, statSync as statSync17 } from "fs";
|
|
37195
37198
|
function resolvePersonaName(slug, loadConfig3) {
|
|
37196
37199
|
try {
|
|
37197
37200
|
const config = loadConfig3 ? loadConfig3() : loadConfig();
|
|
@@ -37213,7 +37216,7 @@ function shouldSkipDuplicateBootCard(gate, site) {
|
|
|
37213
37216
|
}
|
|
37214
37217
|
return { skip: false };
|
|
37215
37218
|
}
|
|
37216
|
-
function containerBootStartMs(fsImpl = { readFileSync:
|
|
37219
|
+
function containerBootStartMs(fsImpl = { readFileSync: readFileSync50 }) {
|
|
37217
37220
|
try {
|
|
37218
37221
|
const btimeLine = fsImpl.readFileSync("/proc/stat", "utf-8").split(`
|
|
37219
37222
|
`).find((l) => l.startsWith("btime "));
|
|
@@ -37234,8 +37237,8 @@ function containerBootStartMs(fsImpl = { readFileSync: readFileSync49 }) {
|
|
|
37234
37237
|
return null;
|
|
37235
37238
|
}
|
|
37236
37239
|
}
|
|
37237
|
-
function readRoutingMode(agentDir, bootStartMs, fsImpl = { readFileSync:
|
|
37238
|
-
const path3 =
|
|
37240
|
+
function readRoutingMode(agentDir, bootStartMs, fsImpl = { readFileSync: readFileSync50, statSync: statSync17 }) {
|
|
37241
|
+
const path3 = join55(agentDir, ".routing-mode");
|
|
37239
37242
|
try {
|
|
37240
37243
|
const raw = fsImpl.readFileSync(path3, "utf-8");
|
|
37241
37244
|
const line = raw.split(`
|
|
@@ -37342,7 +37345,7 @@ function renderBootCard(opts) {
|
|
|
37342
37345
|
return stackCardLines(flatLines);
|
|
37343
37346
|
}
|
|
37344
37347
|
async function runAllProbes(opts) {
|
|
37345
|
-
const claudeDir =
|
|
37348
|
+
const claudeDir = join55(opts.agentDir, ".claude");
|
|
37346
37349
|
const probes = {};
|
|
37347
37350
|
const slug = opts.agentSlug ?? opts.agentName;
|
|
37348
37351
|
await Promise.allSettled([
|
|
@@ -39140,7 +39143,7 @@ __export(exports_materialize_bot_token, {
|
|
|
39140
39143
|
materializeBotToken: () => materializeBotToken,
|
|
39141
39144
|
BotTokenMaterializeError: () => BotTokenMaterializeError
|
|
39142
39145
|
});
|
|
39143
|
-
import { existsSync as
|
|
39146
|
+
import { existsSync as existsSync57 } from "node:fs";
|
|
39144
39147
|
function pickConfiguredToken(config, agentName3) {
|
|
39145
39148
|
if (agentName3) {
|
|
39146
39149
|
const agent = config.agents?.[agentName3];
|
|
@@ -39154,7 +39157,7 @@ function tryDirectVaultRead4(ref, config, passphrase) {
|
|
|
39154
39157
|
if (!passphrase)
|
|
39155
39158
|
return null;
|
|
39156
39159
|
const vaultPath = resolvePath(config.vault?.path ?? "~/.switchroom/vault.enc");
|
|
39157
|
-
if (!
|
|
39160
|
+
if (!existsSync57(vaultPath))
|
|
39158
39161
|
return null;
|
|
39159
39162
|
try {
|
|
39160
39163
|
const secrets = openVault(passphrase, vaultPath);
|
|
@@ -39309,18 +39312,18 @@ var import_runner3 = __toESM(require_mod3(), 1);
|
|
|
39309
39312
|
import { randomBytes as randomBytes13, createHash as createHash8 } from "crypto";
|
|
39310
39313
|
import { execFileSync as execFileSync9, execSync as execSync2, spawn as spawn2 } from "child_process";
|
|
39311
39314
|
import {
|
|
39312
|
-
readFileSync as
|
|
39315
|
+
readFileSync as readFileSync61,
|
|
39313
39316
|
writeFileSync as writeFileSync50,
|
|
39314
39317
|
mkdirSync as mkdirSync51,
|
|
39315
39318
|
readdirSync as readdirSync16,
|
|
39316
39319
|
rmSync as rmSync8,
|
|
39317
39320
|
statSync as statSync23,
|
|
39318
39321
|
renameSync as renameSync27,
|
|
39319
|
-
realpathSync as
|
|
39322
|
+
realpathSync as realpathSync5,
|
|
39320
39323
|
chmodSync as chmodSync14,
|
|
39321
39324
|
openSync as openSync15,
|
|
39322
39325
|
closeSync as closeSync15,
|
|
39323
|
-
existsSync as
|
|
39326
|
+
existsSync as existsSync58,
|
|
39324
39327
|
unlinkSync as unlinkSync31,
|
|
39325
39328
|
appendFileSync as appendFileSync9
|
|
39326
39329
|
} from "fs";
|
|
@@ -39376,7 +39379,7 @@ function fsyncPathSync(path) {
|
|
|
39376
39379
|
|
|
39377
39380
|
// gateway/gateway.ts
|
|
39378
39381
|
import { homedir as homedir20 } from "os";
|
|
39379
|
-
import { join as
|
|
39382
|
+
import { join as join68, sep as sep4, basename as basename17 } from "path";
|
|
39380
39383
|
|
|
39381
39384
|
// plugin-logger.ts
|
|
39382
39385
|
import { appendFileSync, mkdirSync, renameSync as renameSync2, statSync, existsSync } from "fs";
|
|
@@ -85592,9 +85595,66 @@ async function discoverModels(agentName3, opts = {}) {
|
|
|
85592
85595
|
}
|
|
85593
85596
|
|
|
85594
85597
|
// ../src/agents/scaffold.ts
|
|
85595
|
-
import { dirname as dirname18, isAbsolute, join as join44, relative, resolve as resolve8 } from "node:path";
|
|
85596
85598
|
init_atomic();
|
|
85597
85599
|
|
|
85600
|
+
// ../src/util/shipped-assets.ts
|
|
85601
|
+
import { existsSync as existsSync32, readFileSync as readFileSync31, realpathSync as realpathSync2 } from "node:fs";
|
|
85602
|
+
import { dirname as dirname18, resolve as resolve7 } from "node:path";
|
|
85603
|
+
var FHS_SHARE_ROOTS = [
|
|
85604
|
+
"/usr/local/share/switchroom",
|
|
85605
|
+
"/usr/share/switchroom"
|
|
85606
|
+
];
|
|
85607
|
+
var PROFILES_ASSET = {
|
|
85608
|
+
asset: "profiles",
|
|
85609
|
+
envVar: "SWITCHROOM_PROFILES_ROOT"
|
|
85610
|
+
};
|
|
85611
|
+
function orderedCandidates(spec, probe) {
|
|
85612
|
+
const out = [];
|
|
85613
|
+
const push2 = (path2, source) => {
|
|
85614
|
+
if (!out.some((c) => c.path === path2))
|
|
85615
|
+
out.push({ path: path2, source });
|
|
85616
|
+
};
|
|
85617
|
+
if (probe.bundleDir) {
|
|
85618
|
+
push2(resolve7(probe.bundleDir, "../..", spec.asset), "npm");
|
|
85619
|
+
push2(resolve7(probe.bundleDir, spec.asset), "image");
|
|
85620
|
+
}
|
|
85621
|
+
if (probe.execPath) {
|
|
85622
|
+
push2(resolve7(dirname18(probe.execPath), "../share/switchroom", spec.asset), "sea-sibling");
|
|
85623
|
+
}
|
|
85624
|
+
for (const root of FHS_SHARE_ROOTS) {
|
|
85625
|
+
push2(resolve7(root, spec.asset), "fhs");
|
|
85626
|
+
}
|
|
85627
|
+
return out;
|
|
85628
|
+
}
|
|
85629
|
+
function resolveShippedAsset(spec, probe) {
|
|
85630
|
+
const env = probe.env ?? process.env;
|
|
85631
|
+
const override = env[spec.envVar]?.trim();
|
|
85632
|
+
if (override) {
|
|
85633
|
+
const path2 = canonicalise(resolve7(override), probe);
|
|
85634
|
+
return { path: path2, candidates: [path2], source: "env" };
|
|
85635
|
+
}
|
|
85636
|
+
const exists = probe.exists ?? existsSync32;
|
|
85637
|
+
const candidates = orderedCandidates(spec, probe);
|
|
85638
|
+
for (const c of candidates) {
|
|
85639
|
+
if (exists(c.path)) {
|
|
85640
|
+
return {
|
|
85641
|
+
path: canonicalise(c.path, probe),
|
|
85642
|
+
candidates: candidates.map((x) => x.path),
|
|
85643
|
+
source: c.source
|
|
85644
|
+
};
|
|
85645
|
+
}
|
|
85646
|
+
}
|
|
85647
|
+
return { path: null, candidates: candidates.map((x) => x.path), source: "none" };
|
|
85648
|
+
}
|
|
85649
|
+
function canonicalise(path2, probe) {
|
|
85650
|
+
const realpath = probe.realpath ?? realpathSync2;
|
|
85651
|
+
try {
|
|
85652
|
+
return realpath(path2);
|
|
85653
|
+
} catch {
|
|
85654
|
+
return path2;
|
|
85655
|
+
}
|
|
85656
|
+
}
|
|
85657
|
+
|
|
85598
85658
|
// ../src/agents/agent-uid.ts
|
|
85599
85659
|
init_peercred();
|
|
85600
85660
|
|
|
@@ -85641,37 +85701,29 @@ var AUDIT_ROOT = join42(homedir11(), ".switchroom", "audit");
|
|
|
85641
85701
|
|
|
85642
85702
|
// ../src/agents/profiles.ts
|
|
85643
85703
|
var import_handlebars = __toESM(require_lib(), 1);
|
|
85644
|
-
import { readFileSync as
|
|
85645
|
-
import { resolve as
|
|
85646
|
-
function
|
|
85647
|
-
|
|
85648
|
-
|
|
85649
|
-
|
|
85650
|
-
}
|
|
85651
|
-
const candidates = [
|
|
85652
|
-
resolve7(import.meta.dirname, "../../profiles"),
|
|
85653
|
-
resolve7(import.meta.dirname, "profiles")
|
|
85654
|
-
];
|
|
85655
|
-
for (const candidate of candidates) {
|
|
85656
|
-
if (existsSync33(candidate)) {
|
|
85657
|
-
return candidate;
|
|
85658
|
-
}
|
|
85659
|
-
}
|
|
85660
|
-
return candidates[0];
|
|
85704
|
+
import { readFileSync as readFileSync33, writeFileSync as writeFileSync29, existsSync as existsSync34, readdirSync as readdirSync8, statSync as statSync13, copyFileSync, mkdirSync as mkdirSync32, realpathSync as realpathSync3 } from "node:fs";
|
|
85705
|
+
import { resolve as resolve8, join as join43, sep as pathSep } from "node:path";
|
|
85706
|
+
function resolveProfilesRootDetailed() {
|
|
85707
|
+
return resolveShippedAsset(PROFILES_ASSET, {
|
|
85708
|
+
bundleDir: import.meta.dirname,
|
|
85709
|
+
execPath: process.execPath
|
|
85710
|
+
});
|
|
85661
85711
|
}
|
|
85662
|
-
var
|
|
85712
|
+
var PROFILES_RESOLUTION = resolveProfilesRootDetailed();
|
|
85713
|
+
var PROFILES_ROOT = PROFILES_RESOLUTION.path ?? PROFILES_RESOLUTION.candidates[0];
|
|
85714
|
+
var PROFILES_ROOT_SEARCH = PROFILES_RESOLUTION.candidates;
|
|
85663
85715
|
import_handlebars.default.registerHelper("json", (value) => {
|
|
85664
85716
|
return new import_handlebars.default.SafeString(JSON.stringify(value, null, 2));
|
|
85665
85717
|
});
|
|
85666
85718
|
import_handlebars.default.registerHelper("isNumber", (value) => {
|
|
85667
85719
|
return typeof value === "number" && Number.isFinite(value);
|
|
85668
85720
|
});
|
|
85669
|
-
var SHARED_FRAGMENTS_DIR =
|
|
85721
|
+
var SHARED_FRAGMENTS_DIR = resolve8(PROFILES_ROOT, "_shared");
|
|
85670
85722
|
var SHARED_FRAGMENTS = ["vault-protocol", "agent-self-service", "execution-discipline", "reply-discipline", "dev-protocol"];
|
|
85671
85723
|
for (const name of SHARED_FRAGMENTS) {
|
|
85672
85724
|
const fragPath = join43(SHARED_FRAGMENTS_DIR, `${name}.md.hbs`);
|
|
85673
|
-
if (
|
|
85674
|
-
import_handlebars.default.registerPartial(name,
|
|
85725
|
+
if (existsSync34(fragPath)) {
|
|
85726
|
+
import_handlebars.default.registerPartial(name, readFileSync33(fragPath, "utf-8"));
|
|
85675
85727
|
}
|
|
85676
85728
|
}
|
|
85677
85729
|
|
|
@@ -85874,7 +85926,8 @@ var HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS = new Set([
|
|
|
85874
85926
|
"HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY",
|
|
85875
85927
|
"HINDSIGHT_MCP_RECALL_BUDGET_MODE",
|
|
85876
85928
|
"HINDSIGHT_API_LLM_TEMPERATURE_REFLECT",
|
|
85877
|
-
"HINDSIGHT_API_RETAIN_WALL_TIMEOUT"
|
|
85929
|
+
"HINDSIGHT_API_RETAIN_WALL_TIMEOUT",
|
|
85930
|
+
"HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT"
|
|
85878
85931
|
]);
|
|
85879
85932
|
var HINDSIGHT_WORKER_SLOT_TYPES = [
|
|
85880
85933
|
"consolidation",
|
|
@@ -85969,6 +86022,15 @@ var DEFAULT_RETAIN_MISSION = `Extract durable facts that will still be true and
|
|
|
85969
86022
|
` + `- Hindsight's own errors, retries, backlogs, or internal state \u2014 the memory
|
|
85970
86023
|
` + ` system's self-reports are not memories.
|
|
85971
86024
|
` + `- Restatements of the user's current request or the task in progress.
|
|
86025
|
+
` + `- The assistant's own answers, summaries, recaps, or reflect output. Before
|
|
86026
|
+
` + ` extracting, ask: does anything in this transcript support this claim OTHER
|
|
86027
|
+
` + ` than the assistant having asserted it? If not, drop it \u2014 a model's own
|
|
86028
|
+
` + ` synthesis re-extracted as a fact is how a guess becomes permanent.
|
|
86029
|
+
` + ` Concretely, never produce a fact whose only support is the assistant
|
|
86030
|
+
` + ` stating a date, a version, an attribution, a total, or a decision that the
|
|
86031
|
+
` + ` user never confirmed and no tool output shows. An unverified claim recalls
|
|
86032
|
+
` + ` later as though it had been established, which is worse than not
|
|
86033
|
+
` + ` remembering it at all.
|
|
85972
86034
|
` + `- Volatile state written as a timeless assertion. A version, count, size,
|
|
85973
86035
|
` + ` backlog, status, or any "X is running Y" / "X is at Y" / "X is currently Y"
|
|
85974
86036
|
` + ` claim is true only at the instant it was said. Concretely, never produce a
|
|
@@ -86124,6 +86186,64 @@ var SUPERSEDED_RETAIN_MISSIONS = [
|
|
|
86124
86186
|
` + `
|
|
86125
86187
|
` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
|
|
86126
86188
|
` + `nothing durable remains, return an empty facts list.
|
|
86189
|
+
`,
|
|
86190
|
+
`Extract durable facts that will still be true and useful weeks from now, once this session is forgotten.
|
|
86191
|
+
` + `
|
|
86192
|
+
` + `DURABILITY GATE. Emit a candidate ONLY if it is one of these five classes:
|
|
86193
|
+
` + `- PREFERENCE \u2014 what the user likes, wants, or always does; a standing rule or correction.
|
|
86194
|
+
` + `- DECISION \u2014 a settled choice that changes how future work is done, including a choice NOT to do something. A decision about the mechanics of the CURRENT task (which worker to dispatch, which branch to rebase, which PR to merge now, what to do next) is process narration, not a durable decision \u2014 drop it unless it establishes a standing rule or permanently changes a system.
|
|
86195
|
+
` + `- FINDING \u2014 a root cause, a measurement, or verified behaviour of a system. Include the number.
|
|
86196
|
+
` + `- OUTCOME \u2014 a completed result that changed the world: what shipped, what a thing turned out to be. Not the act of shipping it.
|
|
86197
|
+
` + `- RELATIONSHIP \u2014 who a person is, what a project or tool is, and how they connect.
|
|
86198
|
+
` + `If a candidate fits none of the five, it is not a memory. Drop it; do not reword it into one.
|
|
86199
|
+
` + `
|
|
86200
|
+
` + `A preference revealed by a request is durable \u2014 record the preference (what the user likes, wants, or always does), not the request itself.
|
|
86201
|
+
` + `
|
|
86202
|
+
` + `A TOOL RESULT IS NOT A FACT. Before extracting, ask: is the subject of this
|
|
86203
|
+
` + `candidate a file path, a command/process/agent/session id, a temp directory, or
|
|
86204
|
+
` + `the location where some output was written? If yes, drop it \u2014 it is transcript
|
|
86205
|
+
` + `exhaust, not memory.
|
|
86206
|
+
` + `
|
|
86207
|
+
` + `NEVER extract:
|
|
86208
|
+
` + `- Tool results verbatim or paraphrased. Concretely, never produce a fact whose
|
|
86209
|
+
` + ` text resembles any of these: "File created successfully at /path/to/file",
|
|
86210
|
+
` + ` "A background command with ID bctz4yskm is running, and its output will be
|
|
86211
|
+
` + ` written to /tmp/...", "Async agent a745598ba84e71df1 was launched successfully
|
|
86212
|
+
` + ` and is running in the background", "User executed a Bash command to sleep for
|
|
86213
|
+
` + ` 200 seconds", "The assistant used grep to locate 'truncateSync' in src/foo.ts".
|
|
86214
|
+
` + `- Anything mentioning a path under /tmp, a scratchpad directory, or a .tmp file.
|
|
86215
|
+
` + `- Agent tool-use traces or narration of what the assistant did (e.g. "the
|
|
86216
|
+
` + ` assistant used X to query Y", "ran a search", "sent the message").
|
|
86217
|
+
` + `- The act of delegating, dispatching, spawning, launching, steering or merging
|
|
86218
|
+
` + ` work \u2014 including when it succeeded. "X was dispatched and completed" is the
|
|
86219
|
+
` + ` session describing itself. Record only what the work LEARNED or CHANGED.
|
|
86220
|
+
` + `- In-flight workflow/process narration (a sub-task started, paused, or is still
|
|
86221
|
+
` + ` running) \u2014 retain the outcome only once the task completes or a decision is made.
|
|
86222
|
+
` + `- Operation, request, batch, agent, command or session IDs, UUIDs, hashes, or error codes.
|
|
86223
|
+
` + `- Slash commands the user typed and their effects (e.g. "User issued /clear to
|
|
86224
|
+
` + ` reset assistant state").
|
|
86225
|
+
` + `- Hindsight's own errors, retries, backlogs, or internal state \u2014 the memory
|
|
86226
|
+
` + ` system's self-reports are not memories.
|
|
86227
|
+
` + `- Restatements of the user's current request or the task in progress.
|
|
86228
|
+
` + `- Volatile state written as a timeless assertion. A version, count, size,
|
|
86229
|
+
` + ` backlog, status, or any "X is running Y" / "X is at Y" / "X is currently Y"
|
|
86230
|
+
` + ` claim is true only at the instant it was said. Concretely, never produce a
|
|
86231
|
+
` + ` fact whose text resembles any of these: "Switchroom fleet is running image
|
|
86232
|
+
` + ` version v0.18.19", "The switchroom repo is at /path/to/fleet, version
|
|
86233
|
+
` + ` v0.19.5", "Bank overlord has 43155 pending consolidations", "The build is
|
|
86234
|
+
` + ` currently green". If the claim is worth keeping, put the date INSIDE the
|
|
86235
|
+
` + ` fact text ("As of 2026-07-19 the fleet was running v0.18.19"); if you
|
|
86236
|
+
` + ` cannot date it, drop it. An undated one is recalled forever as though it
|
|
86237
|
+
` + ` were still true, which is worse than not remembering it at all.
|
|
86238
|
+
` + `- Transient state (unread counts, build status, what is running right now) unless
|
|
86239
|
+
` + ` the fact is explicitly dated, in which case record it as a dated observation.
|
|
86240
|
+
` + `- Greetings, acknowledgements, and routine operational chatter.
|
|
86241
|
+
` + `
|
|
86242
|
+
` + `Write each fact so it stands alone: name the thing, the number, and the date. A
|
|
86243
|
+
` + `sentence that only makes sense while reading this transcript is not durable.
|
|
86244
|
+
` + `
|
|
86245
|
+
` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
|
|
86246
|
+
` + `nothing durable remains, return an empty facts list.
|
|
86127
86247
|
`
|
|
86128
86248
|
];
|
|
86129
86249
|
var DEFAULT_OBSERVATIONS_MISSION = `Synthesise durable, standing knowledge about the people, projects, and systems this agent works with: preferences and standing rules, roles and relationships, skills and recurring patterns, technical and operational decisions with their rationale, and the state of long-running work once it lands.
|
|
@@ -86201,6 +86321,22 @@ var PROFILE_MEMORY_DEFAULTS = {
|
|
|
86201
86321
|
var warnedMissingPool = new Set;
|
|
86202
86322
|
var warnedMissingDefault = new Set;
|
|
86203
86323
|
|
|
86324
|
+
// ../src/memory/hindsight-retain-provenance.ts
|
|
86325
|
+
var RETAIN_PROVENANCE_TAG = "source:transcript";
|
|
86326
|
+
var RETAIN_TAGS_DEFAULT = Object.freeze([
|
|
86327
|
+
"{session_id}",
|
|
86328
|
+
RETAIN_PROVENANCE_TAG
|
|
86329
|
+
]);
|
|
86330
|
+
|
|
86331
|
+
// ../src/memory/hindsight-seed-directives.ts
|
|
86332
|
+
var ANTI_CONFABULATION_DIRECTIVE = `When the retrieved memories do not support an answer, say so instead of composing one.
|
|
86333
|
+
` + `
|
|
86334
|
+
` + `- If nothing retrieved scores meaningfully above zero, or what came back is off-topic, the honest answer is that the bank does not know. Say that plainly, and say what would settle it.
|
|
86335
|
+
` + `- Never assert a date, a version, a number, an attribution, a decision, or an outcome that no retrieved memory states. A question that presupposes something is not evidence for it: asked when a decision was made, when the bank records no such decision, answer that none is recorded \u2014 do not supply one.
|
|
86336
|
+
` + `- Keep what the bank RECORDED separate from what you INFER. State inferences as inferences, and say which memory a recorded fact came from.
|
|
86337
|
+
` + `- Treat a memory that was extracted from a conversation transcript as an unverified claim, not an established fact \u2014 it may be an assistant's own earlier guess. If it is the only support for an answer, say that it is.
|
|
86338
|
+
` + "- Partial knowledge with its gaps named is more useful than a fluent answer that fills them in.";
|
|
86339
|
+
|
|
86204
86340
|
// ../src/telegram/state.ts
|
|
86205
86341
|
init_paths();
|
|
86206
86342
|
|
|
@@ -86238,7 +86374,6 @@ var RECALL_PASSTHROUGH_DEFAULTS = Object.freeze({
|
|
|
86238
86374
|
init_paths();
|
|
86239
86375
|
|
|
86240
86376
|
// ../src/agents/scaffold.ts
|
|
86241
|
-
var REPO_ROOT = resolve8(import.meta.dirname, "../..");
|
|
86242
86377
|
var SWITCHROOM_DEFAULT_MAIN_MODEL = "claude-sonnet-5";
|
|
86243
86378
|
var SWITCHROOM_DEFAULT_THINKING_EFFORT = "low";
|
|
86244
86379
|
function resolveMainModel(model) {
|
|
@@ -86798,7 +86933,7 @@ init_overlay_loader();
|
|
|
86798
86933
|
init_merge();
|
|
86799
86934
|
init_timezone();
|
|
86800
86935
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
86801
|
-
import { readFileSync as
|
|
86936
|
+
import { readFileSync as readFileSync34, existsSync as existsSync35 } from "node:fs";
|
|
86802
86937
|
import { homedir as homedir12 } from "node:os";
|
|
86803
86938
|
import { resolve as resolve9 } from "node:path";
|
|
86804
86939
|
|
|
@@ -86874,7 +87009,7 @@ function findConfigFile2(startDir) {
|
|
|
86874
87009
|
resolve9(userDir, "clerk.yml")
|
|
86875
87010
|
].filter(Boolean);
|
|
86876
87011
|
for (const path2 of searchPaths) {
|
|
86877
|
-
if (
|
|
87012
|
+
if (existsSync35(path2)) {
|
|
86878
87013
|
return path2;
|
|
86879
87014
|
}
|
|
86880
87015
|
}
|
|
@@ -86882,12 +87017,12 @@ function findConfigFile2(startDir) {
|
|
|
86882
87017
|
}
|
|
86883
87018
|
function loadConfig2(configPath) {
|
|
86884
87019
|
const filePath = configPath ?? findConfigFile2();
|
|
86885
|
-
if (!
|
|
87020
|
+
if (!existsSync35(filePath)) {
|
|
86886
87021
|
throw new ConfigError2(`Config file not found: ${filePath}`);
|
|
86887
87022
|
}
|
|
86888
87023
|
let raw;
|
|
86889
87024
|
try {
|
|
86890
|
-
raw =
|
|
87025
|
+
raw = readFileSync34(filePath, "utf-8");
|
|
86891
87026
|
} catch (err) {
|
|
86892
87027
|
throw new ConfigError2(`Failed to read config file: ${filePath}`, [
|
|
86893
87028
|
` ${err.message}`
|
|
@@ -87417,15 +87552,15 @@ function topicForRecipient(args) {
|
|
|
87417
87552
|
}
|
|
87418
87553
|
|
|
87419
87554
|
// ../src/agents/perf.ts
|
|
87420
|
-
import { existsSync as
|
|
87555
|
+
import { existsSync as existsSync36, readFileSync as readFileSync35 } from "node:fs";
|
|
87421
87556
|
function readTurnUsages(jsonlPath, lastN) {
|
|
87422
|
-
if (!
|
|
87557
|
+
if (!existsSync36(jsonlPath))
|
|
87423
87558
|
return [];
|
|
87424
87559
|
if (lastN <= 0)
|
|
87425
87560
|
return [];
|
|
87426
87561
|
let raw;
|
|
87427
87562
|
try {
|
|
87428
|
-
raw =
|
|
87563
|
+
raw = readFileSync35(jsonlPath, "utf-8");
|
|
87429
87564
|
} catch {
|
|
87430
87565
|
return [];
|
|
87431
87566
|
}
|
|
@@ -87517,7 +87652,7 @@ function numField(obj, key) {
|
|
|
87517
87652
|
|
|
87518
87653
|
// gateway/context-occupancy.ts
|
|
87519
87654
|
import { mkdirSync as mkdirSync33, writeFileSync as writeFileSync30 } from "node:fs";
|
|
87520
|
-
import { join as
|
|
87655
|
+
import { join as join44 } from "node:path";
|
|
87521
87656
|
var CONTEXT_OCCUPANCY_FILENAME = "context-occupancy.json";
|
|
87522
87657
|
var TIGHT_FRACTION = 0.8;
|
|
87523
87658
|
function buildContextOccupancy(occupancy, cap, now) {
|
|
@@ -87540,7 +87675,7 @@ function buildContextOccupancy(occupancy, cap, now) {
|
|
|
87540
87675
|
}
|
|
87541
87676
|
function writeContextOccupancySnapshot(stateDir, snapshot, deps) {
|
|
87542
87677
|
try {
|
|
87543
|
-
const path2 =
|
|
87678
|
+
const path2 = join44(stateDir, CONTEXT_OCCUPANCY_FILENAME);
|
|
87544
87679
|
(deps?.mkdir ?? ((p, o) => mkdirSync33(p, o)))(stateDir, { recursive: true });
|
|
87545
87680
|
(deps?.writeFile ?? ((p, d) => writeFileSync30(p, d)))(path2, JSON.stringify(snapshot, null, 2) + `
|
|
87546
87681
|
`);
|
|
@@ -87696,7 +87831,7 @@ function nextCompactNotify(state6, ev) {
|
|
|
87696
87831
|
}
|
|
87697
87832
|
|
|
87698
87833
|
// gateway/hostd-dispatch.ts
|
|
87699
|
-
import { existsSync as
|
|
87834
|
+
import { existsSync as existsSync37 } from "node:fs";
|
|
87700
87835
|
import { randomBytes as randomBytes10 } from "node:crypto";
|
|
87701
87836
|
init_loader();
|
|
87702
87837
|
var _hostdEnabled2;
|
|
@@ -87720,13 +87855,13 @@ function hostdSocketPath2(agentName3) {
|
|
|
87720
87855
|
function hostdWillBeUsed2(agentName3) {
|
|
87721
87856
|
if (!isHostdEnabled2())
|
|
87722
87857
|
return false;
|
|
87723
|
-
return
|
|
87858
|
+
return existsSync37(hostdSocketPath2(agentName3));
|
|
87724
87859
|
}
|
|
87725
87860
|
async function tryHostdDispatch2(agentName3, req, timeoutMs = 5000) {
|
|
87726
87861
|
if (!isHostdEnabled2())
|
|
87727
87862
|
return "not-configured";
|
|
87728
87863
|
const sockPath = hostdSocketPath2(agentName3);
|
|
87729
|
-
if (!
|
|
87864
|
+
if (!existsSync37(sockPath))
|
|
87730
87865
|
return "not-configured";
|
|
87731
87866
|
try {
|
|
87732
87867
|
return await hostdRequest({ socketPath: sockPath, timeoutMs }, req);
|
|
@@ -87755,7 +87890,7 @@ async function pollHostdStatus(agentName3, targetRequestId, opts) {
|
|
|
87755
87890
|
if (!isHostdEnabled2())
|
|
87756
87891
|
return "not-configured";
|
|
87757
87892
|
const sockPath = hostdSocketPath2(agentName3);
|
|
87758
|
-
if (!
|
|
87893
|
+
if (!existsSync37(sockPath))
|
|
87759
87894
|
return "not-configured";
|
|
87760
87895
|
const now = opts.now ?? Date.now;
|
|
87761
87896
|
const sleep2 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
@@ -88721,7 +88856,7 @@ function createGatewayStalePinSweeper(w) {
|
|
|
88721
88856
|
|
|
88722
88857
|
// gateway/webhook-ingest-server.ts
|
|
88723
88858
|
import net4 from "node:net";
|
|
88724
|
-
import { chmodSync as chmodSync10, existsSync as
|
|
88859
|
+
import { chmodSync as chmodSync10, existsSync as existsSync38, unlinkSync as unlinkSync18 } from "node:fs";
|
|
88725
88860
|
var MAX_REQUEST_BYTES = 1024 * 1024;
|
|
88726
88861
|
function fdOf(conn) {
|
|
88727
88862
|
const handle = conn._handle;
|
|
@@ -88733,7 +88868,7 @@ function startWebhookIngestServer(opts) {
|
|
|
88733
88868
|
const log = opts.log ?? ((s) => process.stderr.write(s));
|
|
88734
88869
|
const allowed = new Set(opts.allowedUids);
|
|
88735
88870
|
try {
|
|
88736
|
-
if (
|
|
88871
|
+
if (existsSync38(opts.socketPath))
|
|
88737
88872
|
unlinkSync18(opts.socketPath);
|
|
88738
88873
|
} catch (err) {
|
|
88739
88874
|
log(`webhook-ingest-server: could not unlink stale socket: ${err.message}
|
|
@@ -88826,7 +88961,7 @@ function startWebhookIngestServer(opts) {
|
|
|
88826
88961
|
server.close();
|
|
88827
88962
|
} catch {}
|
|
88828
88963
|
try {
|
|
88829
|
-
if (
|
|
88964
|
+
if (existsSync38(opts.socketPath))
|
|
88830
88965
|
unlinkSync18(opts.socketPath);
|
|
88831
88966
|
} catch {}
|
|
88832
88967
|
}
|
|
@@ -88835,12 +88970,12 @@ function startWebhookIngestServer(opts) {
|
|
|
88835
88970
|
|
|
88836
88971
|
// ../src/web/webhook-gateway-record.ts
|
|
88837
88972
|
import { appendFileSync as appendFileSync8, mkdirSync as mkdirSync36 } from "fs";
|
|
88838
|
-
import { join as
|
|
88973
|
+
import { join as join48 } from "path";
|
|
88839
88974
|
import { homedir as homedir14 } from "os";
|
|
88840
88975
|
|
|
88841
88976
|
// ../src/web/webhook-handler.ts
|
|
88842
|
-
import { appendFileSync as appendFileSync7, existsSync as
|
|
88843
|
-
import { join as
|
|
88977
|
+
import { appendFileSync as appendFileSync7, existsSync as existsSync40, mkdirSync as mkdirSync34, readFileSync as readFileSync36, writeFileSync as writeFileSync31 } from "fs";
|
|
88978
|
+
import { join as join46 } from "path";
|
|
88844
88979
|
|
|
88845
88980
|
// ../src/util/log-rotation.ts
|
|
88846
88981
|
import * as fs2 from "node:fs";
|
|
@@ -89178,9 +89313,9 @@ var DEDUP_MAX = 1000;
|
|
|
89178
89313
|
var DEDUP_TTL_MS = 24 * 60 * 60 * 1000;
|
|
89179
89314
|
function loadDedupFile(path3) {
|
|
89180
89315
|
try {
|
|
89181
|
-
if (!
|
|
89316
|
+
if (!existsSync40(path3))
|
|
89182
89317
|
return {};
|
|
89183
|
-
const raw = JSON.parse(
|
|
89318
|
+
const raw = JSON.parse(readFileSync36(path3, "utf-8"));
|
|
89184
89319
|
return typeof raw.deliveries === "object" && raw.deliveries !== null ? raw.deliveries : {};
|
|
89185
89320
|
} catch {
|
|
89186
89321
|
return {};
|
|
@@ -89202,8 +89337,8 @@ var agentDedupCache = new Map;
|
|
|
89202
89337
|
function createFileDedupStore(resolveAgentDir) {
|
|
89203
89338
|
return {
|
|
89204
89339
|
check(agent, deliveryId, now) {
|
|
89205
|
-
const telegramDir =
|
|
89206
|
-
const filePath =
|
|
89340
|
+
const telegramDir = join46(resolveAgentDir(agent), "telegram");
|
|
89341
|
+
const filePath = join46(telegramDir, "webhook-dedup.json");
|
|
89207
89342
|
if (!agentDedupCache.has(agent)) {
|
|
89208
89343
|
agentDedupCache.set(agent, loadDedupFile(filePath));
|
|
89209
89344
|
}
|
|
@@ -89224,8 +89359,8 @@ var tokenBuckets = new Map;
|
|
|
89224
89359
|
var throttleIssueWindow = new Map;
|
|
89225
89360
|
|
|
89226
89361
|
// ../src/web/webhook-dispatch.ts
|
|
89227
|
-
import { existsSync as
|
|
89228
|
-
import { join as
|
|
89362
|
+
import { existsSync as existsSync41, mkdirSync as mkdirSync35, readFileSync as readFileSync37, writeFileSync as writeFileSync32 } from "fs";
|
|
89363
|
+
import { join as join47 } from "path";
|
|
89229
89364
|
import { homedir as homedir13 } from "os";
|
|
89230
89365
|
|
|
89231
89366
|
// ../src/agent-scheduler/ipc-client.ts
|
|
@@ -89524,9 +89659,9 @@ function cooldownKey(source, eventType, repo, number, ruleIndex) {
|
|
|
89524
89659
|
}
|
|
89525
89660
|
function loadCooldownFile(path3) {
|
|
89526
89661
|
try {
|
|
89527
|
-
if (!
|
|
89662
|
+
if (!existsSync41(path3))
|
|
89528
89663
|
return {};
|
|
89529
|
-
const raw = JSON.parse(
|
|
89664
|
+
const raw = JSON.parse(readFileSync37(path3, "utf-8"));
|
|
89530
89665
|
return typeof raw.dispatches === "object" && raw.dispatches !== null ? raw.dispatches : {};
|
|
89531
89666
|
} catch {
|
|
89532
89667
|
return {};
|
|
@@ -89545,8 +89680,8 @@ function createFileCooldownStore(resolveAgentDir) {
|
|
|
89545
89680
|
isCoolingDown(agent, key, cooldownMs, now) {
|
|
89546
89681
|
if (cooldownMs <= 0)
|
|
89547
89682
|
return false;
|
|
89548
|
-
const telegramDir =
|
|
89549
|
-
const filePath =
|
|
89683
|
+
const telegramDir = join47(resolveAgentDir(agent), "telegram");
|
|
89684
|
+
const filePath = join47(telegramDir, "webhook-cooldown.json");
|
|
89550
89685
|
if (!cache.has(agent)) {
|
|
89551
89686
|
cache.set(agent, loadCooldownFile(filePath));
|
|
89552
89687
|
}
|
|
@@ -89603,9 +89738,9 @@ async function defaultInject(socketPath, agentName3, inbound) {
|
|
|
89603
89738
|
}
|
|
89604
89739
|
function injectWebhookInbound(agent, prompt, ctx, deps = {}) {
|
|
89605
89740
|
const log = deps.log ?? ((s) => process.stderr.write(s));
|
|
89606
|
-
const resolveAgentDir = deps.resolveAgentDir ?? ((a) =>
|
|
89741
|
+
const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join47(homedir13(), ".switchroom", "agents", a));
|
|
89607
89742
|
const now = (deps.now ?? Date.now)();
|
|
89608
|
-
const socketPath =
|
|
89743
|
+
const socketPath = join47(resolveAgentDir(agent), "telegram", "gateway.sock");
|
|
89609
89744
|
const inbound = {
|
|
89610
89745
|
type: "inbound",
|
|
89611
89746
|
chatId: ctx.chatId,
|
|
@@ -89677,7 +89812,7 @@ function evaluateDispatch(args, deps = {}) {
|
|
|
89677
89812
|
const log = deps.log ?? ((s) => process.stderr.write(s));
|
|
89678
89813
|
const now = (deps.now ?? Date.now)();
|
|
89679
89814
|
const nowDate = deps.nowDate ?? (() => new Date(now));
|
|
89680
|
-
const resolveAgentDir = deps.resolveAgentDir ?? ((a) =>
|
|
89815
|
+
const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join47(homedir13(), ".switchroom", "agents", a));
|
|
89681
89816
|
const cooldownStore = deps.cooldownStore ?? createFileCooldownStore(resolveAgentDir);
|
|
89682
89817
|
if (!DISPATCH_SOURCES.includes(args.source))
|
|
89683
89818
|
return 0;
|
|
@@ -89755,10 +89890,10 @@ var CONSOLIDATION_COMPLETED_EVENT = "consolidation.completed";
|
|
|
89755
89890
|
function recordWebhookEvent(rec, deps = {}) {
|
|
89756
89891
|
const log = deps.log ?? ((s) => process.stderr.write(s));
|
|
89757
89892
|
const now = rec.ts || (deps.now ?? Date.now)();
|
|
89758
|
-
const resolveAgentDir = deps.resolveAgentDir ?? ((a) =>
|
|
89893
|
+
const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join48(homedir14(), ".switchroom", "agents", a));
|
|
89759
89894
|
const dedupStore = deps.dedupStore ?? createFileDedupStore(resolveAgentDir);
|
|
89760
89895
|
const agent = rec.agent;
|
|
89761
|
-
const telegramDir =
|
|
89896
|
+
const telegramDir = join48(resolveAgentDir(agent), "telegram");
|
|
89762
89897
|
if (rec.source === "github" && rec.delivery_id) {
|
|
89763
89898
|
const originalTs = dedupStore.check(agent, rec.delivery_id, now);
|
|
89764
89899
|
if (originalTs !== undefined) {
|
|
@@ -89767,7 +89902,7 @@ function recordWebhookEvent(rec, deps = {}) {
|
|
|
89767
89902
|
return { status: "deduped", ts: originalTs };
|
|
89768
89903
|
}
|
|
89769
89904
|
}
|
|
89770
|
-
const logPath =
|
|
89905
|
+
const logPath = join48(telegramDir, "webhook-events.jsonl");
|
|
89771
89906
|
try {
|
|
89772
89907
|
mkdirSync36(telegramDir, { recursive: true });
|
|
89773
89908
|
rotateWebhookLogIfNeeded(logPath);
|
|
@@ -94030,14 +94165,14 @@ function purgeStaleTurnsForChat(chatId, keys, purger, isStale = () => true) {
|
|
|
94030
94165
|
// gateway/compaction-marker.ts
|
|
94031
94166
|
import { statSync as statSync15, unlinkSync as unlinkSync21 } from "node:fs";
|
|
94032
94167
|
import { homedir as homedir15 } from "node:os";
|
|
94033
|
-
import { join as
|
|
94168
|
+
import { join as join49 } from "node:path";
|
|
94034
94169
|
var COMPACTION_MARKER_FILE = "compaction-in-flight.json";
|
|
94035
94170
|
function resolveTelegramStateDir() {
|
|
94036
|
-
return process.env.TELEGRAM_STATE_DIR ??
|
|
94171
|
+
return process.env.TELEGRAM_STATE_DIR ?? join49(homedir15(), ".claude", "channels", "telegram");
|
|
94037
94172
|
}
|
|
94038
94173
|
function readCompactionMarkerAgeMs(stateDir, now) {
|
|
94039
94174
|
try {
|
|
94040
|
-
const st = statSync15(
|
|
94175
|
+
const st = statSync15(join49(stateDir, COMPACTION_MARKER_FILE));
|
|
94041
94176
|
return (now ?? Date.now()) - st.mtimeMs;
|
|
94042
94177
|
} catch {
|
|
94043
94178
|
return null;
|
|
@@ -94045,7 +94180,7 @@ function readCompactionMarkerAgeMs(stateDir, now) {
|
|
|
94045
94180
|
}
|
|
94046
94181
|
function removeCompactionMarker(stateDir) {
|
|
94047
94182
|
try {
|
|
94048
|
-
unlinkSync21(
|
|
94183
|
+
unlinkSync21(join49(stateDir, COMPACTION_MARKER_FILE));
|
|
94049
94184
|
} catch {}
|
|
94050
94185
|
}
|
|
94051
94186
|
|
|
@@ -94867,26 +95002,26 @@ function skillProposalKeyboard(id) {
|
|
|
94867
95002
|
// ../src/self-improve/skill-proposals.ts
|
|
94868
95003
|
import {
|
|
94869
95004
|
closeSync as closeSync9,
|
|
94870
|
-
existsSync as
|
|
95005
|
+
existsSync as existsSync42,
|
|
94871
95006
|
mkdirSync as mkdirSync37,
|
|
94872
95007
|
openSync as openSync9,
|
|
94873
|
-
readFileSync as
|
|
95008
|
+
readFileSync as readFileSync38,
|
|
94874
95009
|
writeSync as writeSync6
|
|
94875
95010
|
} from "node:fs";
|
|
94876
|
-
import { join as
|
|
95011
|
+
import { join as join50 } from "node:path";
|
|
94877
95012
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
94878
95013
|
var PROPOSALS_FILE2 = "skill-proposals.jsonl";
|
|
94879
95014
|
var REJECTED_FILE2 = "skill-proposals-rejected.jsonl";
|
|
94880
95015
|
var REJECTION_TTL_MS2 = 90 * 24 * 60 * 60 * 1000;
|
|
94881
95016
|
var PROPOSAL_SIM_THRESHOLD = 0.5;
|
|
94882
95017
|
function proposalsPath2(stateDir) {
|
|
94883
|
-
return
|
|
95018
|
+
return join50(stateDir, PROPOSALS_FILE2);
|
|
94884
95019
|
}
|
|
94885
95020
|
function rejectedPath2(stateDir) {
|
|
94886
|
-
return
|
|
95021
|
+
return join50(stateDir, REJECTED_FILE2);
|
|
94887
95022
|
}
|
|
94888
95023
|
function ensureDir3(stateDir) {
|
|
94889
|
-
if (!
|
|
95024
|
+
if (!existsSync42(stateDir)) {
|
|
94890
95025
|
mkdirSync37(stateDir, { recursive: true, mode: 493 });
|
|
94891
95026
|
}
|
|
94892
95027
|
}
|
|
@@ -94900,11 +95035,11 @@ function appendLine2(path3, obj) {
|
|
|
94900
95035
|
}
|
|
94901
95036
|
}
|
|
94902
95037
|
function readLines2(path3, isValid2) {
|
|
94903
|
-
if (!
|
|
95038
|
+
if (!existsSync42(path3))
|
|
94904
95039
|
return [];
|
|
94905
95040
|
let raw;
|
|
94906
95041
|
try {
|
|
94907
|
-
raw =
|
|
95042
|
+
raw = readFileSync38(path3, "utf-8");
|
|
94908
95043
|
} catch {
|
|
94909
95044
|
return [];
|
|
94910
95045
|
}
|
|
@@ -95501,7 +95636,7 @@ function escapeBody2(s) {
|
|
|
95501
95636
|
}
|
|
95502
95637
|
|
|
95503
95638
|
// gateway/pid-file.ts
|
|
95504
|
-
import { writeFileSync as writeFileSync33, readFileSync as
|
|
95639
|
+
import { writeFileSync as writeFileSync33, readFileSync as readFileSync39, unlinkSync as unlinkSync22, renameSync as renameSync18 } from "node:fs";
|
|
95505
95640
|
function writePidFile(path3, record) {
|
|
95506
95641
|
const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
|
|
95507
95642
|
writeFileSync33(tmp, JSON.stringify(record), "utf-8");
|
|
@@ -95520,10 +95655,10 @@ import {
|
|
|
95520
95655
|
writeFile as writeFileAsync,
|
|
95521
95656
|
readFile as readFileAsync
|
|
95522
95657
|
} from "node:fs/promises";
|
|
95523
|
-
import { readFileSync as
|
|
95658
|
+
import { readFileSync as readFileSync40 } from "node:fs";
|
|
95524
95659
|
function readCurrentBootId() {
|
|
95525
95660
|
try {
|
|
95526
|
-
const stat =
|
|
95661
|
+
const stat = readFileSync40("/proc/1/stat", "utf-8");
|
|
95527
95662
|
const lastParen = stat.lastIndexOf(")");
|
|
95528
95663
|
if (lastParen < 0)
|
|
95529
95664
|
return null;
|
|
@@ -95726,7 +95861,7 @@ function safeCount(fn) {
|
|
|
95726
95861
|
}
|
|
95727
95862
|
|
|
95728
95863
|
// gateway/session-marker.ts
|
|
95729
|
-
import { writeFileSync as writeFileSync34, readFileSync as
|
|
95864
|
+
import { writeFileSync as writeFileSync34, readFileSync as readFileSync41, renameSync as renameSync19, unlinkSync as unlinkSync23 } from "node:fs";
|
|
95730
95865
|
function writeSessionMarker(path3, marker) {
|
|
95731
95866
|
const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
|
|
95732
95867
|
writeFileSync34(tmp, JSON.stringify(marker), "utf-8");
|
|
@@ -95734,7 +95869,7 @@ function writeSessionMarker(path3, marker) {
|
|
|
95734
95869
|
}
|
|
95735
95870
|
function readSessionMarker(path3) {
|
|
95736
95871
|
try {
|
|
95737
|
-
const raw =
|
|
95872
|
+
const raw = readFileSync41(path3, "utf-8");
|
|
95738
95873
|
const parsed = JSON.parse(raw);
|
|
95739
95874
|
if (typeof parsed.pid === "number" && typeof parsed.startedAtMs === "number" && Number.isFinite(parsed.pid) && Number.isFinite(parsed.startedAtMs)) {
|
|
95740
95875
|
return { pid: parsed.pid, startedAtMs: parsed.startedAtMs };
|
|
@@ -95756,7 +95891,7 @@ function shouldFireRestartBanner(input) {
|
|
|
95756
95891
|
}
|
|
95757
95892
|
|
|
95758
95893
|
// gateway/clean-shutdown-marker.ts
|
|
95759
|
-
import { writeFileSync as writeFileSync35, readFileSync as
|
|
95894
|
+
import { writeFileSync as writeFileSync35, readFileSync as readFileSync42, renameSync as renameSync20, unlinkSync as unlinkSync24 } from "node:fs";
|
|
95760
95895
|
var DEFAULT_MAX_AGE_MS = 60000;
|
|
95761
95896
|
function writeCleanShutdownMarker(path3, marker) {
|
|
95762
95897
|
const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
|
|
@@ -95765,7 +95900,7 @@ function writeCleanShutdownMarker(path3, marker) {
|
|
|
95765
95900
|
}
|
|
95766
95901
|
function readCleanShutdownMarker(path3) {
|
|
95767
95902
|
try {
|
|
95768
|
-
const raw =
|
|
95903
|
+
const raw = readFileSync42(path3, "utf-8");
|
|
95769
95904
|
const parsed = JSON.parse(raw);
|
|
95770
95905
|
if (typeof parsed.ts === "number" && Number.isFinite(parsed.ts) && typeof parsed.signal === "string" && parsed.signal.length > 0) {
|
|
95771
95906
|
const out = { ts: parsed.ts, signal: parsed.signal };
|
|
@@ -96137,16 +96272,16 @@ function classifyAdminGate(text4, myAgentName) {
|
|
|
96137
96272
|
|
|
96138
96273
|
// subagent-watcher.ts
|
|
96139
96274
|
import {
|
|
96140
|
-
existsSync as
|
|
96275
|
+
existsSync as existsSync43,
|
|
96141
96276
|
openSync as openSync10,
|
|
96142
96277
|
readSync as readSync2,
|
|
96143
96278
|
statSync as statSync16,
|
|
96144
96279
|
closeSync as closeSync10,
|
|
96145
96280
|
watch,
|
|
96146
96281
|
readdirSync as readdirSync10,
|
|
96147
|
-
readFileSync as
|
|
96282
|
+
readFileSync as readFileSync43
|
|
96148
96283
|
} from "fs";
|
|
96149
|
-
import { join as
|
|
96284
|
+
import { join as join51 } from "path";
|
|
96150
96285
|
|
|
96151
96286
|
// session-tail.ts
|
|
96152
96287
|
function sanitizeCwdToProjectName2(cwd) {
|
|
@@ -96496,7 +96631,7 @@ function backfillJsonlAgentId(db3, jsonlPath, agentId, log) {
|
|
|
96496
96631
|
const metaPath = jsonlPath.replace(/\.jsonl$/, ".meta.json");
|
|
96497
96632
|
let meta;
|
|
96498
96633
|
try {
|
|
96499
|
-
const raw =
|
|
96634
|
+
const raw = readFileSync43(metaPath, "utf8");
|
|
96500
96635
|
meta = JSON.parse(raw);
|
|
96501
96636
|
} catch {
|
|
96502
96637
|
log?.(`subagent-watcher: backfill skip ${agentId} \u2014 meta.json not readable at ${metaPath}`);
|
|
@@ -96951,7 +97086,7 @@ function startSubagentWatcher(config) {
|
|
|
96951
97086
|
clearTimeout(ref.ref);
|
|
96952
97087
|
});
|
|
96953
97088
|
const fs3 = config.fs ?? {
|
|
96954
|
-
existsSync:
|
|
97089
|
+
existsSync: existsSync43,
|
|
96955
97090
|
readdirSync: readdirSync10,
|
|
96956
97091
|
statSync: statSync16,
|
|
96957
97092
|
openSync: openSync10,
|
|
@@ -97469,8 +97604,8 @@ function startSubagentWatcher(config) {
|
|
|
97469
97604
|
if (stopped)
|
|
97470
97605
|
return;
|
|
97471
97606
|
pruneVanishedDirWatchers();
|
|
97472
|
-
const claudeHome =
|
|
97473
|
-
const projectsRoot =
|
|
97607
|
+
const claudeHome = join51(agentDir, ".claude");
|
|
97608
|
+
const projectsRoot = join51(claudeHome, "projects");
|
|
97474
97609
|
if (!fs3.existsSync(projectsRoot))
|
|
97475
97610
|
return;
|
|
97476
97611
|
let projectDirs;
|
|
@@ -97504,7 +97639,7 @@ function startSubagentWatcher(config) {
|
|
|
97504
97639
|
continue;
|
|
97505
97640
|
}
|
|
97506
97641
|
warnedForeignSlugs.delete(pDir);
|
|
97507
|
-
const projectPath =
|
|
97642
|
+
const projectPath = join51(projectsRoot, pDir);
|
|
97508
97643
|
let sessionDirs;
|
|
97509
97644
|
try {
|
|
97510
97645
|
sessionDirs = fs3.readdirSync(projectPath);
|
|
@@ -97514,7 +97649,7 @@ function startSubagentWatcher(config) {
|
|
|
97514
97649
|
for (const sDir of sessionDirs) {
|
|
97515
97650
|
if (sDir.endsWith(".jsonl"))
|
|
97516
97651
|
continue;
|
|
97517
|
-
const subagentsPath =
|
|
97652
|
+
const subagentsPath = join51(projectPath, sDir, "subagents");
|
|
97518
97653
|
if (!fs3.existsSync(subagentsPath))
|
|
97519
97654
|
continue;
|
|
97520
97655
|
const watchAndScan = (dirPath) => {
|
|
@@ -97523,7 +97658,7 @@ function startSubagentWatcher(config) {
|
|
|
97523
97658
|
const w = fs3.watch(dirPath, (_event, filename) => {
|
|
97524
97659
|
if (!filename || !filename.toString().startsWith("agent-") || !filename.toString().endsWith(".jsonl"))
|
|
97525
97660
|
return;
|
|
97526
|
-
const filePath =
|
|
97661
|
+
const filePath = join51(dirPath, filename.toString());
|
|
97527
97662
|
if (!knownFiles.has(filePath)) {
|
|
97528
97663
|
scanSubagentsDir(dirPath);
|
|
97529
97664
|
}
|
|
@@ -97537,7 +97672,7 @@ function startSubagentWatcher(config) {
|
|
|
97537
97672
|
scanSubagentsDir(dirPath);
|
|
97538
97673
|
};
|
|
97539
97674
|
watchAndScan(subagentsPath);
|
|
97540
|
-
const workflowsPath =
|
|
97675
|
+
const workflowsPath = join51(subagentsPath, "workflows");
|
|
97541
97676
|
if (fs3.existsSync(workflowsPath)) {
|
|
97542
97677
|
let wfDirs;
|
|
97543
97678
|
try {
|
|
@@ -97547,7 +97682,7 @@ function startSubagentWatcher(config) {
|
|
|
97547
97682
|
}
|
|
97548
97683
|
for (const wfDir of wfDirs) {
|
|
97549
97684
|
try {
|
|
97550
|
-
const wfPath =
|
|
97685
|
+
const wfPath = join51(workflowsPath, wfDir);
|
|
97551
97686
|
if (!fs3.statSync(wfPath).isDirectory())
|
|
97552
97687
|
continue;
|
|
97553
97688
|
watchAndScan(wfPath);
|
|
@@ -97567,7 +97702,7 @@ function startSubagentWatcher(config) {
|
|
|
97567
97702
|
for (const e of entries) {
|
|
97568
97703
|
if (!e.startsWith("agent-") || !e.endsWith(".jsonl"))
|
|
97569
97704
|
continue;
|
|
97570
|
-
const filePath =
|
|
97705
|
+
const filePath = join51(subagentsPath, e);
|
|
97571
97706
|
if (knownFiles.has(filePath))
|
|
97572
97707
|
continue;
|
|
97573
97708
|
const agentId = e.slice("agent-".length, -".jsonl".length);
|
|
@@ -97697,19 +97832,19 @@ function startSubagentWatcher(config) {
|
|
|
97697
97832
|
import {
|
|
97698
97833
|
mkdirSync as mkdirSync38,
|
|
97699
97834
|
writeFileSync as writeFileSync36,
|
|
97700
|
-
readFileSync as
|
|
97835
|
+
readFileSync as readFileSync44,
|
|
97701
97836
|
readdirSync as readdirSync11,
|
|
97702
97837
|
unlinkSync as unlinkSync25,
|
|
97703
|
-
existsSync as
|
|
97838
|
+
existsSync as existsSync44,
|
|
97704
97839
|
renameSync as renameSync21
|
|
97705
97840
|
} from "node:fs";
|
|
97706
|
-
import { join as
|
|
97841
|
+
import { join as join52, resolve as resolve10 } from "node:path";
|
|
97707
97842
|
import { homedir as homedir16 } from "node:os";
|
|
97708
97843
|
function registryDir() {
|
|
97709
|
-
return resolve10(process.env.SWITCHROOM_WORKTREE_DIR ??
|
|
97844
|
+
return resolve10(process.env.SWITCHROOM_WORKTREE_DIR ?? join52(homedir16(), ".switchroom", "worktrees"));
|
|
97710
97845
|
}
|
|
97711
97846
|
function recordPath(id) {
|
|
97712
|
-
return
|
|
97847
|
+
return join52(registryDir(), `${id}.json`);
|
|
97713
97848
|
}
|
|
97714
97849
|
function ensureDir4() {
|
|
97715
97850
|
mkdirSync38(registryDir(), { recursive: true });
|
|
@@ -97725,7 +97860,7 @@ function writeRecord(record) {
|
|
|
97725
97860
|
function readRecord(id) {
|
|
97726
97861
|
const path3 = recordPath(id);
|
|
97727
97862
|
try {
|
|
97728
|
-
const raw =
|
|
97863
|
+
const raw = readFileSync44(path3, "utf8");
|
|
97729
97864
|
return JSON.parse(raw);
|
|
97730
97865
|
} catch {
|
|
97731
97866
|
return null;
|
|
@@ -97755,11 +97890,11 @@ function touchHeartbeat(id, onAfterRead) {
|
|
|
97755
97890
|
writeRecord({ ...rec, heartbeatAt: new Date().toISOString() });
|
|
97756
97891
|
}
|
|
97757
97892
|
function recordExists(id) {
|
|
97758
|
-
return
|
|
97893
|
+
return existsSync44(recordPath(id));
|
|
97759
97894
|
}
|
|
97760
97895
|
|
|
97761
97896
|
// worktree-watch-cwds.ts
|
|
97762
|
-
import { realpathSync as
|
|
97897
|
+
import { realpathSync as realpathSync4 } from "node:fs";
|
|
97763
97898
|
import { basename as basename13 } from "node:path";
|
|
97764
97899
|
var identityEscalated = false;
|
|
97765
97900
|
function defaultDeriveName(agentDir) {
|
|
@@ -97785,7 +97920,7 @@ function ownedWorktreeCwds(opts) {
|
|
|
97785
97920
|
}
|
|
97786
97921
|
return [];
|
|
97787
97922
|
}
|
|
97788
|
-
const rp = opts.realpath ??
|
|
97923
|
+
const rp = opts.realpath ?? realpathSync4;
|
|
97789
97924
|
try {
|
|
97790
97925
|
return opts.listRecords().filter((r) => r.ownerAgent === resolved).map((r) => {
|
|
97791
97926
|
try {
|
|
@@ -97884,20 +98019,20 @@ function determineRestartReason(opts) {
|
|
|
97884
98019
|
}
|
|
97885
98020
|
|
|
97886
98021
|
// gateway/update-announce.ts
|
|
97887
|
-
import { existsSync as
|
|
97888
|
-
import { join as
|
|
98022
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync42, openSync as openSync11, closeSync as closeSync11, readFileSync as readFileSync51 } from "node:fs";
|
|
98023
|
+
import { join as join57 } from "node:path";
|
|
97889
98024
|
import { homedir as homedir18 } from "node:os";
|
|
97890
98025
|
|
|
97891
98026
|
// ../src/host-control/audit-reader.ts
|
|
97892
98027
|
import { homedir as homedir17 } from "node:os";
|
|
97893
|
-
import { join as
|
|
98028
|
+
import { join as join56 } from "node:path";
|
|
97894
98029
|
|
|
97895
98030
|
// ../src/host-control/audit-rotation-config.ts
|
|
97896
98031
|
var DEFAULT_HOSTD_AUDIT_MAX_BYTES = 32 * 1024 * 1024;
|
|
97897
98032
|
|
|
97898
98033
|
// ../src/host-control/audit-reader.ts
|
|
97899
98034
|
function defaultAuditLogPath(home2 = homedir17()) {
|
|
97900
|
-
return
|
|
98035
|
+
return join56(home2, ".switchroom", "host-control-audit.log");
|
|
97901
98036
|
}
|
|
97902
98037
|
var AUDIT_READ_WINDOW_BYTES = 4 * 1024 * 1024;
|
|
97903
98038
|
function parseAuditLine(line) {
|
|
@@ -98031,8 +98166,8 @@ init_status_no_truncate();
|
|
|
98031
98166
|
var DEFAULT_LOOKBACK_MS = 10 * 60 * 1000;
|
|
98032
98167
|
function readLastTerminalUpdateAudit(opts = {}) {
|
|
98033
98168
|
const path3 = opts.auditLogPath ?? defaultAuditLogPath();
|
|
98034
|
-
const exists = opts.exists ??
|
|
98035
|
-
const readFile = opts.readFile ?? ((p) =>
|
|
98169
|
+
const exists = opts.exists ?? existsSync49;
|
|
98170
|
+
const readFile = opts.readFile ?? ((p) => readFileSync51(p, "utf-8"));
|
|
98036
98171
|
if (!exists(path3))
|
|
98037
98172
|
return null;
|
|
98038
98173
|
let raw;
|
|
@@ -98096,15 +98231,15 @@ function renderUpdateOutcomeLine(entry) {
|
|
|
98096
98231
|
`);
|
|
98097
98232
|
}
|
|
98098
98233
|
function claimUpdateAnnouncement(requestId, opts = {}) {
|
|
98099
|
-
const stateDir = opts.stateDir ?? process.env.TELEGRAM_STATE_DIR ??
|
|
98100
|
-
const dir =
|
|
98234
|
+
const stateDir = opts.stateDir ?? process.env.TELEGRAM_STATE_DIR ?? join57(homedir18(), ".switchroom");
|
|
98235
|
+
const dir = join57(stateDir, "update-announced");
|
|
98101
98236
|
try {
|
|
98102
98237
|
mkdirSync42(dir, { recursive: true });
|
|
98103
98238
|
} catch {
|
|
98104
98239
|
return false;
|
|
98105
98240
|
}
|
|
98106
98241
|
const safeId = requestId.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 200);
|
|
98107
|
-
const path3 =
|
|
98242
|
+
const path3 = join57(dir, safeId);
|
|
98108
98243
|
try {
|
|
98109
98244
|
const fd = openSync11(path3, "wx");
|
|
98110
98245
|
closeSync11(fd);
|
|
@@ -98124,7 +98259,7 @@ function maybeRenderUpdateAnnouncement(opts = {}) {
|
|
|
98124
98259
|
|
|
98125
98260
|
// issues-card.ts
|
|
98126
98261
|
init_card_format();
|
|
98127
|
-
import { readFileSync as
|
|
98262
|
+
import { readFileSync as readFileSync52, writeFileSync as writeFileSync41 } from "node:fs";
|
|
98128
98263
|
var SEVERITY_EMOJI = {
|
|
98129
98264
|
info: "\u2139\ufe0f",
|
|
98130
98265
|
warn: "\u26a0\ufe0f",
|
|
@@ -98216,7 +98351,7 @@ function extractRetryAfterSecs2(err) {
|
|
|
98216
98351
|
var COOLDOWN_JITTER_MS2 = 500;
|
|
98217
98352
|
function readPersistedMessageId(path3, log) {
|
|
98218
98353
|
try {
|
|
98219
|
-
const raw =
|
|
98354
|
+
const raw = readFileSync52(path3, "utf8");
|
|
98220
98355
|
const parsed = JSON.parse(raw);
|
|
98221
98356
|
const v = parsed.messageId;
|
|
98222
98357
|
if (typeof v === "number" && Number.isInteger(v) && v > 0)
|
|
@@ -98325,24 +98460,24 @@ function createIssuesCardHandle(opts) {
|
|
|
98325
98460
|
}
|
|
98326
98461
|
|
|
98327
98462
|
// issues-watcher.ts
|
|
98328
|
-
import { existsSync as
|
|
98329
|
-
import { join as
|
|
98463
|
+
import { existsSync as existsSync51, statSync as statSync19 } from "node:fs";
|
|
98464
|
+
import { join as join59 } from "node:path";
|
|
98330
98465
|
|
|
98331
98466
|
// ../src/issues/store.ts
|
|
98332
98467
|
import {
|
|
98333
98468
|
closeSync as closeSync12,
|
|
98334
|
-
existsSync as
|
|
98469
|
+
existsSync as existsSync50,
|
|
98335
98470
|
mkdirSync as mkdirSync43,
|
|
98336
98471
|
openSync as openSync12,
|
|
98337
98472
|
readdirSync as readdirSync13,
|
|
98338
|
-
readFileSync as
|
|
98473
|
+
readFileSync as readFileSync53,
|
|
98339
98474
|
renameSync as renameSync24,
|
|
98340
98475
|
statSync as statSync18,
|
|
98341
98476
|
unlinkSync as unlinkSync26,
|
|
98342
98477
|
writeFileSync as writeFileSync42,
|
|
98343
98478
|
writeSync as writeSync7
|
|
98344
98479
|
} from "node:fs";
|
|
98345
|
-
import { join as
|
|
98480
|
+
import { join as join58 } from "node:path";
|
|
98346
98481
|
import { randomBytes as randomBytes11 } from "node:crypto";
|
|
98347
98482
|
import { execSync } from "node:child_process";
|
|
98348
98483
|
|
|
@@ -98361,12 +98496,12 @@ init_redact();
|
|
|
98361
98496
|
var ISSUES_FILE = "issues.jsonl";
|
|
98362
98497
|
var ISSUES_LOCK = "issues.lock";
|
|
98363
98498
|
function readAll(stateDir) {
|
|
98364
|
-
const path3 =
|
|
98365
|
-
if (!
|
|
98499
|
+
const path3 = join58(stateDir, ISSUES_FILE);
|
|
98500
|
+
if (!existsSync50(path3))
|
|
98366
98501
|
return [];
|
|
98367
98502
|
let raw;
|
|
98368
98503
|
try {
|
|
98369
|
-
raw =
|
|
98504
|
+
raw = readFileSync53(path3, "utf-8");
|
|
98370
98505
|
} catch {
|
|
98371
98506
|
return [];
|
|
98372
98507
|
}
|
|
@@ -98398,7 +98533,7 @@ function list2(stateDir, opts = {}) {
|
|
|
98398
98533
|
});
|
|
98399
98534
|
}
|
|
98400
98535
|
function resolve11(stateDir, fingerprint, nowFn = Date.now) {
|
|
98401
|
-
if (!
|
|
98536
|
+
if (!existsSync50(join58(stateDir, ISSUES_FILE)))
|
|
98402
98537
|
return 0;
|
|
98403
98538
|
return withLock(stateDir, () => {
|
|
98404
98539
|
const all2 = readAll(stateDir);
|
|
@@ -98416,7 +98551,7 @@ function resolve11(stateDir, fingerprint, nowFn = Date.now) {
|
|
|
98416
98551
|
});
|
|
98417
98552
|
}
|
|
98418
98553
|
function writeAll(stateDir, events) {
|
|
98419
|
-
const path3 =
|
|
98554
|
+
const path3 = join58(stateDir, ISSUES_FILE);
|
|
98420
98555
|
sweepOrphanTmpFiles(stateDir);
|
|
98421
98556
|
const tmp = `${path3}.tmp-${process.pid}-${randomBytes11(4).toString("hex")}`;
|
|
98422
98557
|
const body = events.length === 0 ? "" : events.map((e) => JSON.stringify(e)).join(`
|
|
@@ -98438,7 +98573,7 @@ function sweepOrphanTmpFiles(stateDir) {
|
|
|
98438
98573
|
for (const entry of entries) {
|
|
98439
98574
|
if (!entry.startsWith(TMP_PREFIX))
|
|
98440
98575
|
continue;
|
|
98441
|
-
const tmpPath2 =
|
|
98576
|
+
const tmpPath2 = join58(stateDir, entry);
|
|
98442
98577
|
try {
|
|
98443
98578
|
const stat = statSync18(tmpPath2);
|
|
98444
98579
|
if (stat.mtimeMs < cutoff) {
|
|
@@ -98450,7 +98585,7 @@ function sweepOrphanTmpFiles(stateDir) {
|
|
|
98450
98585
|
var LOCK_RETRY_MS = 25;
|
|
98451
98586
|
var LOCK_TIMEOUT_MS = 1e4;
|
|
98452
98587
|
function withLock(stateDir, fn) {
|
|
98453
|
-
const lockPath =
|
|
98588
|
+
const lockPath = join58(stateDir, ISSUES_LOCK);
|
|
98454
98589
|
const startedAt = Date.now();
|
|
98455
98590
|
let fd = null;
|
|
98456
98591
|
while (fd === null) {
|
|
@@ -98485,7 +98620,7 @@ function withLock(stateDir, fn) {
|
|
|
98485
98620
|
function tryStealStaleLock(lockPath) {
|
|
98486
98621
|
let pidStr;
|
|
98487
98622
|
try {
|
|
98488
|
-
pidStr =
|
|
98623
|
+
pidStr = readFileSync53(lockPath, "utf-8").trim();
|
|
98489
98624
|
} catch {
|
|
98490
98625
|
return true;
|
|
98491
98626
|
}
|
|
@@ -98535,7 +98670,7 @@ function isIssueEvent(v) {
|
|
|
98535
98670
|
// issues-watcher.ts
|
|
98536
98671
|
var DEFAULT_POLL_INTERVAL_MS2 = 2000;
|
|
98537
98672
|
function startIssuesWatcher(opts) {
|
|
98538
|
-
const path3 =
|
|
98673
|
+
const path3 = join59(opts.stateDir, ISSUES_FILE);
|
|
98539
98674
|
const log = opts.log ?? (() => {});
|
|
98540
98675
|
const intervalMs = opts.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS2;
|
|
98541
98676
|
const setIntervalFn = opts.setInterval ?? setInterval;
|
|
@@ -98583,7 +98718,7 @@ function startIssuesWatcher(opts) {
|
|
|
98583
98718
|
};
|
|
98584
98719
|
}
|
|
98585
98720
|
function defaultSignatureProvider(path3) {
|
|
98586
|
-
if (!
|
|
98721
|
+
if (!existsSync51(path3))
|
|
98587
98722
|
return null;
|
|
98588
98723
|
try {
|
|
98589
98724
|
const stat = statSync19(path3);
|
|
@@ -99295,7 +99430,7 @@ function readBashCommand(inputPreview) {
|
|
|
99295
99430
|
|
|
99296
99431
|
// gateway/scoped-grant-store.ts
|
|
99297
99432
|
init_atomic();
|
|
99298
|
-
import { join as
|
|
99433
|
+
import { join as join60 } from "node:path";
|
|
99299
99434
|
|
|
99300
99435
|
// scoped-approval.ts
|
|
99301
99436
|
var SCOPED_APPROVAL_DEFAULT_TTL_MS2 = 30 * 60 * 1000;
|
|
@@ -99337,7 +99472,7 @@ function scopedGrantPersistEnabled(env = process.env) {
|
|
|
99337
99472
|
return env.SWITCHROOM_SCOPED_GRANT_PERSIST !== "0";
|
|
99338
99473
|
}
|
|
99339
99474
|
function createScopedGrantStore(stateDir, env = process.env, log = (l) => process.stderr.write(l)) {
|
|
99340
|
-
const filePath =
|
|
99475
|
+
const filePath = join60(stateDir, "scoped-grants.json");
|
|
99341
99476
|
const enabled7 = scopedGrantPersistEnabled(env);
|
|
99342
99477
|
let unreadable = false;
|
|
99343
99478
|
function read() {
|
|
@@ -99715,8 +99850,8 @@ function isDiffPreApproved(agentName3, unifiedDiff, deps) {
|
|
|
99715
99850
|
|
|
99716
99851
|
// credits-watch.ts
|
|
99717
99852
|
init_card_format();
|
|
99718
|
-
import { readFileSync as
|
|
99719
|
-
import { join as
|
|
99853
|
+
import { readFileSync as readFileSync54, writeFileSync as writeFileSync43, existsSync as existsSync52, mkdirSync as mkdirSync44 } from "fs";
|
|
99854
|
+
import { join as join61 } from "path";
|
|
99720
99855
|
var STATE_FILE = "credits-watch.json";
|
|
99721
99856
|
var DEFAULT_CREDIT_FATAL_REASONS = new Set;
|
|
99722
99857
|
var KNOWN_CREDIT_REASONS = [
|
|
@@ -99738,12 +99873,12 @@ function emptyCreditState() {
|
|
|
99738
99873
|
return { lastNotifiedReason: null, lastNotifiedAt: 0 };
|
|
99739
99874
|
}
|
|
99740
99875
|
function readClaudeJsonOverage(claudeConfigDir) {
|
|
99741
|
-
const path3 =
|
|
99742
|
-
if (!
|
|
99876
|
+
const path3 = join61(claudeConfigDir, ".claude.json");
|
|
99877
|
+
if (!existsSync52(path3))
|
|
99743
99878
|
return null;
|
|
99744
99879
|
let raw;
|
|
99745
99880
|
try {
|
|
99746
|
-
raw =
|
|
99881
|
+
raw = readFileSync54(path3, "utf-8");
|
|
99747
99882
|
} catch {
|
|
99748
99883
|
return null;
|
|
99749
99884
|
}
|
|
@@ -99821,11 +99956,11 @@ function humanizeReason(reason) {
|
|
|
99821
99956
|
}
|
|
99822
99957
|
}
|
|
99823
99958
|
function loadCreditState(stateDir) {
|
|
99824
|
-
const path3 =
|
|
99825
|
-
if (!
|
|
99959
|
+
const path3 = join61(stateDir, STATE_FILE);
|
|
99960
|
+
if (!existsSync52(path3))
|
|
99826
99961
|
return emptyCreditState();
|
|
99827
99962
|
try {
|
|
99828
|
-
const raw =
|
|
99963
|
+
const raw = readFileSync54(path3, "utf-8");
|
|
99829
99964
|
const parsed = JSON.parse(raw);
|
|
99830
99965
|
if (parsed && typeof parsed === "object" && (parsed.lastNotifiedReason === null || typeof parsed.lastNotifiedReason === "string") && typeof parsed.lastNotifiedAt === "number" && Number.isFinite(parsed.lastNotifiedAt)) {
|
|
99831
99966
|
return {
|
|
@@ -99838,7 +99973,7 @@ function loadCreditState(stateDir) {
|
|
|
99838
99973
|
}
|
|
99839
99974
|
function saveCreditState(stateDir, state7) {
|
|
99840
99975
|
mkdirSync44(stateDir, { recursive: true });
|
|
99841
|
-
const path3 =
|
|
99976
|
+
const path3 = join61(stateDir, STATE_FILE);
|
|
99842
99977
|
writeFileSync43(path3, JSON.stringify(state7, null, 2) + `
|
|
99843
99978
|
`, { mode: 384 });
|
|
99844
99979
|
}
|
|
@@ -99846,8 +99981,8 @@ function saveCreditState(stateDir, state7) {
|
|
|
99846
99981
|
// quota-watch.ts
|
|
99847
99982
|
init_auth_snapshot_format();
|
|
99848
99983
|
init_card_format();
|
|
99849
|
-
import { readFileSync as
|
|
99850
|
-
import { join as
|
|
99984
|
+
import { readFileSync as readFileSync55, writeFileSync as writeFileSync44, existsSync as existsSync53, mkdirSync as mkdirSync45 } from "fs";
|
|
99985
|
+
import { join as join62 } from "path";
|
|
99851
99986
|
var STATE_FILE2 = "quota-watch.json";
|
|
99852
99987
|
function emptyQuotaWatchState() {
|
|
99853
99988
|
return {};
|
|
@@ -100085,11 +100220,11 @@ function buildRecoveryMessage(agentName3, snap) {
|
|
|
100085
100220
|
`);
|
|
100086
100221
|
}
|
|
100087
100222
|
function loadQuotaWatchState(stateDir) {
|
|
100088
|
-
const path3 =
|
|
100089
|
-
if (!
|
|
100223
|
+
const path3 = join62(stateDir, STATE_FILE2);
|
|
100224
|
+
if (!existsSync53(path3))
|
|
100090
100225
|
return emptyQuotaWatchState();
|
|
100091
100226
|
try {
|
|
100092
|
-
const raw =
|
|
100227
|
+
const raw = readFileSync55(path3, "utf-8");
|
|
100093
100228
|
const parsed = JSON.parse(raw);
|
|
100094
100229
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
100095
100230
|
return emptyQuotaWatchState();
|
|
@@ -100107,7 +100242,7 @@ function loadQuotaWatchState(stateDir) {
|
|
|
100107
100242
|
}
|
|
100108
100243
|
function saveQuotaWatchState(stateDir, state7) {
|
|
100109
100244
|
mkdirSync45(stateDir, { recursive: true });
|
|
100110
|
-
const path3 =
|
|
100245
|
+
const path3 = join62(stateDir, STATE_FILE2);
|
|
100111
100246
|
writeFileSync44(path3, JSON.stringify(state7, null, 2) + `
|
|
100112
100247
|
`, { mode: 384 });
|
|
100113
100248
|
}
|
|
@@ -100156,27 +100291,27 @@ init_auth_snapshot_format2();
|
|
|
100156
100291
|
// gateway/turn-active-marker.ts
|
|
100157
100292
|
import {
|
|
100158
100293
|
closeSync as closeSync13,
|
|
100159
|
-
existsSync as
|
|
100294
|
+
existsSync as existsSync54,
|
|
100160
100295
|
mkdirSync as mkdirSync46,
|
|
100161
100296
|
openSync as openSync13,
|
|
100162
|
-
readFileSync as
|
|
100297
|
+
readFileSync as readFileSync56,
|
|
100163
100298
|
statSync as statSync20,
|
|
100164
100299
|
unlinkSync as unlinkSync27,
|
|
100165
100300
|
utimesSync as utimesSync2,
|
|
100166
100301
|
writeFileSync as writeFileSync45
|
|
100167
100302
|
} from "node:fs";
|
|
100168
|
-
import { join as
|
|
100303
|
+
import { join as join63 } from "node:path";
|
|
100169
100304
|
var TURN_ACTIVE_MARKER_FILE2 = "turn-active.json";
|
|
100170
100305
|
var TURN_ACTIVE_HARD_TTL_MS2 = 10 * 60000;
|
|
100171
100306
|
var TURN_ACTIVE_IDLE_SWEEP_MS = 60000;
|
|
100172
100307
|
function removeTurnActiveMarker2(stateDir) {
|
|
100173
100308
|
try {
|
|
100174
|
-
unlinkSync27(
|
|
100309
|
+
unlinkSync27(join63(stateDir, TURN_ACTIVE_MARKER_FILE2));
|
|
100175
100310
|
} catch {}
|
|
100176
100311
|
}
|
|
100177
100312
|
function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
100178
|
-
const path3 =
|
|
100179
|
-
if (!
|
|
100313
|
+
const path3 = join63(stateDir, TURN_ACTIVE_MARKER_FILE2);
|
|
100314
|
+
if (!existsSync54(path3))
|
|
100180
100315
|
return false;
|
|
100181
100316
|
const now = opts.now ?? Date.now();
|
|
100182
100317
|
try {
|
|
@@ -100188,7 +100323,7 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
|
100188
100323
|
return false;
|
|
100189
100324
|
let payload = null;
|
|
100190
100325
|
try {
|
|
100191
|
-
payload =
|
|
100326
|
+
payload = readFileSync56(path3, "utf8");
|
|
100192
100327
|
} catch {}
|
|
100193
100328
|
unlinkSync27(path3);
|
|
100194
100329
|
if (opts.onRemove) {
|
|
@@ -100206,7 +100341,7 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
|
100206
100341
|
}
|
|
100207
100342
|
}
|
|
100208
100343
|
function readTurnActiveMarkerAgeMs2(stateDir, now) {
|
|
100209
|
-
const path3 =
|
|
100344
|
+
const path3 = join63(stateDir, TURN_ACTIVE_MARKER_FILE2);
|
|
100210
100345
|
try {
|
|
100211
100346
|
const st = statSync20(path3);
|
|
100212
100347
|
return (now ?? Date.now()) - st.mtimeMs;
|
|
@@ -100220,11 +100355,11 @@ function effectiveTurnAgeMs(markerAgeMs, turnStartedAt, now) {
|
|
|
100220
100355
|
|
|
100221
100356
|
// gateway/gateway-heartbeat.ts
|
|
100222
100357
|
import { mkdirSync as mkdirSync47, utimesSync as utimesSync3, writeFileSync as writeFileSync46 } from "node:fs";
|
|
100223
|
-
import { join as
|
|
100358
|
+
import { join as join64 } from "node:path";
|
|
100224
100359
|
var GATEWAY_HEARTBEAT_FILE = "gateway-heartbeat";
|
|
100225
100360
|
var GATEWAY_HEARTBEAT_INTERVAL_MS = 15000;
|
|
100226
100361
|
function touchGatewayHeartbeat(stateDir) {
|
|
100227
|
-
const path3 =
|
|
100362
|
+
const path3 = join64(stateDir, GATEWAY_HEARTBEAT_FILE);
|
|
100228
100363
|
const now = new Date;
|
|
100229
100364
|
try {
|
|
100230
100365
|
utimesSync3(path3, now, now);
|
|
@@ -100250,12 +100385,12 @@ import {
|
|
|
100250
100385
|
fsyncSync as fsyncSync5,
|
|
100251
100386
|
mkdirSync as mkdirSync48,
|
|
100252
100387
|
openSync as openSync14,
|
|
100253
|
-
readFileSync as
|
|
100388
|
+
readFileSync as readFileSync57,
|
|
100254
100389
|
renameSync as renameSync25,
|
|
100255
100390
|
unlinkSync as unlinkSync28,
|
|
100256
100391
|
writeFileSync as writeFileSync47
|
|
100257
100392
|
} from "node:fs";
|
|
100258
|
-
import { join as
|
|
100393
|
+
import { join as join65 } from "node:path";
|
|
100259
100394
|
var BOOT_BEACON_FILE = "gateway-beacon.json";
|
|
100260
100395
|
var HOST_BOOT_ID_PATH = "/proc/sys/kernel/random/boot_id";
|
|
100261
100396
|
var CGROUP_MEMORY_EVENTS_PATH = "/sys/fs/cgroup/memory.events";
|
|
@@ -100332,7 +100467,7 @@ function serializeBootBeacon(beacon) {
|
|
|
100332
100467
|
}
|
|
100333
100468
|
function readTextOrNull(path3) {
|
|
100334
100469
|
try {
|
|
100335
|
-
return
|
|
100470
|
+
return readFileSync57(path3, "utf-8");
|
|
100336
100471
|
} catch {
|
|
100337
100472
|
return null;
|
|
100338
100473
|
}
|
|
@@ -100354,7 +100489,7 @@ function sampleBeaconHost(paths = {}) {
|
|
|
100354
100489
|
return sample3;
|
|
100355
100490
|
}
|
|
100356
100491
|
function writeBootBeaconFile(stateDir, beacon) {
|
|
100357
|
-
const path3 =
|
|
100492
|
+
const path3 = join65(stateDir, BOOT_BEACON_FILE);
|
|
100358
100493
|
const tmp = `${path3}.tmp-${process.pid}`;
|
|
100359
100494
|
let fd;
|
|
100360
100495
|
try {
|
|
@@ -100731,10 +100866,10 @@ function startOutboxSweep(deps) {
|
|
|
100731
100866
|
}
|
|
100732
100867
|
|
|
100733
100868
|
// ../src/build-info.ts
|
|
100734
|
-
var VERSION2 = "0.19.
|
|
100735
|
-
var COMMIT_SHA = "
|
|
100736
|
-
var COMMIT_DATE = "2026-08-
|
|
100737
|
-
var LATEST_PR =
|
|
100869
|
+
var VERSION2 = "0.19.44";
|
|
100870
|
+
var COMMIT_SHA = "82d3b0b2";
|
|
100871
|
+
var COMMIT_DATE = "2026-08-01T23:02:10Z";
|
|
100872
|
+
var LATEST_PR = 4186;
|
|
100738
100873
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
100739
100874
|
|
|
100740
100875
|
// gateway/boot-version.ts
|
|
@@ -100812,11 +100947,11 @@ init_peercred();
|
|
|
100812
100947
|
import * as net5 from "node:net";
|
|
100813
100948
|
import * as fs3 from "node:fs";
|
|
100814
100949
|
import { homedir as homedir19 } from "node:os";
|
|
100815
|
-
import { join as
|
|
100950
|
+
import { join as join66 } from "node:path";
|
|
100816
100951
|
var DEFAULT_TIMEOUT_MS4 = 2000;
|
|
100817
100952
|
var UNLOCK_TIMEOUT_MS = 30000;
|
|
100818
|
-
var LEGACY_SOCKET_PATH2 =
|
|
100819
|
-
var OPERATOR_SOCKET_PATH2 =
|
|
100953
|
+
var LEGACY_SOCKET_PATH2 = join66(homedir19(), ".switchroom", "vault-broker.sock");
|
|
100954
|
+
var OPERATOR_SOCKET_PATH2 = join66(homedir19(), ".switchroom", "broker-operator", "sock");
|
|
100820
100955
|
function defaultBrokerSocketPath2() {
|
|
100821
100956
|
if (fs3.existsSync(OPERATOR_SOCKET_PATH2))
|
|
100822
100957
|
return OPERATOR_SOCKET_PATH2;
|
|
@@ -101699,7 +101834,7 @@ function resolveVaultApprovalPosture(broker) {
|
|
|
101699
101834
|
|
|
101700
101835
|
// registry/turns-schema.ts
|
|
101701
101836
|
import { chmodSync as chmodSync12, mkdirSync as mkdirSync49 } from "fs";
|
|
101702
|
-
import { join as
|
|
101837
|
+
import { join as join67 } from "path";
|
|
101703
101838
|
var DatabaseClass3 = null;
|
|
101704
101839
|
function loadDatabaseClass3() {
|
|
101705
101840
|
if (DatabaseClass3 != null)
|
|
@@ -101771,9 +101906,9 @@ function applySchema(db3) {
|
|
|
101771
101906
|
}
|
|
101772
101907
|
function openTurnsDb(agentDir) {
|
|
101773
101908
|
const Database = loadDatabaseClass3();
|
|
101774
|
-
const dir =
|
|
101909
|
+
const dir = join67(agentDir, "telegram");
|
|
101775
101910
|
mkdirSync49(dir, { recursive: true, mode: 448 });
|
|
101776
|
-
const path3 =
|
|
101911
|
+
const path3 = join67(dir, "registry.db");
|
|
101777
101912
|
const db3 = new Database(path3, { create: true });
|
|
101778
101913
|
applySchema(db3);
|
|
101779
101914
|
try {
|
|
@@ -102118,7 +102253,7 @@ function selectResumeBuilder(endedVia, opts) {
|
|
|
102118
102253
|
}
|
|
102119
102254
|
|
|
102120
102255
|
// gateway/bridge-dead-watchdog.ts
|
|
102121
|
-
import { readFileSync as
|
|
102256
|
+
import { readFileSync as readFileSync59, writeFileSync as writeFileSync48, renameSync as renameSync26, unlinkSync as unlinkSync29 } from "node:fs";
|
|
102122
102257
|
|
|
102123
102258
|
// gateway/cron-session.ts
|
|
102124
102259
|
var CRON_IDENTITY_SUFFIX2 = "-cron";
|
|
@@ -102151,7 +102286,7 @@ function readFreshCrashLogTail(path3, opts = {}) {
|
|
|
102151
102286
|
const nowMs3 = opts.nowMs ?? Date.now();
|
|
102152
102287
|
const freshWindowMs = opts.freshWindowMs ?? CRASH_LOG_FRESH_WINDOW_MS;
|
|
102153
102288
|
const maxLines = opts.maxLines ?? CRASH_LOG_TAIL_LINES;
|
|
102154
|
-
const readFile = opts.readFile ?? ((p) =>
|
|
102289
|
+
const readFile = opts.readFile ?? ((p) => readFileSync59(p, "utf8"));
|
|
102155
102290
|
let raw;
|
|
102156
102291
|
try {
|
|
102157
102292
|
raw = readFile(path3);
|
|
@@ -102178,7 +102313,7 @@ function writeBridgeDeadEscalationMarker(path3, marker) {
|
|
|
102178
102313
|
function consumeBridgeDeadEscalationMarker(path3, nowMs3 = Date.now(), maxAgeMs = ESCALATION_MARKER_MAX_AGE_MS) {
|
|
102179
102314
|
let marker = null;
|
|
102180
102315
|
try {
|
|
102181
|
-
const parsed = JSON.parse(
|
|
102316
|
+
const parsed = JSON.parse(readFileSync59(path3, "utf8"));
|
|
102182
102317
|
if (typeof parsed.ts === "number" && Number.isFinite(parsed.ts) && typeof parsed.reason === "string") {
|
|
102183
102318
|
const age = nowMs3 - parsed.ts;
|
|
102184
102319
|
if (age >= 0 && age < maxAgeMs) {
|
|
@@ -102331,7 +102466,7 @@ function createBridgeDeadWatchdog(opts) {
|
|
|
102331
102466
|
}
|
|
102332
102467
|
|
|
102333
102468
|
// gateway/boot-probes.ts
|
|
102334
|
-
import { readFileSync as
|
|
102469
|
+
import { readFileSync as readFileSync60, readdirSync as readdirSync14, existsSync as existsSync56 } from "fs";
|
|
102335
102470
|
init_quota_cache();
|
|
102336
102471
|
init_generation_stamp();
|
|
102337
102472
|
init_quota_check();
|
|
@@ -102340,7 +102475,7 @@ import { promisify as promisify2 } from "util";
|
|
|
102340
102475
|
var execFile2 = promisify2(execFileCb2);
|
|
102341
102476
|
var realProcFs2 = {
|
|
102342
102477
|
readdir: (p) => readdirSync14(p),
|
|
102343
|
-
readFile: (p) =>
|
|
102478
|
+
readFile: (p) => readFileSync60(p, "utf-8")
|
|
102344
102479
|
};
|
|
102345
102480
|
function findAgentProcessInContainer2(fs4 = realProcFs2) {
|
|
102346
102481
|
let entries;
|
|
@@ -102590,7 +102725,7 @@ if (isGatewayMain) {
|
|
|
102590
102725
|
shutdownAnalytics();
|
|
102591
102726
|
});
|
|
102592
102727
|
}
|
|
102593
|
-
var STATE_DIR = process.env.TELEGRAM_STATE_DIR ??
|
|
102728
|
+
var STATE_DIR = process.env.TELEGRAM_STATE_DIR ?? join68(homedir20(), ".claude", "channels", "telegram");
|
|
102594
102729
|
var permCardStore = createPermissionCardStore(STATE_DIR);
|
|
102595
102730
|
var BLOCKED_APPROVALS_DIR = process.env.SWITCHROOM_BLOCKED_APPROVALS_DIR ?? "/state/blocked-approvals";
|
|
102596
102731
|
var AGENT_NAME = process.env.SWITCHROOM_AGENT_NAME ?? "agent";
|
|
@@ -102629,7 +102764,7 @@ function alwaysAllowDrainDeps() {
|
|
|
102629
102764
|
return {
|
|
102630
102765
|
readConfigText: () => {
|
|
102631
102766
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
102632
|
-
return
|
|
102767
|
+
return readFileSync61(cfgPath, "utf8");
|
|
102633
102768
|
},
|
|
102634
102769
|
resolveAllowList: (_configText, agentName3) => {
|
|
102635
102770
|
const cfg = loadConfig2();
|
|
@@ -102690,11 +102825,11 @@ function scheduleAlwaysAllowPersistDrain() {
|
|
|
102690
102825
|
}, ALWAYS_ALLOW_DRAIN_INTERVAL_MS);
|
|
102691
102826
|
timer3.unref?.();
|
|
102692
102827
|
}
|
|
102693
|
-
var ACCESS_FILE =
|
|
102694
|
-
var APPROVED_DIR =
|
|
102695
|
-
var ENV_FILE =
|
|
102696
|
-
var INBOX_DIR =
|
|
102697
|
-
var PEOPLE_FILE =
|
|
102828
|
+
var ACCESS_FILE = join68(STATE_DIR, "access.json");
|
|
102829
|
+
var APPROVED_DIR = join68(STATE_DIR, "approved");
|
|
102830
|
+
var ENV_FILE = join68(STATE_DIR, ".env");
|
|
102831
|
+
var INBOX_DIR = join68(STATE_DIR, "inbox");
|
|
102832
|
+
var PEOPLE_FILE = join68(STATE_DIR, "people.json");
|
|
102698
102833
|
function triggerSelfRestart(targetAgent, reason, delayMs = 300) {
|
|
102699
102834
|
const isDocker = process.env.SWITCHROOM_RUNTIME === "docker";
|
|
102700
102835
|
const selfAgent = process.env.SWITCHROOM_AGENT_NAME;
|
|
@@ -102759,7 +102894,7 @@ function formatBootVersion() {
|
|
|
102759
102894
|
}
|
|
102760
102895
|
try {
|
|
102761
102896
|
chmodSync14(ENV_FILE, 384);
|
|
102762
|
-
for (const line of
|
|
102897
|
+
for (const line of readFileSync61(ENV_FILE, "utf8").split(`
|
|
102763
102898
|
`)) {
|
|
102764
102899
|
const m = line.match(/^(\w+)=(.*)$/);
|
|
102765
102900
|
if (m && process.env[m[1]] === undefined)
|
|
@@ -102780,7 +102915,7 @@ var bot;
|
|
|
102780
102915
|
var lastGetUpdatesHeartbeatMs = Date.now();
|
|
102781
102916
|
var GRAMMY_VERSION = (() => {
|
|
102782
102917
|
try {
|
|
102783
|
-
const raw =
|
|
102918
|
+
const raw = readFileSync61(new URL("../../node_modules/grammy/package.json", import.meta.url), "utf8");
|
|
102784
102919
|
return JSON.parse(raw).version ?? "unknown";
|
|
102785
102920
|
} catch {
|
|
102786
102921
|
return "unknown";
|
|
@@ -102819,12 +102954,12 @@ function assertSendable(f) {
|
|
|
102819
102954
|
}
|
|
102820
102955
|
let real, stateReal;
|
|
102821
102956
|
try {
|
|
102822
|
-
real =
|
|
102823
|
-
stateReal =
|
|
102957
|
+
real = realpathSync5(f);
|
|
102958
|
+
stateReal = realpathSync5(STATE_DIR);
|
|
102824
102959
|
} catch {
|
|
102825
102960
|
throw new Error(`refusing to send file \u2014 cannot resolve real path: ${f}`);
|
|
102826
102961
|
}
|
|
102827
|
-
const inbox =
|
|
102962
|
+
const inbox = join68(stateReal, "inbox");
|
|
102828
102963
|
if (real.startsWith(stateReal + sep4) && !real.startsWith(inbox + sep4)) {
|
|
102829
102964
|
throw new Error(`refusing to send channel state: ${f}`);
|
|
102830
102965
|
}
|
|
@@ -102843,7 +102978,7 @@ function assertSendable(f) {
|
|
|
102843
102978
|
}
|
|
102844
102979
|
function readAccessFile() {
|
|
102845
102980
|
try {
|
|
102846
|
-
const raw =
|
|
102981
|
+
const raw = readFileSync61(ACCESS_FILE, "utf8");
|
|
102847
102982
|
const parsed = JSON.parse(raw);
|
|
102848
102983
|
const allowFrom = validateStringArray("allowFrom", parsed.allowFrom ?? []);
|
|
102849
102984
|
const groups = {};
|
|
@@ -102905,7 +103040,7 @@ function loadAccess() {
|
|
|
102905
103040
|
}
|
|
102906
103041
|
function readPeopleFile() {
|
|
102907
103042
|
try {
|
|
102908
|
-
const raw =
|
|
103043
|
+
const raw = readFileSync61(PEOPLE_FILE, "utf8");
|
|
102909
103044
|
const parsed = JSON.parse(raw);
|
|
102910
103045
|
if (!Array.isArray(parsed.entries))
|
|
102911
103046
|
return [];
|
|
@@ -102949,7 +103084,7 @@ var HISTORY_ENABLED = HISTORY_ACCESS.historyEnabled !== false;
|
|
|
102949
103084
|
if (isGatewayMain && HISTORY_ENABLED) {
|
|
102950
103085
|
try {
|
|
102951
103086
|
initHistory(STATE_DIR, HISTORY_ACCESS.historyRetentionDays ?? 30);
|
|
102952
|
-
process.stderr.write(`telegram gateway: history capture enabled at ${
|
|
103087
|
+
process.stderr.write(`telegram gateway: history capture enabled at ${join68(STATE_DIR, "history.db")}
|
|
102953
103088
|
`);
|
|
102954
103089
|
} catch (err) {
|
|
102955
103090
|
process.stderr.write(`telegram gateway: history init failed (${err.message}) \u2014 capture disabled
|
|
@@ -102968,12 +103103,12 @@ if (isGatewayMain)
|
|
|
102968
103103
|
let markerTurnKey = null;
|
|
102969
103104
|
let markerAgeMs = null;
|
|
102970
103105
|
try {
|
|
102971
|
-
const markerPath =
|
|
102972
|
-
if (
|
|
103106
|
+
const markerPath = join68(STATE_DIR, TURN_ACTIVE_MARKER_FILE2);
|
|
103107
|
+
if (existsSync58(markerPath)) {
|
|
102973
103108
|
const st = statSync23(markerPath);
|
|
102974
103109
|
markerAgeMs = Date.now() - st.mtimeMs;
|
|
102975
103110
|
try {
|
|
102976
|
-
const payload = JSON.parse(
|
|
103111
|
+
const payload = JSON.parse(readFileSync61(markerPath, "utf8"));
|
|
102977
103112
|
if (typeof payload.turnKey === "string" && payload.turnKey.length > 0) {
|
|
102978
103113
|
markerTurnKey = payload.turnKey;
|
|
102979
103114
|
}
|
|
@@ -102993,10 +103128,10 @@ if (isGatewayMain)
|
|
|
102993
103128
|
process.stderr.write(`telegram gateway: turn-registry boot-reaper stamped ${reaped} orphaned turn(s)` + `${timeoutTurnKey ? ` (turnKey=${timeoutTurnKey} as 'timeout', markerAgeMs=${markerAgeMs})` : " as 'restart'"}
|
|
102994
103129
|
`);
|
|
102995
103130
|
} else {
|
|
102996
|
-
process.stderr.write(`telegram gateway: turn-registry initialized at ${
|
|
103131
|
+
process.stderr.write(`telegram gateway: turn-registry initialized at ${join68(agentDir, "telegram", "registry.db")}
|
|
102997
103132
|
`);
|
|
102998
103133
|
}
|
|
102999
|
-
const bridgeDeadMarker = consumeBridgeDeadEscalationMarker(
|
|
103134
|
+
const bridgeDeadMarker = consumeBridgeDeadEscalationMarker(join68(STATE_DIR, "bridge-dead-escalation.json"));
|
|
103000
103135
|
if (bridgeDeadMarker != null) {
|
|
103001
103136
|
bridgeDeadPriorStreak = bridgeDeadMarker.count ?? 1;
|
|
103002
103137
|
process.stderr.write(`telegram gateway: boot: prior restart was a bridge-dead escalation (reason=${bridgeDeadMarker.reason}` + `, consecutive=${bridgeDeadPriorStreak}` + `${bridgeDeadMarker.crashTail ? `, crashTail=${bridgeDeadMarker.crashTail}` : ""})
|
|
@@ -103009,7 +103144,7 @@ if (isGatewayMain)
|
|
|
103009
103144
|
const pending2 = findLatestTurnIfInterrupted(turnsDb);
|
|
103010
103145
|
const selfAgent = process.env.SWITCHROOM_AGENT_NAME ?? "";
|
|
103011
103146
|
if (pending2 != null && selfAgent) {
|
|
103012
|
-
const bootResumeMarkerPath = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ??
|
|
103147
|
+
const bootResumeMarkerPath = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join68(STATE_DIR, "clean-shutdown.json");
|
|
103013
103148
|
const bootResumeCleanMarker = readCleanShutdownMarker(bootResumeMarkerPath);
|
|
103014
103149
|
const bootResumeForceAlways = process.env.SWITCHROOM_BOOT_RESUME_ALWAYS === "1";
|
|
103015
103150
|
const bootResumeMode = parseBootResumeMode(process.env.SWITCHROOM_BOOT_RESUME);
|
|
@@ -103122,7 +103257,7 @@ if (isGatewayMain)
|
|
|
103122
103257
|
`);
|
|
103123
103258
|
}
|
|
103124
103259
|
}
|
|
103125
|
-
const pendingEnvPath =
|
|
103260
|
+
const pendingEnvPath = join68(agentDir, ".pending-turn.env");
|
|
103126
103261
|
try {
|
|
103127
103262
|
if (pending2 != null) {
|
|
103128
103263
|
const lines = [
|
|
@@ -103142,7 +103277,7 @@ if (isGatewayMain)
|
|
|
103142
103277
|
renameSync27(pendingEnvTmp, pendingEnvPath);
|
|
103143
103278
|
process.stderr.write(`telegram gateway: pending-turn env written to ${pendingEnvPath} turnKey=${pending2.turn_key} endedVia=${pending2.ended_via ?? "open"}
|
|
103144
103279
|
`);
|
|
103145
|
-
} else if (
|
|
103280
|
+
} else if (existsSync58(pendingEnvPath)) {
|
|
103146
103281
|
rmSync8(pendingEnvPath, { force: true });
|
|
103147
103282
|
process.stderr.write(`telegram gateway: pending-turn env cleared (clean previous shutdown)
|
|
103148
103283
|
`);
|
|
@@ -103250,7 +103385,7 @@ function checkApprovals() {
|
|
|
103250
103385
|
return;
|
|
103251
103386
|
}
|
|
103252
103387
|
for (const senderId of files) {
|
|
103253
|
-
const file =
|
|
103388
|
+
const file = join68(APPROVED_DIR, senderId);
|
|
103254
103389
|
bot.api.sendMessage(senderId, "Paired! Say hi to Claude.").then(() => rmSync8(file, { force: true }), (err) => {
|
|
103255
103390
|
process.stderr.write(`telegram gateway: failed to send approval confirm: ${err}
|
|
103256
103391
|
`);
|
|
@@ -103425,12 +103560,12 @@ function noteAgentOutputAt(key, ts) {
|
|
|
103425
103560
|
lastAgentOutputAt.delete(oldest);
|
|
103426
103561
|
}
|
|
103427
103562
|
}
|
|
103428
|
-
var OBLIGATION_STORE_PATH =
|
|
103563
|
+
var OBLIGATION_STORE_PATH = join68(STATE_DIR, "obligations.json");
|
|
103429
103564
|
var obligationStoreFs = {
|
|
103430
|
-
readFileSync: (p) =>
|
|
103565
|
+
readFileSync: (p) => readFileSync61(p, "utf8"),
|
|
103431
103566
|
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
103432
103567
|
renameSync: (a, b) => renameSync27(a, b),
|
|
103433
|
-
existsSync: (p) =>
|
|
103568
|
+
existsSync: (p) => existsSync58(p),
|
|
103434
103569
|
fsyncFileSync: fsyncPathSync,
|
|
103435
103570
|
fsyncDirSync: fsyncPathSync,
|
|
103436
103571
|
unlinkSync: unlinkSync31
|
|
@@ -105773,28 +105908,28 @@ var PIN_STATUS_WHILE_WORKING = (() => {
|
|
|
105773
105908
|
})();
|
|
105774
105909
|
var statusPinClaims = new Map;
|
|
105775
105910
|
var statusPinRightsCache = new PinRightsCache2;
|
|
105776
|
-
var STATUS_PIN_STORE_PATH =
|
|
105911
|
+
var STATUS_PIN_STORE_PATH = join68(STATE_DIR, "status-pins.json");
|
|
105777
105912
|
var statusPinStoreFs = {
|
|
105778
|
-
readFileSync: (p) =>
|
|
105913
|
+
readFileSync: (p) => readFileSync61(p, "utf8"),
|
|
105779
105914
|
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
105780
105915
|
renameSync: (a, b) => renameSync27(a, b),
|
|
105781
|
-
existsSync: (p) =>
|
|
105916
|
+
existsSync: (p) => existsSync58(p)
|
|
105782
105917
|
};
|
|
105783
105918
|
var statusPinPersistEnabled = !STATIC && PIN_STATUS_WHILE_WORKING;
|
|
105784
|
-
var ACTIVITY_CARD_STORE_PATH =
|
|
105919
|
+
var ACTIVITY_CARD_STORE_PATH = join68(STATE_DIR, "activity-cards-pending.json");
|
|
105785
105920
|
var activityCardStoreFs = {
|
|
105786
|
-
readFileSync: (p) =>
|
|
105921
|
+
readFileSync: (p) => readFileSync61(p, "utf8"),
|
|
105787
105922
|
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
105788
105923
|
renameSync: (a, b) => renameSync27(a, b),
|
|
105789
|
-
existsSync: (p) =>
|
|
105924
|
+
existsSync: (p) => existsSync58(p)
|
|
105790
105925
|
};
|
|
105791
105926
|
var activityCardPersistEnabled = !STATIC;
|
|
105792
|
-
var QUEUED_CARD_STORE_PATH =
|
|
105927
|
+
var QUEUED_CARD_STORE_PATH = join68(STATE_DIR, "queued-cards-pending.json");
|
|
105793
105928
|
var queuedCardStoreFs = {
|
|
105794
|
-
readFileSync: (p) =>
|
|
105929
|
+
readFileSync: (p) => readFileSync61(p, "utf8"),
|
|
105795
105930
|
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
105796
105931
|
renameSync: (a, b) => renameSync27(a, b),
|
|
105797
|
-
existsSync: (p) =>
|
|
105932
|
+
existsSync: (p) => existsSync58(p)
|
|
105798
105933
|
};
|
|
105799
105934
|
var queuedCardPersistEnabled = !STATIC;
|
|
105800
105935
|
function persistQueuedCard(key, chatId, threadId, messageId) {
|
|
@@ -106081,7 +106216,7 @@ async function unpinAllStatusPins() {
|
|
|
106081
106216
|
}
|
|
106082
106217
|
}
|
|
106083
106218
|
var stalePinSweepEligible = false;
|
|
106084
|
-
var STALE_PIN_SWEEP_STORE_PATH =
|
|
106219
|
+
var STALE_PIN_SWEEP_STORE_PATH = join68(STATE_DIR, "stale-pin-sweep.json");
|
|
106085
106220
|
var stalePinSweeper = createGatewayStalePinSweeper({
|
|
106086
106221
|
telegram: { handle: () => lockedBot, call: robustApiCall },
|
|
106087
106222
|
claims: () => statusPinClaims.values(),
|
|
@@ -106090,9 +106225,9 @@ var stalePinSweeper = createGatewayStalePinSweeper({
|
|
|
106090
106225
|
store: {
|
|
106091
106226
|
path: STALE_PIN_SWEEP_STORE_PATH,
|
|
106092
106227
|
fs: {
|
|
106093
|
-
readFileSync: (p) =>
|
|
106228
|
+
readFileSync: (p) => readFileSync61(p, "utf-8"),
|
|
106094
106229
|
writeFileSync: (p, data) => atomicWriteFileSync(p, data, 384),
|
|
106095
|
-
existsSync: (p) =>
|
|
106230
|
+
existsSync: (p) => existsSync58(p)
|
|
106096
106231
|
}
|
|
106097
106232
|
},
|
|
106098
106233
|
allowUnpinAllForumTopic: process.env.SWITCHROOM_PIN_SWEEP_UNPIN_ALL_TOPIC == null ? undefined : process.env.SWITCHROOM_PIN_SWEEP_UNPIN_ALL_TOPIC === "1"
|
|
@@ -106122,12 +106257,12 @@ var getPinnedProgressCardMessageId = null;
|
|
|
106122
106257
|
var completeProgressCardTurn = null;
|
|
106123
106258
|
var subagentWatcher = null;
|
|
106124
106259
|
var workerActivityFeed = null;
|
|
106125
|
-
var SOCKET_PATH = process.env.SWITCHROOM_GATEWAY_SOCKET ??
|
|
106260
|
+
var SOCKET_PATH = process.env.SWITCHROOM_GATEWAY_SOCKET ?? join68(STATE_DIR, "gateway.sock");
|
|
106126
106261
|
if (isGatewayMain)
|
|
106127
106262
|
mkdirSync51(STATE_DIR, { recursive: true, mode: 448 });
|
|
106128
|
-
var GATEWAY_PID_PATH = process.env.SWITCHROOM_GATEWAY_PID_FILE ??
|
|
106129
|
-
var GATEWAY_SESSION_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_SESSION_MARKER ??
|
|
106130
|
-
var GATEWAY_CLEAN_SHUTDOWN_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ??
|
|
106263
|
+
var GATEWAY_PID_PATH = process.env.SWITCHROOM_GATEWAY_PID_FILE ?? join68(STATE_DIR, "gateway.pid.json");
|
|
106264
|
+
var GATEWAY_SESSION_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_SESSION_MARKER ?? join68(STATE_DIR, "gateway-session.json");
|
|
106265
|
+
var GATEWAY_CLEAN_SHUTDOWN_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join68(STATE_DIR, "clean-shutdown.json");
|
|
106131
106266
|
var GATEWAY_STARTED_AT_MS = Date.now();
|
|
106132
106267
|
var BOOT_CARD_ENABLED = process.env.SWITCHROOM_BOOT_CARD !== "false";
|
|
106133
106268
|
var activeBootCard = null;
|
|
@@ -106156,7 +106291,7 @@ function ensureIssuesCard(chatId, threadId) {
|
|
|
106156
106291
|
bot: botApi,
|
|
106157
106292
|
log: (msg) => process.stderr.write(`telegram gateway: ${msg}
|
|
106158
106293
|
`),
|
|
106159
|
-
persistPath:
|
|
106294
|
+
persistPath: join68(stateDir, "issues-card.json")
|
|
106160
106295
|
});
|
|
106161
106296
|
activeIssuesWatcher = startIssuesWatcher({
|
|
106162
106297
|
stateDir,
|
|
@@ -106361,13 +106496,13 @@ if (isGatewayMain)
|
|
|
106361
106496
|
var inboundSpool;
|
|
106362
106497
|
if (isGatewayMain)
|
|
106363
106498
|
inboundSpool = STATIC ? undefined : createInboundSpool({
|
|
106364
|
-
path:
|
|
106499
|
+
path: join68(STATE_DIR, "inbound-spool.jsonl"),
|
|
106365
106500
|
fs: {
|
|
106366
106501
|
appendFileSync: (p, d) => appendFileSync9(p, d),
|
|
106367
|
-
readFileSync: (p) =>
|
|
106502
|
+
readFileSync: (p) => readFileSync61(p, "utf8"),
|
|
106368
106503
|
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
106369
106504
|
renameSync: (a, b) => renameSync27(a, b),
|
|
106370
|
-
existsSync: (p) =>
|
|
106505
|
+
existsSync: (p) => existsSync58(p),
|
|
106371
106506
|
statSizeSync: (p) => statSync23(p).size,
|
|
106372
106507
|
fsyncFileSync: fsyncPathSync,
|
|
106373
106508
|
fsyncDirSync: fsyncPathSync
|
|
@@ -106431,13 +106566,13 @@ async function maybeRedeliverUndeliveredAnswer() {
|
|
|
106431
106566
|
let transcriptText;
|
|
106432
106567
|
try {
|
|
106433
106568
|
const projectsDir = getProjectsDirForCwd();
|
|
106434
|
-
const path3 =
|
|
106435
|
-
if (!
|
|
106569
|
+
const path3 = join68(projectsDir, `${sessionId}.jsonl`);
|
|
106570
|
+
if (!existsSync58(path3)) {
|
|
106436
106571
|
process.stderr.write(`telegram gateway: crash-redelivery \u2014 transcript not found for turnKey=${turn.turn_key} session=${sessionId} (${path3}); skipping
|
|
106437
106572
|
`);
|
|
106438
106573
|
return;
|
|
106439
106574
|
}
|
|
106440
|
-
transcriptText =
|
|
106575
|
+
transcriptText = readFileSync61(path3, "utf8");
|
|
106441
106576
|
} catch (err) {
|
|
106442
106577
|
process.stderr.write(`telegram gateway: crash-redelivery \u2014 transcript read failed turnKey=${turn.turn_key}: ${err.message}
|
|
106443
106578
|
`);
|
|
@@ -106596,8 +106731,8 @@ var bridgeDeadWatchdog = createBridgeDeadWatchdog({
|
|
|
106596
106731
|
isSessionAlive: () => findAgentProcessInContainer2()?.comm === "claude",
|
|
106597
106732
|
isShuttingDown: () => shuttingDown,
|
|
106598
106733
|
escalate: (reason) => triggerSelfRestart(process.env.SWITCHROOM_AGENT_NAME ?? "", reason, 1500),
|
|
106599
|
-
crashLogPath:
|
|
106600
|
-
markerPath:
|
|
106734
|
+
crashLogPath: join68(STATE_DIR, "bridge-crash.log"),
|
|
106735
|
+
markerPath: join68(STATE_DIR, "bridge-dead-escalation.json"),
|
|
106601
106736
|
log: (line) => process.stderr.write(`${line}
|
|
106602
106737
|
`),
|
|
106603
106738
|
priorStreak: bridgeDeadPriorStreak,
|
|
@@ -106703,8 +106838,8 @@ if (isGatewayMain)
|
|
|
106703
106838
|
probeQuotaViaBroker: (t) => probeQuotaForBootCard(agentSlug, t),
|
|
106704
106839
|
tmuxSupervisor: process.env.SWITCHROOM_TMUX_SUPERVISOR === "1",
|
|
106705
106840
|
dockerMode: process.env.SWITCHROOM_RUNTIME === "docker",
|
|
106706
|
-
configSnapshotPath:
|
|
106707
|
-
bootCardStatePath:
|
|
106841
|
+
configSnapshotPath: join68(resolvedAgentDirForCard, ".config-snapshot.json"),
|
|
106842
|
+
bootCardStatePath: join68(resolvedAgentDirForCard, ".boot-card-msgid.json"),
|
|
106708
106843
|
floodStatePath: FLOOD_STATE_PATH,
|
|
106709
106844
|
...updateOutcomeLine ? { updateOutcomeLine } : {}
|
|
106710
106845
|
}, ackMsgId).then((handle) => {
|
|
@@ -107371,7 +107506,7 @@ if (isGatewayMain)
|
|
|
107371
107506
|
const receiverUid = receiverUidRaw ? Number(receiverUidRaw) : NaN;
|
|
107372
107507
|
if (Number.isInteger(receiverUid))
|
|
107373
107508
|
allowedUids.push(receiverUid);
|
|
107374
|
-
const socketPath =
|
|
107509
|
+
const socketPath = join68(STATE_DIR, "webhook.sock");
|
|
107375
107510
|
const webhookInject = (agentName3, inbound) => {
|
|
107376
107511
|
const msg = inbound;
|
|
107377
107512
|
const delivered = ipcServer.sendToAgent(agentName3, msg);
|
|
@@ -107622,9 +107757,9 @@ function redactOutboundText(text5, site) {
|
|
|
107622
107757
|
var VOICE_OUT_DEFAULT_CHUNK_CHARS = 600;
|
|
107623
107758
|
var VOICE_OUT_HARD_CHUNK_CAP = 4096;
|
|
107624
107759
|
var voiceOnDemandCache = new VoiceOnDemandCache({
|
|
107625
|
-
persistPath:
|
|
107760
|
+
persistPath: join68(STATE_DIR, "voice-ondemand.json")
|
|
107626
107761
|
});
|
|
107627
|
-
var VOICE_CACHE_DIR =
|
|
107762
|
+
var VOICE_CACHE_DIR = join68(STATE_DIR, "voice-cache");
|
|
107628
107763
|
var voicePreSynthQueue = new PreSynthQueue({
|
|
107629
107764
|
runJob: async (job) => {
|
|
107630
107765
|
const sidecarToken = await materializeSidecarToken2();
|
|
@@ -108026,11 +108161,11 @@ async function executeSendGif(rawArgs) {
|
|
|
108026
108161
|
};
|
|
108027
108162
|
}
|
|
108028
108163
|
async function publishToTelegraph(text5, shortName, authorName) {
|
|
108029
|
-
const accountPath =
|
|
108164
|
+
const accountPath = join68(STATE_DIR, "telegraph-account.json");
|
|
108030
108165
|
let account = null;
|
|
108031
108166
|
try {
|
|
108032
|
-
if (
|
|
108033
|
-
const raw =
|
|
108167
|
+
if (existsSync58(accountPath)) {
|
|
108168
|
+
const raw = readFileSync61(accountPath, "utf-8");
|
|
108034
108169
|
const parsed = JSON.parse(raw);
|
|
108035
108170
|
if (parsed.shortName && parsed.accessToken) {
|
|
108036
108171
|
account = parsed;
|
|
@@ -108166,7 +108301,7 @@ _The secret was NOT saved. The agent can re-request with \`request_secret\`._`,
|
|
|
108166
108301
|
}
|
|
108167
108302
|
function readLiveSwitchroomConfigText() {
|
|
108168
108303
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
108169
|
-
return
|
|
108304
|
+
return readFileSync61(cfgPath, "utf8");
|
|
108170
108305
|
}
|
|
108171
108306
|
async function executeReact(args) {
|
|
108172
108307
|
if (!args.chat_id)
|
|
@@ -109579,7 +109714,7 @@ function restartMarkerPath() {
|
|
|
109579
109714
|
const agentDir = resolveAgentDirFromEnv();
|
|
109580
109715
|
if (!agentDir)
|
|
109581
109716
|
return null;
|
|
109582
|
-
return
|
|
109717
|
+
return join68(agentDir, "restart-pending.json");
|
|
109583
109718
|
}
|
|
109584
109719
|
function writeRestartMarker(marker) {
|
|
109585
109720
|
const p = restartMarkerPath();
|
|
@@ -109605,7 +109740,7 @@ function readRestartMarker() {
|
|
|
109605
109740
|
if (!p)
|
|
109606
109741
|
return null;
|
|
109607
109742
|
try {
|
|
109608
|
-
return JSON.parse(
|
|
109743
|
+
return JSON.parse(readFileSync61(p, "utf8"));
|
|
109609
109744
|
} catch {
|
|
109610
109745
|
return null;
|
|
109611
109746
|
}
|
|
@@ -109754,7 +109889,7 @@ var _dockerReachable;
|
|
|
109754
109889
|
function isDockerReachable() {
|
|
109755
109890
|
if (_dockerReachable !== undefined)
|
|
109756
109891
|
return _dockerReachable;
|
|
109757
|
-
if (!
|
|
109892
|
+
if (!existsSync58("/var/run/docker.sock")) {
|
|
109758
109893
|
_dockerReachable = false;
|
|
109759
109894
|
return _dockerReachable;
|
|
109760
109895
|
}
|
|
@@ -109771,7 +109906,7 @@ function _resetDockerReachableCache() {
|
|
|
109771
109906
|
}
|
|
109772
109907
|
function spawnSwitchroomDetached(args, onFailure) {
|
|
109773
109908
|
const fullArgs = SWITCHROOM_CONFIG ? ["--config", SWITCHROOM_CONFIG, ...args] : args;
|
|
109774
|
-
const logPath =
|
|
109909
|
+
const logPath = join68(STATE_DIR, "detached-spawn.log");
|
|
109775
109910
|
let outFd = null;
|
|
109776
109911
|
try {
|
|
109777
109912
|
mkdirSync51(STATE_DIR, { recursive: true });
|
|
@@ -109802,7 +109937,7 @@ function spawnSwitchroomDetached(args, onFailure) {
|
|
|
109802
109937
|
return;
|
|
109803
109938
|
let tail = "";
|
|
109804
109939
|
try {
|
|
109805
|
-
const full =
|
|
109940
|
+
const full = readFileSync61(logPath, "utf8");
|
|
109806
109941
|
tail = full.split(`
|
|
109807
109942
|
`).slice(-30).join(`
|
|
109808
109943
|
`).trim();
|
|
@@ -110064,10 +110199,10 @@ ${preBlock(formatSwitchroomOutput(detail))}`, { html: true });
|
|
|
110064
110199
|
}
|
|
110065
110200
|
function readRecentDenialsForAgent(agentName3, windowMs, limit) {
|
|
110066
110201
|
try {
|
|
110067
|
-
const auditPath =
|
|
110068
|
-
if (!
|
|
110202
|
+
const auditPath = join68(homedir20(), ".switchroom", "vault-audit.log");
|
|
110203
|
+
if (!existsSync58(auditPath))
|
|
110069
110204
|
return [];
|
|
110070
|
-
const raw =
|
|
110205
|
+
const raw = readFileSync61(auditPath, "utf8");
|
|
110071
110206
|
return recentDenialsFromAuditLog(raw, { agentName: agentName3, windowMs, limit });
|
|
110072
110207
|
} catch {
|
|
110073
110208
|
return [];
|
|
@@ -110118,7 +110253,7 @@ async function buildAgentMetadata(agentName3) {
|
|
|
110118
110253
|
try {
|
|
110119
110254
|
const agentDir = resolveAgentDirFromEnv();
|
|
110120
110255
|
if (agentDir) {
|
|
110121
|
-
const raw =
|
|
110256
|
+
const raw = readFileSync61(join68(agentDir, ".claude", ".claude.json"), "utf8");
|
|
110122
110257
|
claudeJson = JSON.parse(raw);
|
|
110123
110258
|
}
|
|
110124
110259
|
} catch {}
|
|
@@ -110247,7 +110382,7 @@ function buildModelDeps(restartCtx) {
|
|
|
110247
110382
|
try {
|
|
110248
110383
|
const agentDir = resolveAgentDirFromEnv();
|
|
110249
110384
|
if (agentDir) {
|
|
110250
|
-
const local = await fetchQuota2({ claudeConfigDir:
|
|
110385
|
+
const local = await fetchQuota2({ claudeConfigDir: join68(agentDir, ".claude") });
|
|
110251
110386
|
if (local.ok)
|
|
110252
110387
|
return formatQuotaLine2(local.data);
|
|
110253
110388
|
}
|
|
@@ -110494,9 +110629,9 @@ function effortMenuReplyMarkup(reply) {
|
|
|
110494
110629
|
function flushAgentHandoff(agentDir) {
|
|
110495
110630
|
let removed = 0;
|
|
110496
110631
|
for (const fname of [".handoff.md", ".handoff-topic"]) {
|
|
110497
|
-
const p =
|
|
110632
|
+
const p = join68(agentDir, fname);
|
|
110498
110633
|
try {
|
|
110499
|
-
if (
|
|
110634
|
+
if (existsSync58(p)) {
|
|
110500
110635
|
unlinkSync31(p);
|
|
110501
110636
|
removed++;
|
|
110502
110637
|
}
|
|
@@ -110552,7 +110687,7 @@ async function handleNewCommand(ctx) {
|
|
|
110552
110687
|
writeRestartMarker({ chat_id: chatId, thread_id: threadId ?? null, ack_message_id: ackId, ts: Date.now() });
|
|
110553
110688
|
if (agentDir != null) {
|
|
110554
110689
|
try {
|
|
110555
|
-
writeFileSync50(
|
|
110690
|
+
writeFileSync50(join68(agentDir, ".force-fresh-session"), `${kind} at ${new Date().toISOString()}
|
|
110556
110691
|
`, "utf8");
|
|
110557
110692
|
} catch (err) {
|
|
110558
110693
|
process.stderr.write(`telegram gateway: failed to write force-fresh marker: ${err}
|
|
@@ -110665,16 +110800,16 @@ function buildFolderPickerDeps() {
|
|
|
110665
110800
|
};
|
|
110666
110801
|
}
|
|
110667
110802
|
var lockoutOps = {
|
|
110668
|
-
readFileSync: (p, enc) =>
|
|
110803
|
+
readFileSync: (p, enc) => readFileSync61(p, enc),
|
|
110669
110804
|
writeFileSync: (p, data, opts) => writeFileSync50(p, data, opts),
|
|
110670
|
-
existsSync: (p) =>
|
|
110805
|
+
existsSync: (p) => existsSync58(p),
|
|
110671
110806
|
mkdirSync: (p, opts) => mkdirSync51(p, opts),
|
|
110672
|
-
joinPath: (...parts) =>
|
|
110807
|
+
joinPath: (...parts) => join68(...parts)
|
|
110673
110808
|
};
|
|
110674
110809
|
var FLEET_FALLBACK_DEDUP_MS = 30000;
|
|
110675
110810
|
function isAuthBrokerSocketReachable() {
|
|
110676
110811
|
try {
|
|
110677
|
-
return
|
|
110812
|
+
return existsSync58(resolveAuthBrokerSocketPath2());
|
|
110678
110813
|
} catch {
|
|
110679
110814
|
return false;
|
|
110680
110815
|
}
|
|
@@ -110929,7 +111064,7 @@ async function runCreditWatch() {
|
|
|
110929
111064
|
if (!agentDir)
|
|
110930
111065
|
return;
|
|
110931
111066
|
const agentName3 = getMyAgentName();
|
|
110932
|
-
const claudeConfigDir =
|
|
111067
|
+
const claudeConfigDir = join68(agentDir, ".claude");
|
|
110933
111068
|
const stateDir = STATE_DIR;
|
|
110934
111069
|
const reason = readClaudeJsonOverage(claudeConfigDir);
|
|
110935
111070
|
const prev = loadCreditState(stateDir);
|
|
@@ -112685,7 +112820,7 @@ Send \`/auth ${parsed.provider} cancel\` to abort.`, { html: true });
|
|
|
112685
112820
|
await switchroomReply(ctx, "**/usage:** cannot resolve agent dir.", { html: true });
|
|
112686
112821
|
return;
|
|
112687
112822
|
}
|
|
112688
|
-
const result = await fetchQuota2({ claudeConfigDir:
|
|
112823
|
+
const result = await fetchQuota2({ claudeConfigDir: join68(agentDir, ".claude") });
|
|
112689
112824
|
if (!result.ok) {
|
|
112690
112825
|
await switchroomReply(ctx, `**/usage:** ${escapeHtmlForTg2(result.reason)}`, { html: true });
|
|
112691
112826
|
return;
|
|
@@ -113072,7 +113207,7 @@ ${interimLabel}` : interimLabel
|
|
|
113072
113207
|
const unifiedDiff = (() => {
|
|
113073
113208
|
try {
|
|
113074
113209
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
113075
|
-
const raw =
|
|
113210
|
+
const raw = readFileSync61(cfgPath, "utf8");
|
|
113076
113211
|
return synthesizeAllowRuleDiff({ agentName: agentName3, rule: chosen.rule, configText: raw });
|
|
113077
113212
|
} catch (err) {
|
|
113078
113213
|
process.stderr.write(`telegram gateway: always-allow diff synth failed: ${err.message}
|
|
@@ -113941,7 +114076,7 @@ async function startGateway() {
|
|
|
113941
114076
|
return;
|
|
113942
114077
|
}
|
|
113943
114078
|
})();
|
|
113944
|
-
const resolvedAgentDirForBootCard = agentDir ??
|
|
114079
|
+
const resolvedAgentDirForBootCard = agentDir ?? join68(homedir20(), ".switchroom", "agents", agentSlug);
|
|
113945
114080
|
const handle = await startBootCard(chatId, threadId, botApiForCard, {
|
|
113946
114081
|
agentName: agentDisplayName,
|
|
113947
114082
|
agentSlug,
|
|
@@ -113955,8 +114090,8 @@ async function startGateway() {
|
|
|
113955
114090
|
probeQuotaViaBroker: (t) => probeQuotaForBootCard(agentSlug, t),
|
|
113956
114091
|
tmuxSupervisor: process.env.SWITCHROOM_TMUX_SUPERVISOR === "1",
|
|
113957
114092
|
dockerMode: process.env.SWITCHROOM_RUNTIME === "docker",
|
|
113958
|
-
configSnapshotPath:
|
|
113959
|
-
bootCardStatePath:
|
|
114093
|
+
configSnapshotPath: join68(resolvedAgentDirForBootCard, ".config-snapshot.json"),
|
|
114094
|
+
bootCardStatePath: join68(resolvedAgentDirForBootCard, ".boot-card-msgid.json"),
|
|
113960
114095
|
floodStatePath: FLOOD_STATE_PATH,
|
|
113961
114096
|
...updateOutcomeLine ? { updateOutcomeLine } : {}
|
|
113962
114097
|
}, ackMsgId);
|
|
@@ -113989,7 +114124,7 @@ async function startGateway() {
|
|
|
113989
114124
|
if (smAgentDir) {
|
|
113990
114125
|
const resolutionTimeoutMs = resolveSessionModelResolutionTimeoutMs(process.env.SWITCHROOM_SESSION_MODEL_RESOLUTION_TIMEOUT_MS);
|
|
113991
114126
|
const resolved = await waitForSessionModelResolution({
|
|
113992
|
-
barrierExists: () =>
|
|
114127
|
+
barrierExists: () => existsSync58(join68(smAgentDir, ".session-model-resolved")),
|
|
113993
114128
|
timeoutMs: resolutionTimeoutMs
|
|
113994
114129
|
});
|
|
113995
114130
|
if (!resolved) {
|
|
@@ -113997,10 +114132,10 @@ async function startGateway() {
|
|
|
113997
114132
|
process.stderr.write(`telegram gateway: gw /model relaunch UNRESOLVED agent=${getMyAgentName()} target=${target} (barrier timeout after ${resolutionTimeoutMs}ms)
|
|
113998
114133
|
`);
|
|
113999
114134
|
} else {
|
|
114000
|
-
const activePath =
|
|
114001
|
-
if (
|
|
114135
|
+
const activePath = join68(smAgentDir, ".active-session-model");
|
|
114136
|
+
if (existsSync58(activePath)) {
|
|
114002
114137
|
try {
|
|
114003
|
-
const launched =
|
|
114138
|
+
const launched = readFileSync61(activePath, "utf8").trim();
|
|
114004
114139
|
const configured = (() => {
|
|
114005
114140
|
const d = switchroomExecJson(["agent", "list"]);
|
|
114006
114141
|
const raw = d?.agents?.find((a) => a.name === getMyAgentName())?.model ?? null;
|
|
@@ -114033,24 +114168,24 @@ async function startGateway() {
|
|
|
114033
114168
|
deliverModelSwitchBootNotice({
|
|
114034
114169
|
...modelBootCardDeps,
|
|
114035
114170
|
confirmation,
|
|
114036
|
-
hasSessionModelAlert:
|
|
114171
|
+
hasSessionModelAlert: existsSync58(join68(smAgentDir, ".session-model-alert"))
|
|
114037
114172
|
});
|
|
114038
114173
|
}
|
|
114039
114174
|
} catch {}
|
|
114040
114175
|
}
|
|
114041
|
-
const activeEffortPath =
|
|
114042
|
-
if (
|
|
114176
|
+
const activeEffortPath = join68(smAgentDir, ".active-session-effort");
|
|
114177
|
+
if (existsSync58(activeEffortPath)) {
|
|
114043
114178
|
try {
|
|
114044
|
-
const launchedEffort =
|
|
114179
|
+
const launchedEffort = readFileSync61(activeEffortPath, "utf8").trim();
|
|
114045
114180
|
const configuredEffort = getConfiguredEffortForPersist();
|
|
114046
114181
|
sessionEffortOverride = launchedEffort.length > 0 && launchedEffort !== configuredEffort ? launchedEffort : null;
|
|
114047
114182
|
} catch {}
|
|
114048
114183
|
}
|
|
114049
|
-
const alertPath =
|
|
114050
|
-
if (
|
|
114184
|
+
const alertPath = join68(smAgentDir, ".session-model-alert");
|
|
114185
|
+
if (existsSync58(alertPath)) {
|
|
114051
114186
|
let alertText = null;
|
|
114052
114187
|
try {
|
|
114053
|
-
alertText =
|
|
114188
|
+
alertText = readFileSync61(alertPath, "utf8").trim();
|
|
114054
114189
|
} catch {
|
|
114055
114190
|
alertText = null;
|
|
114056
114191
|
}
|