@h-rig/cli 0.0.6-alpha.23 → 0.0.6-alpha.24
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.
- package/dist/bin/rig.js +144 -28
- package/dist/src/commands/_operator-view.js +145 -29
- package/dist/src/commands/_pi-frontend.js +145 -29
- package/dist/src/commands/_pi-worker-bridge-extension.js +145 -29
- package/dist/src/commands/run.js +145 -29
- package/dist/src/commands/task.js +145 -29
- package/dist/src/commands.js +144 -28
- package/dist/src/index.js +144 -28
- package/package.json +6 -6
package/dist/src/commands.js
CHANGED
|
@@ -6496,6 +6496,15 @@ function appendTranscript(state, label, text2) {
|
|
|
6496
6496
|
state.transcript.splice(0, state.transcript.length - MAX_TRANSCRIPT_LINES);
|
|
6497
6497
|
}
|
|
6498
6498
|
}
|
|
6499
|
+
function nativePiUi(ctx) {
|
|
6500
|
+
const ui = ctx.ui;
|
|
6501
|
+
return typeof ui.emitSessionEvent === "function" && typeof ui.appendSessionMessages === "function" ? ui : null;
|
|
6502
|
+
}
|
|
6503
|
+
function syncNativeDisplayCwd(ctx, state) {
|
|
6504
|
+
const ui = nativePiUi(ctx);
|
|
6505
|
+
if (ui?.setDisplayCwd && state.cwd)
|
|
6506
|
+
ui.setDisplayCwd(state.cwd);
|
|
6507
|
+
}
|
|
6499
6508
|
function parseExtensionUiRequest(value) {
|
|
6500
6509
|
const request = recordOf(value) ?? {};
|
|
6501
6510
|
const requestId = String(request.requestId ?? request.id ?? `ui-${Date.now()}`);
|
|
@@ -6539,8 +6548,13 @@ function renderBridgeWidget(state) {
|
|
|
6539
6548
|
function updatePiUi(ctx, state) {
|
|
6540
6549
|
ctx.ui.setTitle("Pi \xB7 Rig worker daemon");
|
|
6541
6550
|
ctx.ui.setStatus("rig-worker-pi", state.wsConnected ? "worker Pi WS live" : state.status);
|
|
6551
|
+
syncNativeDisplayCwd(ctx, state);
|
|
6552
|
+
if (state.nativeStream && nativePiUi(ctx)) {
|
|
6553
|
+
ctx.ui.setWidget("rig-worker-pi-transcript", undefined);
|
|
6554
|
+
return;
|
|
6555
|
+
}
|
|
6542
6556
|
ctx.ui.setWorkingVisible(false);
|
|
6543
|
-
ctx.ui.setWidget("rig-worker-pi-transcript", renderBridgeWidget(state), { placement: "aboveEditor" });
|
|
6557
|
+
ctx.ui.setWidget("rig-worker-pi-transcript", [`Worker Pi daemon bridge \xB7 degraded widget transcript`, ...renderBridgeWidget(state)], { placement: "aboveEditor" });
|
|
6544
6558
|
}
|
|
6545
6559
|
function applyStatus(state, payload) {
|
|
6546
6560
|
const status = recordOf(payload.status) ?? payload;
|
|
@@ -6558,7 +6572,7 @@ function applyMessage(state, message2) {
|
|
|
6558
6572
|
const label = role === "assistant" ? "Pi" : role === "user" ? "You" : role === "tool" || role === "toolResult" ? "Tool" : "System";
|
|
6559
6573
|
appendTranscript(state, label, textFromContent(record.content ?? record.message ?? record.text ?? ""));
|
|
6560
6574
|
}
|
|
6561
|
-
function applyPiEvent(state, eventValue) {
|
|
6575
|
+
function applyPiEvent(ctx, state, eventValue) {
|
|
6562
6576
|
const event = recordOf(eventValue);
|
|
6563
6577
|
if (!event)
|
|
6564
6578
|
return;
|
|
@@ -6566,11 +6580,20 @@ function applyPiEvent(state, eventValue) {
|
|
|
6566
6580
|
if (type === "agent_start") {
|
|
6567
6581
|
state.streaming = true;
|
|
6568
6582
|
state.status = "streaming";
|
|
6583
|
+
} else if (type === "agent_end") {
|
|
6584
|
+
state.streaming = false;
|
|
6585
|
+
state.status = "idle";
|
|
6586
|
+
} else if (type === "queue_update") {
|
|
6587
|
+
const steering = Array.isArray(event.steering) ? event.steering.length : 0;
|
|
6588
|
+
const followUp = Array.isArray(event.followUp) ? event.followUp.length : 0;
|
|
6589
|
+
state.status = `queued \xB7 steer ${steering} \xB7 follow-up ${followUp}`;
|
|
6590
|
+
}
|
|
6591
|
+
const native = nativePiUi(ctx);
|
|
6592
|
+
if (state.nativeStream && native?.emitSessionEvent) {
|
|
6593
|
+
native.emitSessionEvent(eventValue);
|
|
6569
6594
|
return;
|
|
6570
6595
|
}
|
|
6571
6596
|
if (type === "agent_end") {
|
|
6572
|
-
state.streaming = false;
|
|
6573
|
-
state.status = "idle";
|
|
6574
6597
|
appendTranscript(state, "System", "Agent turn complete.");
|
|
6575
6598
|
return;
|
|
6576
6599
|
}
|
|
@@ -6595,29 +6618,60 @@ function applyPiEvent(state, eventValue) {
|
|
|
6595
6618
|
}
|
|
6596
6619
|
if (type === "tool_execution_end") {
|
|
6597
6620
|
appendTranscript(state, event.isError === true ? "Error" : "Tool", asText(event.result ?? `${String(event.toolName ?? "tool")} complete`));
|
|
6598
|
-
return;
|
|
6599
|
-
}
|
|
6600
|
-
if (type === "queue_update") {
|
|
6601
|
-
const steering = Array.isArray(event.steering) ? event.steering.length : 0;
|
|
6602
|
-
const followUp = Array.isArray(event.followUp) ? event.followUp.length : 0;
|
|
6603
|
-
state.status = `queued \xB7 steer ${steering} \xB7 follow-up ${followUp}`;
|
|
6604
6621
|
}
|
|
6605
6622
|
}
|
|
6623
|
+
function firstPendingShell(state) {
|
|
6624
|
+
return state.pendingShells[0];
|
|
6625
|
+
}
|
|
6626
|
+
function finishPendingShell(state, shell, result) {
|
|
6627
|
+
const index = state.pendingShells.indexOf(shell);
|
|
6628
|
+
if (index !== -1)
|
|
6629
|
+
state.pendingShells.splice(index, 1);
|
|
6630
|
+
shell.resolve(result);
|
|
6631
|
+
}
|
|
6632
|
+
function failPendingShell(state, shell, error) {
|
|
6633
|
+
const index = state.pendingShells.indexOf(shell);
|
|
6634
|
+
if (index !== -1)
|
|
6635
|
+
state.pendingShells.splice(index, 1);
|
|
6636
|
+
shell.reject(error);
|
|
6637
|
+
}
|
|
6606
6638
|
function applyUiEvent(state, value) {
|
|
6607
6639
|
const event = recordOf(value);
|
|
6608
6640
|
if (!event)
|
|
6609
6641
|
return;
|
|
6610
6642
|
const type = String(event.type ?? "ui");
|
|
6611
|
-
if (type === "shell.
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6643
|
+
if (type === "shell.chunk") {
|
|
6644
|
+
const pending = firstPendingShell(state);
|
|
6645
|
+
const chunk = asText(event.chunk);
|
|
6646
|
+
if (pending) {
|
|
6647
|
+
pending.sawChunk = true;
|
|
6648
|
+
pending.onData(Buffer.from(chunk));
|
|
6649
|
+
} else {
|
|
6650
|
+
appendTranscript(state, "Tool", chunk);
|
|
6651
|
+
}
|
|
6652
|
+
return;
|
|
6653
|
+
}
|
|
6654
|
+
if (type === "shell.end") {
|
|
6655
|
+
const pending = firstPendingShell(state);
|
|
6656
|
+
const output = asText(event.output ?? "");
|
|
6657
|
+
const exitCode = typeof event.exitCode === "number" ? event.exitCode : event.isError === true ? 1 : 0;
|
|
6658
|
+
if (pending) {
|
|
6659
|
+
if (output && !pending.sawChunk)
|
|
6660
|
+
pending.onData(Buffer.from(output));
|
|
6661
|
+
finishPendingShell(state, pending, { exitCode });
|
|
6662
|
+
} else {
|
|
6663
|
+
appendTranscript(state, event.isError === true ? "Error" : "Tool", output || `exit ${String(exitCode)}`);
|
|
6664
|
+
}
|
|
6665
|
+
return;
|
|
6666
|
+
}
|
|
6667
|
+
if (type === "shell.start") {
|
|
6668
|
+
if (!firstPendingShell(state))
|
|
6669
|
+
appendTranscript(state, "Tool", `$ ${asText(event.command)}`);
|
|
6670
|
+
return;
|
|
6671
|
+
}
|
|
6672
|
+
appendTranscript(state, "System", `${type}: ${asText(event)}`);
|
|
6619
6673
|
}
|
|
6620
|
-
function applyEnvelope(state, envelopeValue) {
|
|
6674
|
+
function applyEnvelope(ctx, state, envelopeValue) {
|
|
6621
6675
|
const envelope = recordOf(envelopeValue);
|
|
6622
6676
|
if (!envelope)
|
|
6623
6677
|
return;
|
|
@@ -6626,7 +6680,8 @@ function applyEnvelope(state, envelopeValue) {
|
|
|
6626
6680
|
const metadata = recordOf(envelope.metadata);
|
|
6627
6681
|
state.cwd = typeof metadata?.cwd === "string" ? metadata.cwd : state.cwd;
|
|
6628
6682
|
state.status = "worker Pi daemon ready";
|
|
6629
|
-
|
|
6683
|
+
if (!state.nativeStream)
|
|
6684
|
+
appendTranscript(state, "System", "Connected to worker Pi daemon.");
|
|
6630
6685
|
} else if (type === "status.update") {
|
|
6631
6686
|
applyStatus(state, envelope);
|
|
6632
6687
|
} else if (type === "activity.update") {
|
|
@@ -6638,10 +6693,11 @@ function applyEnvelope(state, envelopeValue) {
|
|
|
6638
6693
|
} else if (type === "pi.ui_event") {
|
|
6639
6694
|
applyUiEvent(state, envelope.event);
|
|
6640
6695
|
} else if (type === "pi.event") {
|
|
6641
|
-
applyPiEvent(state, envelope.event);
|
|
6696
|
+
applyPiEvent(ctx, state, envelope.event);
|
|
6642
6697
|
} else if (type === "error") {
|
|
6643
6698
|
appendTranscript(state, "Error", asText(envelope.message ?? envelope.detail ?? "unknown error"));
|
|
6644
6699
|
}
|
|
6700
|
+
syncNativeDisplayCwd(ctx, state);
|
|
6645
6701
|
}
|
|
6646
6702
|
async function waitForWorkerReady(options, ctx, state) {
|
|
6647
6703
|
while (true) {
|
|
@@ -6662,7 +6718,7 @@ async function waitForWorkerReady(options, ctx, state) {
|
|
|
6662
6718
|
continue;
|
|
6663
6719
|
}
|
|
6664
6720
|
const sessionRecord = recordOf(session) ?? {};
|
|
6665
|
-
applyEnvelope(state, { type: "ready", metadata: sessionRecord.metadata ?? sessionRecord });
|
|
6721
|
+
applyEnvelope(ctx, state, { type: "ready", metadata: sessionRecord.metadata ?? sessionRecord });
|
|
6666
6722
|
updatePiUi(ctx, state);
|
|
6667
6723
|
return true;
|
|
6668
6724
|
}
|
|
@@ -6692,7 +6748,7 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
6692
6748
|
if (!catchupDone)
|
|
6693
6749
|
buffered.push(payload);
|
|
6694
6750
|
else {
|
|
6695
|
-
applyEnvelope(state, payload);
|
|
6751
|
+
applyEnvelope(ctx, state, payload);
|
|
6696
6752
|
updatePiUi(ctx, state);
|
|
6697
6753
|
}
|
|
6698
6754
|
} catch (error) {
|
|
@@ -6715,8 +6771,12 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
6715
6771
|
getRunPiCommandsViaServer(options.context, options.runId)
|
|
6716
6772
|
]);
|
|
6717
6773
|
const messages = Array.isArray(messagesPayload.messages) ? messagesPayload.messages : [];
|
|
6718
|
-
|
|
6719
|
-
|
|
6774
|
+
const native = nativePiUi(ctx);
|
|
6775
|
+
if (state.nativeStream && native?.appendSessionMessages)
|
|
6776
|
+
native.appendSessionMessages(messages);
|
|
6777
|
+
else
|
|
6778
|
+
for (const message2 of messages)
|
|
6779
|
+
applyMessage(state, message2);
|
|
6720
6780
|
applyStatus(state, statusPayload);
|
|
6721
6781
|
const commands = Array.isArray(commandsPayload.commands) ? commandsPayload.commands : [];
|
|
6722
6782
|
state.commands = commands.flatMap((command) => {
|
|
@@ -6725,7 +6785,7 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
6725
6785
|
});
|
|
6726
6786
|
catchupDone = true;
|
|
6727
6787
|
for (const payload of buffered.splice(0))
|
|
6728
|
-
applyEnvelope(state, payload);
|
|
6788
|
+
applyEnvelope(ctx, state, payload);
|
|
6729
6789
|
updatePiUi(ctx, state);
|
|
6730
6790
|
} catch (error) {
|
|
6731
6791
|
appendTranscript(state, "Error", `Worker Pi catch-up failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -6734,6 +6794,51 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
6734
6794
|
}
|
|
6735
6795
|
await closePromise;
|
|
6736
6796
|
}
|
|
6797
|
+
function createRemoteBashOperations(options, state, excludeFromContext) {
|
|
6798
|
+
return {
|
|
6799
|
+
exec(command, _cwd, execOptions) {
|
|
6800
|
+
return new Promise((resolve19, reject) => {
|
|
6801
|
+
const pending = {
|
|
6802
|
+
command,
|
|
6803
|
+
onData: execOptions.onData,
|
|
6804
|
+
resolve: resolve19,
|
|
6805
|
+
reject,
|
|
6806
|
+
sawChunk: false
|
|
6807
|
+
};
|
|
6808
|
+
const cleanup = () => {
|
|
6809
|
+
execOptions.signal?.removeEventListener("abort", onAbort);
|
|
6810
|
+
if (timer)
|
|
6811
|
+
clearTimeout(timer);
|
|
6812
|
+
};
|
|
6813
|
+
const onAbort = () => {
|
|
6814
|
+
cleanup();
|
|
6815
|
+
failPendingShell(state, pending, new Error("Remote worker shell command aborted locally."));
|
|
6816
|
+
};
|
|
6817
|
+
const timeoutMs = typeof execOptions.timeout === "number" && execOptions.timeout > 0 ? execOptions.timeout : 0;
|
|
6818
|
+
const timer = timeoutMs > 0 ? setTimeout(() => {
|
|
6819
|
+
cleanup();
|
|
6820
|
+
failPendingShell(state, pending, new Error(`Remote worker shell command timed out after ${timeoutMs}ms.`));
|
|
6821
|
+
}, timeoutMs) : null;
|
|
6822
|
+
const wrappedResolve = pending.resolve;
|
|
6823
|
+
const wrappedReject = pending.reject;
|
|
6824
|
+
pending.resolve = (result) => {
|
|
6825
|
+
cleanup();
|
|
6826
|
+
wrappedResolve(result);
|
|
6827
|
+
};
|
|
6828
|
+
pending.reject = (error) => {
|
|
6829
|
+
cleanup();
|
|
6830
|
+
wrappedReject(error);
|
|
6831
|
+
};
|
|
6832
|
+
execOptions.signal?.addEventListener("abort", onAbort, { once: true });
|
|
6833
|
+
state.pendingShells.push(pending);
|
|
6834
|
+
sendRunPiShellViaServer(options.context, options.runId, `${excludeFromContext ? "!!" : "!"}${command}`).catch((error) => {
|
|
6835
|
+
cleanup();
|
|
6836
|
+
failPendingShell(state, pending, error instanceof Error ? error : new Error(String(error)));
|
|
6837
|
+
});
|
|
6838
|
+
});
|
|
6839
|
+
}
|
|
6840
|
+
};
|
|
6841
|
+
}
|
|
6737
6842
|
async function answerPendingUi(options, state, line) {
|
|
6738
6843
|
const pending = state.pendingUi;
|
|
6739
6844
|
if (!pending)
|
|
@@ -6799,13 +6904,22 @@ function createRigWorkerPiBridgeExtension(options) {
|
|
|
6799
6904
|
commands: [],
|
|
6800
6905
|
streaming: false,
|
|
6801
6906
|
pendingUi: null,
|
|
6802
|
-
|
|
6907
|
+
pendingShells: [],
|
|
6908
|
+
wsConnected: false,
|
|
6909
|
+
nativeStream: false
|
|
6803
6910
|
};
|
|
6804
6911
|
if (options.initialMessageSent)
|
|
6805
6912
|
appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
|
|
6913
|
+
let nativePiUiContextAvailable = false;
|
|
6914
|
+
pi.on("user_bash", (event) => {
|
|
6915
|
+
state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
|
|
6916
|
+
return { operations: createRemoteBashOperations(options, state, event.excludeFromContext === true) };
|
|
6917
|
+
});
|
|
6806
6918
|
pi.on("session_start", async (_event, ctx) => {
|
|
6919
|
+
nativePiUiContextAvailable = Boolean(nativePiUi(ctx));
|
|
6920
|
+
state.nativeStream = nativePiUiContextAvailable;
|
|
6807
6921
|
updatePiUi(ctx, state);
|
|
6808
|
-
ctx.ui.notify("Rig worker Pi bridge extension loaded", "info");
|
|
6922
|
+
ctx.ui.notify(nativePiUiContextAvailable ? "Rig worker Pi native stream bridge loaded" : "Rig worker Pi bridge extension loaded (degraded widget fallback)", "info");
|
|
6809
6923
|
ctx.ui.onTerminalInput((data) => {
|
|
6810
6924
|
if (data.includes("\x04")) {
|
|
6811
6925
|
ctx.shutdown();
|
|
@@ -6819,6 +6933,8 @@ function createRigWorkerPiBridgeExtension(options) {
|
|
|
6819
6933
|
const text2 = [editorText, inlineText].filter(Boolean).join(" ").trim();
|
|
6820
6934
|
if (!text2)
|
|
6821
6935
|
return;
|
|
6936
|
+
if (text2.startsWith("!"))
|
|
6937
|
+
return;
|
|
6822
6938
|
ctx.ui.setEditorText("");
|
|
6823
6939
|
routeInput(options, ctx, state, text2).catch((error) => {
|
|
6824
6940
|
appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
|
package/dist/src/index.js
CHANGED
|
@@ -6699,6 +6699,15 @@ function appendTranscript(state, label, text2) {
|
|
|
6699
6699
|
state.transcript.splice(0, state.transcript.length - MAX_TRANSCRIPT_LINES);
|
|
6700
6700
|
}
|
|
6701
6701
|
}
|
|
6702
|
+
function nativePiUi(ctx) {
|
|
6703
|
+
const ui = ctx.ui;
|
|
6704
|
+
return typeof ui.emitSessionEvent === "function" && typeof ui.appendSessionMessages === "function" ? ui : null;
|
|
6705
|
+
}
|
|
6706
|
+
function syncNativeDisplayCwd(ctx, state) {
|
|
6707
|
+
const ui = nativePiUi(ctx);
|
|
6708
|
+
if (ui?.setDisplayCwd && state.cwd)
|
|
6709
|
+
ui.setDisplayCwd(state.cwd);
|
|
6710
|
+
}
|
|
6702
6711
|
function parseExtensionUiRequest(value) {
|
|
6703
6712
|
const request = recordOf(value) ?? {};
|
|
6704
6713
|
const requestId = String(request.requestId ?? request.id ?? `ui-${Date.now()}`);
|
|
@@ -6742,8 +6751,13 @@ function renderBridgeWidget(state) {
|
|
|
6742
6751
|
function updatePiUi(ctx, state) {
|
|
6743
6752
|
ctx.ui.setTitle("Pi \xB7 Rig worker daemon");
|
|
6744
6753
|
ctx.ui.setStatus("rig-worker-pi", state.wsConnected ? "worker Pi WS live" : state.status);
|
|
6754
|
+
syncNativeDisplayCwd(ctx, state);
|
|
6755
|
+
if (state.nativeStream && nativePiUi(ctx)) {
|
|
6756
|
+
ctx.ui.setWidget("rig-worker-pi-transcript", undefined);
|
|
6757
|
+
return;
|
|
6758
|
+
}
|
|
6745
6759
|
ctx.ui.setWorkingVisible(false);
|
|
6746
|
-
ctx.ui.setWidget("rig-worker-pi-transcript", renderBridgeWidget(state), { placement: "aboveEditor" });
|
|
6760
|
+
ctx.ui.setWidget("rig-worker-pi-transcript", [`Worker Pi daemon bridge \xB7 degraded widget transcript`, ...renderBridgeWidget(state)], { placement: "aboveEditor" });
|
|
6747
6761
|
}
|
|
6748
6762
|
function applyStatus(state, payload) {
|
|
6749
6763
|
const status = recordOf(payload.status) ?? payload;
|
|
@@ -6761,7 +6775,7 @@ function applyMessage(state, message2) {
|
|
|
6761
6775
|
const label = role === "assistant" ? "Pi" : role === "user" ? "You" : role === "tool" || role === "toolResult" ? "Tool" : "System";
|
|
6762
6776
|
appendTranscript(state, label, textFromContent(record.content ?? record.message ?? record.text ?? ""));
|
|
6763
6777
|
}
|
|
6764
|
-
function applyPiEvent(state, eventValue) {
|
|
6778
|
+
function applyPiEvent(ctx, state, eventValue) {
|
|
6765
6779
|
const event = recordOf(eventValue);
|
|
6766
6780
|
if (!event)
|
|
6767
6781
|
return;
|
|
@@ -6769,11 +6783,20 @@ function applyPiEvent(state, eventValue) {
|
|
|
6769
6783
|
if (type === "agent_start") {
|
|
6770
6784
|
state.streaming = true;
|
|
6771
6785
|
state.status = "streaming";
|
|
6786
|
+
} else if (type === "agent_end") {
|
|
6787
|
+
state.streaming = false;
|
|
6788
|
+
state.status = "idle";
|
|
6789
|
+
} else if (type === "queue_update") {
|
|
6790
|
+
const steering = Array.isArray(event.steering) ? event.steering.length : 0;
|
|
6791
|
+
const followUp = Array.isArray(event.followUp) ? event.followUp.length : 0;
|
|
6792
|
+
state.status = `queued \xB7 steer ${steering} \xB7 follow-up ${followUp}`;
|
|
6793
|
+
}
|
|
6794
|
+
const native = nativePiUi(ctx);
|
|
6795
|
+
if (state.nativeStream && native?.emitSessionEvent) {
|
|
6796
|
+
native.emitSessionEvent(eventValue);
|
|
6772
6797
|
return;
|
|
6773
6798
|
}
|
|
6774
6799
|
if (type === "agent_end") {
|
|
6775
|
-
state.streaming = false;
|
|
6776
|
-
state.status = "idle";
|
|
6777
6800
|
appendTranscript(state, "System", "Agent turn complete.");
|
|
6778
6801
|
return;
|
|
6779
6802
|
}
|
|
@@ -6798,29 +6821,60 @@ function applyPiEvent(state, eventValue) {
|
|
|
6798
6821
|
}
|
|
6799
6822
|
if (type === "tool_execution_end") {
|
|
6800
6823
|
appendTranscript(state, event.isError === true ? "Error" : "Tool", asText(event.result ?? `${String(event.toolName ?? "tool")} complete`));
|
|
6801
|
-
return;
|
|
6802
|
-
}
|
|
6803
|
-
if (type === "queue_update") {
|
|
6804
|
-
const steering = Array.isArray(event.steering) ? event.steering.length : 0;
|
|
6805
|
-
const followUp = Array.isArray(event.followUp) ? event.followUp.length : 0;
|
|
6806
|
-
state.status = `queued \xB7 steer ${steering} \xB7 follow-up ${followUp}`;
|
|
6807
6824
|
}
|
|
6808
6825
|
}
|
|
6826
|
+
function firstPendingShell(state) {
|
|
6827
|
+
return state.pendingShells[0];
|
|
6828
|
+
}
|
|
6829
|
+
function finishPendingShell(state, shell, result) {
|
|
6830
|
+
const index = state.pendingShells.indexOf(shell);
|
|
6831
|
+
if (index !== -1)
|
|
6832
|
+
state.pendingShells.splice(index, 1);
|
|
6833
|
+
shell.resolve(result);
|
|
6834
|
+
}
|
|
6835
|
+
function failPendingShell(state, shell, error) {
|
|
6836
|
+
const index = state.pendingShells.indexOf(shell);
|
|
6837
|
+
if (index !== -1)
|
|
6838
|
+
state.pendingShells.splice(index, 1);
|
|
6839
|
+
shell.reject(error);
|
|
6840
|
+
}
|
|
6809
6841
|
function applyUiEvent(state, value) {
|
|
6810
6842
|
const event = recordOf(value);
|
|
6811
6843
|
if (!event)
|
|
6812
6844
|
return;
|
|
6813
6845
|
const type = String(event.type ?? "ui");
|
|
6814
|
-
if (type === "shell.
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6846
|
+
if (type === "shell.chunk") {
|
|
6847
|
+
const pending = firstPendingShell(state);
|
|
6848
|
+
const chunk = asText(event.chunk);
|
|
6849
|
+
if (pending) {
|
|
6850
|
+
pending.sawChunk = true;
|
|
6851
|
+
pending.onData(Buffer.from(chunk));
|
|
6852
|
+
} else {
|
|
6853
|
+
appendTranscript(state, "Tool", chunk);
|
|
6854
|
+
}
|
|
6855
|
+
return;
|
|
6856
|
+
}
|
|
6857
|
+
if (type === "shell.end") {
|
|
6858
|
+
const pending = firstPendingShell(state);
|
|
6859
|
+
const output = asText(event.output ?? "");
|
|
6860
|
+
const exitCode = typeof event.exitCode === "number" ? event.exitCode : event.isError === true ? 1 : 0;
|
|
6861
|
+
if (pending) {
|
|
6862
|
+
if (output && !pending.sawChunk)
|
|
6863
|
+
pending.onData(Buffer.from(output));
|
|
6864
|
+
finishPendingShell(state, pending, { exitCode });
|
|
6865
|
+
} else {
|
|
6866
|
+
appendTranscript(state, event.isError === true ? "Error" : "Tool", output || `exit ${String(exitCode)}`);
|
|
6867
|
+
}
|
|
6868
|
+
return;
|
|
6869
|
+
}
|
|
6870
|
+
if (type === "shell.start") {
|
|
6871
|
+
if (!firstPendingShell(state))
|
|
6872
|
+
appendTranscript(state, "Tool", `$ ${asText(event.command)}`);
|
|
6873
|
+
return;
|
|
6874
|
+
}
|
|
6875
|
+
appendTranscript(state, "System", `${type}: ${asText(event)}`);
|
|
6822
6876
|
}
|
|
6823
|
-
function applyEnvelope(state, envelopeValue) {
|
|
6877
|
+
function applyEnvelope(ctx, state, envelopeValue) {
|
|
6824
6878
|
const envelope = recordOf(envelopeValue);
|
|
6825
6879
|
if (!envelope)
|
|
6826
6880
|
return;
|
|
@@ -6829,7 +6883,8 @@ function applyEnvelope(state, envelopeValue) {
|
|
|
6829
6883
|
const metadata = recordOf(envelope.metadata);
|
|
6830
6884
|
state.cwd = typeof metadata?.cwd === "string" ? metadata.cwd : state.cwd;
|
|
6831
6885
|
state.status = "worker Pi daemon ready";
|
|
6832
|
-
|
|
6886
|
+
if (!state.nativeStream)
|
|
6887
|
+
appendTranscript(state, "System", "Connected to worker Pi daemon.");
|
|
6833
6888
|
} else if (type === "status.update") {
|
|
6834
6889
|
applyStatus(state, envelope);
|
|
6835
6890
|
} else if (type === "activity.update") {
|
|
@@ -6841,10 +6896,11 @@ function applyEnvelope(state, envelopeValue) {
|
|
|
6841
6896
|
} else if (type === "pi.ui_event") {
|
|
6842
6897
|
applyUiEvent(state, envelope.event);
|
|
6843
6898
|
} else if (type === "pi.event") {
|
|
6844
|
-
applyPiEvent(state, envelope.event);
|
|
6899
|
+
applyPiEvent(ctx, state, envelope.event);
|
|
6845
6900
|
} else if (type === "error") {
|
|
6846
6901
|
appendTranscript(state, "Error", asText(envelope.message ?? envelope.detail ?? "unknown error"));
|
|
6847
6902
|
}
|
|
6903
|
+
syncNativeDisplayCwd(ctx, state);
|
|
6848
6904
|
}
|
|
6849
6905
|
async function waitForWorkerReady(options, ctx, state) {
|
|
6850
6906
|
while (true) {
|
|
@@ -6865,7 +6921,7 @@ async function waitForWorkerReady(options, ctx, state) {
|
|
|
6865
6921
|
continue;
|
|
6866
6922
|
}
|
|
6867
6923
|
const sessionRecord = recordOf(session) ?? {};
|
|
6868
|
-
applyEnvelope(state, { type: "ready", metadata: sessionRecord.metadata ?? sessionRecord });
|
|
6924
|
+
applyEnvelope(ctx, state, { type: "ready", metadata: sessionRecord.metadata ?? sessionRecord });
|
|
6869
6925
|
updatePiUi(ctx, state);
|
|
6870
6926
|
return true;
|
|
6871
6927
|
}
|
|
@@ -6895,7 +6951,7 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
6895
6951
|
if (!catchupDone)
|
|
6896
6952
|
buffered.push(payload);
|
|
6897
6953
|
else {
|
|
6898
|
-
applyEnvelope(state, payload);
|
|
6954
|
+
applyEnvelope(ctx, state, payload);
|
|
6899
6955
|
updatePiUi(ctx, state);
|
|
6900
6956
|
}
|
|
6901
6957
|
} catch (error) {
|
|
@@ -6918,8 +6974,12 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
6918
6974
|
getRunPiCommandsViaServer(options.context, options.runId)
|
|
6919
6975
|
]);
|
|
6920
6976
|
const messages = Array.isArray(messagesPayload.messages) ? messagesPayload.messages : [];
|
|
6921
|
-
|
|
6922
|
-
|
|
6977
|
+
const native = nativePiUi(ctx);
|
|
6978
|
+
if (state.nativeStream && native?.appendSessionMessages)
|
|
6979
|
+
native.appendSessionMessages(messages);
|
|
6980
|
+
else
|
|
6981
|
+
for (const message2 of messages)
|
|
6982
|
+
applyMessage(state, message2);
|
|
6923
6983
|
applyStatus(state, statusPayload);
|
|
6924
6984
|
const commands = Array.isArray(commandsPayload.commands) ? commandsPayload.commands : [];
|
|
6925
6985
|
state.commands = commands.flatMap((command) => {
|
|
@@ -6928,7 +6988,7 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
6928
6988
|
});
|
|
6929
6989
|
catchupDone = true;
|
|
6930
6990
|
for (const payload of buffered.splice(0))
|
|
6931
|
-
applyEnvelope(state, payload);
|
|
6991
|
+
applyEnvelope(ctx, state, payload);
|
|
6932
6992
|
updatePiUi(ctx, state);
|
|
6933
6993
|
} catch (error) {
|
|
6934
6994
|
appendTranscript(state, "Error", `Worker Pi catch-up failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -6937,6 +6997,51 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
6937
6997
|
}
|
|
6938
6998
|
await closePromise;
|
|
6939
6999
|
}
|
|
7000
|
+
function createRemoteBashOperations(options, state, excludeFromContext) {
|
|
7001
|
+
return {
|
|
7002
|
+
exec(command, _cwd, execOptions) {
|
|
7003
|
+
return new Promise((resolve20, reject) => {
|
|
7004
|
+
const pending = {
|
|
7005
|
+
command,
|
|
7006
|
+
onData: execOptions.onData,
|
|
7007
|
+
resolve: resolve20,
|
|
7008
|
+
reject,
|
|
7009
|
+
sawChunk: false
|
|
7010
|
+
};
|
|
7011
|
+
const cleanup = () => {
|
|
7012
|
+
execOptions.signal?.removeEventListener("abort", onAbort);
|
|
7013
|
+
if (timer)
|
|
7014
|
+
clearTimeout(timer);
|
|
7015
|
+
};
|
|
7016
|
+
const onAbort = () => {
|
|
7017
|
+
cleanup();
|
|
7018
|
+
failPendingShell(state, pending, new Error("Remote worker shell command aborted locally."));
|
|
7019
|
+
};
|
|
7020
|
+
const timeoutMs = typeof execOptions.timeout === "number" && execOptions.timeout > 0 ? execOptions.timeout : 0;
|
|
7021
|
+
const timer = timeoutMs > 0 ? setTimeout(() => {
|
|
7022
|
+
cleanup();
|
|
7023
|
+
failPendingShell(state, pending, new Error(`Remote worker shell command timed out after ${timeoutMs}ms.`));
|
|
7024
|
+
}, timeoutMs) : null;
|
|
7025
|
+
const wrappedResolve = pending.resolve;
|
|
7026
|
+
const wrappedReject = pending.reject;
|
|
7027
|
+
pending.resolve = (result) => {
|
|
7028
|
+
cleanup();
|
|
7029
|
+
wrappedResolve(result);
|
|
7030
|
+
};
|
|
7031
|
+
pending.reject = (error) => {
|
|
7032
|
+
cleanup();
|
|
7033
|
+
wrappedReject(error);
|
|
7034
|
+
};
|
|
7035
|
+
execOptions.signal?.addEventListener("abort", onAbort, { once: true });
|
|
7036
|
+
state.pendingShells.push(pending);
|
|
7037
|
+
sendRunPiShellViaServer(options.context, options.runId, `${excludeFromContext ? "!!" : "!"}${command}`).catch((error) => {
|
|
7038
|
+
cleanup();
|
|
7039
|
+
failPendingShell(state, pending, error instanceof Error ? error : new Error(String(error)));
|
|
7040
|
+
});
|
|
7041
|
+
});
|
|
7042
|
+
}
|
|
7043
|
+
};
|
|
7044
|
+
}
|
|
6940
7045
|
async function answerPendingUi(options, state, line) {
|
|
6941
7046
|
const pending = state.pendingUi;
|
|
6942
7047
|
if (!pending)
|
|
@@ -7002,13 +7107,22 @@ function createRigWorkerPiBridgeExtension(options) {
|
|
|
7002
7107
|
commands: [],
|
|
7003
7108
|
streaming: false,
|
|
7004
7109
|
pendingUi: null,
|
|
7005
|
-
|
|
7110
|
+
pendingShells: [],
|
|
7111
|
+
wsConnected: false,
|
|
7112
|
+
nativeStream: false
|
|
7006
7113
|
};
|
|
7007
7114
|
if (options.initialMessageSent)
|
|
7008
7115
|
appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
|
|
7116
|
+
let nativePiUiContextAvailable = false;
|
|
7117
|
+
pi.on("user_bash", (event) => {
|
|
7118
|
+
state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
|
|
7119
|
+
return { operations: createRemoteBashOperations(options, state, event.excludeFromContext === true) };
|
|
7120
|
+
});
|
|
7009
7121
|
pi.on("session_start", async (_event, ctx) => {
|
|
7122
|
+
nativePiUiContextAvailable = Boolean(nativePiUi(ctx));
|
|
7123
|
+
state.nativeStream = nativePiUiContextAvailable;
|
|
7010
7124
|
updatePiUi(ctx, state);
|
|
7011
|
-
ctx.ui.notify("Rig worker Pi bridge extension loaded", "info");
|
|
7125
|
+
ctx.ui.notify(nativePiUiContextAvailable ? "Rig worker Pi native stream bridge loaded" : "Rig worker Pi bridge extension loaded (degraded widget fallback)", "info");
|
|
7012
7126
|
ctx.ui.onTerminalInput((data) => {
|
|
7013
7127
|
if (data.includes("\x04")) {
|
|
7014
7128
|
ctx.shutdown();
|
|
@@ -7022,6 +7136,8 @@ function createRigWorkerPiBridgeExtension(options) {
|
|
|
7022
7136
|
const text2 = [editorText, inlineText].filter(Boolean).join(" ").trim();
|
|
7023
7137
|
if (!text2)
|
|
7024
7138
|
return;
|
|
7139
|
+
if (text2.startsWith("!"))
|
|
7140
|
+
return;
|
|
7025
7141
|
ctx.ui.setEditorText("");
|
|
7026
7142
|
routeInput(options, ctx, state, text2).catch((error) => {
|
|
7027
7143
|
appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h-rig/cli",
|
|
3
|
-
"version": "0.0.6-alpha.
|
|
3
|
+
"version": "0.0.6-alpha.24",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Rig package",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@clack/prompts": "^1.2.0",
|
|
26
|
-
"@earendil-works/pi-coding-agent": "npm:@h-rig/pi-coding-agent@0.0.6-alpha.
|
|
27
|
-
"@rig/core": "npm:@h-rig/core@0.0.6-alpha.
|
|
28
|
-
"@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.
|
|
29
|
-
"@rig/client": "npm:@h-rig/client@0.0.6-alpha.
|
|
30
|
-
"@rig/server": "npm:@h-rig/server@0.0.6-alpha.
|
|
26
|
+
"@earendil-works/pi-coding-agent": "npm:@h-rig/pi-coding-agent@0.0.6-alpha.24",
|
|
27
|
+
"@rig/core": "npm:@h-rig/core@0.0.6-alpha.24",
|
|
28
|
+
"@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.24",
|
|
29
|
+
"@rig/client": "npm:@h-rig/client@0.0.6-alpha.24",
|
|
30
|
+
"@rig/server": "npm:@h-rig/server@0.0.6-alpha.24",
|
|
31
31
|
"picocolors": "^1.1.1"
|
|
32
32
|
}
|
|
33
33
|
}
|