Merge 3641e4633944ca5917fe8a3c241b153e1fc15d7e into 8a05c05596ca9ba0735dafd8e359885de4c2c969
This commit is contained in:
commit
53ed5aae26
@ -203,6 +203,59 @@ describe("session_status tool", () => {
|
||||
expect(updateSessionStoreMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("resolves sessionKey=current to the requester session", async () => {
|
||||
resetSessionStore({
|
||||
main: {
|
||||
sessionId: "s1",
|
||||
updatedAt: 10,
|
||||
},
|
||||
});
|
||||
|
||||
const tool = getSessionStatusTool();
|
||||
|
||||
const result = await tool.execute("call-current", { sessionKey: "current" });
|
||||
const details = result.details as { ok?: boolean; sessionKey?: string };
|
||||
expect(details.ok).toBe(true);
|
||||
expect(details.sessionKey).toBe("main");
|
||||
});
|
||||
|
||||
it("resolves sessionKey=current to the requester agent session", async () => {
|
||||
loadSessionStoreMock.mockClear();
|
||||
updateSessionStoreMock.mockClear();
|
||||
callGatewayMock.mockClear();
|
||||
loadCombinedSessionStoreForGatewayMock.mockClear();
|
||||
const stores = new Map<string, Record<string, unknown>>([
|
||||
[
|
||||
"/tmp/main/sessions.json",
|
||||
{
|
||||
"agent:main:main": { sessionId: "s-main", updatedAt: 10 },
|
||||
},
|
||||
],
|
||||
[
|
||||
"/tmp/support/sessions.json",
|
||||
{
|
||||
main: { sessionId: "s-support", updatedAt: 20 },
|
||||
},
|
||||
],
|
||||
]);
|
||||
loadSessionStoreMock.mockImplementation((storePath: string) => {
|
||||
return stores.get(storePath) ?? {};
|
||||
});
|
||||
loadCombinedSessionStoreForGatewayMock.mockReturnValue({
|
||||
storePath: "(multiple)",
|
||||
store: Object.fromEntries([...stores.values()].flatMap((s) => Object.entries(s))),
|
||||
});
|
||||
|
||||
const tool = getSessionStatusTool("agent:support:main");
|
||||
|
||||
// "current" resolves to the support agent's own session via the "main" alias.
|
||||
const result = await tool.execute("call-current-child", { sessionKey: "current" });
|
||||
const details = result.details as { ok?: boolean; sessionKey?: string };
|
||||
expect(details.ok).toBe(true);
|
||||
// The resolved key is "main" within the support agent's store scope.
|
||||
expect(details.sessionKey).toBe("main");
|
||||
});
|
||||
|
||||
it("resolves sessionId inputs", async () => {
|
||||
const sessionId = "sess-main";
|
||||
resetSessionStore({
|
||||
|
||||
@ -56,6 +56,7 @@ function resolveSessionEntry(params: {
|
||||
keyRaw: string;
|
||||
alias: string;
|
||||
mainKey: string;
|
||||
requesterInternalKey?: string;
|
||||
}): { key: string; entry: SessionEntry } | null {
|
||||
const keyRaw = params.keyRaw.trim();
|
||||
if (!keyRaw) {
|
||||
@ -65,6 +66,7 @@ function resolveSessionEntry(params: {
|
||||
key: keyRaw,
|
||||
alias: params.alias,
|
||||
mainKey: params.mainKey,
|
||||
requesterInternalKey: params.requesterInternalKey,
|
||||
});
|
||||
|
||||
const candidates = new Set<string>([keyRaw, internal]);
|
||||
@ -72,7 +74,7 @@ function resolveSessionEntry(params: {
|
||||
candidates.add(`agent:${DEFAULT_AGENT_ID}:${keyRaw}`);
|
||||
candidates.add(`agent:${DEFAULT_AGENT_ID}:${internal}`);
|
||||
}
|
||||
if (keyRaw === "main") {
|
||||
if (keyRaw === "main" || keyRaw === "current") {
|
||||
candidates.add(
|
||||
buildAgentMainSessionKey({
|
||||
agentId: DEFAULT_AGENT_ID,
|
||||
@ -251,6 +253,12 @@ export function createSessionStatusTool(opts?: {
|
||||
if (!requestedKeyRaw?.trim()) {
|
||||
throw new Error("sessionKey required");
|
||||
}
|
||||
// Normalize "current" to the requester's own session key. The "main"
|
||||
// alias is already scoped to the requester agent's store, so this gives
|
||||
// every caller their own session regardless of agent identity.
|
||||
if (requestedKeyRaw.trim().toLowerCase() === "current") {
|
||||
requestedKeyRaw = "main";
|
||||
}
|
||||
const ensureAgentAccess = (targetAgentId: string) => {
|
||||
if (targetAgentId === requesterAgentId) {
|
||||
return;
|
||||
@ -290,6 +298,7 @@ export function createSessionStatusTool(opts?: {
|
||||
keyRaw: requestedKeyRaw,
|
||||
alias,
|
||||
mainKey,
|
||||
requesterInternalKey: effectiveRequesterKey,
|
||||
});
|
||||
|
||||
if (!resolved && shouldResolveSessionIdInput(requestedKeyRaw)) {
|
||||
@ -310,6 +319,7 @@ export function createSessionStatusTool(opts?: {
|
||||
keyRaw: requestedKeyRaw,
|
||||
alias,
|
||||
mainKey,
|
||||
requesterInternalKey: effectiveRequesterKey,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,6 +67,23 @@ describe("session key display/internal mapping", () => {
|
||||
resolveInternalSessionKey({ key: "agent:ops:main", alias: "global", mainKey: "main" }),
|
||||
).toBe("agent:ops:main");
|
||||
});
|
||||
|
||||
it("maps current to requester session key", () => {
|
||||
expect(
|
||||
resolveInternalSessionKey({
|
||||
key: "current",
|
||||
alias: "global",
|
||||
mainKey: "main",
|
||||
requesterInternalKey: "agent:support:main",
|
||||
}),
|
||||
).toBe("agent:support:main");
|
||||
});
|
||||
|
||||
it("maps current to alias when no requester key is provided", () => {
|
||||
expect(resolveInternalSessionKey({ key: "current", alias: "global", mainKey: "main" })).toBe(
|
||||
"global",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("session reference shape detection", () => {
|
||||
@ -77,6 +94,7 @@ describe("session reference shape detection", () => {
|
||||
|
||||
it("detects canonical session key families", () => {
|
||||
expect(looksLikeSessionKey("main")).toBe(true);
|
||||
expect(looksLikeSessionKey("current")).toBe(true);
|
||||
expect(looksLikeSessionKey("agent:main:main")).toBe(true);
|
||||
expect(looksLikeSessionKey("cron:daily-report")).toBe(true);
|
||||
expect(looksLikeSessionKey("node:macbook")).toBe(true);
|
||||
@ -86,6 +104,7 @@ describe("session reference shape detection", () => {
|
||||
|
||||
it("treats non-keys as session-id candidates", () => {
|
||||
expect(shouldResolveSessionIdInput("agent:main:main")).toBe(false);
|
||||
expect(shouldResolveSessionIdInput("current")).toBe(false);
|
||||
expect(shouldResolveSessionIdInput("d4f5a5a1-9f75-42cf-83a6-8d170e6a1538")).toBe(true);
|
||||
expect(shouldResolveSessionIdInput("random-slug")).toBe(true);
|
||||
});
|
||||
|
||||
@ -25,7 +25,16 @@ export function resolveDisplaySessionKey(params: { key: string; alias: string; m
|
||||
return params.key;
|
||||
}
|
||||
|
||||
export function resolveInternalSessionKey(params: { key: string; alias: string; mainKey: string }) {
|
||||
export function resolveInternalSessionKey(params: {
|
||||
key: string;
|
||||
alias: string;
|
||||
mainKey: string;
|
||||
requesterInternalKey?: string;
|
||||
}) {
|
||||
if (params.key === "current") {
|
||||
// "current" resolves to the requester's own session, falling back to alias.
|
||||
return params.requesterInternalKey ?? params.alias;
|
||||
}
|
||||
if (params.key === "main") {
|
||||
return params.alias;
|
||||
}
|
||||
@ -121,7 +130,7 @@ export function looksLikeSessionKey(value: string): boolean {
|
||||
return false;
|
||||
}
|
||||
// These are canonical key shapes that should never be treated as sessionIds.
|
||||
if (raw === "main" || raw === "global" || raw === "unknown") {
|
||||
if (raw === "main" || raw === "global" || raw === "unknown" || raw === "current") {
|
||||
return true;
|
||||
}
|
||||
if (isAcpSessionKey(raw)) {
|
||||
@ -264,7 +273,11 @@ export async function resolveSessionReference(params: {
|
||||
requesterInternalKey?: string;
|
||||
restrictToSpawned: boolean;
|
||||
}): Promise<SessionReferenceResolution> {
|
||||
const raw = params.sessionKey.trim();
|
||||
const rawInput = params.sessionKey.trim();
|
||||
// Normalize "current" to the requester's own session key so every session
|
||||
// tool resolves it consistently without per-tool special-casing.
|
||||
const raw =
|
||||
rawInput === "current" && params.requesterInternalKey ? params.requesterInternalKey : rawInput;
|
||||
if (shouldResolveSessionIdInput(raw)) {
|
||||
// Prefer key resolution to avoid misclassifying custom keys as sessionIds.
|
||||
const resolvedByKey = await resolveSessionKeyFromKey({
|
||||
@ -290,6 +303,7 @@ export async function resolveSessionReference(params: {
|
||||
key: raw,
|
||||
alias: params.alias,
|
||||
mainKey: params.mainKey,
|
||||
requesterInternalKey: params.requesterInternalKey,
|
||||
});
|
||||
const displayKey = resolveDisplaySessionKey({
|
||||
key: resolvedKey,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user