feat(FN-1085): align agent routing and runtime contracts

- Harden core AgentStore lifecycle behavior and heartbeat runtime integration paths
- Align dashboard agent APIs, server routes, and agent UI flows with the updated contract
- Tighten CLI agent/message command routing and validate payload handling semantics
- Expand test coverage across core, dashboard, engine, and CLI for route, heartbeat, and instruction regressions
This commit is contained in:
gsxdsm
2026-04-08 00:44:33 -07:00
parent 92e6aa2b49
commit 07697b2f5b
19 changed files with 942 additions and 169 deletions

View File

@@ -22,6 +22,15 @@ const runNodeAdd = vi.fn();
const runNodeRemove = vi.fn();
const runNodeShow = vi.fn();
const runNodeHealth = vi.fn();
const runAgentStop = vi.fn();
const runAgentStart = vi.fn();
const runAgentMailbox = vi.fn();
const runAgentImport = vi.fn();
const runMessageInbox = vi.fn();
const runMessageOutbox = vi.fn();
const runMessageSend = vi.fn();
const runMessageRead = vi.fn();
const runMessageDelete = vi.fn();
vi.mock("../commands/dashboard.js", () => ({
runDashboard: vi.fn(),
@@ -94,6 +103,24 @@ vi.mock("../commands/node.js", () => ({
runNodeHealth,
}));
vi.mock("../commands/agent.js", () => ({
runAgentStop,
runAgentStart,
}));
vi.mock("../commands/agent-import.js", () => ({
runAgentImport,
}));
vi.mock("../commands/message.js", () => ({
runMessageInbox,
runMessageOutbox,
runMessageSend,
runMessageRead,
runMessageDelete,
runAgentMailbox,
}));
describe("bin", () => {
let logSpy: ReturnType<typeof vi.spyOn>;
let errorSpy: ReturnType<typeof vi.spyOn>;
@@ -173,6 +200,20 @@ describe("bin", () => {
expect(runGitFetch).toHaveBeenCalledWith("origin", "demo");
});
it("passes projectName through to agent import handler", async () => {
await runBin(["agent", "import", "./agents.sh", "--dry-run", "--skip-existing", "--project", "demo"]);
expect(runAgentImport).toHaveBeenCalledWith("./agents.sh", {
dryRun: true,
skipExisting: true,
project: "demo",
});
});
it("parses multi-word message send content and project flag", async () => {
await runBin(["message", "send", "agent-123", "Hello", "from", "CLI", "--project", "demo"]);
expect(runMessageSend).toHaveBeenCalledWith("agent-123", "Hello from CLI", "demo");
});
it("routes project subcommands and aliases", async () => {
await runBin(["project", "list"]);
await runBin(["project", "ls"]);

View File

@@ -864,7 +864,7 @@ async function main() {
}
case "send": {
const toId = args[2];
const content = args[3];
const content = args.slice(3).join(" ").trim();
if (!toId || !content) {
console.error("Usage: fn message send <agent-id> <content>");
process.exit(1);