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.
|
- 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.
|
- 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: 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
|
## 2026.1.10
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,14 @@ describe("resolveSandboxContext", () => {
|
|||||||
}),
|
}),
|
||||||
).toBeNull();
|
).toBeNull();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await resolveSandboxContext({
|
||||||
|
config: cfg,
|
||||||
|
sessionKey: "agent:main:main",
|
||||||
|
workspaceDir: "/tmp/clawdbot-test",
|
||||||
|
}),
|
||||||
|
).toBeNull();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await ensureSandboxWorkspaceForSession({
|
await ensureSandboxWorkspaceForSession({
|
||||||
config: cfg,
|
config: cfg,
|
||||||
@@ -113,6 +121,14 @@ describe("resolveSandboxContext", () => {
|
|||||||
}),
|
}),
|
||||||
).toBeNull();
|
).toBeNull();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await ensureSandboxWorkspaceForSession({
|
||||||
|
config: cfg,
|
||||||
|
sessionKey: "agent:main:main",
|
||||||
|
workspaceDir: "/tmp/clawdbot-test",
|
||||||
|
}),
|
||||||
|
).toBeNull();
|
||||||
|
|
||||||
expect(spawn).not.toHaveBeenCalled();
|
expect(spawn).not.toHaveBeenCalled();
|
||||||
|
|
||||||
vi.doUnmock("node:child_process");
|
vi.doUnmock("node:child_process");
|
||||||
|
|||||||
@@ -19,9 +19,12 @@ import {
|
|||||||
loadConfig,
|
loadConfig,
|
||||||
STATE_DIR_CLAWDBOT,
|
STATE_DIR_CLAWDBOT,
|
||||||
} from "../config/config.js";
|
} 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 { 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 { defaultRuntime } from "../runtime.js";
|
||||||
import { resolveUserPath } from "../utils.js";
|
import { resolveUserPath } from "../utils.js";
|
||||||
import {
|
import {
|
||||||
@@ -566,22 +569,11 @@ function resolveComparableSessionKeyForSandbox(params: {
|
|||||||
agentId: string;
|
agentId: string;
|
||||||
sessionKey: string;
|
sessionKey: string;
|
||||||
}): string {
|
}): string {
|
||||||
const trimmed = params.sessionKey.trim();
|
return canonicalizeMainSessionAlias({
|
||||||
if (!trimmed) return trimmed;
|
|
||||||
|
|
||||||
const mainKey = normalizeMainKey(params.cfg?.session?.mainKey);
|
|
||||||
const agentMainSessionKey = resolveAgentMainSessionKey({
|
|
||||||
cfg: params.cfg,
|
cfg: params.cfg,
|
||||||
agentId: params.agentId,
|
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: {
|
export function resolveSandboxRuntimeStatus(params: {
|
||||||
|
|||||||
@@ -250,6 +250,33 @@ export function resolveAgentMainSessionKey(params: {
|
|||||||
return buildAgentMainSessionKey({ agentId: params.agentId, mainKey });
|
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) {
|
function normalizeGroupLabel(raw?: string) {
|
||||||
const trimmed = raw?.trim().toLowerCase() ?? "";
|
const trimmed = raw?.trim().toLowerCase() ?? "";
|
||||||
if (!trimmed) return "";
|
if (!trimmed) return "";
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ describe("gateway session utils", () => {
|
|||||||
expect(resolveSessionStoreKey({ cfg, sessionKey: "work" })).toBe(
|
expect(resolveSessionStoreKey({ cfg, sessionKey: "work" })).toBe(
|
||||||
"agent:ops:work",
|
"agent:ops:work",
|
||||||
);
|
);
|
||||||
|
expect(resolveSessionStoreKey({ cfg, sessionKey: "agent:ops:main" })).toBe(
|
||||||
|
"agent:ops:work",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("resolveSessionStoreKey canonicalizes bare keys to default agent", () => {
|
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 { resolveStateDir } from "../config/paths.js";
|
||||||
import {
|
import {
|
||||||
buildGroupDisplayName,
|
buildGroupDisplayName,
|
||||||
|
canonicalizeMainSessionAlias,
|
||||||
loadSessionStore,
|
loadSessionStore,
|
||||||
resolveMainSessionKey,
|
resolveMainSessionKey,
|
||||||
resolveSessionTranscriptPath,
|
resolveSessionTranscriptPath,
|
||||||
@@ -299,11 +300,23 @@ export function resolveSessionStoreKey(params: {
|
|||||||
const raw = params.sessionKey.trim();
|
const raw = params.sessionKey.trim();
|
||||||
if (!raw) return raw;
|
if (!raw) return raw;
|
||||||
if (raw === "global" || raw === "unknown") 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);
|
const rawMainKey = normalizeMainKey(params.cfg.session?.mainKey);
|
||||||
if (raw === "main" || raw === rawMainKey) {
|
if (raw === "main" || raw === rawMainKey) {
|
||||||
return resolveMainSessionKey(params.cfg);
|
return resolveMainSessionKey(params.cfg);
|
||||||
}
|
}
|
||||||
if (raw.startsWith("agent:")) return raw;
|
|
||||||
const agentId = resolveDefaultStoreAgentId(params.cfg);
|
const agentId = resolveDefaultStoreAgentId(params.cfg);
|
||||||
return canonicalizeSessionKeyForAgent(agentId, raw);
|
return canonicalizeSessionKeyForAgent(agentId, raw);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user