agent-from-zero 0.30.0 → 0.31.0
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/agent.js +4 -4
- package/dist/editor.js +15 -4
- package/dist/ui.js +6 -0
- package/package.json +2 -2
package/dist/agent.js
CHANGED
|
@@ -19,7 +19,7 @@ import { clearTodos, getTodos, renderTodos } from "./todos.js"; // the agent's p
|
|
|
19
19
|
import { renderDiff } from "./diff.js"; // show what /undo put back / what /diff changed, reusing the Day 21 diff renderer
|
|
20
20
|
import path from "node:path"; // shorten paths for the /diff summary
|
|
21
21
|
import { expandMentions } from "./mentions.js"; // @file mentions: pull referenced files into context (secret files refused)
|
|
22
|
-
import { banner, framedPrompt, formatModelChoices, statusLine } from "./ui.js"; // welcome box, prompt, model labels, status line
|
|
22
|
+
import { banner, framedPrompt, formatModelChoices, statusLine, sentMessage } from "./ui.js"; // welcome box, prompt, model labels, status line, sent-message echo
|
|
23
23
|
import { gitBranch, toggleLastCollapsed, revealReasoning, clearReasoning, revealToolCalls, clearToolCalls, cleanup as tuiCleanup } from "./tui.js"; // git branch + collapsible output + collapsed reasoning (Ctrl+R) + folded tool-call trace (Ctrl+T)
|
|
24
24
|
import { promptSelect, promptForm } from "./menu.js"; // arrow-key approval menu + multi-question form
|
|
25
25
|
import { editLine } from "./editor.js"; // our own line editor (keeps the status footer pinned even when input wraps)
|
|
@@ -249,7 +249,7 @@ async function main() {
|
|
|
249
249
|
lineWaiters.shift()("exit"); // wake every waiter with a polite "exit"
|
|
250
250
|
});
|
|
251
251
|
// Get the next line of user input, showing a prompt if we have to wait.
|
|
252
|
-
const readUserLine = async (prompt, footer) => {
|
|
252
|
+
const readUserLine = async (prompt, footer, echo) => {
|
|
253
253
|
if (pendingLines.length)
|
|
254
254
|
return pendingLines.shift(); // typed-ahead (or piped) line — use it
|
|
255
255
|
if (stdinDone)
|
|
@@ -259,7 +259,7 @@ async function main() {
|
|
|
259
259
|
// so the status bar stays pinned below however the line wraps.
|
|
260
260
|
editing = true;
|
|
261
261
|
try {
|
|
262
|
-
const res = await editLine(rl, { prompt, footer, history, onTab: () => toggleLastCollapsed(), onReveal: () => revealReasoning(), onTools: () => revealToolCalls(), transformPaste: normalizeDroppedPaths });
|
|
262
|
+
const res = await editLine(rl, { prompt, footer, history, echo, onTab: () => toggleLastCollapsed(), onReveal: () => revealReasoning(), onTools: () => revealToolCalls(), transformPaste: normalizeDroppedPaths });
|
|
263
263
|
if (res.type === "line") {
|
|
264
264
|
if (res.value.trim())
|
|
265
265
|
history.push(res.value); // remember non-empty entries for ↑/↓
|
|
@@ -648,7 +648,7 @@ async function main() {
|
|
|
648
648
|
console.log(""); // one blank line separates the previous answer from the prompt
|
|
649
649
|
footer = statusLine(CONFIG.model, path.basename(process.cwd()), gitBranch(), ctxPct, costMeter.cost(), Date.now() - sessionStartedAt); // status pinned below the prompt
|
|
650
650
|
}
|
|
651
|
-
const line = (await readUserLine(framedPrompt(isPlanMode()), footer)).trim(); // next input, or "exit" on EOF
|
|
651
|
+
const line = (await readUserLine(framedPrompt(isPlanMode()), footer, sentMessage)).trim(); // next input (echoed as a sent message above), or "exit" on EOF
|
|
652
652
|
if (!line)
|
|
653
653
|
continue; // empty line — just re-prompt
|
|
654
654
|
if (line === "exit" || line === "quit") {
|
package/dist/editor.js
CHANGED
|
@@ -239,13 +239,24 @@ export function editLine(rl, opts) {
|
|
|
239
239
|
input.off("keypress", onKey);
|
|
240
240
|
for (const l of otherKeypress)
|
|
241
241
|
input.on("keypress", l); // give readline its keypress handler back
|
|
242
|
-
//
|
|
243
|
-
const { rows } = layout(state.buffer, state.cursor, promptW, cols());
|
|
242
|
+
// Climb to the top of the input block and wipe it (prompt + wrapped input + footer).
|
|
244
243
|
if (prevCursorRow > 0)
|
|
245
244
|
out.write(`\x1b[${prevCursorRow}A`);
|
|
246
245
|
out.write("\r\x1b[0J");
|
|
247
|
-
|
|
248
|
-
|
|
246
|
+
// What stays on screen: with an echo styler (the main REPL prompt), a
|
|
247
|
+
// submitted message is re-rendered as a distinct "sent" line and the input
|
|
248
|
+
// box vanishes — your message scrolls up, the input clears, like a chat app.
|
|
249
|
+
// Without it (sub-prompts), leave the typed command under its prompt.
|
|
250
|
+
if (opts.echo) {
|
|
251
|
+
if (result.type === "line" && state.buffer.trim())
|
|
252
|
+
out.write(opts.echo(state.buffer) + "\r\n");
|
|
253
|
+
// empty submit / cancel / eof: leave nothing — the wipe above already cleared it
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
const { rows } = layout(state.buffer, state.cursor, promptW, cols());
|
|
257
|
+
const inputRows = rows.map((r, i) => (i === 0 ? opts.prompt + r : r));
|
|
258
|
+
out.write(inputRows.join("\r\n") + "\r\n");
|
|
259
|
+
}
|
|
249
260
|
try {
|
|
250
261
|
input.setRawMode(wasRaw); // hand stdin back exactly as we found it
|
|
251
262
|
}
|
package/dist/ui.js
CHANGED
|
@@ -124,6 +124,12 @@ export function inputRule() {
|
|
|
124
124
|
export function framedPrompt(planMode) {
|
|
125
125
|
return planMode ? chalk.yellow.bold("⏸ plan ❯ ") : chalk.cyan.bold("❯ ");
|
|
126
126
|
}
|
|
127
|
+
// How a SUBMITTED message is echoed into the scrollback once you hit Enter: a
|
|
128
|
+
// distinct, muted "> …" line (not the bright ❯ prompt) so each turn reads like a
|
|
129
|
+
// sent chat message scrolling up, leaving the input box empty below.
|
|
130
|
+
export function sentMessage(text) {
|
|
131
|
+
return chalk.dim("> " + text);
|
|
132
|
+
}
|
|
127
133
|
// ---- the selection menu -----------------------------------------------------
|
|
128
134
|
// Render a numbered list of options with one highlighted. The interactive part
|
|
129
135
|
// (raw-mode arrow keys) lives in menu.ts; this is just the pure drawing, so it's
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-from-zero",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"description": "Build a Claude Code-style CLI agent from scratch, with AI as your pair programmer — companion code for a 10-day tutorial (DeepSeek by default, any OpenAI-compatible model)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"eval": "tsx --env-file=.env eval/run.ts",
|
|
17
17
|
"build": "tsc -p tsconfig.build.json",
|
|
18
18
|
"prepare": "npm run build",
|
|
19
|
-
"test": "tsx tests/tools.test.ts && tsx tests/permissions.test.ts && tsx tests/context.test.ts && tsx tests/hooks.test.ts && tsx tests/mcp.test.ts && tsx tests/judge.test.ts && tsx tests/memory.test.ts && tsx tests/cost.test.ts && tsx tests/validate.test.ts && tsx tests/plan.test.ts && tsx tests/diff.test.ts && tsx tests/undo.test.ts && tsx tests/tiering.test.ts && tsx tests/mcp-http.test.ts && tsx tests/changes.test.ts && tsx tests/mentions.test.ts && tsx tests/session.test.ts && tsx tests/ui.test.ts && tsx tests/approval.test.ts && tsx tests/form.test.ts && tsx tests/model.test.ts && tsx tests/reasoning.test.ts && tsx tests/skills.test.ts && tsx tests/markdown.test.ts && tsx tests/editor.test.ts && tsx tests/todos.test.ts && tsx tests/background.test.ts && tsx tests/team.test.ts && tsx tests/board.test.ts && tsx tests/drop.test.ts"
|
|
19
|
+
"test": "tsx tests/tools.test.ts && tsx tests/permissions.test.ts && tsx tests/context.test.ts && tsx tests/hooks.test.ts && tsx tests/mcp.test.ts && tsx tests/judge.test.ts && tsx tests/memory.test.ts && tsx tests/cost.test.ts && tsx tests/validate.test.ts && tsx tests/plan.test.ts && tsx tests/diff.test.ts && tsx tests/undo.test.ts && tsx tests/tiering.test.ts && tsx tests/mcp-http.test.ts && tsx tests/changes.test.ts && tsx tests/mentions.test.ts && tsx tests/session.test.ts && tsx tests/ui.test.ts && tsx tests/approval.test.ts && tsx tests/form.test.ts && tsx tests/model.test.ts && tsx tests/reasoning.test.ts && tsx tests/skills.test.ts && tsx tests/markdown.test.ts && tsx tests/editor.test.ts && tsx tests/todos.test.ts && tsx tests/background.test.ts && tsx tests/team.test.ts && tsx tests/board.test.ts && tsx tests/drop.test.ts && tsx tests/editline.test.ts"
|
|
20
20
|
},
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=20.6"
|