@goah/cli 0.13.4 → 0.13.5

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.
@@ -228,6 +228,8 @@ var ProcessRunner = class {
228
228
  const message = JSON.parse(line);
229
229
  if (message.type === "trace")
230
230
  request.emit(message.event);
231
+ else if (message.type === "live")
232
+ request.emitLive?.(message.event);
231
233
  else if (message.type === "steer_ack") {
232
234
  const pending = pendingSteering.get(message.id);
233
235
  if (pending) {
@@ -397,7 +399,8 @@ async function runProcessWorker(run) {
397
399
  deliverSteer(message.id, message.message);
398
400
  } };
399
401
  const result = await run(start.request, (event) => process.stdout.write(`${JSON.stringify({ type: "trace", event })}
400
- `), rpc, controls);
402
+ `), rpc, controls, (event) => process.stdout.write(`${JSON.stringify({ type: "live", event })}
403
+ `));
401
404
  process.stdout.write(`${JSON.stringify({ type: "result", result })}
402
405
  `);
403
406
  input.close();
@@ -3,7 +3,7 @@ const require = __goahCreateRequire(import.meta.url);
3
3
  import {
4
4
  createPiProcessRunner,
5
5
  piRunnerConfigurator
6
- } from "./chunk-EK6BTCFG.js";
6
+ } from "./chunk-24NAHA3D.js";
7
7
 
8
8
  // node_modules/.dist-original/runner-registry.js
9
9
  var plugins = /* @__PURE__ */ new Map([
@@ -2,7 +2,7 @@ import { createRequire as __goahCreateRequire } from "node:module";
2
2
  const require = __goahCreateRequire(import.meta.url);
3
3
  import {
4
4
  runnerPlugin
5
- } from "./chunk-R6GKCNTB.js";
5
+ } from "./chunk-J32EKOQ4.js";
6
6
  import {
7
7
  SQLITE_SCHEMA_VERSION,
8
8
  SqliteLedger
@@ -11,12 +11,12 @@ import {
11
11
  RunnerRouter,
12
12
  Supervisor,
13
13
  deriveRecoveryViews
14
- } from "./chunk-SQJZ5OFH.js";
14
+ } from "./chunk-RDUUXBZ2.js";
15
15
  import {
16
16
  ProcessRunner,
17
17
  piWorkerPath,
18
18
  resolveEnvSpec
19
- } from "./chunk-EK6BTCFG.js";
19
+ } from "./chunk-24NAHA3D.js";
20
20
  import {
21
21
  createPiModel
22
22
  } from "./chunk-6M3OOCKO.js";
@@ -337,13 +337,13 @@ async function dispatch(request, socket, supervisor, ledger, reloadRuntime, stop
337
337
  if (request.op === "goal.interact") {
338
338
  const accepted = await supervisor.startHumanGoalTurn(request.objective, request.id);
339
339
  write(socket, { type: "accepted", turnId: accepted.turnId, value: accepted });
340
- for await (const frame of turnFrames(accepted.turnId, ledger, () => !socket.destroyed))
340
+ for await (const frame of turnFrames(accepted.turnId, supervisor, ledger, () => !socket.destroyed))
341
341
  write(socket, frame);
342
342
  socket.end();
343
343
  return;
344
344
  }
345
345
  if (request.op === "turn.attach") {
346
- for await (const frame of turnFrames(request.turnId, ledger, () => !socket.destroyed))
346
+ for await (const frame of turnFrames(request.turnId, supervisor, ledger, () => !socket.destroyed))
347
347
  write(socket, frame);
348
348
  socket.end();
349
349
  return;
@@ -413,10 +413,11 @@ async function* interactFrames(message, supervisor, ledger, isActive = () => tru
413
413
  throw new Error("message is required");
414
414
  const accepted = await supervisor.startHumanTurn(message);
415
415
  yield { type: "accepted", turnId: accepted.turnId, value: accepted };
416
- yield* turnFrames(accepted.turnId, ledger, isActive);
416
+ yield* turnFrames(accepted.turnId, supervisor, ledger, isActive);
417
417
  }
418
- async function* turnFrames(turnId, ledger, isActive) {
418
+ async function* turnFrames(turnId, supervisor, ledger, isActive) {
419
419
  let nextStreamSeq = 1;
420
+ let liveRevision = 0;
420
421
  const turn = ledger.turn(turnId);
421
422
  if (!turn)
422
423
  throw new Error("Turn not found");
@@ -428,10 +429,18 @@ async function* turnFrames(turnId, ledger, isActive) {
428
429
  yield { type: "event", event };
429
430
  }
430
431
  };
432
+ const drainLive = async function* () {
433
+ const live = supervisor.liveTurnSnapshot(turnId, liveRevision);
434
+ if (!live)
435
+ return;
436
+ liveRevision = live.revision;
437
+ yield { type: "event", event: { type: "message.assistant.live", data: live } };
438
+ };
431
439
  while (true) {
432
440
  if (!isActive())
433
441
  return;
434
442
  yield* drain();
443
+ yield* drainLive();
435
444
  const current = ledger.turn(turnId);
436
445
  if (!current)
437
446
  throw new Error("Turn disappeared");
@@ -334,6 +334,7 @@ var Supervisor = class {
334
334
  #goalExecutionBarriers = /* @__PURE__ */ new Map();
335
335
  #handoffValidations = /* @__PURE__ */ new Map();
336
336
  #handoffAttemptSeq = /* @__PURE__ */ new Map();
337
+ #liveTurns = /* @__PURE__ */ new Map();
337
338
  #runner;
338
339
  constructor(ledger, runner, clock, options = {}) {
339
340
  this.ledger = ledger;
@@ -500,6 +501,7 @@ var Supervisor = class {
500
501
  const turn = this.ledger.turn(turnId);
501
502
  if (!turn || turn.status !== "in_progress")
502
503
  throw new Error("active Turn not found");
504
+ this.#liveTurns.delete(turn.id);
503
505
  this.#clearHandoffState(turn.id);
504
506
  this.ledger.finishTurn(turn.id, "interrupted", { message: reason }, this.#now(), actor);
505
507
  await this.#cleanupTerminalTurn(turn);
@@ -513,7 +515,7 @@ var Supervisor = class {
513
515
  let renewal = null;
514
516
  let processClean = true;
515
517
  try {
516
- handle = this.runner.prepare({ agent, execution, ...sourceWake ? { sourceWake, sourceWakeTriggers } : {}, turn: turnContext, context: contextFactory(), now: () => this.#now(), emit: (trace) => this.#recordTurnTrace(initial.id, leaseToken, trace.type, trace.data, agent), rpc: (method, params) => this.#agentRpcForTurn(initial.id, agent, turnContext, method, params, sourceWake?.id) });
518
+ handle = this.runner.prepare({ agent, execution, ...sourceWake ? { sourceWake, sourceWakeTriggers } : {}, turn: turnContext, context: contextFactory(), now: () => this.#now(), emit: (trace) => this.#recordTurnTrace(initial.id, leaseToken, trace.type, trace.data, agent), emitLive: (trace) => this.#recordLiveTrace(initial.id, leaseToken, trace), rpc: (method, params) => this.#agentRpcForTurn(initial.id, agent, turnContext, method, params, sourceWake?.id) });
517
519
  this.#handles.set(initial.id, handle);
518
520
  if (handle.pid)
519
521
  this.ledger.attachTurnProcess(initial.id, leaseToken, handle.pid);
@@ -754,6 +756,7 @@ ${history}` } : {} };
754
756
  const current = this.ledger.turn(turnId);
755
757
  if (!current || current.status !== "in_progress")
756
758
  return;
759
+ this.#liveTurns.delete(turnId);
757
760
  this.#clearHandoffState(turnId);
758
761
  this.ledger.finishTurn(turnId, "failed", { message: reason }, this.#now(), "supervisor");
759
762
  }
@@ -761,6 +764,7 @@ ${history}` } : {} };
761
764
  const turn = this.ledger.turns().find((candidate) => candidate.status === "in_progress" && candidate.goalId === goalId);
762
765
  if (!turn)
763
766
  return;
767
+ this.#liveTurns.delete(turn.id);
764
768
  this.#clearHandoffState(turn.id);
765
769
  this.ledger.finishTurn(turn.id, "interrupted", { message: reason }, this.#now(), "supervisor");
766
770
  void this.#cleanupTerminalTurn(turn);
@@ -821,6 +825,10 @@ ${history}` } : {} };
821
825
  return item;
822
826
  }
823
827
  #recordTurnTrace(turnId, leaseToken, type, data, actor = "ceo") {
828
+ if (type === "message.assistant.delta") {
829
+ this.#recordLiveTrace(turnId, leaseToken, { type, data });
830
+ return;
831
+ }
824
832
  if (type === "transcript.completed" || type === "transcript.interrupted")
825
833
  return;
826
834
  if (type === "transcript.started" && this.ledger.readStream(`turn:${turnId}`).some((event) => event.type === "transcript.started"))
@@ -834,30 +842,20 @@ ${history}` } : {} };
834
842
  }
835
843
  this.ledger.appendTurnEvent({ streamId: `turn:${turnId}`, ts: this.#now(), actor, type, data }, leaseToken);
836
844
  if (type === "message.assistant.completed") {
845
+ this.#liveTurns.delete(turnId);
837
846
  const value = data;
838
847
  const text = messageTextContent(value.message?.content);
839
- if (text) {
840
- const id = typeof value.message?.id === "string" ? value.message.id.trim() : "";
841
- if (!id)
842
- throw new Error("Runner assistant completion is missing a message Item id");
848
+ const reasoning = messageReasoningContent(value.message?.content);
849
+ const id = typeof value.message?.id === "string" ? value.message.id.trim() : "";
850
+ if ((text || reasoning) && !id)
851
+ throw new Error("Runner assistant completion is missing a message Item id");
852
+ if (reasoning)
853
+ this.#appendTurnItem(turnId, "reasoning", { text: reasoning }, actor, `${id}:reasoning`);
854
+ if (text)
843
855
  this.#appendTurnItem(turnId, "assistant_message", { text }, actor, id);
844
- }
845
856
  } else if (type === "plan.updated")
846
857
  this.#appendTurnItem(turnId, "plan", data, actor);
847
- else if (type === "message.assistant.delta") {
848
- const input = data;
849
- const delta = input.delta;
850
- if (delta?.type === "thinking_start" || delta?.type === "thinking_delta" || delta?.type === "thinking_end") {
851
- const turn = this.ledger.turn(turnId);
852
- const id = `${turnId}:attempt:${turn.attempt}:reasoning:${String(input.messageId ?? "message")}`;
853
- const existing = this.ledger.turnItems(turnId).find((item) => item.id === id);
854
- const text = `${String(existing?.data?.text ?? "")}${delta.type === "thinking_delta" ? String(delta.delta ?? "") : ""}`;
855
- if (!existing)
856
- this.#appendTurnItem(turnId, "reasoning", { text }, actor, id, delta.type === "thinking_end" ? "completed" : "in_progress");
857
- else
858
- this.ledger.putTurnItem({ ...existing, data: { text }, status: delta.type === "thinking_end" ? "completed" : "in_progress", completedAt: delta.type === "thinking_end" ? this.#now() : null }, actor);
859
- }
860
- } else if (type === "tool.called") {
858
+ else if (type === "tool.called") {
861
859
  const input = data;
862
860
  const turn = this.ledger.turn(turnId);
863
861
  const id = `${turnId}:attempt:${turn.attempt}:tool:${String(input.callId)}`;
@@ -875,6 +873,37 @@ ${history}` } : {} };
875
873
  this.#appendTurnItem(turnId, "tool_result", { callId: String(input.callId), result: input.result ?? null }, actor);
876
874
  }
877
875
  }
876
+ #recordLiveTrace(turnId, leaseToken, event) {
877
+ const turn = this.ledger.turn(turnId);
878
+ if (!turn || turn.status !== "in_progress" || turn.leaseToken !== leaseToken)
879
+ return;
880
+ const input = event.data;
881
+ const delta = input.delta;
882
+ let state = this.#liveTurns.get(turnId);
883
+ if (!state || state.messageId !== input.messageId || delta.type === "start") {
884
+ state = { revision: 0, messageId: input.messageId, text: /* @__PURE__ */ new Map(), thinking: /* @__PURE__ */ new Map(), thinkingActive: false };
885
+ this.#liveTurns.set(turnId, state);
886
+ }
887
+ const index = delta.contentIndex ?? 0;
888
+ if (delta.type === "text_start")
889
+ state.text.set(index, []);
890
+ else if (delta.type === "text_delta")
891
+ appendLiveChunk(state.text, index, delta.delta);
892
+ else if (delta.type === "thinking_start") {
893
+ state.thinking.set(index, []);
894
+ state.thinkingActive = true;
895
+ } else if (delta.type === "thinking_delta")
896
+ appendLiveChunk(state.thinking, index, delta.delta);
897
+ else if (delta.type === "thinking_end")
898
+ state.thinkingActive = false;
899
+ state.revision += 1;
900
+ }
901
+ liveTurnSnapshot(turnId, afterRevision = 0) {
902
+ const state = this.#liveTurns.get(turnId);
903
+ if (!state || state.revision <= afterRevision)
904
+ return null;
905
+ return { revision: state.revision, messageId: state.messageId, text: joinLiveChunks(state.text), thinking: joinLiveChunks(state.thinking), thinkingActive: state.thinkingActive };
906
+ }
878
907
  async sendToCeo(body) {
879
908
  const value = body && typeof body === "object" && !Array.isArray(body) ? body : {};
880
909
  const message = String(value.message ?? "").trim();
@@ -1681,6 +1710,25 @@ function messageTextContent(content) {
1681
1710
  return "";
1682
1711
  return content.map((part) => part && typeof part === "object" && !Array.isArray(part) && part.type === "text" ? normalizeAssistantText(String(part.text ?? "")) : "").filter(Boolean).join("\n");
1683
1712
  }
1713
+ function messageReasoningContent(content) {
1714
+ if (!Array.isArray(content))
1715
+ return "";
1716
+ return content.map((part) => part && typeof part === "object" && !Array.isArray(part) && part.type === "thinking" ? normalizeAssistantText(String(part.thinking ?? "")) : "").filter(Boolean).join("\n");
1717
+ }
1718
+ function appendLiveChunk(target, index, delta) {
1719
+ if (!delta)
1720
+ return;
1721
+ const chunks = target.get(index) ?? [];
1722
+ const last = chunks.at(-1);
1723
+ if (last !== void 0 && last.length < 4096)
1724
+ chunks[chunks.length - 1] = last + delta;
1725
+ else
1726
+ chunks.push(delta);
1727
+ target.set(index, chunks);
1728
+ }
1729
+ function joinLiveChunks(target) {
1730
+ return [...target.entries()].sort(([left], [right]) => left - right).map(([, chunks]) => chunks.join("")).join("\n");
1731
+ }
1684
1732
  function goalBoundCapability(method) {
1685
1733
  return ["goal.delegate", "goal.reassign", "goal.revise", "goal.put", "work_record.update", "schedule.set", "human.request"].includes(method);
1686
1734
  }
package/dist/cli.js CHANGED
@@ -25,14 +25,14 @@ import {
25
25
  streamEvents,
26
26
  updateWorkspaceRunnerProfile,
27
27
  writeDefaultConfig
28
- } from "./chunk-5PZFP5CO.js";
28
+ } from "./chunk-ORAANUAR.js";
29
29
  import {
30
30
  runnerManifests,
31
31
  runnerPlugin
32
- } from "./chunk-R6GKCNTB.js";
32
+ } from "./chunk-J32EKOQ4.js";
33
33
  import "./chunk-CDELLMIJ.js";
34
- import "./chunk-SQJZ5OFH.js";
35
- import "./chunk-EK6BTCFG.js";
34
+ import "./chunk-RDUUXBZ2.js";
35
+ import "./chunk-24NAHA3D.js";
36
36
  import "./chunk-6M3OOCKO.js";
37
37
  import "./chunk-K26BVR6O.js";
38
38
  import "./chunk-IIJQ3DW4.js";
@@ -12696,6 +12696,11 @@ var ConversationView = class {
12696
12696
  appendLiveMarkdown(content) {
12697
12697
  this.liveMarkdown += content;
12698
12698
  }
12699
+ setLive(text, thinking, thinkingActive) {
12700
+ this.liveMarkdown = text;
12701
+ this.liveThinking = thinking;
12702
+ this.thinkingActive = thinkingActive;
12703
+ }
12699
12704
  clearLiveMarkdown() {
12700
12705
  this.liveMarkdown = "";
12701
12706
  }
@@ -13013,6 +13018,10 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
13013
13018
  transcriptView.updateThinking(activity);
13014
13019
  tui.requestRender();
13015
13020
  };
13021
+ const replaceLive = (text, thinking, thinkingActive) => {
13022
+ transcriptView.setLive(text, thinking, thinkingActive);
13023
+ tui.requestRender();
13024
+ };
13016
13025
  const setWakeState = (mode) => {
13017
13026
  statusView.setText(statusText(mode, mode === "queued" ? 1 : queued.length));
13018
13027
  tui.requestRender();
@@ -13074,7 +13083,7 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
13074
13083
  activeInteractionTurnId = frame.turnId;
13075
13084
  if (frame.type === "result" || frame.type === "error")
13076
13085
  activeInteractionTurnId = null;
13077
- renderFrame(frame, push, appendLive, commitLive, pushResponse, updateTool, updateThinking, setWakeState, () => commitLive(""));
13086
+ renderFrame(frame, push, appendLive, commitLive, pushResponse, updateTool, updateThinking, setWakeState, () => commitLive(""), replaceLive);
13078
13087
  }, controller.signal);
13079
13088
  } catch (error) {
13080
13089
  if (!ownsStream) {
@@ -13126,7 +13135,7 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
13126
13135
  return;
13127
13136
  if (frame.type === "result" || frame.type === "error")
13128
13137
  activeInteractionTurnId = null;
13129
- renderFrame(frame, push, appendLive, commitLive, pushResponse, updateTool, updateThinking, setWakeState, () => commitLive(""));
13138
+ renderFrame(frame, push, appendLive, commitLive, pushResponse, updateTool, updateThinking, setWakeState, () => commitLive(""), replaceLive);
13130
13139
  }, controller.signal);
13131
13140
  } catch (error) {
13132
13141
  if (streams.isCurrent(controller) && !controller.signal.aborted)
@@ -13394,6 +13403,7 @@ function frameToLine(frame) {
13394
13403
  function renderFrame(frame, push, appendLive = push, commitLive = push, pushResponse = push, updateTool = (activity) => push(toolActivityLine(activity)), updateThinking = () => {
13395
13404
  }, setWakeState = () => {
13396
13405
  }, clearLive = () => {
13406
+ }, replaceLive = () => {
13397
13407
  }) {
13398
13408
  if (frame.type === "error") {
13399
13409
  updateThinking({ phase: "clear", text: "" });
@@ -13435,6 +13445,10 @@ function renderFrame(frame, push, appendLive = push, commitLive = push, pushResp
13435
13445
  setWakeState("working");
13436
13446
  return;
13437
13447
  }
13448
+ if (record.type === "message.assistant.live") {
13449
+ replaceLive(typeof data.text === "string" ? data.text : "", typeof data.thinking === "string" ? data.thinking : "", data.thinkingActive === true);
13450
+ return;
13451
+ }
13438
13452
  if (record.type === "tool.called") {
13439
13453
  updateThinking({ phase: "done", text: "" });
13440
13454
  updateTool({ kind: "tool", callId: String(data.callId ?? "tool"), name: String(data.name ?? "tool"), detail: toolDetail(data.arguments), status: "running" });
@@ -13961,7 +13975,7 @@ async function main() {
13961
13975
  console.log(JSON.stringify({ goal }, null, 2));
13962
13976
  } else if (command === "dashboard") {
13963
13977
  const path4 = option("--output") ?? join7(config.stateDir, "status.html");
13964
- writeFileSync(path4, (await import("./dist-QW77PKUJ.js")).renderDashboard(ledger));
13978
+ writeFileSync(path4, (await import("./dist-EYYNPOYG.js")).renderDashboard(ledger));
13965
13979
  console.log(path4);
13966
13980
  } else
13967
13981
  throw new Error(`unknown command: ${command}`);
@@ -13971,7 +13985,7 @@ async function main() {
13971
13985
  }
13972
13986
  }
13973
13987
  async function run(supervisor, signal) {
13974
- const { runSupervisorDaemon } = await import("./dist-QW77PKUJ.js");
13988
+ const { runSupervisorDaemon } = await import("./dist-EYYNPOYG.js");
13975
13989
  await runSupervisorDaemon(supervisor, { signal });
13976
13990
  }
13977
13991
  async function waitForConsole(stateDir) {
@@ -14206,7 +14220,7 @@ async function runRunnerCommand(command, commandArgs, configPath) {
14206
14220
  async function runRunnerEarly(configPath) {
14207
14221
  const action = args[1] ?? "list";
14208
14222
  if (action === "list") {
14209
- for (const manifest of (await import("./runner-registry-3WSOMXRW.js")).runnerManifests())
14223
+ for (const manifest of (await import("./runner-registry-XCGUS2P3.js")).runnerManifests())
14210
14224
  console.log(`${manifest.id.padEnd(16)} ${manifest.description}`);
14211
14225
  return;
14212
14226
  }