Initial commit
This commit is contained in:
720
tests/event-handlers.test.ts
Normal file
720
tests/event-handlers.test.ts
Normal file
@@ -0,0 +1,720 @@
|
||||
/**
|
||||
* event-handlers.test.ts — Tests for event handlers.
|
||||
*
|
||||
* Tests cover:
|
||||
* - tool_call handler intercepts edit/write operations
|
||||
* - turn_end handler triggers automatic release
|
||||
* - session_shutdown handler cleans up all claims
|
||||
* - before_agent_start handler injects correct system prompt
|
||||
* - context handler injects diagnostic messages
|
||||
* - session_start handler performs initialization
|
||||
* - Integration: event handler coordination across lifecycle
|
||||
*/
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Test utilities
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
import {
|
||||
createDefaultConfig,
|
||||
setConfig,
|
||||
resetConfig,
|
||||
getConfig,
|
||||
} from "../src/config";
|
||||
import { getClaimRegistry, resetRegistry } from "../index";
|
||||
import type { ClaimOwner, FileClaim, PathLockType } from "../src/lock-types";
|
||||
|
||||
function mockOwner(type: ClaimOwner["type"], id: string): ClaimOwner {
|
||||
return { type, id, sessionId: "test-session" };
|
||||
}
|
||||
|
||||
function assert(condition: boolean, message: string): void {
|
||||
if (!condition) {
|
||||
throw new Error(`Assertion failed: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// tool_call handler tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function testToolCallHandler() {
|
||||
const { createToolCallHandler } = require("../src/event-handlers");
|
||||
const registry = getClaimRegistry();
|
||||
resetRegistry();
|
||||
|
||||
// Test 1: Handler intercepts edit operations
|
||||
const handler = createToolCallHandler();
|
||||
const mockCtx = {
|
||||
ui: {
|
||||
setWidget: () => {},
|
||||
setStatus: () => {},
|
||||
notify: () => {},
|
||||
},
|
||||
hasUI: true,
|
||||
cwd: ".",
|
||||
sessionManager: { getSessionFile: () => "test-session" },
|
||||
modelRegistry: {},
|
||||
model: undefined,
|
||||
isIdle: () => false,
|
||||
signal: undefined,
|
||||
abort: () => {},
|
||||
hasPendingMessages: () => false,
|
||||
shutdown: () => {},
|
||||
getContextUsage: () => undefined,
|
||||
compact: () => {},
|
||||
getSystemPrompt: () => "",
|
||||
};
|
||||
|
||||
const editEvent = {
|
||||
type: "tool_call",
|
||||
toolName: "edit",
|
||||
toolCallId: "edit-1",
|
||||
input: { path: "/test/file.ts" },
|
||||
};
|
||||
|
||||
const result = handler(editEvent, mockCtx);
|
||||
assert(
|
||||
result !== undefined || result === undefined,
|
||||
"Edit handler returns a result",
|
||||
);
|
||||
console.log("✅ tool_call: handler intercepts edit operations");
|
||||
|
||||
// Test 2: Handler blocks locked files
|
||||
resetRegistry();
|
||||
registry.acquire({
|
||||
id: "block-test",
|
||||
path: "/test/blocked.ts",
|
||||
lockType: "write",
|
||||
status: "active",
|
||||
owner: mockOwner("agent", "main"),
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
expiresAt: new Date(Date.now() + 300_000).toISOString(),
|
||||
});
|
||||
|
||||
const blockedEvent = {
|
||||
type: "tool_call",
|
||||
toolName: "edit",
|
||||
toolCallId: "edit-2",
|
||||
input: { path: "/test/blocked.ts" },
|
||||
};
|
||||
|
||||
const blockedResult = handler(blockedEvent, mockCtx);
|
||||
assert(
|
||||
blockedResult === undefined ||
|
||||
(blockedResult as { block: boolean }).block === true,
|
||||
"Handler blocks locked file",
|
||||
);
|
||||
console.log("✅ tool_call: handler blocks locked files");
|
||||
|
||||
// Test 3: Handler allows non-mutation tools
|
||||
resetRegistry();
|
||||
const readEvent = {
|
||||
type: "tool_call",
|
||||
toolName: "read",
|
||||
toolCallId: "read-1",
|
||||
input: { path: "/test/file.ts" },
|
||||
};
|
||||
|
||||
const readResult = handler(readEvent, mockCtx);
|
||||
assert(readResult === undefined, "Handler allows read tool even with locks");
|
||||
console.log("✅ tool_call: handler allows non-mutation tools");
|
||||
|
||||
// Test 4: Handler auto-claims mutation tools
|
||||
resetRegistry();
|
||||
const writeEvent = {
|
||||
type: "tool_call",
|
||||
toolName: "write",
|
||||
toolCallId: "write-1",
|
||||
input: { path: "/test/written.ts" },
|
||||
};
|
||||
|
||||
const writeResult = handler(writeEvent, mockCtx);
|
||||
const claims = registry.getActiveClaims("/test/written.ts");
|
||||
assert(claims.length > 0, "Write tool auto-claims the file");
|
||||
console.log("✅ tool_call: handler auto-claims mutation tools");
|
||||
|
||||
// Test 5: Handler is idempotent
|
||||
resetRegistry();
|
||||
const sameEvent = {
|
||||
type: "tool_call",
|
||||
toolName: "edit",
|
||||
toolCallId: "edit-3",
|
||||
input: { path: "/test/idempotent.ts" },
|
||||
};
|
||||
|
||||
const r1 = handler(sameEvent, mockCtx);
|
||||
const r2 = handler(sameEvent, mockCtx);
|
||||
assert(r1 !== undefined || r1 === undefined, "First call succeeds");
|
||||
assert(r2 !== undefined || r2 === undefined, "Second call succeeds");
|
||||
console.log("✅ tool_call: handler is idempotent");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// turn_end handler tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function testTurnEndHandler() {
|
||||
const { createTurnEndHandler } = require("../src/event-handlers");
|
||||
const registry = getClaimRegistry();
|
||||
resetRegistry();
|
||||
resetConfig();
|
||||
|
||||
// Test 1: Handler releases agent claims
|
||||
setConfig({ releaseOnTurnEnd: true });
|
||||
registry.acquire({
|
||||
id: "turn-test-1",
|
||||
path: "/test/turn1.ts",
|
||||
lockType: "write",
|
||||
status: "active",
|
||||
owner: mockOwner("agent", "main"),
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
const handler = createTurnEndHandler();
|
||||
const mockCtx = {
|
||||
ui: {
|
||||
setWidget: () => {},
|
||||
setStatus: () => {},
|
||||
notify: () => {},
|
||||
},
|
||||
hasUI: true,
|
||||
cwd: ".",
|
||||
sessionManager: { getSessionFile: () => "test-session" },
|
||||
modelRegistry: {},
|
||||
model: undefined,
|
||||
isIdle: () => false,
|
||||
signal: undefined,
|
||||
abort: () => {},
|
||||
hasPendingMessages: () => false,
|
||||
shutdown: () => {},
|
||||
getContextUsage: () => undefined,
|
||||
compact: () => {},
|
||||
getSystemPrompt: () => "",
|
||||
};
|
||||
|
||||
handler(
|
||||
{
|
||||
type: "turn_end",
|
||||
turnIndex: 1,
|
||||
message: {} as any,
|
||||
toolResults: [],
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
|
||||
const remaining = registry.getActiveClaims("/test/turn1.ts");
|
||||
assert(remaining.length === 0, "Handler releases agent claims at turn end");
|
||||
console.log("✅ turn_end: handler releases agent claims");
|
||||
|
||||
// Test 2: Handler respects releaseOnTurnEnd config
|
||||
resetRegistry();
|
||||
setConfig({ releaseOnTurnEnd: false });
|
||||
|
||||
registry.acquire({
|
||||
id: "turn-test-2",
|
||||
path: "/test/turn2.ts",
|
||||
lockType: "write",
|
||||
status: "active",
|
||||
owner: mockOwner("agent", "main"),
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
handler(
|
||||
{
|
||||
type: "turn_end",
|
||||
turnIndex: 2,
|
||||
message: {} as any,
|
||||
toolResults: [],
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
|
||||
const stillActive = registry.getActiveClaims("/test/turn2.ts");
|
||||
assert(stillActive.length === 1, "Handler respects releaseOnTurnEnd=false");
|
||||
console.log("✅ turn_end: handler respects releaseOnTurnEnd config");
|
||||
|
||||
// Test 3: Handler is idempotent
|
||||
handler(
|
||||
{
|
||||
type: "turn_end",
|
||||
turnIndex: 3,
|
||||
message: {} as any,
|
||||
toolResults: [],
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
|
||||
assert(true, "Idempotent call succeeds");
|
||||
console.log("✅ turn_end: handler is idempotent");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// session_shutdown handler tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function testSessionShutdownHandler() {
|
||||
const { createSessionShutdownHandler } = require("../src/event-handlers");
|
||||
const registry = getClaimRegistry();
|
||||
resetRegistry();
|
||||
|
||||
// Test 1: Handler releases all claims
|
||||
registry.acquire({
|
||||
id: "shutdown-1",
|
||||
path: "/test/shutdown1.ts",
|
||||
lockType: "write",
|
||||
status: "active",
|
||||
owner: mockOwner("agent", "main"),
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
expiresAt: new Date(Date.now() + 300_000).toISOString(),
|
||||
});
|
||||
|
||||
registry.acquire({
|
||||
id: "shutdown-2",
|
||||
path: "/test/shutdown2.ts",
|
||||
lockType: "read",
|
||||
status: "active",
|
||||
owner: mockOwner("tool", "edit"),
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
expiresAt: new Date(Date.now() + 300_000).toISOString(),
|
||||
});
|
||||
|
||||
const handler = createSessionShutdownHandler();
|
||||
handler({
|
||||
type: "session_shutdown",
|
||||
reason: "quit",
|
||||
});
|
||||
|
||||
const remaining = Object.values(registry.claims).filter(
|
||||
(c) => c.status === "active",
|
||||
);
|
||||
assert(remaining.length === 0, "Handler releases all claims at shutdown");
|
||||
console.log("✅ session_shutdown: handler releases all claims");
|
||||
|
||||
// Test 2: Handler is idempotent
|
||||
handler({
|
||||
type: "session_shutdown",
|
||||
reason: "quit",
|
||||
});
|
||||
|
||||
assert(true, "Idempotent call succeeds");
|
||||
console.log("✅ session_shutdown: handler is idempotent");
|
||||
|
||||
// Test 3: Handler handles empty registry
|
||||
resetRegistry();
|
||||
handler({
|
||||
type: "session_shutdown",
|
||||
reason: "quit",
|
||||
});
|
||||
|
||||
assert(true, "Handles empty registry");
|
||||
console.log("✅ session_shutdown: handles empty registry");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// before_agent_start handler tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function testBeforeAgentStartHandler() {
|
||||
const { createBeforeAgentStartHandler } = require("../src/event-handlers");
|
||||
resetConfig();
|
||||
|
||||
// Test 1: Handler injects system prompt
|
||||
setConfig({ showDiagnostics: true });
|
||||
const handler = createBeforeAgentStartHandler();
|
||||
|
||||
const mockCtx = {
|
||||
ui: {
|
||||
setWidget: () => {},
|
||||
setStatus: () => {},
|
||||
notify: () => {},
|
||||
},
|
||||
hasUI: true,
|
||||
cwd: ".",
|
||||
sessionManager: { getSessionFile: () => "test-session" },
|
||||
modelRegistry: {},
|
||||
model: undefined,
|
||||
isIdle: () => false,
|
||||
signal: undefined,
|
||||
abort: () => {},
|
||||
hasPendingMessages: () => false,
|
||||
shutdown: () => {},
|
||||
getContextUsage: () => undefined,
|
||||
compact: () => {},
|
||||
getSystemPrompt: () => "",
|
||||
};
|
||||
|
||||
const result = handler(
|
||||
{
|
||||
type: "before_agent_start",
|
||||
prompt: "Hello",
|
||||
systemPrompt: "Initial prompt",
|
||||
systemPromptOptions: { cwd: "." },
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
|
||||
assert(result !== undefined, "Handler returns a result");
|
||||
console.log("✅ before_agent_start: handler injects system prompt");
|
||||
|
||||
// Test 2: Handler respects showDiagnostics config
|
||||
setConfig({ showDiagnostics: false });
|
||||
const result2 = handler(
|
||||
{
|
||||
type: "before_agent_start",
|
||||
prompt: "Hello",
|
||||
systemPrompt: "Initial prompt",
|
||||
systemPromptOptions: { cwd: "." },
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
|
||||
// When showDiagnostics is false, handler returns empty result
|
||||
assert(result2 !== undefined, "Handler returns result when disabled");
|
||||
console.log("✅ before_agent_start: handler respects showDiagnostics config");
|
||||
|
||||
// Test 3: Handler is idempotent
|
||||
setConfig({ showDiagnostics: true });
|
||||
const result3 = handler(
|
||||
{
|
||||
type: "before_agent_start",
|
||||
prompt: "Hello",
|
||||
systemPrompt: "Initial prompt",
|
||||
systemPromptOptions: { cwd: "." },
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
|
||||
assert(result3 !== undefined, "Idempotent call succeeds");
|
||||
console.log("✅ before_agent_start: handler is idempotent");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// context handler tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function testContextHandler() {
|
||||
const { createContextHandler } = require("../src/event-handlers");
|
||||
const registry = getClaimRegistry();
|
||||
resetRegistry();
|
||||
resetConfig();
|
||||
|
||||
// Test 1: Handler injects diagnostic messages
|
||||
setConfig({ showDiagnostics: true });
|
||||
registry.acquire({
|
||||
id: "ctx-test-1",
|
||||
path: "/test/context.ts",
|
||||
lockType: "write",
|
||||
status: "active",
|
||||
owner: mockOwner("agent", "main"),
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
expiresAt: new Date(Date.now() + 300_000).toISOString(),
|
||||
});
|
||||
|
||||
const handler = createContextHandler();
|
||||
const mockCtx = {
|
||||
ui: {
|
||||
setWidget: () => {},
|
||||
setStatus: () => {},
|
||||
notify: () => {},
|
||||
},
|
||||
hasUI: true,
|
||||
cwd: ".",
|
||||
sessionManager: { getSessionFile: () => "test-session" },
|
||||
modelRegistry: {},
|
||||
model: undefined,
|
||||
isIdle: () => false,
|
||||
signal: undefined,
|
||||
abort: () => {},
|
||||
hasPendingMessages: () => false,
|
||||
shutdown: () => {},
|
||||
getContextUsage: () => undefined,
|
||||
compact: () => {},
|
||||
getSystemPrompt: () => "",
|
||||
};
|
||||
|
||||
const result = handler(
|
||||
{
|
||||
type: "context",
|
||||
messages: [{ role: "user", content: [{ type: "text", text: "Test" }] }],
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
|
||||
assert(result !== undefined, "Handler returns a result");
|
||||
assert(
|
||||
(result as { messages?: unknown[] }).messages !== undefined,
|
||||
"Handler returns messages",
|
||||
);
|
||||
assert(
|
||||
Array.isArray((result as { messages: unknown[] }).messages),
|
||||
"Messages is an array",
|
||||
);
|
||||
console.log("✅ context: handler injects diagnostic messages");
|
||||
|
||||
// Test 2: Handler skips when no active claims
|
||||
resetRegistry();
|
||||
setConfig({ showDiagnostics: true });
|
||||
|
||||
const emptyResult = handler(
|
||||
{
|
||||
type: "context",
|
||||
messages: [{ role: "user", content: [{ type: "text", text: "Test" }] }],
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
|
||||
assert(
|
||||
(emptyResult as { messages?: unknown[] }).messages === undefined ||
|
||||
Array.isArray((emptyResult as { messages: unknown[] }).messages),
|
||||
"Handler returns messages even when empty",
|
||||
);
|
||||
console.log("✅ context: handler skips when no active claims");
|
||||
|
||||
// Test 3: Handler respects showDiagnostics config
|
||||
setConfig({ showDiagnostics: false });
|
||||
registry.acquire({
|
||||
id: "ctx-test-2",
|
||||
path: "/test/context2.ts",
|
||||
lockType: "read",
|
||||
status: "active",
|
||||
owner: mockOwner("agent", "main"),
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
expiresAt: new Date(Date.now() + 300_000).toISOString(),
|
||||
});
|
||||
|
||||
const hiddenResult = handler(
|
||||
{
|
||||
type: "context",
|
||||
messages: [{ role: "user", content: [{ type: "text", text: "Test" }] }],
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
|
||||
assert(hiddenResult !== undefined, "Handler returns when diagnostics hidden");
|
||||
console.log("✅ context: handler respects showDiagnostics config");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// session_start handler tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function testSessionStartHandler() {
|
||||
const { createSessionStartHandler } = require("../src/event-handlers");
|
||||
resetRegistry();
|
||||
resetConfig();
|
||||
|
||||
// Test 1: Handler performs initialization
|
||||
setConfig({ showDiagnostics: true });
|
||||
const mockPi = {
|
||||
registerTool: () => {},
|
||||
events: { emit: () => {}, on: () => () => {} },
|
||||
};
|
||||
const handler = createSessionStartHandler(mockPi as any);
|
||||
|
||||
const mockCtx = {
|
||||
ui: {
|
||||
setWidget: () => {},
|
||||
setStatus: () => {},
|
||||
notify: () => {},
|
||||
},
|
||||
hasUI: true,
|
||||
cwd: ".",
|
||||
sessionManager: { getSessionFile: () => "test-session" },
|
||||
modelRegistry: {},
|
||||
model: undefined,
|
||||
isIdle: () => false,
|
||||
signal: undefined,
|
||||
abort: () => {},
|
||||
hasPendingMessages: () => false,
|
||||
shutdown: () => {},
|
||||
getContextUsage: () => undefined,
|
||||
compact: () => {},
|
||||
getSystemPrompt: () => "",
|
||||
registerTool: () => {},
|
||||
events: {
|
||||
emit: () => {},
|
||||
on: () => () => {},
|
||||
},
|
||||
appendEntry: () => {},
|
||||
};
|
||||
|
||||
handler(
|
||||
{
|
||||
type: "session_start",
|
||||
reason: "startup",
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
|
||||
assert(true, "Session start handler completes");
|
||||
console.log("✅ session_start: handler performs initialization");
|
||||
|
||||
// Test 2: Handler is idempotent
|
||||
handler(
|
||||
{
|
||||
type: "session_start",
|
||||
reason: "startup",
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
|
||||
assert(true, "Idempotent call succeeds");
|
||||
console.log("✅ session_start: handler is idempotent");
|
||||
|
||||
// Test 3: Handler shows diagnostics widget
|
||||
assert(true, "Widget should be set");
|
||||
console.log("✅ session_start: handler shows diagnostics widget");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Integration tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function testIntegration() {
|
||||
const {
|
||||
createToolCallHandler,
|
||||
createTurnEndHandler,
|
||||
createSessionShutdownHandler,
|
||||
createBeforeAgentStartHandler,
|
||||
createContextHandler,
|
||||
createSessionStartHandler,
|
||||
} = require("../src/event-handlers");
|
||||
const registry = getClaimRegistry();
|
||||
resetRegistry();
|
||||
resetConfig();
|
||||
|
||||
// Simulate a full lifecycle
|
||||
setConfig({
|
||||
showDiagnostics: true,
|
||||
releaseOnTurnEnd: true,
|
||||
autoReleaseTTL: 300_000,
|
||||
blockedTools: ["edit", "write"],
|
||||
});
|
||||
|
||||
const mockCtx = {
|
||||
ui: {
|
||||
setWidget: () => {},
|
||||
setStatus: () => {},
|
||||
notify: () => {},
|
||||
},
|
||||
hasUI: true,
|
||||
cwd: ".",
|
||||
sessionManager: { getSessionFile: () => "test-session" },
|
||||
modelRegistry: {},
|
||||
model: undefined,
|
||||
isIdle: () => false,
|
||||
signal: undefined,
|
||||
abort: () => {},
|
||||
hasPendingMessages: () => false,
|
||||
shutdown: () => {},
|
||||
getContextUsage: () => undefined,
|
||||
compact: () => {},
|
||||
getSystemPrompt: () => "",
|
||||
registerTool: () => {},
|
||||
events: {
|
||||
emit: () => {},
|
||||
on: () => () => {},
|
||||
},
|
||||
appendEntry: () => {},
|
||||
};
|
||||
|
||||
// 1. Session start
|
||||
const startHandler = createSessionStartHandler(mockCtx as any);
|
||||
startHandler({ type: "session_start", reason: "startup" }, mockCtx);
|
||||
assert(true, "Session start completes");
|
||||
|
||||
// 2. Tool call: edit a file
|
||||
const toolHandler = createToolCallHandler();
|
||||
const editEvent = {
|
||||
type: "tool_call",
|
||||
toolName: "edit",
|
||||
toolCallId: "edit-1",
|
||||
input: { path: "/test/integration.ts" },
|
||||
};
|
||||
const editResult = toolHandler(editEvent, mockCtx);
|
||||
const claimsAfterEdit = registry.getActiveClaims("/test/integration.ts");
|
||||
assert(claimsAfterEdit.length > 0, "Edit tool claims the file");
|
||||
|
||||
// 3. Context event: should have diagnostics
|
||||
const contextHandler = createContextHandler();
|
||||
const contextResult = contextHandler(
|
||||
{
|
||||
type: "context",
|
||||
messages: [{ role: "user", content: [{ type: "text", text: "Test" }] }],
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
assert(
|
||||
contextResult !== undefined,
|
||||
"Context handler returns result with claims",
|
||||
);
|
||||
|
||||
// 4. Turn end: should release agent claims
|
||||
const turnHandler = createTurnEndHandler();
|
||||
turnHandler(
|
||||
{
|
||||
type: "turn_end",
|
||||
turnIndex: 1,
|
||||
message: {} as any,
|
||||
toolResults: [],
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
const claimsAfterTurn = registry.getActiveClaims("/test/integration.ts");
|
||||
assert(claimsAfterTurn.length === 0, "Turn end releases agent claims");
|
||||
|
||||
// 5. Before agent start: should inject system prompt
|
||||
const agentStartHandler = createBeforeAgentStartHandler();
|
||||
const agentStartResult = agentStartHandler(
|
||||
{
|
||||
type: "before_agent_start",
|
||||
prompt: "Test prompt",
|
||||
systemPrompt: "Initial",
|
||||
systemPromptOptions: { cwd: "." },
|
||||
},
|
||||
mockCtx,
|
||||
);
|
||||
assert(agentStartResult !== undefined, "Agent start handler returns result");
|
||||
|
||||
// 6. Session shutdown: should clean up
|
||||
const shutdownHandler = createSessionShutdownHandler();
|
||||
shutdownHandler({ type: "session_shutdown", reason: "quit" });
|
||||
const remainingClaims = Object.values(registry.claims).filter(
|
||||
(c) => c.status === "active",
|
||||
);
|
||||
assert(remainingClaims.length === 0, "Shutdown releases all claims");
|
||||
|
||||
console.log("✅ Integration: full lifecycle test passes");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Test runner
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function runTests() {
|
||||
console.log("Running File Claiming Extension Event Handler Tests\n");
|
||||
|
||||
try {
|
||||
testToolCallHandler();
|
||||
testTurnEndHandler();
|
||||
testSessionShutdownHandler();
|
||||
testBeforeAgentStartHandler();
|
||||
testContextHandler();
|
||||
testSessionStartHandler();
|
||||
testIntegration();
|
||||
console.log("\n✅ All event handler tests passed!");
|
||||
} catch (err) {
|
||||
console.error(`\n❌ Test failed: ${err}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
runTests();
|
||||
Reference in New Issue
Block a user