agent.libx.js 0.94.8 → 0.94.10
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 -0
- package/dist/cli.d.ts +9 -1
- package/dist/cli.js +102 -3
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -108,6 +108,7 @@ agentx --resume <id> "…" # resume a specific session
|
|
|
108
108
|
- **Diffs** — every `Edit`/`Write`/`MultiEdit` renders a colorized `+/-` diff (TTY-gated; plain when piped).
|
|
109
109
|
- **Slash commands** — `/help /tools /model /compact /memory /clear /sessions /resume /commands /init`; `/compact <focus>` preserves matching lines from the folded span; `/memory` opens the memory index in `$EDITOR`; user-defined `./.agent/commands/<name>.md` are invokable directly as `/<name>` (the same registry the model's `SlashCommand` tool uses).
|
|
110
110
|
- **Live chrome** — the thinking spinner shows elapsed seconds + `esc to interrupt`; the terminal tab title tracks the session topic; a bell rings when a long (>10s) turn finishes in a backgrounded tab; the footer warns at 80%/90% context pressure and auto-trims announce themselves.
|
|
111
|
+
- **`/transcript [n]`** — the full session transcript including complete tool-result bodies (the past-turn equivalent of Ctrl-O live verbose), paged through `less`; **`/doctor`** — one-shot environment sanity check (keys, model pricing, config, session-store writability, memory, MCP mounts).
|
|
111
112
|
- **Project instructions** — `./AGENTS.md` (or `CLAUDE.md`) auto-loads into every run; `/init` scaffolds one.
|
|
112
113
|
- **Any provider** — set `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `GOOGLE_API_KEY` / `GROQ_API_KEY`; choose with `-m provider/model`.
|
|
113
114
|
- **@-file mentions & headless JSON** — reference files inline in a prompt with `@path` (e.g. `explain @src/Agent.ts`); script with `-p --output-format json` to get one machine-readable result object on stdout (activity stays on stderr).
|
package/dist/cli.d.ts
CHANGED
|
@@ -100,6 +100,14 @@ declare function condenseReplay(t: string): string;
|
|
|
100
100
|
* prompts, assistant narration, and a condensed line per tool action. Tool *results* are omitted
|
|
101
101
|
* (verbose) and inlined @-mention blocks are stripped from prompts. Pure → unit-testable. */
|
|
102
102
|
declare function formatHistory(messages: Message[]): string;
|
|
103
|
+
/** Render the FULL transcript — user prompts, assistant text, every tool call AND its complete
|
|
104
|
+
* result body — for `/transcript` (the past-turn equivalent of Ctrl-O live verbose; CC's
|
|
105
|
+
* transcript-viewer parity). `lastTurns` bounds output to the most recent N user turns.
|
|
106
|
+
* Each tool result is capped at `resultLines` lines with an elision marker. Pure → unit-testable. */
|
|
107
|
+
declare function formatTranscriptFull(messages: Message[], opts?: {
|
|
108
|
+
lastTurns?: number;
|
|
109
|
+
resultLines?: number;
|
|
110
|
+
}): string;
|
|
103
111
|
/** Render a transcript to portable Markdown (no ANSI) for `/export`. Same shape as formatHistory —
|
|
104
112
|
* user prompts + assistant narration + one quoted line per tool action; tool results omitted. Pure → unit-testable. */
|
|
105
113
|
declare function exportMarkdown(meta: {
|
|
@@ -204,4 +212,4 @@ declare function jsonResult(res: RunResult, session: SessionData): {
|
|
|
204
212
|
*/
|
|
205
213
|
declare function readMultiline(readLine: (continuing: boolean) => Promise<string | null>): Promise<string | null>;
|
|
206
214
|
|
|
207
|
-
export { type PermMode, appendMemoryNote, cacheMultipliers, condenseReplay, costOf, estimateTranscriptTokens, expandMentions, exportMarkdown, fmtUsd, formatHistory, formatStatus, jsonResult, parseArgs, pastePathClassifier, readImageParts, readMultiline, resolvePermMode, runShellLine };
|
|
215
|
+
export { type PermMode, appendMemoryNote, cacheMultipliers, condenseReplay, costOf, estimateTranscriptTokens, expandMentions, exportMarkdown, fmtUsd, formatHistory, formatStatus, formatTranscriptFull, jsonResult, parseArgs, pastePathClassifier, readImageParts, readMultiline, resolvePermMode, runShellLine };
|
package/dist/cli.js
CHANGED
|
@@ -1619,7 +1619,7 @@ var init_tools_shell = __esm({
|
|
|
1619
1619
|
|
|
1620
1620
|
// cli/cli.ts
|
|
1621
1621
|
import { createInterface } from "readline/promises";
|
|
1622
|
-
import { existsSync as existsSync8, readFileSync as readFileSync5, appendFileSync, mkdirSync as mkdirSync7, writeFileSync as writeFileSync6, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
|
|
1622
|
+
import { existsSync as existsSync8, readFileSync as readFileSync5, appendFileSync, mkdirSync as mkdirSync7, writeFileSync as writeFileSync6, readdirSync as readdirSync2, statSync as statSync3, unlinkSync as unlinkSync2 } from "fs";
|
|
1623
1623
|
import { homedir as homedir6, tmpdir as tmpdir2 } from "os";
|
|
1624
1624
|
|
|
1625
1625
|
// cli/clipboard.ts
|
|
@@ -7410,7 +7410,8 @@ var EditorState = class _EditorState {
|
|
|
7410
7410
|
this.hits = r.hits;
|
|
7411
7411
|
this.token = r.token;
|
|
7412
7412
|
this.describe = r.describe;
|
|
7413
|
-
|
|
7413
|
+
const exact = r.hits.length === 1 && r.hits[0] === r.token;
|
|
7414
|
+
this.menuOpen = r.hits.length > 0 && (!exact || r.token.startsWith("/"));
|
|
7414
7415
|
if (this.sel >= r.hits.length) this.sel = 0;
|
|
7415
7416
|
}
|
|
7416
7417
|
// ── Editor undo (Ctrl-_): snapshot before every mutation, pop to restore ──
|
|
@@ -8629,7 +8630,7 @@ Project instructions: ./AGENTS.md or ./CLAUDE.md are auto-loaded (scaffold with
|
|
|
8629
8630
|
Auto-loaded from ./.agent/: commands/, skills/, memory/, agents/.
|
|
8630
8631
|
|
|
8631
8632
|
REPL shortcuts: !<cmd> runs a shell command inline \xB7 #<note> saves a memory \xB7 @path inlines a file
|
|
8632
|
-
REPL slash commands: /help /version /tools /permissions /status /cost /context /cwd /model /reasoning /config /rename /compact /memory /rewind /undo /clear /sessions /resume /commands /skills /mcp /init /export /paste /goal /exit (duplex: /act /think /tasks /voice /voice-model /think-model)
|
|
8633
|
+
REPL slash commands: /help /version /tools /permissions /status /cost /context /transcript /doctor /cwd /model /reasoning /config /rename /compact /memory /rewind /undo /clear /sessions /resume /commands /skills /mcp /init /export /paste /goal /exit (duplex: /act /think /tasks /voice /voice-model /think-model)
|
|
8633
8634
|
REPL completion: type / (commands+skills) or @ (files) for a LIVE menu \u2014 \u2191/\u2193 select, \u23CE/Tab accept, Esc dismiss.
|
|
8634
8635
|
REPL multi-line: Option/Alt+Enter inserts a newline, or end a line with \\ to continue. Esc cancels a running turn / clears the input line; double-Esc jumps back to edit a previous message.
|
|
8635
8636
|
REPL shortcuts: Shift+Tab cycles permission posture (ask \u2192 accept-edits \u2192 plan) \xB7 Alt+T toggles reasoning \xB7 Alt+P switches model \xB7 Ctrl+O toggles verbose tool output \xB7 \u2192 or Tab accepts the dim history ghost-suggestion \xB7 Alt+S/Ctrl+S stash/unstash.
|
|
@@ -8859,6 +8860,44 @@ function formatHistory(messages) {
|
|
|
8859
8860
|
out.push(dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
|
|
8860
8861
|
return out.join("");
|
|
8861
8862
|
}
|
|
8863
|
+
function formatTranscriptFull(messages, opts) {
|
|
8864
|
+
const cap = opts?.resultLines ?? 200;
|
|
8865
|
+
let shown = messages.filter((m) => m.role !== "system");
|
|
8866
|
+
if (opts?.lastTurns) {
|
|
8867
|
+
const userIdxs = shown.map((m, i) => m.role === "user" ? i : -1).filter((i) => i >= 0);
|
|
8868
|
+
if (userIdxs.length > opts.lastTurns) shown = shown.slice(userIdxs[userIdxs.length - opts.lastTurns]);
|
|
8869
|
+
}
|
|
8870
|
+
if (!shown.length) return dim(" (empty transcript)\n");
|
|
8871
|
+
const results = /* @__PURE__ */ new Map();
|
|
8872
|
+
for (const m of shown) if (m.role === "tool" && m.tool_call_id) results.set(m.tool_call_id, m);
|
|
8873
|
+
const clip = (s) => {
|
|
8874
|
+
const lines = s.split("\n");
|
|
8875
|
+
return lines.length > cap ? lines.slice(0, cap).join("\n") + `
|
|
8876
|
+
\u2026 (+${lines.length - cap} more lines)` : s;
|
|
8877
|
+
};
|
|
8878
|
+
const out = [dim("\n \u2500\u2500 transcript \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n")];
|
|
8879
|
+
for (const m of shown) {
|
|
8880
|
+
if (m.role === "user") {
|
|
8881
|
+
const t = contentText(m.content).trim();
|
|
8882
|
+
if (t) out.push("\n" + bold(cyan(" \u203A ")) + t.replace(/\n/g, "\n ") + "\n");
|
|
8883
|
+
} else if (m.role === "assistant") {
|
|
8884
|
+
const at = contentText(m.content).trim();
|
|
8885
|
+
if (at) out.push(" " + at.replace(/\n/g, "\n ") + "\n");
|
|
8886
|
+
for (const tc of m.tool_calls ?? []) {
|
|
8887
|
+
let args = {};
|
|
8888
|
+
try {
|
|
8889
|
+
args = JSON.parse(tc.function.arguments || "{}");
|
|
8890
|
+
} catch {
|
|
8891
|
+
}
|
|
8892
|
+
out.push(cyan(" \u2699 ") + tc.function.name + dim(" " + summarizeCall(tc.function.name, args)) + "\n");
|
|
8893
|
+
const r = results.get(tc.id);
|
|
8894
|
+
if (r) out.push(dim(" " + clip(contentText(r.content).trimEnd()).replace(/\n/g, "\n ")) + "\n");
|
|
8895
|
+
}
|
|
8896
|
+
}
|
|
8897
|
+
}
|
|
8898
|
+
out.push(dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n"));
|
|
8899
|
+
return out.join("");
|
|
8900
|
+
}
|
|
8862
8901
|
function exportMarkdown(meta, messages) {
|
|
8863
8902
|
const shown = messages.filter((m) => m.role !== "system");
|
|
8864
8903
|
const stamp = meta.created ? new Date(meta.created).toISOString() : "";
|
|
@@ -10044,6 +10083,65 @@ ${extra}` : body);
|
|
|
10044
10083
|
`));
|
|
10045
10084
|
}
|
|
10046
10085
|
},
|
|
10086
|
+
transcript: {
|
|
10087
|
+
desc: "full session transcript incl. complete tool results \u2014 /transcript [n] (last n turns), paged via less",
|
|
10088
|
+
run: async (a) => {
|
|
10089
|
+
const n = a[0] ? Math.max(1, Number(a[0]) || 1) : void 0;
|
|
10090
|
+
const text = formatTranscriptFull(face.transcript, { lastTurns: n });
|
|
10091
|
+
if (tty && text.split("\n").length > (process.stderr.rows ?? 40)) {
|
|
10092
|
+
const wasRaw = process.stdin.isTTY && process.stdin.isRaw;
|
|
10093
|
+
if (wasRaw) process.stdin.setRawMode(false);
|
|
10094
|
+
try {
|
|
10095
|
+
const { spawnSync: spawnSync3 } = await import("child_process");
|
|
10096
|
+
const r = spawnSync3("less", ["-R"], { input: text, stdio: ["pipe", "inherit", "inherit"] });
|
|
10097
|
+
if (r.error) err(text);
|
|
10098
|
+
} finally {
|
|
10099
|
+
if (wasRaw) process.stdin.setRawMode(true);
|
|
10100
|
+
}
|
|
10101
|
+
} else err(text);
|
|
10102
|
+
}
|
|
10103
|
+
},
|
|
10104
|
+
doctor: {
|
|
10105
|
+
desc: "environment sanity check \u2014 keys, config, sessions, memory, MCP, model pricing",
|
|
10106
|
+
run: async () => {
|
|
10107
|
+
const ok = (s) => err(green(" \u2713 ") + s + "\n");
|
|
10108
|
+
const warn = (s) => err(yellow(" \u26A0 ") + s + "\n");
|
|
10109
|
+
const bad = (s) => err(red(" \u2717 ") + s + "\n");
|
|
10110
|
+
err(dim(` agentx v${VERSION} \xB7 bun ${process.versions.bun ?? "?"} \xB7 ${process.platform}
|
|
10111
|
+
`));
|
|
10112
|
+
const keys = ["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GOOGLE_API_KEY", "GROQ_API_KEY"].filter((k) => process.env[k]);
|
|
10113
|
+
keys.length ? ok(`provider keys: ${keys.join(", ")}`) : bad("no provider keys set (ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_API_KEY / GROQ_API_KEY)");
|
|
10114
|
+
const info = getModelInfo(work.model);
|
|
10115
|
+
info?.pricing ? ok(`model ${work.model} \u2014 priced (${info.pricing.inputCostPer1K}/${info.pricing.outputCostPer1K} per 1k in/out)`) : warn(`model ${work.model} \u2014 no pricing in the catalog (costs will show ~$0; verify the id)`);
|
|
10116
|
+
const cfgFiles = ["ts", "js", "json"].flatMap((e) => [`${cwd}/.agent/config.${e}`, `${homedir6()}/.agent/config.${e}`]).filter((p) => existsSync8(p));
|
|
10117
|
+
cfgFiles.length ? ok(`config: ${cfgFiles.join(", ")}`) : warn("no .agent/config.* found (project or ~) \u2014 running on defaults");
|
|
10118
|
+
try {
|
|
10119
|
+
const probe = `${cwd}/.agent/sessions/.doctor-probe`;
|
|
10120
|
+
mkdirSync7(`${cwd}/.agent/sessions`, { recursive: true });
|
|
10121
|
+
writeFileSync6(probe, "ok");
|
|
10122
|
+
unlinkSync2(probe);
|
|
10123
|
+
ok(`session store writable (${cwd}/.agent/sessions)`);
|
|
10124
|
+
} catch (e) {
|
|
10125
|
+
bad(`session store not writable: ${e?.message ?? e}`);
|
|
10126
|
+
}
|
|
10127
|
+
const memDir = primaryMemDir(face.options.memoryDir, adot("memory"));
|
|
10128
|
+
try {
|
|
10129
|
+
const idx = await face.options.fs.readFile(`${memDir}/MEMORY.md`);
|
|
10130
|
+
ok(`memory: ${memDir} (${idx.split("\n").filter((l) => l.startsWith("- ")).length} pointer(s))`);
|
|
10131
|
+
} catch {
|
|
10132
|
+
warn(`memory: ${memDir} \u2014 no MEMORY.md yet (save one with #<note>)`);
|
|
10133
|
+
}
|
|
10134
|
+
const conf = Object.keys(cfg.mcpServers ?? {});
|
|
10135
|
+
const up = new Set(mounted.map((m) => m.name));
|
|
10136
|
+
const down = conf.filter((n) => !up.has(n) && !cfg.mcpServers?.[n]?.disabled);
|
|
10137
|
+
if (!conf.length && !mounted.length) ok("mcp: none configured");
|
|
10138
|
+
else if (down.length) bad(`mcp: ${down.length} configured server(s) not mounted: ${down.join(", ")} (try /mcp reconnect <name>)`);
|
|
10139
|
+
else ok(`mcp: ${mounted.length} server(s) mounted${conf.length ? ` (${conf.length} configured)` : ""}`);
|
|
10140
|
+
ok(`fs: ${args.vfs ? "sandbox (VFS)" : args.boddb ? `boddb (${args.boddb})` : "disk"} \xB7 checkpoints: ${args.vfs || args.boddb ? "in-memory/db" : "git-backed"}`);
|
|
10141
|
+
const hookCount = Object.values(cfg.hooks ?? {}).reduce((n, v) => n + (Array.isArray(v) ? v.length : 0), 0);
|
|
10142
|
+
if (hookCount) ok(`hooks: ${hookCount} configured`);
|
|
10143
|
+
}
|
|
10144
|
+
},
|
|
10047
10145
|
cwd: {
|
|
10048
10146
|
desc: "print the working directory (to switch, relaunch with -C <dir>)",
|
|
10049
10147
|
run: (a) => {
|
|
@@ -11221,6 +11319,7 @@ export {
|
|
|
11221
11319
|
fmtUsd,
|
|
11222
11320
|
formatHistory,
|
|
11223
11321
|
formatStatus,
|
|
11322
|
+
formatTranscriptFull,
|
|
11224
11323
|
jsonResult,
|
|
11225
11324
|
parseArgs,
|
|
11226
11325
|
pastePathClassifier,
|