refactor: make spike a standalone script

- Remove spike command from extension registration
- Add run-spike.sh wrapper script
- Add npm script 'spike' to run the PoC
- Spike can be run via: npm run spike or ./run-spike.sh
This commit is contained in:
jay 2026-05-15 03:44:13 +02:00
parent befb1fc98b
commit 4aab59947f
4 changed files with 41 additions and 36 deletions

View File

@ -24,7 +24,6 @@ import {
} from "./config.js";
import { type RawMessage, serializeMessage } from "./messages.js";
import { type RemoteServer, startServer } from "./server.js";
import { registerSpikeCommand } from "./spike.js";
// ── Extension entry point ────────────────────────────────────────────────────
@ -34,9 +33,6 @@ const QRCode = _require("qrcode") as {
};
export default function remoteControl(pi: ExtensionAPI) {
// Register spike command for Phase 0 PoC
registerSpikeCommand(pi);
let server: RemoteServer | undefined;
let pendingSyncTimer: ReturnType<typeof setTimeout> | undefined;

View File

@ -14,9 +14,8 @@
import * as fs from "node:fs";
import * as path from "node:path";
import * as os from "node:os";
import { spawn, execSync } from "node:child_process";
import { execSync } from "node:child_process";
import { WebSocketServer } from "ws";
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
const SPIKE_SESSION = "pi-spike";
const WS_PORT = 7799;
@ -113,23 +112,24 @@ function startWebSocketServer(fifoPath: string): { wss: WebSocketServer, cleanup
}
/**
* Attach to the tmux session in the current terminal
* Print instructions for connecting to the session
*/
function attachToSession(sessionName: string): void {
console.log(`[spike] Attaching to tmux session: ${sessionName}`);
console.log(`[spike] To detach: Ctrl+B, then D`);
console.log(`[spike] WebSocket available at: ws://127.0.0.1:${WS_PORT}/spike`);
function printInstructions(sessionName: string): void {
console.log("");
console.log("=== Spike Server Running ===");
console.log("");
console.log("To attach to the tmux session (in another terminal):");
console.log(` tmux attach -t ${sessionName}`);
console.log("");
console.log("WebSocket endpoint:");
console.log(` ws://127.0.0.1:${WS_PORT}/spike`);
console.log("");
console.log("To test with the HTML client:");
const clientPath = path.join(path.dirname(new URL(import.meta.url).pathname), "spike-client.html");
console.log(` open ${clientPath}`);
console.log("");
console.log("To stop: Ctrl+C in this terminal");
console.log("");
// Spawn tmux attach in the foreground
// This will take over the terminal until the user detaches
const attach = spawn("tmux", ["attach", "-t", sessionName], {
stdio: "inherit",
});
attach.on("exit", (code) => {
console.log(`\n[spike] Detached from session (exit code: ${code})`);
});
}
/**
@ -159,14 +159,15 @@ function cleanup(cleanupFn: (() => void) | null): void {
/**
* Main spike entry point
*/
export async function runSpike(_ctx: ExtensionContext): Promise<void> {
export async function runSpike(): Promise<void> {
console.log("=== Phase 0 Spike: tmux Stream PoC ===\n");
let cleanupFn: (() => void) | null = null;
// Setup cleanup handlers
process.on("SIGINT", () => cleanup(cleanupFn));
process.on("SIGTERM", () => cleanup(cleanupFn));
const cleanupHandler = () => cleanup(cleanupFn);
process.on("SIGINT", cleanupHandler);
process.on("SIGTERM", cleanupHandler);
try {
// Step 1: Create or reuse tmux session
@ -186,8 +187,12 @@ export async function runSpike(_ctx: ExtensionContext): Promise<void> {
// Give the server a moment to start
await new Promise(resolve => setTimeout(resolve, 500));
// Step 4: Attach to session
attachToSession(SPIKE_SESSION);
// Step 4: Print instructions
printInstructions(SPIKE_SESSION);
// Keep the process alive
// User can Ctrl+C to stop
await new Promise(() => {}); // Never resolves
} catch (err) {
console.error("[spike] Error:", err);
@ -195,14 +200,7 @@ export async function runSpike(_ctx: ExtensionContext): Promise<void> {
}
}
/**
* Register the spike command with pi
*/
export function registerSpikeCommand(pi: ExtensionAPI): void {
pi.registerCommand("spike", {
description: "Phase 0 Spike: Start tmux stream PoC (ws://127.0.0.1:7799/spike)",
handler: async (_args, ctx) => {
await runSpike(ctx);
},
});
// Run if invoked directly
if (import.meta.url === `file://${process.argv[1]}`) {
runSpike();
}

View File

@ -15,6 +15,7 @@
"@earendil-works/pi-tui": "*"
},
"scripts": {
"spike": "./run-spike.sh",
"lint": "biome check --write .",
"lint:check": "biome check .",
"prepare": "node .husky/install.mjs"

10
run-spike.sh Executable file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
# Phase 0 Spike runner
# Transpiles and runs the spike PoC
set -e
cd "$(dirname "$0")"
echo "=== Building spike.ts ==="
npx --yes tsx extensions/remote-control/spike.ts