@falkenslab/agent-kit 0.13.0 → 0.13.1

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,6 @@
1
1
  import type { Mode } from "../../core/agentSpec.js";
2
2
  import { type ConsoleRenderer, type ConsoleRendererOptions } from "../consoleRenderer.js";
3
+ import { type SessionModel } from "./sessionModel.js";
3
4
  import { type RenderApproval } from "./SessionView.js";
4
5
  import type { ToolPhrase } from "./toolGroup.js";
5
6
  import { type Theme } from "../theme.js";
@@ -31,6 +32,13 @@ export interface ProgressView extends ConsoleRenderer {
31
32
  /** Removes the live area and restores the previous interaction port; await it before printing anything else. */
32
33
  close(): Promise<void>;
33
34
  }
35
+ /**
36
+ * The console renderer's methods on top of a session model, so what a caller writes lands in
37
+ * the view (and in `onWrite`, through the model), not only in the model's inner console
38
+ * renderer, whose own output goes nowhere. The view draws whole lines: `write()` text waits
39
+ * until its line ends (a "\n" in it, `writeLine()` or `endLine()`).
40
+ */
41
+ export declare function progressRenderer(model: SessionModel): ConsoleRenderer;
34
42
  /**
35
43
  * The Ink counterpart of `createConsoleRenderer()` for one-shot ("run"-style) sessions: the
36
44
  * same methods and the same text (so `onWrite` logs exactly what the console version
@@ -23,6 +23,43 @@ function ProgressApp({ model, interaction, renderApproval, mode, closed }) {
23
23
  }, { isActive: checkpoint !== null });
24
24
  return _jsx(SessionView, { model: model, interaction: interaction, renderApproval: renderApproval, mode: mode, closed: closed });
25
25
  }
26
+ /**
27
+ * The console renderer's methods on top of a session model, so what a caller writes lands in
28
+ * the view (and in `onWrite`, through the model), not only in the model's inner console
29
+ * renderer, whose own output goes nowhere. The view draws whole lines: `write()` text waits
30
+ * until its line ends (a "\n" in it, `writeLine()` or `endLine()`).
31
+ */
32
+ export function progressRenderer(model) {
33
+ let partial = "";
34
+ const flush = () => {
35
+ if (!partial)
36
+ return;
37
+ const line = partial;
38
+ partial = "";
39
+ model.writeLine(line);
40
+ };
41
+ return {
42
+ render: (event) => {
43
+ flush();
44
+ model.render(event);
45
+ },
46
+ write(text) {
47
+ const lines = (partial + text).split("\n");
48
+ partial = lines.pop() ?? "";
49
+ for (const line of lines)
50
+ model.writeLine(line);
51
+ },
52
+ writeLine(text) {
53
+ flush();
54
+ model.writeLine(text);
55
+ },
56
+ endLine: flush,
57
+ startTurn: () => model.startTurn(),
58
+ get atLineStart() {
59
+ return partial === "" && model.renderer.atLineStart;
60
+ },
61
+ };
62
+ }
26
63
  /**
27
64
  * The Ink counterpart of `createConsoleRenderer()` for one-shot ("run"-style) sessions: the
28
65
  * same methods and the same text (so `onWrite` logs exactly what the console version
@@ -47,14 +84,7 @@ export function createProgressView(options = {}) {
47
84
  model.startTurn();
48
85
  let closing = null;
49
86
  return {
50
- render: model.render,
51
- write: (text) => model.renderer.write(text),
52
- writeLine: (text) => model.renderer.writeLine(text),
53
- endLine: () => model.renderer.endLine(),
54
- startTurn: () => model.startTurn(),
55
- get atLineStart() {
56
- return model.renderer.atLineStart;
57
- },
87
+ ...progressRenderer(model),
58
88
  close() {
59
89
  closing ??= (async () => {
60
90
  setInteractionPort(previousPort);
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { stdin, stdout } from "node:process";
3
- import { useState } from "react";
3
+ import { useEffect, useState } from "react";
4
4
  import { Box, render, Static, Text, useApp, useInput, useStdout } from "ink";
5
5
  import wrapAnsi from "wrap-ansi";
6
6
  import { liveWidth } from "./sessionModel.js";
@@ -77,6 +77,16 @@ export function Wizard({ steps, title, onDone }) {
77
77
  const [answers, setAnswers] = useState({});
78
78
  const [done, setDone] = useState([]);
79
79
  const [index, setIndex] = useState(() => nextIndex(steps, -1, {}));
80
+ const [finished, setFinished] = useState(null);
81
+ // Exits after the render that writes the last answer's ✔ line: exiting in the same handler
82
+ // unmounted Ink before it wrote that <Static> item, leaving the last question unanswered on
83
+ // screen.
84
+ useEffect(() => {
85
+ if (!finished)
86
+ return;
87
+ onDone(finished);
88
+ exit();
89
+ }, [finished]);
80
90
  useInput((input, key) => {
81
91
  if (key.ctrl && input === "c") {
82
92
  onDone(null);
@@ -90,10 +100,8 @@ export function Wizard({ steps, title, onDone }) {
90
100
  setDone([...done, { message: resolve(step.message, answers), text: summary(step, value, answers) }]);
91
101
  const following = nextIndex(steps, index, next);
92
102
  setIndex(following);
93
- if (following >= steps.length) {
94
- onDone(next);
95
- exit();
96
- }
103
+ if (following >= steps.length)
104
+ setFinished(next);
97
105
  }
98
106
  // The title and the answered steps go to <Static>: written once, never redrawn, so a long
99
107
  // menu can't grow the live area past the terminal's height.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@falkenslab/agent-kit",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "description": "Library for building an agent on top of the Claude Agent SDK",
5
5
  "author": "Francisco Vargas Ruiz",
6
6
  "license": "MIT",