feat(connect-local): add Pi extension for local agent bridge

Monorepo Pi package with outbound WebSocket, pairing/reconnect flow,
presence reporting, and single-flight task.dispatch handling.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Chengdong Zhang
2026-07-23 20:55:36 +08:00
commit 94721227c0
10 changed files with 575 additions and 0 deletions

42
src/credentialStore.ts Normal file
View File

@@ -0,0 +1,42 @@
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
import path from 'node:path';
export interface StoredReconnectCredential {
readonly projectName: string;
readonly credential: string;
readonly wsUrl: string;
readonly updatedAt: string;
}
export function credentialFilePath(baseDir: string): string {
return path.join(baseDir, 'local-agent-reconnect.json');
}
export async function loadReconnectCredential(baseDir: string): Promise<StoredReconnectCredential | undefined> {
try {
const raw = await readFile(credentialFilePath(baseDir), 'utf8');
const parsed = JSON.parse(raw) as StoredReconnectCredential;
if (!parsed?.projectName || !parsed?.credential || !parsed?.wsUrl) {
return undefined;
}
return parsed;
} catch {
return undefined;
}
}
export async function saveReconnectCredential(
baseDir: string,
value: StoredReconnectCredential,
): Promise<void> {
await mkdir(baseDir, { recursive: true });
await writeFile(credentialFilePath(baseDir), JSON.stringify(value, null, 2), 'utf8');
}
export async function clearReconnectCredential(baseDir: string): Promise<void> {
try {
await rm(credentialFilePath(baseDir));
} catch {
/* already absent */
}
}