update
This commit is contained in:
1 parent
2ab001b18a
commit
810e2d5967
28 files changed
+1015
-85
No files matched your search
@@ -66,14 +66,15 @@ async function createHarness() {
|
||||
workspaceId: null,
|
||||
connectorId: "openai-codex",
|
||||
});
|
||||
const logger = {
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
const bridge = new RuntimeBridge({
|
||||
db,
|
||||
emitEvent: vi.fn(),
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
},
|
||||
logger,
|
||||
credentialResolver: {
|
||||
resolve: vi.fn(async () => ({ apiKey: "test-api-key", extraEnv: {} })),
|
||||
} as unknown as CredentialResolver,
|
||||
@@ -105,6 +106,7 @@ async function createHarness() {
|
||||
agentId,
|
||||
taskId,
|
||||
runId: run.id,
|
||||
logger,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -143,4 +145,43 @@ describe("artifact projection durable ack", () => {
|
||||
harness.db.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("evicts deleted run contexts without writing artifact projection events", async () => {
|
||||
const harness = await createHarness();
|
||||
try {
|
||||
harness.db.core.company.deleteCompany(harness.companyId);
|
||||
|
||||
const result = harness.bridge.releaseRunResources(harness.runId);
|
||||
|
||||
expect(result).toEqual({ ok: true });
|
||||
} finally {
|
||||
harness.db.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects destructive tool hooks from deleted run contexts before approval lookup", async () => {
|
||||
const harness = await createHarness();
|
||||
try {
|
||||
harness.db.core.company.deleteCompany(harness.companyId);
|
||||
|
||||
const response = await harness.bridge.handleRpc({
|
||||
rpcId: "before-tool-call",
|
||||
method: "beforeToolCall",
|
||||
runId: harness.runId,
|
||||
payload: {
|
||||
toolName: "bash",
|
||||
toolCallId: "tool-1",
|
||||
args: {},
|
||||
},
|
||||
});
|
||||
|
||||
expect(response).toEqual({
|
||||
ok: false,
|
||||
error: expect.stringContaining("stale run"),
|
||||
});
|
||||
expect(harness.logger.error).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
harness.db.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -6,6 +6,7 @@ import { AppDatabase } from "../../src/main/database";
|
||||
import { createBudgetEnforcementService } from "../../src/main/budget-enforcement-service";
|
||||
import { createRunDispatch } from "../../src/main/orchestration/run-dispatch";
|
||||
import { createTaskRunner } from "../../src/main/orchestration/task-runner";
|
||||
import { resolveModels } from "../../src/main/model-resolver";
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
@@ -64,6 +65,93 @@ function createOrchestrationHarness(db: AppDatabase) {
|
||||
}
|
||||
|
||||
describe("connector model enforcement", () => {
|
||||
it("auto picker excludes disabled connector models before run eligibility validation", async () => {
|
||||
const profileDir = await createTempDir("agentcompany-auto-model-pool-");
|
||||
const db = new AppDatabase(profileDir);
|
||||
db.init();
|
||||
|
||||
db.core.connectors.updateConnectorHealth({
|
||||
id: "openai-codex",
|
||||
status: "ready",
|
||||
authState: "authenticated",
|
||||
version: "test",
|
||||
lastError: null,
|
||||
});
|
||||
db.core.connectors.updateConnectorHealth({
|
||||
id: "zai",
|
||||
status: "ready",
|
||||
authState: "authenticated",
|
||||
version: "test",
|
||||
lastError: null,
|
||||
});
|
||||
|
||||
const companyId = db.core.company.saveCompany({
|
||||
name: "Auto Model Pool Co",
|
||||
description: "Routes around disabled connector model pools",
|
||||
status: "active",
|
||||
});
|
||||
const workspaceId = db.core.workspaces.saveWorkspace({
|
||||
companyId,
|
||||
name: "Primary",
|
||||
localPath: profileDir,
|
||||
repoUrl: "",
|
||||
repoRef: "",
|
||||
isPrimary: true,
|
||||
});
|
||||
const ceoId = db.core.agents.saveAgent({
|
||||
companyId,
|
||||
name: "CEO",
|
||||
role: "CEO",
|
||||
title: "Chief Executive Officer",
|
||||
status: "idle",
|
||||
reportsTo: null,
|
||||
connectorId: "zai",
|
||||
workspaceId,
|
||||
model: "glm-5.1",
|
||||
capabilities: "Lead the company",
|
||||
budgetMonthlyUsd: 250,
|
||||
});
|
||||
const architectId = db.core.agents.saveAgent({
|
||||
companyId,
|
||||
name: "Architect",
|
||||
role: "Architect",
|
||||
title: "Principal Architect",
|
||||
status: "idle",
|
||||
reportsTo: ceoId,
|
||||
connectorId: "openai-codex",
|
||||
workspaceId,
|
||||
model: "gpt-5.4",
|
||||
modelStrategy: "auto",
|
||||
capabilities: "Plan technical architecture",
|
||||
budgetMonthlyUsd: 250,
|
||||
});
|
||||
const taskId = db.core.tasks.saveTask({
|
||||
companyId,
|
||||
title: "Plan architecture",
|
||||
description: "Needs a hard reasoning model.",
|
||||
assigneeAgentId: architectId,
|
||||
workspaceId,
|
||||
priority: "high",
|
||||
status: "todo",
|
||||
});
|
||||
|
||||
db.core.settings.setDisabledModels(
|
||||
companyId,
|
||||
"openai-codex",
|
||||
resolveModels("openai-codex").map((model) => ({ id: model.id, label: model.name })),
|
||||
);
|
||||
|
||||
const { deps, taskRunner } = createOrchestrationHarness(db);
|
||||
const result = taskRunner.queueTaskRun(taskId, "manual", "board");
|
||||
|
||||
expect(result.ok).toBe(true);
|
||||
expect(deps.enqueueWorkerRun).toHaveBeenCalledTimes(1);
|
||||
expect(deps.enqueueWorkerRun.mock.calls[0]?.[0]?.connectorId).toBe("zai");
|
||||
expect(deps.enqueueWorkerRun.mock.calls[0]?.[0]?.model).toMatch(/^glm-/);
|
||||
|
||||
db.close();
|
||||
});
|
||||
|
||||
it("blocks queueTaskRun when an agent keeps a disabled explicit model", async () => {
|
||||
const profileDir = await createTempDir("agentcompany-model-enforcement-");
|
||||
const db = new AppDatabase(profileDir);
|
||||
|
||||
@@ -200,7 +200,7 @@ describe("skill-aware capability registry", () => {
|
||||
})),
|
||||
companyWorkspaces: snapshot.workspaces
|
||||
.filter((workspace) => workspace.companyId === companyId)
|
||||
.map((workspace) => ({ name: workspace.name, localPath: workspace.localPath })),
|
||||
.map((workspace) => ({ id: workspace.id, name: workspace.name, localPath: workspace.localPath })),
|
||||
companyDocuments: [],
|
||||
skills: [
|
||||
{
|
||||
@@ -214,7 +214,7 @@ describe("skill-aware capability registry", () => {
|
||||
|
||||
expect(prompt).toContain("# Company Capability Registry");
|
||||
expect(prompt).toContain("React UI (`react-ui`)");
|
||||
expect(prompt).toContain("Primary:");
|
||||
expect(prompt).toMatch(/Primary \(`[0-9a-f-]+`\):/);
|
||||
expect(prompt).toContain("Ready Connectors");
|
||||
expect(prompt).toContain("<available_skills>");
|
||||
expect(prompt).toContain("<name>react-standards</name>");
|
||||
|
||||
Reference in new issue
Block a user