@mariozechner/pi-coding-agent 0.13.2 → 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/CHANGELOG.md +21 -1
- package/README.md +62 -0
- package/dist/compaction.d.ts.map +1 -1
- package/dist/compaction.js +5 -2
- package/dist/compaction.js.map +1 -1
- package/dist/export-html.d.ts.map +1 -1
- package/dist/export-html.js +52 -25
- package/dist/export-html.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +120 -9
- package/dist/main.js.map +1 -1
- package/dist/messages.d.ts +43 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +71 -0
- package/dist/messages.js.map +1 -0
- package/dist/model-config.d.ts.map +1 -1
- package/dist/model-config.js +9 -0
- package/dist/model-config.js.map +1 -1
- package/dist/settings-manager.d.ts +6 -3
- package/dist/settings-manager.d.ts.map +1 -1
- package/dist/settings-manager.js +7 -0
- package/dist/settings-manager.js.map +1 -1
- package/dist/shell.d.ts +16 -0
- package/dist/shell.d.ts.map +1 -0
- package/dist/shell.js +108 -0
- package/dist/shell.js.map +1 -0
- package/dist/theme/dark.json +4 -1
- package/dist/theme/light.json +4 -1
- package/dist/theme/theme-schema.json +28 -0
- package/dist/theme/theme.d.ts +3 -2
- package/dist/theme/theme.d.ts.map +1 -1
- package/dist/theme/theme.js +32 -3
- package/dist/theme/theme.js.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +3 -107
- package/dist/tools/bash.js.map +1 -1
- package/dist/tui/bash-execution.d.ts +33 -0
- package/dist/tui/bash-execution.d.ts.map +1 -0
- package/dist/tui/bash-execution.js +134 -0
- package/dist/tui/bash-execution.js.map +1 -0
- package/dist/tui/tui-renderer.d.ts +7 -1
- package/dist/tui/tui-renderer.d.ts.map +1 -1
- package/dist/tui/tui-renderer.js +225 -10
- package/dist/tui/tui-renderer.js.map +1 -1
- package/package.json +4 -4
- package/dist/fuzzy.test.d.ts +0 -2
- package/dist/fuzzy.test.d.ts.map +0 -1
- package/dist/fuzzy.test.js +0 -76
- package/dist/fuzzy.test.js.map +0 -1
package/dist/main.js
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import { Agent, ProviderTransport } from "@mariozechner/pi-agent-core";
|
|
2
2
|
import { ProcessTerminal, TUI } from "@mariozechner/pi-tui";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { spawn } from "child_process";
|
|
5
|
+
import { randomBytes } from "crypto";
|
|
6
|
+
import { createWriteStream, existsSync, readFileSync, statSync } from "fs";
|
|
7
|
+
import { homedir, tmpdir } from "os";
|
|
6
8
|
import { extname, join, resolve } from "path";
|
|
9
|
+
import stripAnsi from "strip-ansi";
|
|
7
10
|
import { getChangelogPath, getNewEntries, parseChangelog } from "./changelog.js";
|
|
8
11
|
import { calculateContextTokens, compact, shouldCompact } from "./compaction.js";
|
|
9
12
|
import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR, getAgentDir, getModelsPath, getReadmePath, VERSION, } from "./config.js";
|
|
10
13
|
import { exportFromFile } from "./export-html.js";
|
|
14
|
+
import { messageTransformer } from "./messages.js";
|
|
11
15
|
import { findModel, getApiKeyForModel, getAvailableModels } from "./model-config.js";
|
|
12
16
|
import { loadSessionFromEntries, SessionManager } from "./session-manager.js";
|
|
13
17
|
import { SettingsManager } from "./settings-manager.js";
|
|
18
|
+
import { getShellConfig } from "./shell.js";
|
|
14
19
|
import { expandSlashCommand, loadSlashCommands } from "./slash-commands.js";
|
|
15
20
|
import { initTheme } from "./theme/theme.js";
|
|
16
21
|
import { allTools, codingTools } from "./tools/index.js";
|
|
22
|
+
import { DEFAULT_MAX_BYTES, truncateTail } from "./tools/truncate.js";
|
|
17
23
|
import { ensureTool } from "./tools-manager.js";
|
|
18
24
|
import { SessionSelectorComponent } from "./tui/session-selector.js";
|
|
19
25
|
import { TuiRenderer } from "./tui/tui-renderer.js";
|
|
@@ -88,11 +94,16 @@ function parseArgs(args) {
|
|
|
88
94
|
}
|
|
89
95
|
else if (arg === "--thinking" && i + 1 < args.length) {
|
|
90
96
|
const level = args[++i];
|
|
91
|
-
if (level === "off" ||
|
|
97
|
+
if (level === "off" ||
|
|
98
|
+
level === "minimal" ||
|
|
99
|
+
level === "low" ||
|
|
100
|
+
level === "medium" ||
|
|
101
|
+
level === "high" ||
|
|
102
|
+
level === "xhigh") {
|
|
92
103
|
result.thinking = level;
|
|
93
104
|
}
|
|
94
105
|
else {
|
|
95
|
-
console.error(chalk.yellow(`Warning: Invalid thinking level "${level}". Valid values: off, minimal, low, medium, high`));
|
|
106
|
+
console.error(chalk.yellow(`Warning: Invalid thinking level "${level}". Valid values: off, minimal, low, medium, high, xhigh`));
|
|
96
107
|
}
|
|
97
108
|
}
|
|
98
109
|
else if (arg === "--print" || arg === "-p") {
|
|
@@ -212,7 +223,7 @@ ${chalk.bold("Options:")}
|
|
|
212
223
|
--models <patterns> Comma-separated model patterns for quick cycling with Ctrl+P
|
|
213
224
|
--tools <tools> Comma-separated list of tools to enable (default: read,bash,edit,write)
|
|
214
225
|
Available: read, bash, edit, write, grep, find, ls
|
|
215
|
-
--thinking <level> Set thinking level: off, minimal, low, medium, high
|
|
226
|
+
--thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh
|
|
216
227
|
--export <file> Export session file to HTML and exit
|
|
217
228
|
--help, -h Show this help
|
|
218
229
|
|
|
@@ -509,7 +520,12 @@ async function resolveModelScope(patterns) {
|
|
|
509
520
|
let thinkingLevel = "off";
|
|
510
521
|
if (parts.length > 1) {
|
|
511
522
|
const level = parts[1];
|
|
512
|
-
if (level === "off" ||
|
|
523
|
+
if (level === "off" ||
|
|
524
|
+
level === "minimal" ||
|
|
525
|
+
level === "low" ||
|
|
526
|
+
level === "medium" ||
|
|
527
|
+
level === "high" ||
|
|
528
|
+
level === "xhigh") {
|
|
513
529
|
thinkingLevel = level;
|
|
514
530
|
}
|
|
515
531
|
else {
|
|
@@ -599,8 +615,8 @@ async function selectSession(sessionManager) {
|
|
|
599
615
|
ui.start();
|
|
600
616
|
});
|
|
601
617
|
}
|
|
602
|
-
async function runInteractiveMode(agent, sessionManager, settingsManager, version, changelogMarkdown = null, modelFallbackMessage = null, versionCheckPromise, scopedModels = [], initialMessages = [], initialMessage, initialAttachments, fdPath = null) {
|
|
603
|
-
const renderer = new TuiRenderer(agent, sessionManager, settingsManager, version, changelogMarkdown, scopedModels, fdPath);
|
|
618
|
+
async function runInteractiveMode(agent, sessionManager, settingsManager, version, changelogMarkdown = null, collapseChangelog = false, modelFallbackMessage = null, versionCheckPromise, scopedModels = [], initialMessages = [], initialMessage, initialAttachments, fdPath = null) {
|
|
619
|
+
const renderer = new TuiRenderer(agent, sessionManager, settingsManager, version, changelogMarkdown, collapseChangelog, scopedModels, fdPath);
|
|
604
620
|
// Initialize TUI (subscribes to agent events internally)
|
|
605
621
|
await renderer.init();
|
|
606
622
|
// Handle version check result when it completes (don't block)
|
|
@@ -687,6 +703,70 @@ async function runSingleShotMode(agent, _sessionManager, messages, mode, initial
|
|
|
687
703
|
}
|
|
688
704
|
}
|
|
689
705
|
}
|
|
706
|
+
/**
|
|
707
|
+
* Execute a bash command for RPC mode.
|
|
708
|
+
* Similar to tui-renderer's executeBashCommand but without streaming callbacks.
|
|
709
|
+
*/
|
|
710
|
+
async function executeRpcBashCommand(command) {
|
|
711
|
+
return new Promise((resolve, reject) => {
|
|
712
|
+
const { shell, args } = getShellConfig();
|
|
713
|
+
const child = spawn(shell, [...args, command], {
|
|
714
|
+
detached: true,
|
|
715
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
716
|
+
});
|
|
717
|
+
const chunks = [];
|
|
718
|
+
let chunksBytes = 0;
|
|
719
|
+
const maxChunksBytes = DEFAULT_MAX_BYTES * 2;
|
|
720
|
+
let tempFilePath;
|
|
721
|
+
let tempFileStream;
|
|
722
|
+
let totalBytes = 0;
|
|
723
|
+
const handleData = (data) => {
|
|
724
|
+
totalBytes += data.length;
|
|
725
|
+
// Start writing to temp file if exceeds threshold
|
|
726
|
+
if (totalBytes > DEFAULT_MAX_BYTES && !tempFilePath) {
|
|
727
|
+
const id = randomBytes(8).toString("hex");
|
|
728
|
+
tempFilePath = join(tmpdir(), `pi-bash-${id}.log`);
|
|
729
|
+
tempFileStream = createWriteStream(tempFilePath);
|
|
730
|
+
for (const chunk of chunks) {
|
|
731
|
+
tempFileStream.write(chunk);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
if (tempFileStream) {
|
|
735
|
+
tempFileStream.write(data);
|
|
736
|
+
}
|
|
737
|
+
// Keep rolling buffer
|
|
738
|
+
chunks.push(data);
|
|
739
|
+
chunksBytes += data.length;
|
|
740
|
+
while (chunksBytes > maxChunksBytes && chunks.length > 1) {
|
|
741
|
+
const removed = chunks.shift();
|
|
742
|
+
chunksBytes -= removed.length;
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
child.stdout?.on("data", handleData);
|
|
746
|
+
child.stderr?.on("data", handleData);
|
|
747
|
+
child.on("close", (code) => {
|
|
748
|
+
if (tempFileStream) {
|
|
749
|
+
tempFileStream.end();
|
|
750
|
+
}
|
|
751
|
+
// Combine buffered chunks
|
|
752
|
+
const fullBuffer = Buffer.concat(chunks);
|
|
753
|
+
const fullOutput = stripAnsi(fullBuffer.toString("utf-8")).replace(/\r/g, "");
|
|
754
|
+
const truncationResult = truncateTail(fullOutput);
|
|
755
|
+
resolve({
|
|
756
|
+
output: fullOutput,
|
|
757
|
+
exitCode: code,
|
|
758
|
+
truncationResult: truncationResult.truncated ? truncationResult : undefined,
|
|
759
|
+
fullOutputPath: tempFilePath,
|
|
760
|
+
});
|
|
761
|
+
});
|
|
762
|
+
child.on("error", (err) => {
|
|
763
|
+
if (tempFileStream) {
|
|
764
|
+
tempFileStream.end();
|
|
765
|
+
}
|
|
766
|
+
reject(err);
|
|
767
|
+
});
|
|
768
|
+
});
|
|
769
|
+
}
|
|
690
770
|
async function runRpcMode(agent, sessionManager, settingsManager) {
|
|
691
771
|
// Track if auto-compaction is in progress
|
|
692
772
|
let autoCompactionInProgress = false;
|
|
@@ -796,6 +876,35 @@ async function runRpcMode(agent, sessionManager, settingsManager) {
|
|
|
796
876
|
console.log(JSON.stringify({ type: "error", error: `Compaction failed: ${error.message}` }));
|
|
797
877
|
}
|
|
798
878
|
}
|
|
879
|
+
else if (input.type === "bash" && input.command) {
|
|
880
|
+
// Execute bash command and add to context
|
|
881
|
+
try {
|
|
882
|
+
const result = await executeRpcBashCommand(input.command);
|
|
883
|
+
// Create bash execution message
|
|
884
|
+
const bashMessage = {
|
|
885
|
+
role: "bashExecution",
|
|
886
|
+
command: input.command,
|
|
887
|
+
output: result.truncationResult?.content || result.output,
|
|
888
|
+
exitCode: result.exitCode,
|
|
889
|
+
cancelled: false,
|
|
890
|
+
truncated: result.truncationResult?.truncated || false,
|
|
891
|
+
fullOutputPath: result.fullOutputPath,
|
|
892
|
+
timestamp: Date.now(),
|
|
893
|
+
};
|
|
894
|
+
// Add to agent state and save to session
|
|
895
|
+
agent.appendMessage(bashMessage);
|
|
896
|
+
sessionManager.saveMessage(bashMessage);
|
|
897
|
+
// Initialize session if needed (same logic as message_end handler)
|
|
898
|
+
if (sessionManager.shouldInitializeSession(agent.state.messages)) {
|
|
899
|
+
sessionManager.startSession(agent.state);
|
|
900
|
+
}
|
|
901
|
+
// Emit bash_end event with the message
|
|
902
|
+
console.log(JSON.stringify({ type: "bash_end", message: bashMessage }));
|
|
903
|
+
}
|
|
904
|
+
catch (error) {
|
|
905
|
+
console.log(JSON.stringify({ type: "error", error: `Bash command failed: ${error.message}` }));
|
|
906
|
+
}
|
|
907
|
+
}
|
|
799
908
|
}
|
|
800
909
|
catch (error) {
|
|
801
910
|
// Output error as JSON
|
|
@@ -1049,6 +1158,7 @@ export async function main(args) {
|
|
|
1049
1158
|
thinkingLevel: initialThinking,
|
|
1050
1159
|
tools: selectedTools,
|
|
1051
1160
|
},
|
|
1161
|
+
messageTransformer,
|
|
1052
1162
|
queueMode: settingsManager.getQueueMode(),
|
|
1053
1163
|
transport: new ProviderTransport({
|
|
1054
1164
|
// Dynamic API key lookup based on current model's provider
|
|
@@ -1163,7 +1273,8 @@ export async function main(args) {
|
|
|
1163
1273
|
// Ensure fd tool is available for file autocomplete
|
|
1164
1274
|
const fdPath = await ensureTool("fd");
|
|
1165
1275
|
// Interactive mode - use TUI (may have initial messages from CLI args)
|
|
1166
|
-
|
|
1276
|
+
const collapseChangelog = settingsManager.getCollapseChangelog();
|
|
1277
|
+
await runInteractiveMode(agent, sessionManager, settingsManager, VERSION, changelogMarkdown, collapseChangelog, modelFallbackMessage, versionCheckPromise, scopedModels, parsed.messages, initialMessage, initialAttachments, fdPath);
|
|
1167
1278
|
}
|
|
1168
1279
|
else {
|
|
1169
1280
|
// Non-interactive mode (--print flag or --mode flag)
|