The founder probes through provider cooldowns; a served request lifts the park

A single transient failure from a background run used to silence the whole
company — founder included — for the full ten-minute cooldown. The
interactive lane now claims one probe per park window: the founder's
message tries the provider immediately, a success lifts the cooldown for
everyone (a served request is proof of health), and a failed probe re-arms
the park with the probe spent, so a real outage is never hammered.
Autonomous work still waits cooldowns out unconditionally.
This commit is contained in:
ZacharyZhang-NY committed 2026-07-14 21:19:14 -04:00
1 parent 9246e7e312
commit 75c73ce6f0
3 files changed
+166 -4

No files matched your search

+127 -1
View File
@@ -10,7 +10,7 @@ import { ProviderService } from "../../src/main/services/provider-service";
import { providerAdapters } from "../../src/main/services/provider-adapters";
import { TaskExecutionService } from "../../src/main/services/task-execution-service";
import { dispatchAgentTool } from "../../src/main/services/agent-tools";
import { startTaskQueueWorker } from "../../src/main/app/task-queue-worker";
import { claimNextQueuedRun, startTaskQueueWorker } from "../../src/main/app/task-queue-worker";
import type { AgentTurnResult, ProviderToolTurnInput, ToolCall } from "../../src/main/services/provider-tool-turn";
const testVault = {
@@ -126,4 +126,130 @@ describe("interactive execution lane", () => {
connection.close();
}
});
test("a founder message probes through a provider cooldown and a served request lifts the park", async () => {
const connection = new DatabaseConnection(join(tmpdir(), `ac-probe-${randomUUID()}.db`));
const organization = new OrganizationService(connection.db);
let orgId = "";
let ceoId = "";
let providerId = "";
connection.transaction(() => {
orgId = organization.createOrganization({ organizationName: "OrbitOps", employeeName: "Yang", mission: "m", goal: "g" });
providerId = (connection.db.prepare("select id from providers where org_id = ? and provider_key = 'openai'").get(orgId) as { id: string }).id;
connection.db.prepare("update providers set enabled = 1 where id = ? and org_id = ?").run(providerId, orgId);
ceoId = organization.createAgent({
orgId, name: "CEO", role: "CEO", department: "Executive",
modelProviderId: providerId, modelId: "gpt-5.4", budgetCents: 25000, managerAgentId: null, roleLevel: "c_suite",
});
organization.createAgent({
orgId, name: "Dana", role: "Engineer", department: "Engineering",
modelProviderId: providerId, modelId: "gpt-5.4", budgetCents: 1000, managerAgentId: ceoId,
});
});
const employeeId = (connection.db.prepare("select id from employees where org_id = ?").get(orgId) as { id: string }).id;
const chat = new ChatService(connection.db);
let ceoReplied = false;
const script = async (input: ProviderToolTurnInput): Promise<AgentTurnResult> => {
const prompt = input.messages.find((message) => message.role === "user")?.text ?? "";
if (prompt.includes("Grind through the migration backlog")) {
throw new Error("The engine is currently overloaded, please try again later");
}
const threadId = /thread_id="([^"]+)"/.exec(prompt)?.[1];
if (prompt.includes("Are we blocked") && threadId && !ceoReplied) {
ceoReplied = true;
return turn("Answering.", [call("send_message", { to: "Yang", body: "Not blocked — one hiccup, already moving.", thread_id: threadId })]);
}
return turn("done");
};
const providers = new ProviderService(connection.db, providerAdapters, testVault, undefined, script);
providers.saveCredential({ orgId, providerId, secret: "sk-test-key", model: "gpt-5.4" });
const taskExecution = new TaskExecutionService(connection.db, providers);
// Autonomous work that will trip the transient failure and park the provider.
dispatchAgentTool({ db: connection.db, organization, chat }, {
orgId, agent: { id: ceoId, modelProviderId: null, modelId: null },
taskProjectId: null, taskGoalId: null, workspace: null,
}, call("send_message", { to: "Dana", body: "Grind through the migration backlog." }));
const stopWorker = startTaskQueueWorker({
connection,
mainWindow: { isDestroyed: () => true } as unknown as BrowserWindow,
intervalMs: 25,
taskExecution,
});
try {
await vi.waitFor(() => {
expect(taskExecution.cooledProviderIds()).toEqual([providerId]);
}, { timeout: 3000, interval: 25 });
// The founder speaks INTO the cooldown; the interactive lane probes through.
const spaceId = chat.ensureDirectSpace(orgId, { type: "employee", id: employeeId }, { type: "agent", id: ceoId });
chat.sendMessage({
orgId, spaceId, threadId: null, senderType: "employee", senderId: employeeId,
bodyMd: "Are we blocked on anything?", attachmentFileIds: [],
});
await vi.waitFor(() => {
const reply = connection.db.prepare(
"select id from chat_messages where org_id = ? and sender_type = 'agent' and sender_id = ? and space_id = ?",
).get(orgId, ceoId, spaceId);
expect(reply).toBeTruthy();
}, { timeout: 3000, interval: 25 });
// The served probe is proof of health: the park lifted for everyone.
expect(taskExecution.cooledProviderIds()).toEqual([]);
} finally {
stopWorker();
connection.close();
}
});
test("a spent probe blocks further interactive claims until the window expires", async () => {
const connection = new DatabaseConnection(join(tmpdir(), `ac-probe-spent-${randomUUID()}.db`));
const organization = new OrganizationService(connection.db);
let orgId = "";
let ceoId = "";
let providerId = "";
connection.transaction(() => {
orgId = organization.createOrganization({ organizationName: "OrbitOps", employeeName: "Yang", mission: "m", goal: "g" });
providerId = (connection.db.prepare("select id from providers where org_id = ? and provider_key = 'openai'").get(orgId) as { id: string }).id;
connection.db.prepare("update providers set enabled = 1 where id = ? and org_id = ?").run(providerId, orgId);
ceoId = organization.createAgent({
orgId, name: "CEO", role: "CEO", department: "Executive",
modelProviderId: providerId, modelId: "gpt-5.4", budgetCents: 25000, managerAgentId: null, roleLevel: "c_suite",
});
organization.createAgent({
orgId, name: "Dana", role: "Engineer", department: "Engineering",
modelProviderId: providerId, modelId: "gpt-5.4", budgetCents: 1000, managerAgentId: ceoId,
});
});
const chat = new ChatService(connection.db);
const alwaysOverloaded = async (): Promise<AgentTurnResult> => {
throw new Error("The engine is currently overloaded, please try again later");
};
const providers = new ProviderService(connection.db, providerAdapters, testVault, undefined, alwaysOverloaded);
providers.saveCredential({ orgId, providerId, secret: "sk-test-key", model: "gpt-5.4" });
const taskExecution = new TaskExecutionService(connection.db, providers);
const wakeDana = () => dispatchAgentTool({ db: connection.db, organization, chat }, {
orgId, agent: { id: ceoId, modelProviderId: null, modelId: null },
taskProjectId: null, taskGoalId: null, workspace: null,
}, call("send_message", { to: "Dana", body: "Grind through the migration backlog." }));
wakeDana();
const first = claimNextQueuedRun(connection)!;
await taskExecution.executeRun(first.org_id, first.id).catch(() => {});
expect(taskExecution.cooledProviderIds()).toEqual([providerId]);
// The park window opens with one probe available to the interactive lane.
expect(taskExecution.interactiveCooledProviderIds()).toEqual([]);
taskExecution.noteInteractiveProbe(providerId);
expect(taskExecution.interactiveCooledProviderIds()).toEqual([providerId]);
// A failed probe re-arms the park WITHOUT restoring the probe: no hammering.
wakeDana();
const second = claimNextQueuedRun(connection)!;
await taskExecution.executeRun(second.org_id, second.id).catch(() => {});
expect(taskExecution.interactiveCooledProviderIds()).toEqual([providerId]);
connection.close();
});
});