@h-rig/pi-rig 0.0.6-alpha.9 → 0.0.6-alpha.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,13 @@
1
1
  // @bun
2
2
  // packages/pi-rig/src/commands.ts
3
+ function runRecordFromPayload(payload) {
4
+ return payload.run && typeof payload.run === "object" && !Array.isArray(payload.run) ? payload.run : payload;
5
+ }
6
+ function formatEntry(entry) {
7
+ const type = String(entry.type ?? entry.title ?? "event");
8
+ const text = typeof entry.text === "string" ? entry.text : typeof entry.detail === "string" ? entry.detail : typeof entry.message === "string" ? entry.message : JSON.stringify(entry);
9
+ return `${type}: ${text}`;
10
+ }
3
11
  function createRigSlashCommands(input) {
4
12
  const notify = input.notify ?? (() => {});
5
13
  async function handleRig(args) {
@@ -28,18 +36,55 @@ function createRigSlashCommands(input) {
28
36
  }
29
37
  if (first === "attach") {
30
38
  const run = await input.client.attach(second);
31
- const runRecord = run.run && typeof run.run === "object" ? run.run : run;
39
+ const runRecord = runRecordFromPayload(run);
32
40
  notify(`Attached to ${String(runRecord.runId ?? second ?? input.context.runId ?? "run")}: ${String(runRecord.status ?? "unknown")}`, "info");
33
41
  return;
34
42
  }
35
- notify("Usage: /rig status | /rig task list | /rig task run [id] | /rig attach [run-id]", "error");
43
+ if (first === "timeline" || first === "logs") {
44
+ const runId = second || input.context.runId;
45
+ const entries = first === "timeline" ? await input.client.runTimeline(runId, 20) : await input.client.runLogs(runId, 20);
46
+ notify(entries.length > 0 ? entries.slice(-10).map(formatEntry).join(`
47
+ `) : `No ${first} entries for ${runId ?? "run"}.`, "info");
48
+ return;
49
+ }
50
+ if (first === "steer") {
51
+ const message = args.trim().slice("steer".length).trim();
52
+ if (!message) {
53
+ notify("Usage: /rig steer <message>", "error");
54
+ return;
55
+ }
56
+ await input.client.steer(message);
57
+ notify("Rig steering message queued.", "info");
58
+ return;
59
+ }
60
+ if (first === "stop") {
61
+ await input.client.stop(second || input.context.runId);
62
+ notify("Rig stop requested.", "info");
63
+ return;
64
+ }
65
+ if (first === "abort") {
66
+ await input.client.workerAbort(second || input.context.runId);
67
+ notify("Worker turn abort requested.", "info");
68
+ return;
69
+ }
70
+ if (first === "sh") {
71
+ const command = args.trim().slice("sh".length).trim();
72
+ if (!command) {
73
+ notify("Usage: /rig sh <command> \u2014 runs in the WORKER workspace", "error");
74
+ return;
75
+ }
76
+ await input.client.workerShell(command, input.context.runId);
77
+ notify("Shell command sent to the worker workspace.", "info");
78
+ return;
79
+ }
80
+ notify("Usage: /rig status | /rig task list | /rig task run [id] | /rig attach [run-id] | /rig timeline [run-id] | /rig logs [run-id] | /rig steer <message> | /rig stop [run-id] | /rig abort [run-id] | /rig sh <command>", "error");
36
81
  } catch (error) {
37
82
  notify(error instanceof Error ? error.message : String(error), "error");
38
83
  }
39
84
  }
40
85
  return {
41
86
  rig: {
42
- description: "Rig control-plane commands: status, task list, task run, attach",
87
+ description: "Rig control-plane commands: status, task list, task run, attach, timeline, logs, steer, stop",
43
88
  handler: handleRig
44
89
  }
45
90
  };
@@ -0,0 +1,59 @@
1
+ import { RigBridgeClient, type RigExtensionContext, type RigProtocolCheck, type RigWebSocketFactory } from "./client";
2
+ export type MinimalPiApi = {
3
+ registerCommand?: (name: string, command: {
4
+ description?: string;
5
+ handler: (args: string, ctx: unknown) => Promise<void>;
6
+ }) => void;
7
+ registerTool?: (tool: {
8
+ name: string;
9
+ } & Record<string, unknown>) => void;
10
+ on?: (eventName: string, handler: (event: unknown, ctx: unknown) => unknown) => void;
11
+ sendUserMessage?: (content: string, options?: {
12
+ deliverAs?: "steer" | "followUp" | "nextTurn";
13
+ triggerTurn?: boolean;
14
+ }) => void | Promise<void>;
15
+ /** Stock Pi custom-message injection: rendered in the transcript without
16
+ * triggering a turn. The operator console's live worker mirror rides this. */
17
+ sendMessage?: (message: {
18
+ customType: string;
19
+ content: string;
20
+ display?: boolean;
21
+ details?: unknown;
22
+ }, options?: {
23
+ triggerTurn?: boolean;
24
+ }) => void | Promise<void>;
25
+ /** Stock custom-message renderer registration: the live mirror renders
26
+ * worker turns through Pi's own components via this seam. */
27
+ registerMessageRenderer?: (customType: string, renderer: (message: unknown, options: {
28
+ expanded: boolean;
29
+ }, theme: unknown) => unknown) => void;
30
+ };
31
+ export type PiRigExtensionState = RigExtensionContext & {
32
+ readonly client: RigBridgeClient;
33
+ /** Test seam: lets the suite fake the push socket. Defaults to the global WebSocket. */
34
+ readonly webSocketFactory?: RigWebSocketFactory;
35
+ };
36
+ export declare function createPiRigExtensionState(input?: {
37
+ readonly env?: Record<string, string | undefined>;
38
+ readonly fetchImpl?: typeof fetch;
39
+ readonly webSocketFactory?: RigWebSocketFactory;
40
+ }): PiRigExtensionState;
41
+ export type PiRigBridgeGate = {
42
+ readonly allowed: boolean;
43
+ readonly message: string | null;
44
+ /** Handshake outcome: "compatible" means the server speaks this protocol
45
+ * version and therefore supports the WS push surface. */
46
+ readonly status: RigProtocolCheck["status"];
47
+ };
48
+ export type PiRigBridgeGateCheck = (ctx: unknown) => Promise<PiRigBridgeGate>;
49
+ /** Live refresh control handed to the operator widget by the WS bridge:
50
+ * while the socket is up, pushes (rig.event / snapshotInvalidated) drive the
51
+ * widget instead of the 1s status poll. */
52
+ export type OperatorLiveRefresh = {
53
+ isConnected(): boolean;
54
+ /** Returns true (and resets) when a push arrived since the last check. */
55
+ consumePushTrigger(): boolean;
56
+ };
57
+ export default function createPiRigExtension(pi: MinimalPiApi, options?: {
58
+ state?: PiRigExtensionState;
59
+ }): void;