@lazyingart/agintiflow 0.14.0 → 0.14.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.
- package/README.md +1 -1
- package/docs/agent-runtime-pipe.md +2 -2
- package/package.json +1 -1
- package/scripts/smoke-cli-chat.js +11 -2
- package/src/interactive-cli.js +14 -5
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ aginti
|
|
|
67
67
|
aginti chat
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
Inside chat, type normal requests such as `write a small Python CLI app with tests`. The default is Docker workspace mode with approved package installs, so coding, plotting, and LaTeX tasks can set up project-local tools without touching the host. Use `/help` for commands, `/login` or `/auth` to paste a provider key, `/instructions` to inspect `AGINTI.md`, `/latex on` for PDF work, `/docker off` only when you intentionally want host mode, `/sessions` to list project runs, and `/resume latest` or `/resume <session-id>` to continue work. Type `/` then Tab for command completion. `Ctrl+J` inserts a new line in the colored input panel, Enter sends, arrow keys move through wrapped multiline input, and `Ctrl+A`/`Ctrl+E` jump to the current line start/end. During an active run, Enter sends the draft as an ASAP pipe message (`→`) and Tab queues it for after the run (`↳`); ASAP messages are consumed
|
|
70
|
+
Inside chat, type normal requests such as `write a small Python CLI app with tests`. The default is Docker workspace mode with approved package installs, so coding, plotting, and LaTeX tasks can set up project-local tools without touching the host. Use `/help` for commands, `/login` or `/auth` to paste a provider key, `/instructions` to inspect `AGINTI.md`, `/latex on` for PDF work, `/docker off` only when you intentionally want host mode, `/sessions` to list project runs, and `/resume latest` or `/resume <session-id>` to continue work. Type `/` then Tab for command completion. `Ctrl+J` inserts a new line in the colored input panel, Enter sends, arrow keys move through wrapped multiline input, and `Ctrl+A`/`Ctrl+E` jump to the current line start/end. During an active run, Enter sends the draft as an ASAP pipe message (`→`) and Tab queues it for after the run (`↳`); ASAP messages are consumed before after-finish queued prompts, Alt+Up edits the last piped message, and Shift+Left edits the last after-finish queued message. Idle Esc is ignored so it does not disturb the input panel; during a run, Esc waits when `→` messages are pending and otherwise stops the run cleanly. Ctrl+C always stops and prints the resume command. The input panel always shows the current `cwd` footer and a single live status row, so long goals and tool updates are compacted instead of flooding the transcript. Assistant responses start on a fresh line after the `aginti>` header with a colored response gutter and render common Markdown, including headings, inline code, bold text, lists, quotes, code fences, tables, and red/green patch diff lines. Resuming a session prints the full saved chat history with wrapped messages before the prompt.
|
|
71
71
|
|
|
72
72
|
`aginti init` creates `AGINTI.md` at the project root. This is the editable project-instruction file for both CLI and web runs, similar to `AGENTS.md` or project memory in other agents. Keep durable preferences, commands, and constraints there, but never secrets. You can edit it manually or ask in chat, for example: `update AGINTI.md to remember that this project uses pytest and npm run check`.
|
|
73
73
|
|
|
@@ -9,11 +9,11 @@ AgInTiFlow keeps CLI and web runs equivalent by using the project folder as the
|
|
|
9
9
|
|
|
10
10
|
When a run is active, the web chat and `aginti queue <session-id> "..."` append messages to the inbox instead of trying to mutate the running process directly. The web API exposes `GET /api/sessions/:id/inbox`, `POST /api/sessions/:id/inbox`, `PATCH /api/sessions/:id/inbox/:itemId`, and `DELETE /api/sessions/:id/inbox/:itemId` so browser users can inspect, edit, or remove pending pipe messages before the runner consumes them. The runner drains the inbox at safe boundaries: before each model step and after tool execution. This mirrors the event-queue style used by mature agent UIs while keeping the backend decoupled from any specific frontend.
|
|
11
11
|
|
|
12
|
-
The interactive CLI keeps the input panel visible while a run is working. Enter sends the current draft as an ASAP pipe message and displays it as `→`; the runner drains those messages before normal inbox items. Tab stores the draft as an after-finish queue item and displays it as `↳`; those prompts run only after the current run completes. Alt+Up moves the last pending `→` message back into the editor, and Shift+Left moves the last pending `↳` message back into the editor. The current command cwd is rendered below the input panel in both idle and running states.
|
|
12
|
+
The interactive CLI keeps the input panel visible while a run is working. Enter sends the current draft as an ASAP pipe message and displays it as `→`; the runner drains those messages before normal inbox items and before after-finish queued prompts. Tab stores the draft as an after-finish queue item and displays it as `↳`; those prompts run only after the current run completes. Alt+Up moves the last pending `→` message back into the editor, and Shift+Left moves the last pending `↳` message back into the editor. Idle Esc is ignored so it does not redraw the prompt into the transcript. During a run, Esc waits when `→` pipe messages are still pending and stops the run only when no ASAP pipe message is pending; Ctrl+C always stops. The current command cwd is rendered below the input panel in both idle and running states.
|
|
13
13
|
|
|
14
14
|
The web UI uses a related but browser-appropriate pattern. Enter sends and Shift+Enter adds a newline. `Pipe to run` writes an ASAP inbox item shared with CLI. `Queue after finish` keeps a browser-local next prompt and starts it after the current web-owned run finishes. Both lanes render in a pending panel with Edit and Remove buttons instead of terminal-only keybindings.
|
|
15
15
|
|
|
16
|
-
Runs can be stopped without corrupting session state. The CLI listens for
|
|
16
|
+
Runs can be stopped without corrupting session state. The CLI listens for Ctrl+C during an active run, and Esc stops only when no ASAP pipe message is waiting to be applied. The web UI exposes a Stop button plus Esc. Stop paths send an abort signal, persist `session.stopped`, and leave the session resumable through `aginti resume <session-id>`.
|
|
17
17
|
|
|
18
18
|
Default execution is Docker workspace mode with package installs approved inside the sandbox. The project is mounted at `/workspace`; persistent agent toolchain folders are mounted at `/aginti-home`, `/aginti-cache`, and `/aginti-env` from `~/.agintiflow/docker/`. Python, conda, and other language-level environments should be installed under `/aginti-env` so they survive across runs. Apt/apk package changes are ephemeral unless the Docker image is rebuilt.
|
|
19
19
|
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@ import fs from "node:fs/promises";
|
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { buildPromptLayout, stripMarkdown } from "../src/interactive-cli.js";
|
|
7
|
+
import { buildPromptLayout, classifyEscapeAction, stripMarkdown } from "../src/interactive-cli.js";
|
|
8
8
|
|
|
9
9
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
10
|
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "agintiflow-cli-chat-"));
|
|
@@ -112,6 +112,15 @@ try {
|
|
|
112
112
|
if (!queuedText.includes("run running · tool: apply_patch") || !queuedText.includes("→ apply this") || !queuedText.includes("↳ run this") || !queuedText.includes("cwd /tmp/aginti-project")) {
|
|
113
113
|
throw new Error("terminal prompt layout did not render live input queue and cwd footer");
|
|
114
114
|
}
|
|
115
|
+
if (classifyEscapeAction({ active: false }) !== "noop") {
|
|
116
|
+
throw new Error("idle Esc should not redraw or clear the prompt");
|
|
117
|
+
}
|
|
118
|
+
if (classifyEscapeAction({ active: true, pendingAsap: [{ content: "apply now" }] }) !== "wait-for-asap") {
|
|
119
|
+
throw new Error("active Esc should wait when ASAP pipe messages are pending");
|
|
120
|
+
}
|
|
121
|
+
if (classifyEscapeAction({ active: true, pendingAsap: [] }) !== "abort") {
|
|
122
|
+
throw new Error("active Esc should abort when no ASAP pipe messages are pending");
|
|
123
|
+
}
|
|
115
124
|
|
|
116
125
|
await runCli(["init"], "");
|
|
117
126
|
const instructions = await fs.readFile(path.join(tempRoot, "AGINTI.md"), "utf8");
|
|
@@ -163,7 +172,7 @@ try {
|
|
|
163
172
|
{
|
|
164
173
|
ok: true,
|
|
165
174
|
projectRoot: tempRoot,
|
|
166
|
-
checks: ["markdown-render", "markdown-table-no-duplicate", "patch-diff-render", "prompt-layout", "live-input-status-layout", "agent-response-gutter", "aginti-md", "instructions-command", "skills-command", "instructions-chat-edit", "interactive-chat", "mock-file-write", "run-status", "resume-latest", "resume-history-full"],
|
|
175
|
+
checks: ["markdown-render", "markdown-table-no-duplicate", "patch-diff-render", "prompt-layout", "escape-policy", "live-input-status-layout", "agent-response-gutter", "aginti-md", "instructions-command", "skills-command", "instructions-chat-edit", "interactive-chat", "mock-file-write", "run-status", "resume-latest", "resume-history-full"],
|
|
167
176
|
},
|
|
168
177
|
null,
|
|
169
178
|
2
|
package/src/interactive-cli.js
CHANGED
|
@@ -501,7 +501,7 @@ function printHelp() {
|
|
|
501
501
|
"Type / then Tab to autocomplete commands.",
|
|
502
502
|
"While a run is active, Enter pipes a message into the current run (→), Tab queues it after finish (↳).",
|
|
503
503
|
"Alt+Up edits the last piped message; Shift+Left edits the last queued message.",
|
|
504
|
-
"Esc or
|
|
504
|
+
"Esc is ignored while idle. During a run, Esc waits for pending → pipe messages or stops if none; Ctrl+C always stops.",
|
|
505
505
|
].join("\n")
|
|
506
506
|
);
|
|
507
507
|
}
|
|
@@ -793,6 +793,11 @@ function createAbortError(message = "Aborted with Ctrl+C") {
|
|
|
793
793
|
return error;
|
|
794
794
|
}
|
|
795
795
|
|
|
796
|
+
export function classifyEscapeAction({ active = false, pendingAsap = [] } = {}) {
|
|
797
|
+
if (!active) return "noop";
|
|
798
|
+
return Array.isArray(pendingAsap) && pendingAsap.length > 0 ? "wait-for-asap" : "abort";
|
|
799
|
+
}
|
|
800
|
+
|
|
796
801
|
function readTtyPrompt(options = {}) {
|
|
797
802
|
return new Promise((resolve, reject) => {
|
|
798
803
|
emitKeypressEvents(input);
|
|
@@ -966,10 +971,7 @@ function readTtyPrompt(options = {}) {
|
|
|
966
971
|
return;
|
|
967
972
|
}
|
|
968
973
|
if (key.name === "escape") {
|
|
969
|
-
|
|
970
|
-
cursor = 0;
|
|
971
|
-
preferredColumn = null;
|
|
972
|
-
redraw();
|
|
974
|
+
if (classifyEscapeAction({ active: false }) === "noop") return;
|
|
973
975
|
return;
|
|
974
976
|
}
|
|
975
977
|
if (key.ctrl || key.meta) return;
|
|
@@ -1192,6 +1194,13 @@ class LiveRunInput {
|
|
|
1192
1194
|
return;
|
|
1193
1195
|
}
|
|
1194
1196
|
if (key.name === "escape") {
|
|
1197
|
+
const action = classifyEscapeAction({ active: true, pendingAsap: this.pendingAsap });
|
|
1198
|
+
if (action === "wait-for-asap") {
|
|
1199
|
+
const count = this.pendingAsap.length;
|
|
1200
|
+
this.setStatus(`running · waiting to apply ${count} asap pipe message${count === 1 ? "" : "s"}`);
|
|
1201
|
+
this.redraw();
|
|
1202
|
+
return;
|
|
1203
|
+
}
|
|
1195
1204
|
this.controller.abort(new Error("Interrupted by escape."));
|
|
1196
1205
|
return;
|
|
1197
1206
|
}
|