@bunny-agent/runner-cli 0.10.2 → 0.10.3-beta1
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/bundle.mjs +190 -18
- package/package.json +2 -2
package/dist/bundle.mjs
CHANGED
|
@@ -39690,6 +39690,89 @@ function createOpenCodeRunner(options = {}) {
|
|
|
39690
39690
|
// ../../packages/runner-pi/dist/live-control.js
|
|
39691
39691
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
39692
39692
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
39693
|
+
import { createAssistantMessageEventStream as createAssistantMessageEventStream2 } from "@earendil-works/pi-ai";
|
|
39694
|
+
|
|
39695
|
+
// ../../packages/runner-pi/dist/generation-stream.js
|
|
39696
|
+
import { createAssistantMessageEventStream } from "@earendil-works/pi-ai";
|
|
39697
|
+
function fenceGenerationStream(source, model, signal, onSettled) {
|
|
39698
|
+
const target = createAssistantMessageEventStream();
|
|
39699
|
+
let partial3;
|
|
39700
|
+
let closed = false;
|
|
39701
|
+
const close = () => {
|
|
39702
|
+
closed = true;
|
|
39703
|
+
signal.removeEventListener("abort", abort);
|
|
39704
|
+
onSettled();
|
|
39705
|
+
};
|
|
39706
|
+
const finishFailure = (error109) => {
|
|
39707
|
+
if (closed)
|
|
39708
|
+
return;
|
|
39709
|
+
const message = partial3 ? structuredClone(partial3) : {
|
|
39710
|
+
role: "assistant",
|
|
39711
|
+
content: [],
|
|
39712
|
+
api: model.api,
|
|
39713
|
+
provider: model.provider,
|
|
39714
|
+
model: model.id,
|
|
39715
|
+
timestamp: Date.now(),
|
|
39716
|
+
stopReason: "aborted",
|
|
39717
|
+
usage: {
|
|
39718
|
+
input: 0,
|
|
39719
|
+
output: 0,
|
|
39720
|
+
cacheRead: 0,
|
|
39721
|
+
cacheWrite: 0,
|
|
39722
|
+
totalTokens: 0,
|
|
39723
|
+
cost: {
|
|
39724
|
+
input: 0,
|
|
39725
|
+
output: 0,
|
|
39726
|
+
cacheRead: 0,
|
|
39727
|
+
cacheWrite: 0,
|
|
39728
|
+
total: 0
|
|
39729
|
+
}
|
|
39730
|
+
}
|
|
39731
|
+
};
|
|
39732
|
+
message.stopReason = error109 === void 0 ? "aborted" : "error";
|
|
39733
|
+
if (error109 === void 0)
|
|
39734
|
+
delete message.errorMessage;
|
|
39735
|
+
else
|
|
39736
|
+
message.errorMessage = error109 instanceof Error ? error109.message : String(error109);
|
|
39737
|
+
close();
|
|
39738
|
+
target.push({ type: "error", reason: message.stopReason, error: message });
|
|
39739
|
+
target.end();
|
|
39740
|
+
source.end(message);
|
|
39741
|
+
};
|
|
39742
|
+
const abort = () => finishFailure();
|
|
39743
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
39744
|
+
if (signal.aborted)
|
|
39745
|
+
abort();
|
|
39746
|
+
void (async () => {
|
|
39747
|
+
try {
|
|
39748
|
+
for await (const event of source) {
|
|
39749
|
+
if (closed)
|
|
39750
|
+
break;
|
|
39751
|
+
if ("partial" in event)
|
|
39752
|
+
partial3 = event.partial;
|
|
39753
|
+
if (event.type === "done" || event.type === "error") {
|
|
39754
|
+
close();
|
|
39755
|
+
target.push(event);
|
|
39756
|
+
target.end();
|
|
39757
|
+
return;
|
|
39758
|
+
}
|
|
39759
|
+
target.push(event);
|
|
39760
|
+
}
|
|
39761
|
+
if (!closed) {
|
|
39762
|
+
const message = await source.result();
|
|
39763
|
+
if (closed)
|
|
39764
|
+
return;
|
|
39765
|
+
close();
|
|
39766
|
+
target.end(message);
|
|
39767
|
+
}
|
|
39768
|
+
} catch (error109) {
|
|
39769
|
+
finishFailure(error109);
|
|
39770
|
+
}
|
|
39771
|
+
})();
|
|
39772
|
+
return target;
|
|
39773
|
+
}
|
|
39774
|
+
|
|
39775
|
+
// ../../packages/runner-pi/dist/live-control.js
|
|
39693
39776
|
function createPiLiveController(session, onFirstStreamInvocation) {
|
|
39694
39777
|
const originalSteeringMode = session.agent.steeringMode;
|
|
39695
39778
|
session.agent.steeringMode = "one-at-a-time";
|
|
@@ -39699,6 +39782,7 @@ function createPiLiveController(session, onFirstStreamInvocation) {
|
|
|
39699
39782
|
let consumedCallback;
|
|
39700
39783
|
let disposed = false;
|
|
39701
39784
|
let firstStreamInvocationReported = false;
|
|
39785
|
+
let activeGeneration;
|
|
39702
39786
|
const reportIfConfirmed = (dispatch) => {
|
|
39703
39787
|
if (!disposed && dispatch.outcome === "queued" && dispatch.captured.length === 1 && dispatch.observed && !dispatch.reported) {
|
|
39704
39788
|
dispatch.reported = true;
|
|
@@ -39720,40 +39804,93 @@ function createPiLiveController(session, onFirstStreamInvocation) {
|
|
|
39720
39804
|
session.agent.steer = installedAgentSteer;
|
|
39721
39805
|
const originalStreamFunction = session.agent.streamFunction;
|
|
39722
39806
|
const wrappedStreamFunction = (model, context, streamOptions) => {
|
|
39807
|
+
const generation = new AbortController();
|
|
39808
|
+
activeGeneration = generation;
|
|
39809
|
+
const parentSignal = streamOptions?.signal;
|
|
39810
|
+
const abortFromParent = () => generation.abort(parentSignal?.reason);
|
|
39811
|
+
parentSignal?.addEventListener("abort", abortFromParent, { once: true });
|
|
39812
|
+
if (parentSignal?.aborted)
|
|
39813
|
+
abortFromParent();
|
|
39814
|
+
const settle2 = () => {
|
|
39815
|
+
parentSignal?.removeEventListener("abort", abortFromParent);
|
|
39816
|
+
if (activeGeneration === generation)
|
|
39817
|
+
activeGeneration = void 0;
|
|
39818
|
+
};
|
|
39723
39819
|
const observed = /* @__PURE__ */ new Set();
|
|
39724
|
-
const sanitizedMessages = context.messages.
|
|
39820
|
+
const sanitizedMessages = context.messages.flatMap((candidate) => {
|
|
39821
|
+
if (candidate.role === "assistant" && candidate.stopReason === "aborted") {
|
|
39822
|
+
const text = candidate.content.filter((part) => part.type === "text" && part.text.trim().length > 0);
|
|
39823
|
+
return text.length ? [{ ...candidate, content: text, stopReason: "stop" }] : [];
|
|
39824
|
+
}
|
|
39725
39825
|
if (!Object.getOwnPropertyDescriptor(candidate, "__bunnyLiveControl"))
|
|
39726
|
-
return candidate;
|
|
39826
|
+
return [candidate];
|
|
39727
39827
|
const { __bunnyLiveControl: marker, ...rest } = candidate;
|
|
39728
39828
|
if (marker && marker.controllerNonce === controllerNonce && candidate.role === "user") {
|
|
39729
39829
|
const dispatch = dispatches.get(marker.stableId);
|
|
39730
39830
|
if (dispatch)
|
|
39731
39831
|
observed.add(dispatch);
|
|
39732
39832
|
}
|
|
39733
|
-
return rest;
|
|
39833
|
+
return [rest];
|
|
39734
39834
|
});
|
|
39735
39835
|
const providerContext = {
|
|
39736
39836
|
...context,
|
|
39737
39837
|
messages: sanitizedMessages
|
|
39738
39838
|
};
|
|
39739
|
-
|
|
39740
|
-
|
|
39839
|
+
let result;
|
|
39840
|
+
try {
|
|
39841
|
+
result = originalStreamFunction.call(session.agent, model, providerContext, { ...streamOptions, signal: generation.signal });
|
|
39842
|
+
} catch (error109) {
|
|
39843
|
+
settle2();
|
|
39844
|
+
throw error109;
|
|
39845
|
+
}
|
|
39846
|
+
let abortStartup;
|
|
39847
|
+
const startupAborted = new Promise((resolve6) => {
|
|
39848
|
+
abortStartup = () => resolve6(fenceGenerationStream(createAssistantMessageEventStream2(), model, generation.signal, settle2));
|
|
39849
|
+
generation.signal.addEventListener("abort", abortStartup, {
|
|
39850
|
+
once: true
|
|
39851
|
+
});
|
|
39852
|
+
if (generation.signal.aborted)
|
|
39853
|
+
abortStartup();
|
|
39854
|
+
});
|
|
39855
|
+
const started = Promise.resolve(result).then((stream) => {
|
|
39856
|
+
generation.signal.removeEventListener("abort", abortStartup);
|
|
39857
|
+
if (generation.signal.aborted)
|
|
39858
|
+
return fenceGenerationStream(stream, model, generation.signal, settle2);
|
|
39741
39859
|
if (!disposed && !firstStreamInvocationReported) {
|
|
39742
39860
|
firstStreamInvocationReported = true;
|
|
39743
39861
|
onFirstStreamInvocation?.();
|
|
39744
39862
|
}
|
|
39745
|
-
|
|
39746
|
-
dispatch
|
|
39747
|
-
|
|
39863
|
+
if (!generation.signal.aborted) {
|
|
39864
|
+
for (const dispatch of observed) {
|
|
39865
|
+
dispatch.observed = true;
|
|
39866
|
+
reportIfConfirmed(dispatch);
|
|
39867
|
+
}
|
|
39868
|
+
const waiting = [...dispatches.values()].filter((dispatch) => dispatch.outcome === "queued" && dispatch.captured.length === 1 && !dispatch.observed && !dispatch.preemptionRequested);
|
|
39869
|
+
if (waiting.length) {
|
|
39870
|
+
for (const dispatch of waiting)
|
|
39871
|
+
dispatch.preemptionRequested = true;
|
|
39872
|
+
generation.abort();
|
|
39873
|
+
}
|
|
39748
39874
|
}
|
|
39749
|
-
return stream;
|
|
39875
|
+
return fenceGenerationStream(stream, model, generation.signal, settle2);
|
|
39876
|
+
}, (error109) => {
|
|
39877
|
+
generation.signal.removeEventListener("abort", abortStartup);
|
|
39878
|
+
settle2();
|
|
39879
|
+
throw error109;
|
|
39750
39880
|
});
|
|
39881
|
+
return Promise.race([started, startupAborted]);
|
|
39751
39882
|
};
|
|
39752
39883
|
session.agent.streamFunction = wrappedStreamFunction;
|
|
39753
39884
|
return {
|
|
39885
|
+
supportedPiSteerPreempt: true,
|
|
39754
39886
|
async steer(message) {
|
|
39755
39887
|
if (disposed)
|
|
39756
39888
|
return { disposition: "rejected", reason: "controller disposed" };
|
|
39889
|
+
if (session.isStreaming === false)
|
|
39890
|
+
return {
|
|
39891
|
+
disposition: "rejected",
|
|
39892
|
+
reason: "session is no longer running"
|
|
39893
|
+
};
|
|
39757
39894
|
if (dispatches.has(message.id)) {
|
|
39758
39895
|
return {
|
|
39759
39896
|
disposition: "rejected",
|
|
@@ -39764,7 +39901,8 @@ function createPiLiveController(session, onFirstStreamInvocation) {
|
|
|
39764
39901
|
id: message.id,
|
|
39765
39902
|
captured: [],
|
|
39766
39903
|
observed: false,
|
|
39767
|
-
reported: false
|
|
39904
|
+
reported: false,
|
|
39905
|
+
preemptionRequested: false
|
|
39768
39906
|
};
|
|
39769
39907
|
dispatches.set(message.id, dispatch);
|
|
39770
39908
|
const images = message.images?.map((image) => ({
|
|
@@ -39785,6 +39923,10 @@ function createPiLiveController(session, onFirstStreamInvocation) {
|
|
|
39785
39923
|
if (dispatch.outcome === "handled")
|
|
39786
39924
|
return { disposition: "handled" };
|
|
39787
39925
|
reportIfConfirmed(dispatch);
|
|
39926
|
+
if (dispatch.captured.length === 1 && !dispatch.observed && activeGeneration) {
|
|
39927
|
+
dispatch.preemptionRequested = true;
|
|
39928
|
+
activeGeneration.abort();
|
|
39929
|
+
}
|
|
39788
39930
|
return { disposition: "queued" };
|
|
39789
39931
|
},
|
|
39790
39932
|
onConsumed(callback) {
|
|
@@ -41735,12 +41877,34 @@ function accumulateToolUsage(tally, raw) {
|
|
|
41735
41877
|
}
|
|
41736
41878
|
}
|
|
41737
41879
|
function getUsageFromAgentEndMessages(messages) {
|
|
41738
|
-
|
|
41739
|
-
|
|
41740
|
-
if (
|
|
41741
|
-
|
|
41880
|
+
let total;
|
|
41881
|
+
for (const message of messages) {
|
|
41882
|
+
if (message.role !== "assistant" || !message.usage)
|
|
41883
|
+
continue;
|
|
41884
|
+
const usage = message.usage;
|
|
41885
|
+
if (!total) {
|
|
41886
|
+
total = { ...usage, cost: { ...usage.cost } };
|
|
41887
|
+
continue;
|
|
41888
|
+
}
|
|
41889
|
+
total.input += usage.input;
|
|
41890
|
+
total.output += usage.output;
|
|
41891
|
+
total.cacheRead += usage.cacheRead;
|
|
41892
|
+
total.cacheWrite += usage.cacheWrite;
|
|
41893
|
+
total.totalTokens += usage.totalTokens;
|
|
41894
|
+
if (usage.reasoning !== void 0)
|
|
41895
|
+
total.reasoning = (total.reasoning ?? 0) + usage.reasoning;
|
|
41896
|
+
if (usage.cacheWrite1h !== void 0)
|
|
41897
|
+
total.cacheWrite1h = (total.cacheWrite1h ?? 0) + usage.cacheWrite1h;
|
|
41898
|
+
for (const key of [
|
|
41899
|
+
"input",
|
|
41900
|
+
"output",
|
|
41901
|
+
"cacheRead",
|
|
41902
|
+
"cacheWrite",
|
|
41903
|
+
"total"
|
|
41904
|
+
])
|
|
41905
|
+
total.cost[key] += usage.cost[key];
|
|
41742
41906
|
}
|
|
41743
|
-
return
|
|
41907
|
+
return total;
|
|
41744
41908
|
}
|
|
41745
41909
|
|
|
41746
41910
|
// ../../packages/runner-pi/dist/stream-converter.js
|
|
@@ -45838,8 +46002,10 @@ function applyModelOverrides(model, provider, optionsEnv) {
|
|
|
45838
46002
|
function getErrorFromAgentEndMessages(messages) {
|
|
45839
46003
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
45840
46004
|
const m = messages[i];
|
|
45841
|
-
if (m.role === "assistant"
|
|
45842
|
-
|
|
46005
|
+
if (m.role === "assistant") {
|
|
46006
|
+
if (m.stopReason === "aborted")
|
|
46007
|
+
return m.errorMessage ?? "Generation interrupted before pending input could be consumed.";
|
|
46008
|
+
return m.stopReason === "error" ? m.errorMessage : void 0;
|
|
45843
46009
|
}
|
|
45844
46010
|
}
|
|
45845
46011
|
return void 0;
|
|
@@ -46063,6 +46229,7 @@ function createPiRunner(options = {}) {
|
|
|
46063
46229
|
let promptSettled = false;
|
|
46064
46230
|
let promptError;
|
|
46065
46231
|
let finalAgentEnd;
|
|
46232
|
+
const assistantCompletions = [];
|
|
46066
46233
|
let aborted3 = false;
|
|
46067
46234
|
let wakeConsumer = null;
|
|
46068
46235
|
const notify = () => {
|
|
@@ -46129,6 +46296,8 @@ function createPiRunner(options = {}) {
|
|
|
46129
46296
|
finalAgentEnd = event;
|
|
46130
46297
|
continue;
|
|
46131
46298
|
}
|
|
46299
|
+
if (event.type === "message_end" && event.message.role === "assistant")
|
|
46300
|
+
assistantCompletions.push(event.message);
|
|
46132
46301
|
const chunks = streamConverter.handleEvent(event, aborted3);
|
|
46133
46302
|
for (const chunk of chunks) {
|
|
46134
46303
|
yield chunk;
|
|
@@ -46157,7 +46326,10 @@ function createPiRunner(options = {}) {
|
|
|
46157
46326
|
return;
|
|
46158
46327
|
}
|
|
46159
46328
|
if (finalAgentEnd) {
|
|
46160
|
-
const chunks = streamConverter.handleEvent(
|
|
46329
|
+
const chunks = streamConverter.handleEvent({
|
|
46330
|
+
...finalAgentEnd,
|
|
46331
|
+
messages: assistantCompletions.length ? assistantCompletions : finalAgentEnd.messages
|
|
46332
|
+
}, false);
|
|
46161
46333
|
for (const chunk of chunks) {
|
|
46162
46334
|
yield chunk;
|
|
46163
46335
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bunny-agent/runner-cli",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.3-beta1",
|
|
4
4
|
"description": "BunnyAgent Runner CLI - Like gemini-cli or claude-code, runs in your local terminal with AI SDK UI streaming",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"typescript": "^5.3.0",
|
|
61
61
|
"vitest": "^1.6.1",
|
|
62
62
|
"@bunny-agent/apply-patch": "0.1.0",
|
|
63
|
+
"@bunny-agent/manager": "0.10.3-beta1",
|
|
63
64
|
"@bunny-agent/runner-claude": "0.6.2",
|
|
64
65
|
"@bunny-agent/runner-codex": "0.6.2",
|
|
65
66
|
"@bunny-agent/runner-copilot": "0.1.0",
|
|
@@ -67,7 +68,6 @@
|
|
|
67
68
|
"@bunny-agent/runner-harness": "0.1.1-beta.0",
|
|
68
69
|
"@bunny-agent/runner-opencode": "0.6.2",
|
|
69
70
|
"@bunny-agent/runner-pi": "0.6.4-beta.0",
|
|
70
|
-
"@bunny-agent/manager": "0.10.2",
|
|
71
71
|
"@bunny-agent/server-acp": "0.1.0"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|