mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 15:40:44 +00:00
refactor: simplify gateway and e2e test helpers
This commit is contained in:
@@ -222,13 +222,10 @@ run_wrapper_flow() {
|
||||
export USER="testuser"
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
local wrapper="$HOME/.local/bin/openclaw-wrapper"
|
||||
cat >"$wrapper" <<WRAPPER
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
printf "%s\n" "\$@" >> "$HOME/openclaw-wrapper-argv.log"
|
||||
exec "$npm_bin" "\$@"
|
||||
WRAPPER
|
||||
chmod +x "$wrapper"
|
||||
node scripts/e2e/lib/doctor-install-switch/write-wrapper.mjs \
|
||||
"$wrapper" \
|
||||
"$npm_bin" \
|
||||
"$HOME/openclaw-wrapper-argv.log"
|
||||
|
||||
local unit_path="$HOME/.config/systemd/user/openclaw-gateway.service"
|
||||
|
||||
|
||||
24
scripts/e2e/lib/doctor-install-switch/write-wrapper.mjs
Normal file
24
scripts/e2e/lib/doctor-install-switch/write-wrapper.mjs
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env node
|
||||
import fs from "node:fs";
|
||||
|
||||
const [, , wrapperPath, npmBin, logPath = `${process.env.HOME}/openclaw-wrapper-argv.log`] =
|
||||
process.argv;
|
||||
|
||||
if (!wrapperPath || !npmBin || !logPath || logPath.startsWith("undefined/")) {
|
||||
console.error("usage: write-wrapper.mjs <wrapper-path> <npm-bin> [log-path]");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function shellSingleQuote(value) {
|
||||
return `'${value.replaceAll("'", "'\\''")}'`;
|
||||
}
|
||||
|
||||
fs.writeFileSync(
|
||||
wrapperPath,
|
||||
`#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
printf "%s\\n" "$@" >> ${shellSingleQuote(logPath)}
|
||||
exec ${shellSingleQuote(npmBin)} "$@"
|
||||
`,
|
||||
{ mode: 0o755 },
|
||||
);
|
||||
@@ -62,6 +62,52 @@ parallels_log_progress_extract() {
|
||||
node scripts/e2e/lib/parallels-package/log-progress-extract.mjs "$log_path"
|
||||
}
|
||||
|
||||
parallels_bash_seed_workspace_snippet() {
|
||||
local purpose="$1"
|
||||
cat <<EOF
|
||||
workspace="\${OPENCLAW_WORKSPACE_DIR:-\$HOME/.openclaw/workspace}"
|
||||
mkdir -p "\$workspace/.openclaw"
|
||||
cat > "\$workspace/IDENTITY.md" <<'IDENTITY_EOF'
|
||||
# Identity
|
||||
|
||||
- Name: OpenClaw
|
||||
- Purpose: $purpose
|
||||
IDENTITY_EOF
|
||||
cat > "\$workspace/.openclaw/workspace-state.json" <<'STATE_EOF'
|
||||
{
|
||||
"version": 1,
|
||||
"setupCompletedAt": "2026-01-01T00:00:00.000Z"
|
||||
}
|
||||
STATE_EOF
|
||||
rm -f "\$workspace/BOOTSTRAP.md"
|
||||
EOF
|
||||
}
|
||||
|
||||
parallels_powershell_seed_workspace_snippet() {
|
||||
local purpose="$1"
|
||||
cat <<EOF
|
||||
\$workspace = \$env:OPENCLAW_WORKSPACE_DIR
|
||||
if (-not \$workspace) {
|
||||
\$workspace = Join-Path \$env:USERPROFILE '.openclaw\\workspace'
|
||||
}
|
||||
\$stateDir = Join-Path \$workspace '.openclaw'
|
||||
New-Item -ItemType Directory -Path \$stateDir -Force | Out-Null
|
||||
@'
|
||||
# Identity
|
||||
|
||||
- Name: OpenClaw
|
||||
- Purpose: $purpose
|
||||
'@ | Set-Content -Path (Join-Path \$workspace 'IDENTITY.md') -Encoding UTF8
|
||||
@'
|
||||
{
|
||||
"version": 1,
|
||||
"setupCompletedAt": "2026-01-01T00:00:00.000Z"
|
||||
}
|
||||
'@ | Set-Content -Path (Join-Path \$stateDir 'workspace-state.json') -Encoding UTF8
|
||||
Remove-Item (Join-Path \$workspace 'BOOTSTRAP.md') -Force -ErrorAction SilentlyContinue
|
||||
EOF
|
||||
}
|
||||
|
||||
parallels_child_job_running() {
|
||||
local target="$1"
|
||||
local owner="${2:-}"
|
||||
|
||||
@@ -794,22 +794,8 @@ verify_gateway_status() {
|
||||
}
|
||||
|
||||
prepare_agent_workspace() {
|
||||
guest_exec /bin/sh -lc 'set -eu
|
||||
workspace="${OPENCLAW_WORKSPACE_DIR:-$HOME/.openclaw/workspace}"
|
||||
mkdir -p "$workspace/.openclaw"
|
||||
cat > "$workspace/IDENTITY.md" <<'"'"'IDENTITY_EOF'"'"'
|
||||
# Identity
|
||||
|
||||
- Name: OpenClaw
|
||||
- Purpose: Parallels Linux smoke test assistant.
|
||||
IDENTITY_EOF
|
||||
cat > "$workspace/.openclaw/workspace-state.json" <<'"'"'STATE_EOF'"'"'
|
||||
{
|
||||
"version": 1,
|
||||
"setupCompletedAt": "2026-01-01T00:00:00.000Z"
|
||||
}
|
||||
STATE_EOF
|
||||
rm -f "$workspace/BOOTSTRAP.md"'
|
||||
guest_exec /bin/sh -lc "set -eu
|
||||
$(parallels_bash_seed_workspace_snippet "Parallels Linux smoke test assistant.")"
|
||||
}
|
||||
|
||||
verify_local_turn() {
|
||||
|
||||
@@ -1500,23 +1500,9 @@ show_gateway_status_compat() {
|
||||
verify_turn() {
|
||||
guest_current_user_exec "$GUEST_NODE_BIN" "$GUEST_OPENCLAW_ENTRY" models set "$MODEL_ID"
|
||||
guest_current_user_exec "$GUEST_NODE_BIN" "$GUEST_OPENCLAW_ENTRY" config set agents.defaults.skipBootstrap true --strict-json
|
||||
guest_current_user_sh "$(cat <<EOF
|
||||
guest_current_user_sh "$(cat <<EOF
|
||||
export PATH=$(shell_quote "$GUEST_EXEC_PATH")
|
||||
workspace="\${OPENCLAW_WORKSPACE_DIR:-\$HOME/.openclaw/workspace}"
|
||||
mkdir -p "\$workspace/.openclaw"
|
||||
cat > "\$workspace/IDENTITY.md" <<'IDENTITY_EOF'
|
||||
# Identity
|
||||
|
||||
- Name: OpenClaw
|
||||
- Purpose: Parallels macOS smoke test assistant.
|
||||
IDENTITY_EOF
|
||||
cat > "\$workspace/.openclaw/workspace-state.json" <<'STATE_EOF'
|
||||
{
|
||||
"version": 1,
|
||||
"setupCompletedAt": "2026-01-01T00:00:00.000Z"
|
||||
}
|
||||
STATE_EOF
|
||||
rm -f "\$workspace/BOOTSTRAP.md"
|
||||
$(parallels_bash_seed_workspace_snippet "Parallels macOS smoke test assistant.")
|
||||
exec /usr/bin/env $(shell_quote "$API_KEY_ENV=$API_KEY_VALUE") \
|
||||
$(shell_quote "$GUEST_NODE_BIN") $(shell_quote "$GUEST_OPENCLAW_ENTRY") agent \
|
||||
--agent main \
|
||||
|
||||
@@ -1097,21 +1097,7 @@ if [ "\$gateway_ready" != "1" ]; then
|
||||
echo "gateway did not become ready after transport recovery" >&2
|
||||
exit 1
|
||||
fi
|
||||
workspace="\${OPENCLAW_WORKSPACE_DIR:-\$HOME/.openclaw/workspace}"
|
||||
mkdir -p "\$workspace/.openclaw"
|
||||
cat > "\$workspace/IDENTITY.md" <<'IDENTITY_EOF'
|
||||
# Identity
|
||||
|
||||
- Name: OpenClaw
|
||||
- Purpose: Parallels npm update smoke test assistant.
|
||||
IDENTITY_EOF
|
||||
cat > "\$workspace/.openclaw/workspace-state.json" <<'STATE_EOF'
|
||||
{
|
||||
"version": 1,
|
||||
"setupCompletedAt": "2026-01-01T00:00:00.000Z"
|
||||
}
|
||||
STATE_EOF
|
||||
rm -f "\$workspace/BOOTSTRAP.md"
|
||||
$(parallels_bash_seed_workspace_snippet "Parallels npm update smoke test assistant.")
|
||||
/opt/homebrew/bin/openclaw models set "$MODEL_ID"
|
||||
/opt/homebrew/bin/openclaw config set agents.defaults.skipBootstrap true --strict-json
|
||||
/opt/homebrew/bin/openclaw agent --agent main --session-id "parallels-npm-update-macos-transport-recovery-$expected_needle" --message "Reply with exact ASCII text OK only." --json
|
||||
@@ -1734,21 +1720,7 @@ fi
|
||||
if [ "\$gateway_ready" != "1" ]; then
|
||||
/opt/homebrew/bin/openclaw gateway status --deep --require-rpc
|
||||
fi
|
||||
workspace="\${OPENCLAW_WORKSPACE_DIR:-\$HOME/.openclaw/workspace}"
|
||||
mkdir -p "\$workspace/.openclaw"
|
||||
cat > "\$workspace/IDENTITY.md" <<'IDENTITY_EOF'
|
||||
# Identity
|
||||
|
||||
- Name: OpenClaw
|
||||
- Purpose: Parallels npm update smoke test assistant.
|
||||
IDENTITY_EOF
|
||||
cat > "\$workspace/.openclaw/workspace-state.json" <<'STATE_EOF'
|
||||
{
|
||||
"version": 1,
|
||||
"setupCompletedAt": "2026-01-01T00:00:00.000Z"
|
||||
}
|
||||
STATE_EOF
|
||||
rm -f "\$workspace/BOOTSTRAP.md"
|
||||
$(parallels_bash_seed_workspace_snippet "Parallels npm update smoke test assistant.")
|
||||
/opt/homebrew/bin/openclaw agent --agent main --session-id parallels-npm-update-macos-$expected_needle --message "Reply with exact ASCII text OK only." --json
|
||||
EOF
|
||||
macos_desktop_user_exec /bin/bash /tmp/openclaw-main-update.sh
|
||||
@@ -1838,21 +1810,7 @@ fi
|
||||
openclaw update status --json
|
||||
openclaw models set "$MODEL_ID"
|
||||
openclaw config set agents.defaults.skipBootstrap true --strict-json
|
||||
workspace="\${OPENCLAW_WORKSPACE_DIR:-\$HOME/.openclaw/workspace}"
|
||||
mkdir -p "\$workspace/.openclaw"
|
||||
cat > "\$workspace/IDENTITY.md" <<'IDENTITY_EOF'
|
||||
# Identity
|
||||
|
||||
- Name: OpenClaw
|
||||
- Purpose: Parallels npm update smoke test assistant.
|
||||
IDENTITY_EOF
|
||||
cat > "\$workspace/.openclaw/workspace-state.json" <<'STATE_EOF'
|
||||
{
|
||||
"version": 1,
|
||||
"setupCompletedAt": "2026-01-01T00:00:00.000Z"
|
||||
}
|
||||
STATE_EOF
|
||||
rm -f "\$workspace/BOOTSTRAP.md"
|
||||
$(parallels_bash_seed_workspace_snippet "Parallels npm update smoke test assistant.")
|
||||
openclaw agent --local --agent main --session-id parallels-npm-update-linux-$expected_needle --message "Reply with exact ASCII text OK only." --json
|
||||
EOF
|
||||
prlctl exec "$LINUX_VM" /usr/bin/env "$API_KEY_ENV=$API_KEY_VALUE" /bin/bash /tmp/openclaw-main-update.sh
|
||||
|
||||
@@ -2589,28 +2589,7 @@ show_gateway_status_compat() {
|
||||
verify_turn() {
|
||||
guest_run_openclaw "" "" models set "$MODEL_ID"
|
||||
guest_run_openclaw "" "" config set agents.defaults.skipBootstrap true --strict-json
|
||||
guest_powershell "$(cat <<'EOF'
|
||||
$workspace = $env:OPENCLAW_WORKSPACE_DIR
|
||||
if (-not $workspace) {
|
||||
$workspace = Join-Path $env:USERPROFILE '.openclaw\workspace'
|
||||
}
|
||||
$stateDir = Join-Path $workspace '.openclaw'
|
||||
New-Item -ItemType Directory -Path $stateDir -Force | Out-Null
|
||||
@'
|
||||
# Identity
|
||||
|
||||
- Name: OpenClaw
|
||||
- Purpose: Parallels Windows smoke test assistant.
|
||||
'@ | Set-Content -Path (Join-Path $workspace 'IDENTITY.md') -Encoding UTF8
|
||||
@'
|
||||
{
|
||||
"version": 1,
|
||||
"setupCompletedAt": "2026-01-01T00:00:00.000Z"
|
||||
}
|
||||
'@ | Set-Content -Path (Join-Path $stateDir 'workspace-state.json') -Encoding UTF8
|
||||
Remove-Item (Join-Path $workspace 'BOOTSTRAP.md') -Force -ErrorAction SilentlyContinue
|
||||
EOF
|
||||
)"
|
||||
guest_powershell "$(parallels_powershell_seed_workspace_snippet "Parallels Windows smoke test assistant.")"
|
||||
stop_gateway_processes_for_local_agent_turn
|
||||
guest_run_agent_turn_process
|
||||
}
|
||||
|
||||
@@ -159,6 +159,7 @@ const makeContext = (): GatewayRequestContext =>
|
||||
|
||||
type AgentHandlerArgs = Parameters<typeof agentHandlers.agent>[0];
|
||||
type AgentParams = AgentHandlerArgs["params"];
|
||||
type AgentCommandCall = Record<string, unknown>;
|
||||
|
||||
type AgentIdentityGetHandlerArgs = Parameters<(typeof agentHandlers)["agent.identity.get"]>[0];
|
||||
type AgentIdentityGetParams = AgentIdentityGetHandlerArgs["params"];
|
||||
@@ -254,9 +255,8 @@ function resetTimeConfig() {
|
||||
}
|
||||
|
||||
async function expectResetCall(expectedMessage: string) {
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const call = await waitForAgentCommandCall();
|
||||
expect(mocks.performGatewaySessionReset).toHaveBeenCalledTimes(1);
|
||||
const call = readLastAgentCommandCall();
|
||||
expect(call?.message).toBe(expectedMessage);
|
||||
return call;
|
||||
}
|
||||
@@ -308,15 +308,19 @@ async function runMainAgentAndCaptureEntry(idempotencyKey: string) {
|
||||
return capturedEntry;
|
||||
}
|
||||
|
||||
function readLastAgentCommandCall():
|
||||
| {
|
||||
message?: string;
|
||||
sessionId?: string;
|
||||
}
|
||||
| undefined {
|
||||
return mocks.agentCommand.mock.calls.at(-1)?.[0] as
|
||||
| { message?: string; sessionId?: string }
|
||||
| undefined;
|
||||
function readLastAgentCommandCall(): AgentCommandCall | undefined {
|
||||
return mocks.agentCommand.mock.calls.at(-1)?.[0] as AgentCommandCall | undefined;
|
||||
}
|
||||
|
||||
async function waitForAgentCommandCall<
|
||||
T extends AgentCommandCall = AgentCommandCall,
|
||||
>(): Promise<T> {
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const call = readLastAgentCommandCall();
|
||||
if (!call) {
|
||||
throw new Error("expected agentCommand call");
|
||||
}
|
||||
return call as T;
|
||||
}
|
||||
|
||||
function mockSessionResetSuccess(params: {
|
||||
@@ -551,8 +555,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
const lastCall = mocks.agentCommand.mock.calls.at(-1);
|
||||
expect(lastCall?.[0]).toEqual(
|
||||
await expect(waitForAgentCommandCall()).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
provider: "anthropic",
|
||||
model: "claude-haiku-4-5",
|
||||
@@ -574,9 +577,7 @@ describe("gateway agent handler", () => {
|
||||
{ reqId: "test-acp-turn-source" },
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const lastCall = mocks.agentCommand.mock.calls.at(-1);
|
||||
expect(lastCall?.[0]).toEqual(
|
||||
await expect(waitForAgentCommandCall()).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
acpTurnSource: "manual_spawn",
|
||||
}),
|
||||
@@ -643,8 +644,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
const lastCall = mocks.agentCommand.mock.calls.at(-1);
|
||||
expect(lastCall?.[0]).toEqual(
|
||||
await expect(waitForAgentCommandCall()).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
provider: "anthropic",
|
||||
model: "claude-haiku-4-5",
|
||||
@@ -859,10 +859,7 @@ describe("gateway agent handler", () => {
|
||||
{ reqId: "ts-1" },
|
||||
);
|
||||
|
||||
// Wait for the async agentCommand call
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
|
||||
const callArgs = mocks.agentCommand.mock.calls[0][0];
|
||||
const callArgs = await waitForAgentCommandCall<{ message?: string }>();
|
||||
expect(callArgs.message).toBe("[Wed 2026-01-28 20:30 EST] Is it the weekend?");
|
||||
|
||||
resetTimeConfig();
|
||||
@@ -887,9 +884,7 @@ describe("gateway agent handler", () => {
|
||||
{ reqId: "inter-session-marker" },
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
|
||||
const callArgs = mocks.agentCommand.mock.calls[0][0] as { message?: string };
|
||||
const callArgs = await waitForAgentCommandCall<{ message?: string }>();
|
||||
expect(callArgs.message).toMatch(/^\[Inter-session message\]/);
|
||||
expect(callArgs.message).toContain("isUser=false");
|
||||
expect(callArgs.message).toContain("forwarded reply");
|
||||
@@ -924,13 +919,11 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
|
||||
const callArgs = mocks.agentCommand.mock.calls[0][0] as {
|
||||
const callArgs = await waitForAgentCommandCall<{
|
||||
message?: string;
|
||||
modelRun?: boolean;
|
||||
promptMode?: string;
|
||||
};
|
||||
}>();
|
||||
expect(callArgs).toEqual(
|
||||
expect.objectContaining({
|
||||
message: "Reply exactly: pong",
|
||||
@@ -976,11 +969,8 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const callArgs = mocks.agentCommand.mock.calls.at(-1)?.[0] as
|
||||
| { senderIsOwner?: boolean }
|
||||
| undefined;
|
||||
expect(callArgs?.senderIsOwner).toBe(senderIsOwner);
|
||||
const callArgs = await waitForAgentCommandCall<{ senderIsOwner?: boolean }>();
|
||||
expect(callArgs.senderIsOwner).toBe(senderIsOwner);
|
||||
});
|
||||
|
||||
it("respects explicit bestEffortDeliver=false for main session runs", async () => {
|
||||
@@ -1001,8 +991,7 @@ describe("gateway agent handler", () => {
|
||||
{ reqId: "strict-1" },
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const callArgs = mocks.agentCommand.mock.calls.at(-1)?.[0] as Record<string, unknown>;
|
||||
const callArgs = await waitForAgentCommandCall();
|
||||
expect(callArgs.bestEffortDeliver).toBe(false);
|
||||
});
|
||||
|
||||
@@ -1036,7 +1025,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
await waitForAgentCommandCall();
|
||||
const accepted = respond.mock.calls.find(
|
||||
(call: unknown[]) =>
|
||||
call[0] === true && (call[1] as Record<string, unknown>)?.status === "accepted",
|
||||
@@ -1158,7 +1147,7 @@ describe("gateway agent handler", () => {
|
||||
{ reqId: "music-generation-event-1", respond },
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
await waitForAgentCommandCall();
|
||||
expect(respond).not.toHaveBeenCalledWith(
|
||||
false,
|
||||
undefined,
|
||||
@@ -1205,7 +1194,7 @@ describe("gateway agent handler", () => {
|
||||
{ reqId: "music-generation-event-inter-session" },
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
await waitForAgentCommandCall();
|
||||
expect(findTaskByRunId("music-generation-event-inter-session")).toBeUndefined();
|
||||
});
|
||||
|
||||
@@ -1234,8 +1223,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
{ reqId: "workspace-forwarded-1" },
|
||||
);
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const spawnedCall = mocks.agentCommand.mock.calls.at(-1)?.[0] as { workspaceDir?: string };
|
||||
const spawnedCall = await waitForAgentCommandCall<{ workspaceDir?: string }>();
|
||||
expect(spawnedCall.workspaceDir).toBe("/tmp/inherited");
|
||||
});
|
||||
|
||||
@@ -1277,12 +1265,11 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const callArgs = mocks.agentCommand.mock.calls.at(-1)?.[0] as {
|
||||
const callArgs = await waitForAgentCommandCall<{
|
||||
channel?: string;
|
||||
messageChannel?: string;
|
||||
runContext?: { messageChannel?: string };
|
||||
};
|
||||
}>();
|
||||
expect(callArgs.channel).toBe("telegram");
|
||||
expect(callArgs.messageChannel).toBe("webchat");
|
||||
expect(callArgs.runContext?.messageChannel).toBe("webchat");
|
||||
@@ -1467,15 +1454,14 @@ describe("gateway agent handler", () => {
|
||||
{ reqId: "session-id-agent-resume" },
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const call = mocks.agentCommand.mock.calls.at(-1)?.[0] as {
|
||||
const call = await waitForAgentCommandCall<{
|
||||
agentId?: string;
|
||||
sessionId?: string;
|
||||
sessionKey?: string;
|
||||
};
|
||||
expect(call?.agentId).toBe("main");
|
||||
expect(call?.sessionId).toBe("resume-whatsapp-session");
|
||||
expect(call?.sessionKey).toBeUndefined();
|
||||
}>();
|
||||
expect(call.agentId).toBe("main");
|
||||
expect(call.sessionId).toBe("resume-whatsapp-session");
|
||||
expect(call.sessionKey).toBeUndefined();
|
||||
});
|
||||
|
||||
it("treats whitespace sessionId as absent before resolving the agent session key", async () => {
|
||||
@@ -1496,15 +1482,14 @@ describe("gateway agent handler", () => {
|
||||
{ reqId: "blank-session-id-agent-resume" },
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const call = mocks.agentCommand.mock.calls.at(-1)?.[0] as {
|
||||
const call = await waitForAgentCommandCall<{
|
||||
agentId?: string;
|
||||
sessionId?: string;
|
||||
sessionKey?: string;
|
||||
};
|
||||
expect(call?.agentId).toBe("main");
|
||||
expect(call?.sessionId).toBe("existing-session-id");
|
||||
expect(call?.sessionKey).toBe("agent:main:main");
|
||||
}>();
|
||||
expect(call.agentId).toBe("main");
|
||||
expect(call.sessionId).toBe("existing-session-id");
|
||||
expect(call.sessionKey).toBe("agent:main:main");
|
||||
});
|
||||
|
||||
it("rolls stale gateway agent sessions even when updatedAt was recently touched", async () => {
|
||||
@@ -1554,13 +1539,12 @@ describe("gateway agent handler", () => {
|
||||
{ reqId: "daily-rollover-agent-session" },
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const call = mocks.agentCommand.mock.calls.at(-1)?.[0] as {
|
||||
const call = await waitForAgentCommandCall<{
|
||||
sessionId?: string;
|
||||
sessionKey?: string;
|
||||
};
|
||||
expect(call?.sessionKey).toBe("agent:main:main");
|
||||
expect(call?.sessionId).not.toBe("stale-session-id");
|
||||
}>();
|
||||
expect(call.sessionKey).toBe("agent:main:main");
|
||||
expect(call.sessionId).not.toBe("stale-session-id");
|
||||
expect(capturedEntry?.sessionStartedAt).toBe(now);
|
||||
expect(capturedEntry?.lastInteractionAt).toBe(now);
|
||||
} finally {
|
||||
@@ -1616,13 +1600,12 @@ describe("gateway agent handler", () => {
|
||||
{ reqId: "daily-rollover-agent-session-id" },
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const call = mocks.agentCommand.mock.calls.at(-1)?.[0] as {
|
||||
const call = await waitForAgentCommandCall<{
|
||||
sessionId?: string;
|
||||
sessionKey?: string;
|
||||
};
|
||||
expect(call?.sessionKey).toBe("agent:main:main");
|
||||
expect(call?.sessionId).not.toBe("stale-session-id");
|
||||
}>();
|
||||
expect(call.sessionKey).toBe("agent:main:main");
|
||||
expect(call.sessionId).not.toBe("stale-session-id");
|
||||
expect(capturedEntry?.sessionStartedAt).toBe(now);
|
||||
expect(capturedEntry?.lastInteractionAt).toBe(now);
|
||||
} finally {
|
||||
@@ -1662,13 +1645,12 @@ describe("gateway agent handler", () => {
|
||||
{ reqId: "global-session-agent-id" },
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const call = mocks.agentCommand.mock.calls.at(-1)?.[0] as {
|
||||
const call = await waitForAgentCommandCall<{
|
||||
agentId?: string;
|
||||
sessionKey?: string;
|
||||
};
|
||||
expect(call?.agentId).toBeUndefined();
|
||||
expect(call?.sessionKey).toBe("global");
|
||||
}>();
|
||||
expect(call.agentId).toBeUndefined();
|
||||
expect(call.sessionKey).toBe("global");
|
||||
});
|
||||
|
||||
it("dispatches async gateway agent task creation through the detached task runtime seam", async () => {
|
||||
@@ -1766,8 +1748,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await vi.waitFor(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const callArgs = mocks.agentCommand.mock.calls.at(-1)?.[0] as { sessionKey?: string };
|
||||
const callArgs = await waitForAgentCommandCall<{ sessionKey?: string }>();
|
||||
expect(callArgs.sessionKey).toBe("agent:main:voice");
|
||||
});
|
||||
|
||||
@@ -1810,8 +1791,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await vi.waitFor(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const callArgs = mocks.agentCommand.mock.calls.at(-1)?.[0] as { sessionKey?: string };
|
||||
const callArgs = await waitForAgentCommandCall<{ sessionKey?: string }>();
|
||||
expect(callArgs.sessionKey).toBe("agent:main:main");
|
||||
});
|
||||
|
||||
@@ -1854,8 +1834,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await vi.waitFor(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const callArgs = mocks.agentCommand.mock.calls.at(-1)?.[0] as { sessionKey?: string };
|
||||
const callArgs = await waitForAgentCommandCall<{ sessionKey?: string }>();
|
||||
expect(callArgs.sessionKey).toBe("agent:main:voice");
|
||||
expect(mocks.resolveVoiceWakeRouteByTrigger).toHaveBeenCalledWith({
|
||||
trigger: undefined,
|
||||
@@ -1904,8 +1883,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await vi.waitFor(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const callArgs = mocks.agentCommand.mock.calls.at(-1)?.[0] as { sessionKey?: string };
|
||||
const callArgs = await waitForAgentCommandCall<{ sessionKey?: string }>();
|
||||
expect(callArgs.sessionKey).toBe("agent:main:voice");
|
||||
expect(mocks.resolveVoiceWakeRouteByTrigger).toHaveBeenCalledWith({
|
||||
trigger: "robot wake",
|
||||
@@ -1954,8 +1932,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await vi.waitFor(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const callArgs = mocks.agentCommand.mock.calls.at(-1)?.[0] as { sessionKey?: string };
|
||||
const callArgs = await waitForAgentCommandCall<{ sessionKey?: string }>();
|
||||
expect(callArgs.sessionKey).toBe("agent:main:research");
|
||||
expect(mocks.loadVoiceWakeRoutingConfig).not.toHaveBeenCalled();
|
||||
expect(mocks.resolveVoiceWakeRouteByTrigger).not.toHaveBeenCalled();
|
||||
@@ -2002,8 +1979,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await vi.waitFor(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const callArgs = mocks.agentCommand.mock.calls.at(-1)?.[0] as { sessionKey?: string };
|
||||
const callArgs = await waitForAgentCommandCall<{ sessionKey?: string }>();
|
||||
expect(callArgs.sessionKey).toBe("agent:ops:main");
|
||||
expect(mocks.loadVoiceWakeRoutingConfig).not.toHaveBeenCalled();
|
||||
expect(mocks.resolveVoiceWakeRouteByTrigger).not.toHaveBeenCalled();
|
||||
@@ -2051,8 +2027,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await vi.waitFor(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const callArgs = mocks.agentCommand.mock.calls.at(-1)?.[0] as { sessionKey?: string };
|
||||
const callArgs = await waitForAgentCommandCall<{ sessionKey?: string }>();
|
||||
expect(callArgs.sessionKey).toBe("agent:main:main");
|
||||
expect(mocks.loadVoiceWakeRoutingConfig).not.toHaveBeenCalled();
|
||||
expect(mocks.resolveVoiceWakeRouteByTrigger).not.toHaveBeenCalled();
|
||||
@@ -2129,9 +2104,8 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
expect(mocks.performGatewaySessionReset).toHaveBeenCalledTimes(1);
|
||||
const call = readLastAgentCommandCall();
|
||||
const call = await waitForAgentCommandCall();
|
||||
// Message is now dynamically built with current date — check key substrings
|
||||
expect(call?.message).toContain("Execute your Session Startup sequence now");
|
||||
expect(call?.message).toContain("Current time:");
|
||||
@@ -2168,8 +2142,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const call = readLastAgentCommandCall();
|
||||
const call = await waitForAgentCommandCall();
|
||||
expect(call?.message).toContain("[Startup context loaded by runtime]");
|
||||
expect(call?.message).toContain("[Untrusted daily memory: memory/2026-01-28.md]");
|
||||
expect(call?.message).toContain("today gateway note");
|
||||
@@ -2204,8 +2177,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const call = readLastAgentCommandCall();
|
||||
const call = await waitForAgentCommandCall();
|
||||
expect(call?.message).toContain("while bootstrap is still pending for this workspace");
|
||||
expect(call?.message).toContain("Please read BOOTSTRAP.md from the workspace now");
|
||||
expect(call?.message).not.toContain("Today memory context");
|
||||
@@ -2257,8 +2229,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const call = readLastAgentCommandCall();
|
||||
const call = await waitForAgentCommandCall();
|
||||
expect(call?.message).toContain("while bootstrap is still pending for this workspace");
|
||||
expect(call?.message).toContain(
|
||||
"cannot safely complete the full BOOTSTRAP.md workflow here",
|
||||
@@ -2311,8 +2282,7 @@ describe("gateway agent handler", () => {
|
||||
},
|
||||
);
|
||||
|
||||
await waitForAssertion(() => expect(mocks.agentCommand).toHaveBeenCalled());
|
||||
const call = readLastAgentCommandCall();
|
||||
const call = await waitForAgentCommandCall();
|
||||
expect(call?.message).toContain("Execute your Session Startup sequence now");
|
||||
expect(call?.message).not.toContain("while bootstrap is still pending for this workspace");
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import path from "node:path";
|
||||
import type { AssistantMessage, UserMessage } from "@mariozechner/pi-ai";
|
||||
import { afterAll, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { WebSocket } from "ws";
|
||||
import type { SessionEntry } from "../config/sessions.js";
|
||||
import { isSessionPatchEvent, type InternalHookEvent } from "../hooks/internal-hooks.js";
|
||||
import {
|
||||
enqueueSystemEvent,
|
||||
@@ -273,6 +274,14 @@ async function writeSingleLineSession(dir: string, sessionId: string, content: s
|
||||
);
|
||||
}
|
||||
|
||||
function sessionStoreEntry(sessionId: string, overrides: Partial<SessionEntry> = {}) {
|
||||
return {
|
||||
sessionId,
|
||||
updatedAt: Date.now(),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
async function createCheckpointFixture(dir: string) {
|
||||
const { SessionManager } = await getSessionManagerModule();
|
||||
const session = SessionManager.create(dir, dir);
|
||||
@@ -341,7 +350,7 @@ async function seedActiveMainSession() {
|
||||
await writeSingleLineSession(dir, "sess-main", "hello");
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: { sessionId: "sess-main", updatedAt: Date.now() },
|
||||
main: sessionStoreEntry("sess-main"),
|
||||
},
|
||||
});
|
||||
return { dir, storePath };
|
||||
@@ -486,10 +495,7 @@ describe("gateway server sessions", () => {
|
||||
piSdkMock.models = [{ id: "gpt-test-a", name: "A", provider: "openai" }];
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-parent",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
main: sessionStoreEntry("sess-parent"),
|
||||
},
|
||||
});
|
||||
const created = await directSessionReq<{
|
||||
@@ -733,12 +739,8 @@ describe("gateway server sessions", () => {
|
||||
);
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-parent",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
"dashboard:child": {
|
||||
sessionId: "sess-child",
|
||||
main: sessionStoreEntry("sess-parent"),
|
||||
"dashboard:child": sessionStoreEntry("sess-child", {
|
||||
updatedAt: Date.now() - 1_000,
|
||||
modelProvider: "anthropic",
|
||||
model: "claude-sonnet-4-6",
|
||||
@@ -749,7 +751,7 @@ describe("gateway server sessions", () => {
|
||||
outputTokens: 0,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -792,12 +794,10 @@ describe("gateway server sessions", () => {
|
||||
};
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-main",
|
||||
updatedAt: Date.now(),
|
||||
main: sessionStoreEntry("sess-main", {
|
||||
modelProvider: "test-provider",
|
||||
model: "reasoner",
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -846,10 +846,7 @@ describe("gateway server sessions", () => {
|
||||
await createSessionStoreDir();
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-main",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
main: sessionStoreEntry("sess-main"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -921,15 +918,13 @@ describe("gateway server sessions", () => {
|
||||
);
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-main",
|
||||
updatedAt: Date.now(),
|
||||
main: sessionStoreEntry("sess-main", {
|
||||
modelProvider: "openai-codex",
|
||||
model: "gpt-5.3-codex-spark",
|
||||
contextTokens: 123_456,
|
||||
totalTokens: 0,
|
||||
totalTokensFresh: false,
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -980,9 +975,7 @@ describe("gateway server sessions", () => {
|
||||
await createSessionStoreDir();
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-main",
|
||||
updatedAt: Date.now(),
|
||||
main: sessionStoreEntry("sess-main", {
|
||||
verboseLevel: "on",
|
||||
responseUsage: "full",
|
||||
fastMode: true,
|
||||
@@ -990,7 +983,7 @@ describe("gateway server sessions", () => {
|
||||
lastTo: "-100123",
|
||||
lastAccountId: "acct-1",
|
||||
lastThreadId: 42,
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1042,11 +1035,9 @@ describe("gateway server sessions", () => {
|
||||
await createSessionStoreDir();
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-main",
|
||||
updatedAt: Date.now(),
|
||||
main: sessionStoreEntry("sess-main", {
|
||||
sendPolicy: "deny",
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1092,16 +1083,14 @@ describe("gateway server sessions", () => {
|
||||
await createSessionStoreDir();
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
"subagent:child": {
|
||||
sessionId: "sess-child",
|
||||
updatedAt: Date.now(),
|
||||
"subagent:child": sessionStoreEntry("sess-child", {
|
||||
spawnedBy: "agent:main:main",
|
||||
spawnedWorkspaceDir: "/tmp/subagent-workspace",
|
||||
forkedFromParent: true,
|
||||
spawnDepth: 2,
|
||||
subagentRole: "orchestrator",
|
||||
subagentControlScope: "children",
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1561,10 +1550,8 @@ describe("gateway server sessions", () => {
|
||||
const { SessionManager } = await getSessionManagerModule();
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: fixture.sessionId,
|
||||
main: sessionStoreEntry(fixture.sessionId, {
|
||||
sessionFile: fixture.sessionFile,
|
||||
updatedAt: Date.now(),
|
||||
compactionCheckpoints: [
|
||||
{
|
||||
checkpointId: "checkpoint-1",
|
||||
@@ -1589,7 +1576,7 @@ describe("gateway server sessions", () => {
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1713,12 +1700,10 @@ describe("gateway server sessions", () => {
|
||||
);
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-main",
|
||||
updatedAt: Date.now(),
|
||||
main: sessionStoreEntry("sess-main", {
|
||||
thinkingLevel: "medium",
|
||||
reasoningLevel: "stream",
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1767,10 +1752,7 @@ describe("gateway server sessions", () => {
|
||||
await fs.writeFile(
|
||||
storePath,
|
||||
JSON.stringify({
|
||||
"agent:main:main": {
|
||||
sessionId: "sess-main",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
"agent:main:main": sessionStoreEntry("sess-main"),
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
@@ -1847,10 +1829,7 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId,
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
main: sessionStoreEntry(sessionId),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1879,13 +1858,11 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-stale-model",
|
||||
updatedAt: Date.now(),
|
||||
main: sessionStoreEntry("sess-stale-model", {
|
||||
modelProvider: "qwencode",
|
||||
model: "qwen3.5-plus-2026-02-15",
|
||||
contextTokens: 123456,
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1921,14 +1898,12 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-explicit-model-override",
|
||||
updatedAt: Date.now(),
|
||||
main: sessionStoreEntry("sess-explicit-model-override", {
|
||||
providerOverride: "anthropic",
|
||||
modelOverride: "claude-opus-4-1",
|
||||
modelProvider: "openai",
|
||||
model: "gpt-test-a",
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1978,16 +1953,14 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-fallback-model-override",
|
||||
updatedAt: Date.now(),
|
||||
main: sessionStoreEntry("sess-fallback-model-override", {
|
||||
providerOverride: "anthropic",
|
||||
modelOverride: "claude-opus-4-1",
|
||||
modelOverrideSource: "auto",
|
||||
fallbackNoticeSelectedModel: "openai/gpt-test-a",
|
||||
fallbackNoticeActiveModel: "anthropic/claude-opus-4-1",
|
||||
fallbackNoticeReason: "rate limit",
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2033,16 +2006,14 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-fallback-stale-default",
|
||||
updatedAt: Date.now(),
|
||||
main: sessionStoreEntry("sess-fallback-stale-default", {
|
||||
providerOverride: "anthropic",
|
||||
modelOverride: "claude-opus-4-1",
|
||||
modelOverrideSource: "auto",
|
||||
fallbackNoticeSelectedModel: "openai/gpt-test-a",
|
||||
fallbackNoticeActiveModel: "anthropic/claude-opus-4-1",
|
||||
fallbackNoticeReason: "rate limit",
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2086,10 +2057,8 @@ describe("gateway server sessions", () => {
|
||||
);
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
"subagent:child": {
|
||||
sessionId: "sess-owned-child",
|
||||
"subagent:child": sessionStoreEntry("sess-owned-child", {
|
||||
sessionFile: customSessionFile,
|
||||
updatedAt: Date.now(),
|
||||
chatType: "group",
|
||||
channel: "discord",
|
||||
groupId: "group-1",
|
||||
@@ -2141,7 +2110,7 @@ describe("gateway server sessions", () => {
|
||||
threadId: "thread-1",
|
||||
},
|
||||
label: "owned child",
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2591,11 +2560,8 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: { sessionId: "sess-main", updatedAt: Date.now() },
|
||||
"discord:group:dev": {
|
||||
sessionId: "sess-active",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
main: sessionStoreEntry("sess-main"),
|
||||
"discord:group:dev": sessionStoreEntry("sess-active"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2652,16 +2618,12 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
"agent:main:dreaming-narrative-owned": {
|
||||
sessionId: "sess-owned",
|
||||
updatedAt: Date.now(),
|
||||
"agent:main:dreaming-narrative-owned": sessionStoreEntry("sess-owned", {
|
||||
pluginOwnerId: "memory-core",
|
||||
},
|
||||
"agent:main:dreaming-narrative-foreign": {
|
||||
sessionId: "sess-foreign",
|
||||
updatedAt: Date.now(),
|
||||
}),
|
||||
"agent:main:dreaming-narrative-foreign": sessionStoreEntry("sess-foreign", {
|
||||
pluginOwnerId: "other-plugin",
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2706,10 +2668,8 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: { sessionId: "sess-main", updatedAt: Date.now() },
|
||||
"discord:group:dev": {
|
||||
sessionId: "sess-acp",
|
||||
updatedAt: Date.now(),
|
||||
main: sessionStoreEntry("sess-main"),
|
||||
"discord:group:dev": sessionStoreEntry("sess-acp", {
|
||||
acp: {
|
||||
backend: "acpx",
|
||||
agent: "codex",
|
||||
@@ -2718,7 +2678,7 @@ describe("gateway server sessions", () => {
|
||||
state: "idle",
|
||||
lastActivityAt: Date.now(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
const deleted = await directSessionReq<{ ok: true; deleted: boolean }>("sessions.delete", {
|
||||
@@ -2757,12 +2717,10 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: { sessionId: "sess-main", updatedAt: Date.now() },
|
||||
"discord:group:delete": {
|
||||
sessionId: "sess-delete",
|
||||
main: sessionStoreEntry("sess-main"),
|
||||
"discord:group:delete": sessionStoreEntry("sess-delete", {
|
||||
sessionFile: transcriptPath,
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2799,7 +2757,7 @@ describe("gateway server sessions", () => {
|
||||
await writeSingleLineSession(dir, "sess-main", "hello");
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: { sessionId: "sess-main", updatedAt: Date.now() },
|
||||
main: sessionStoreEntry("sess-main"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2818,10 +2776,7 @@ describe("gateway server sessions", () => {
|
||||
await writeSingleLineSession(dir, "sess-subagent", "hello");
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
"agent:main:subagent:worker": {
|
||||
sessionId: "sess-subagent",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
"agent:main:subagent:worker": sessionStoreEntry("sess-subagent"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2854,10 +2809,7 @@ describe("gateway server sessions", () => {
|
||||
await writeSingleLineSession(dir, "sess-subagent", "hello");
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
"agent:main:subagent:worker": {
|
||||
sessionId: "sess-subagent",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
"agent:main:subagent:worker": sessionStoreEntry("sess-subagent"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2880,10 +2832,7 @@ describe("gateway server sessions", () => {
|
||||
await writeSingleLineSession(dir, "sess-subagent", "hello");
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
"agent:main:subagent:worker": {
|
||||
sessionId: "sess-subagent",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
"agent:main:subagent:worker": sessionStoreEntry("sess-subagent"),
|
||||
},
|
||||
});
|
||||
subagentLifecycleHookState.hasSubagentEndedHook = false;
|
||||
@@ -2970,9 +2919,7 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-main",
|
||||
updatedAt: Date.now(),
|
||||
main: sessionStoreEntry("sess-main", {
|
||||
acp: {
|
||||
backend: "acpx",
|
||||
agent: "codex",
|
||||
@@ -2993,7 +2940,7 @@ describe("gateway server sessions", () => {
|
||||
state: "idle",
|
||||
lastActivityAt: Date.now(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
const reset = await directSessionReq<{
|
||||
@@ -3096,7 +3043,7 @@ describe("gateway server sessions", () => {
|
||||
await writeSingleLineSession(dir, "sess-main", "hello");
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: { sessionId: "sess-main", updatedAt: Date.now() },
|
||||
main: sessionStoreEntry("sess-main"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3118,10 +3065,7 @@ describe("gateway server sessions", () => {
|
||||
await writeSingleLineSession(dir, "sess-subagent", "hello");
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
"agent:main:subagent:worker": {
|
||||
sessionId: "sess-subagent",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
"agent:main:subagent:worker": sessionStoreEntry("sess-subagent"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3159,10 +3103,7 @@ describe("gateway server sessions", () => {
|
||||
await writeSingleLineSession(dir, "sess-main", "hello");
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-main",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
main: sessionStoreEntry("sess-main"),
|
||||
},
|
||||
});
|
||||
subagentLifecycleHookState.hasSubagentEndedHook = false;
|
||||
@@ -3185,7 +3126,7 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: { sessionId: "sess-main", updatedAt: Date.now() },
|
||||
main: sessionStoreEntry("sess-main"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3444,11 +3385,9 @@ describe("gateway server sessions", () => {
|
||||
gatewayStorePath,
|
||||
JSON.stringify(
|
||||
{
|
||||
"agent:main:main": {
|
||||
sessionId: "sess-new",
|
||||
"agent:main:main": sessionStoreEntry("sess-new", {
|
||||
sessionFile: newTranscriptPath,
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
}),
|
||||
},
|
||||
null,
|
||||
2,
|
||||
@@ -3490,10 +3429,7 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
"discord:group:dev": {
|
||||
sessionId: "sess-active",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
"discord:group:dev": sessionStoreEntry("sess-active"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3534,10 +3470,8 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: fixture.sessionId,
|
||||
main: sessionStoreEntry(fixture.sessionId, {
|
||||
sessionFile: fixture.sessionFile,
|
||||
updatedAt: Date.now(),
|
||||
compactionCheckpoints: [
|
||||
{
|
||||
checkpointId: "checkpoint-1",
|
||||
@@ -3562,11 +3496,8 @@ describe("gateway server sessions", () => {
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
"discord:group:dev": {
|
||||
sessionId: "sess-group",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
}),
|
||||
"discord:group:dev": sessionStoreEntry("sess-group"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3622,11 +3553,9 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-hook-test",
|
||||
updatedAt: Date.now(),
|
||||
main: sessionStoreEntry("sess-hook-test", {
|
||||
label: "original-label",
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3668,10 +3597,7 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-webchat-test",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
main: sessionStoreEntry("sess-webchat-test"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3710,10 +3636,7 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-success-test",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
main: sessionStoreEntry("sess-success-test"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3775,10 +3698,7 @@ describe("gateway server sessions", () => {
|
||||
await createSessionStoreDir();
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-cfg-isolation-test",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
main: sessionStoreEntry("sess-cfg-isolation-test"),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3827,14 +3747,8 @@ describe("gateway server sessions", () => {
|
||||
|
||||
await writeSessionStore({
|
||||
entries: {
|
||||
main: {
|
||||
sessionId: "sess-main",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
"discord:group:dev": {
|
||||
sessionId: "sess-group",
|
||||
updatedAt: Date.now(),
|
||||
},
|
||||
main: sessionStoreEntry("sess-main"),
|
||||
"discord:group:dev": sessionStoreEntry("sess-group"),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user