feat(bridge): establish local pi status bridge

Deliver the initial local bridge, Noctalia v4/v5 adapters, desktop client, service unit, tests, and implementation documentation for persistent Pi status and control.
This commit is contained in:
2026-07-27 14:51:45 +02:00
commit b7fea83ed6
91 changed files with 15029 additions and 0 deletions
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env node
import { connectLocalClient } from "./local-client.js";
import { publishNoctaliaState } from "./noctalia-ipc.js";
import { createNoctaliaStateRelay } from "./noctalia-relay.js";
function flag(args, name) {
const index = args.indexOf(name);
return index >= 0 ? args[index + 1] : undefined;
}
async function run() {
const args = process.argv.slice(2);
const socketPath =
flag(args, "--socket") ?? process.env.PI_STATUS_BRIDGE_SOCKET;
const agentId = flag(args, "--agent");
if (!socketPath || !agentId)
throw new Error(
"Usage: pi-status-bridge-noctalia-relay --socket <path> --agent <id>",
);
const client = await connectLocalClient({ socketPath });
const agents = await client.request("list_agents");
const agent = agents.agents.find((candidate) => candidate.id === agentId);
if (!agent) throw new Error(`unknown agent: ${agentId}`);
const relay = createNoctaliaStateRelay({
client,
agent,
onState: (state) => {
void publishNoctaliaState(state).catch((error) =>
process.stderr.write(`${error.message}\n`),
);
},
});
await relay.start();
await new Promise((resolve) => {
const shutdown = () => resolve();
process.once("SIGINT", shutdown);
process.once("SIGTERM", shutdown);
});
relay.stop();
await client.close();
}
run().catch((error) => {
process.stderr.write(
`${error instanceof Error ? error.message : "Noctalia relay failed"}\n`,
);
process.exitCode = 1;
});