fix(sandbox): canonicalize agent main alias
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
- Gateway/Agents: canonicalize main session aliases for store writes and add regression coverage. (#709) — thanks @xMikeMickelson.
|
||||
- Agents: reset sessions and retry when auto-compaction overflows instead of crashing the gateway.
|
||||
- Sandbox: fix non-main mode incorrectly sandboxing the main DM session and align `/status` runtime reporting with effective sandbox state.
|
||||
- Sandbox/Gateway: treat `agent:<id>:main` as a main-session alias when `session.mainKey` is customized (backwards compatible).
|
||||
|
||||
## 2026.1.10
|
||||
|
||||
|
||||
@@ -105,6 +105,14 @@ describe("resolveSandboxContext", () => {
|
||||
}),
|
||||
).toBeNull();
|
||||
|
||||
expect(
|
||||
await resolveSandboxContext({
|
||||
config: cfg,
|
||||
sessionKey: "agent:main:main",
|
||||
workspaceDir: "/tmp/clawdbot-test",
|
||||
}),
|
||||
).toBeNull();
|
||||
|
||||
expect(
|
||||
await ensureSandboxWorkspaceForSession({
|
||||
config: cfg,
|
||||
@@ -113,6 +121,14 @@ describe("resolveSandboxContext", () => {
|
||||
}),
|
||||
).toBeNull();
|
||||
|
||||
expect(
|
||||
await ensureSandboxWorkspaceForSession({
|
||||
config: cfg,
|
||||
sessionKey: "agent:main:main",
|
||||
workspaceDir: "/tmp/clawdbot-test",
|
||||
}),
|
||||
).toBeNull();
|
||||
|
||||
expect(spawn).not.toHaveBeenCalled();
|
||||
|
||||
vi.doUnmock("node:child_process");
|
||||
|
||||
@@ -19,9 +19,12 @@ import {
|
||||
loadConfig,
|
||||
STATE_DIR_CLAWDBOT,
|
||||
} from "../config/config.js";
|
||||
import { resolveAgentMainSessionKey } from "../config/sessions.js";
|
||||
import {
|
||||
canonicalizeMainSessionAlias,
|
||||
resolveAgentMainSessionKey,
|
||||
} from "../config/sessions.js";
|
||||
import { PROVIDER_IDS } from "../providers/registry.js";
|
||||
import { normalizeAgentId, normalizeMainKey } from "../routing/session-key.js";
|
||||
import { normalizeAgentId } from "../routing/session-key.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import {
|
||||
@@ -566,22 +569,11 @@ function resolveComparableSessionKeyForSandbox(params: {
|
||||
agentId: string;
|
||||
sessionKey: string;
|
||||
}): string {
|
||||
const trimmed = params.sessionKey.trim();
|
||||
if (!trimmed) return trimmed;
|
||||
|
||||
const mainKey = normalizeMainKey(params.cfg?.session?.mainKey);
|
||||
const agentMainSessionKey = resolveAgentMainSessionKey({
|
||||
return canonicalizeMainSessionAlias({
|
||||
cfg: params.cfg,
|
||||
agentId: params.agentId,
|
||||
sessionKey: params.sessionKey,
|
||||
});
|
||||
const isMainAlias =
|
||||
trimmed === "main" ||
|
||||
trimmed === mainKey ||
|
||||
trimmed === agentMainSessionKey;
|
||||
|
||||
if (params.cfg?.session?.scope === "global" && isMainAlias) return "global";
|
||||
if (isMainAlias) return agentMainSessionKey;
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
export function resolveSandboxRuntimeStatus(params: {
|
||||
|
||||
@@ -250,6 +250,33 @@ export function resolveAgentMainSessionKey(params: {
|
||||
return buildAgentMainSessionKey({ agentId: params.agentId, mainKey });
|
||||
}
|
||||
|
||||
export function canonicalizeMainSessionAlias(params: {
|
||||
cfg?: { session?: { scope?: SessionScope; mainKey?: string } };
|
||||
agentId: string;
|
||||
sessionKey: string;
|
||||
}): string {
|
||||
const raw = params.sessionKey.trim();
|
||||
if (!raw) return raw;
|
||||
|
||||
const agentId = normalizeAgentId(params.agentId);
|
||||
const mainKey = normalizeMainKey(params.cfg?.session?.mainKey);
|
||||
const agentMainSessionKey = buildAgentMainSessionKey({ agentId, mainKey });
|
||||
const agentMainAliasKey = buildAgentMainSessionKey({
|
||||
agentId,
|
||||
mainKey: "main",
|
||||
});
|
||||
|
||||
const isMainAlias =
|
||||
raw === "main" ||
|
||||
raw === mainKey ||
|
||||
raw === agentMainSessionKey ||
|
||||
raw === agentMainAliasKey;
|
||||
|
||||
if (params.cfg?.session?.scope === "global" && isMainAlias) return "global";
|
||||
if (isMainAlias) return agentMainSessionKey;
|
||||
return raw;
|
||||
}
|
||||
|
||||
function normalizeGroupLabel(raw?: string) {
|
||||
const trimmed = raw?.trim().toLowerCase() ?? "";
|
||||
if (!trimmed) return "";
|
||||
|
||||
@@ -48,6 +48,9 @@ describe("gateway session utils", () => {
|
||||
expect(resolveSessionStoreKey({ cfg, sessionKey: "work" })).toBe(
|
||||
"agent:ops:work",
|
||||
);
|
||||
expect(resolveSessionStoreKey({ cfg, sessionKey: "agent:ops:main" })).toBe(
|
||||
"agent:ops:work",
|
||||
);
|
||||
});
|
||||
|
||||
test("resolveSessionStoreKey canonicalizes bare keys to default agent", () => {
|
||||
|
||||
@@ -13,6 +13,7 @@ import { type ClawdbotConfig, loadConfig } from "../config/config.js";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
import {
|
||||
buildGroupDisplayName,
|
||||
canonicalizeMainSessionAlias,
|
||||
loadSessionStore,
|
||||
resolveMainSessionKey,
|
||||
resolveSessionTranscriptPath,
|
||||
@@ -299,11 +300,23 @@ export function resolveSessionStoreKey(params: {
|
||||
const raw = params.sessionKey.trim();
|
||||
if (!raw) return raw;
|
||||
if (raw === "global" || raw === "unknown") return raw;
|
||||
|
||||
const parsed = parseAgentSessionKey(raw);
|
||||
if (parsed) {
|
||||
const agentId = normalizeAgentId(parsed.agentId);
|
||||
const canonical = canonicalizeMainSessionAlias({
|
||||
cfg: params.cfg,
|
||||
agentId,
|
||||
sessionKey: raw,
|
||||
});
|
||||
if (canonical !== raw) return canonical;
|
||||
return raw;
|
||||
}
|
||||
|
||||
const rawMainKey = normalizeMainKey(params.cfg.session?.mainKey);
|
||||
if (raw === "main" || raw === rawMainKey) {
|
||||
return resolveMainSessionKey(params.cfg);
|
||||
}
|
||||
if (raw.startsWith("agent:")) return raw;
|
||||
const agentId = resolveDefaultStoreAgentId(params.cfg);
|
||||
return canonicalizeSessionKeyForAgent(agentId, raw);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user