agent-repl 0.1.2 → 0.1.3
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 +8 -0
- package/dist/pi-repl.js +84 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@ All notable changes to `agent-repl` are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.1.3] — 2026-10-19
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- Generated from pi-repl 0.8.4.
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- In the Summary and Full displays, output that doesn't end its line no longer runs into the done marker in Python, IPython, Julia, R and Clojure. The marker then stayed in the clean output, as in `c── done · id: … ──`.
|
|
14
|
+
|
|
7
15
|
## [0.1.2] — 2026-10-19
|
|
8
16
|
|
|
9
17
|
### Changed
|
package/dist/pi-repl.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// GENERATED by scripts/sync-from-pi-repl.mjs from pi-repl 0.8.
|
|
1
|
+
// GENERATED by scripts/sync-from-pi-repl.mjs from pi-repl 0.8.4 (6d9234a). Do not edit by hand:
|
|
2
2
|
// change pi-repl and re-sync. Identical to pi-repl's index.ts except that its Pi
|
|
3
3
|
// imports come from ./pi-compat/index.js.
|
|
4
4
|
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead, truncateTail, } from "./pi-compat/index.js";
|
|
@@ -887,9 +887,34 @@ function buildClojureDisplayStatements(display, indent = "") {
|
|
|
887
887
|
return [];
|
|
888
888
|
return display.prefixLines.map((line) => `${indent}(clojure.core/println ${JSON.stringify(line)})`);
|
|
889
889
|
}
|
|
890
|
+
// Prints the pane's cursor column, or exits non-zero; tmux gets 500 ms. A
|
|
891
|
+
// wrapper runs it with Node and ends a line before its footer unless it
|
|
892
|
+
// prints 0. Only the wrapper reads its output, so it never reaches the pane.
|
|
893
|
+
const CURSOR_COLUMN_QUERY = 'try { process.stdout.write(require("node:child_process").execFileSync("tmux", ["-N", "display-message", "-p", "-t", process.env.TMUX_PANE, "#{cursor_x}"], { encoding: "utf8", timeout: 500, killSignal: "SIGKILL", maxBuffer: 128, stdio: ["ignore", "pipe", "ignore"] }).trim()); } catch { process.exitCode = 1; }';
|
|
894
|
+
function buildPythonFooter(display) {
|
|
895
|
+
if (!display.enabled)
|
|
896
|
+
return [];
|
|
897
|
+
return [
|
|
898
|
+
" import subprocess as __pi_repl_subprocess",
|
|
899
|
+
" import sys as __pi_repl_sys",
|
|
900
|
+
" __pi_repl_column = ''",
|
|
901
|
+
" try:",
|
|
902
|
+
" __pi_repl_sys.stdout.flush()",
|
|
903
|
+
" __pi_repl_sys.stderr.flush()",
|
|
904
|
+
` __pi_repl_query = __pi_repl_subprocess.run([${JSON.stringify(process.execPath)}, '-e', ${JSON.stringify(CURSOR_COLUMN_QUERY)}], stdin=__pi_repl_subprocess.DEVNULL, stdout=__pi_repl_subprocess.PIPE, stderr=__pi_repl_subprocess.DEVNULL, timeout=5)`,
|
|
905
|
+
" if __pi_repl_query.returncode == 0:",
|
|
906
|
+
" __pi_repl_column = __pi_repl_query.stdout.decode('utf-8', 'replace').strip()",
|
|
907
|
+
// run() kills the query on any exception. Ctrl-C here must not skip the done file.
|
|
908
|
+
" except BaseException:",
|
|
909
|
+
" pass",
|
|
910
|
+
" if __pi_repl_column != '0':",
|
|
911
|
+
" __pi_repl_builtins.print()",
|
|
912
|
+
...display.suffixLines.map((line) => ` __pi_repl_builtins.print(${JSON.stringify(line)})`),
|
|
913
|
+
];
|
|
914
|
+
}
|
|
890
915
|
function buildPythonControlSource(runtime, code, doneFile, display) {
|
|
891
916
|
const prefix = buildPythonDisplayStatements(display);
|
|
892
|
-
const completion = display
|
|
917
|
+
const completion = buildPythonFooter(display);
|
|
893
918
|
if (runtime === "ipython") {
|
|
894
919
|
return [
|
|
895
920
|
"from pathlib import Path as __pi_repl_path",
|
|
@@ -923,8 +948,25 @@ function buildPythonControlSource(runtime, code, doneFile, display) {
|
|
|
923
948
|
` __pi_repl_path(${JSON.stringify(doneFile)}).write_text('done\\n', encoding='utf-8')`,
|
|
924
949
|
].join("\n");
|
|
925
950
|
}
|
|
951
|
+
function buildJuliaFooter(display) {
|
|
952
|
+
if (!display.enabled)
|
|
953
|
+
return [];
|
|
954
|
+
const query = `Cmd([${juliaStringLiteral(process.execPath)}, "-e", ${juliaStringLiteral(CURSOR_COLUMN_QUERY)}])`;
|
|
955
|
+
return [
|
|
956
|
+
' local __pi_repl_column = ""',
|
|
957
|
+
// read throws if the query fails; catch also takes an interrupt here.
|
|
958
|
+
" try",
|
|
959
|
+
" flush(stdout)",
|
|
960
|
+
" flush(stderr)",
|
|
961
|
+
` __pi_repl_column = strip(read(pipeline(${query}, stdin=devnull, stderr=devnull), String))`,
|
|
962
|
+
" catch",
|
|
963
|
+
" end",
|
|
964
|
+
' __pi_repl_column == "0" || Base.println()',
|
|
965
|
+
...display.suffixLines.map((line) => ` Base.println(${juliaStringLiteral(line)})`),
|
|
966
|
+
];
|
|
967
|
+
}
|
|
926
968
|
function buildJuliaControlSource(code, doneFile, display) {
|
|
927
|
-
const completion = display
|
|
969
|
+
const completion = buildJuliaFooter(display);
|
|
928
970
|
return [
|
|
929
971
|
...buildJuliaDisplayStatements(display),
|
|
930
972
|
"try",
|
|
@@ -940,8 +982,20 @@ function buildJuliaControlSource(code, doneFile, display) {
|
|
|
940
982
|
"end",
|
|
941
983
|
].join("\n");
|
|
942
984
|
}
|
|
985
|
+
function buildRFooter(display) {
|
|
986
|
+
if (!display.enabled)
|
|
987
|
+
return [];
|
|
988
|
+
return [
|
|
989
|
+
" try({ flush(stdout()); flush(stderr()) }, silent = TRUE)",
|
|
990
|
+
// system2 quotes the command but not its arguments. A failed query
|
|
991
|
+
// sets a status; an error or Ctrl-C here gives NULL, not a lost done file.
|
|
992
|
+
` .__pi_repl_column <- tryCatch(suppressWarnings(system2(${JSON.stringify(process.execPath)}, c("-e", ${JSON.stringify(shellQuote(CURSOR_COLUMN_QUERY))}), stdout = TRUE, stderr = FALSE)), error = function(e) NULL, interrupt = function(e) NULL)`,
|
|
993
|
+
' if (!is.null(attr(.__pi_repl_column, "status")) || !identical(trimws(paste(.__pi_repl_column, collapse = "")), "0")) base::cat("\\n")',
|
|
994
|
+
...display.suffixLines.map((line) => ` base::cat(${JSON.stringify(`${line}\n`)})`),
|
|
995
|
+
];
|
|
996
|
+
}
|
|
943
997
|
function buildRControlSource(code, doneFile, display) {
|
|
944
|
-
const completion = display
|
|
998
|
+
const completion = buildRFooter(display);
|
|
945
999
|
return [
|
|
946
1000
|
"local({",
|
|
947
1001
|
...buildRDisplayStatements(display, " "),
|
|
@@ -1065,8 +1119,33 @@ function buildJavaControlSource(code, doneFile, display) {
|
|
|
1065
1119
|
// stays in the outer driver, outside this source file's parser state.
|
|
1066
1120
|
return [...prefix, code.replace(/\r/g, "").trimEnd(), ""].join("\n");
|
|
1067
1121
|
}
|
|
1122
|
+
function buildClojureFooter(display) {
|
|
1123
|
+
if (!display.enabled)
|
|
1124
|
+
return [];
|
|
1125
|
+
const builder = `(java.lang.ProcessBuilder. ^java.util.List [${JSON.stringify(process.execPath)} "-e" ${JSON.stringify(CURSOR_COLUMN_QUERY)}])`;
|
|
1126
|
+
return [
|
|
1127
|
+
" (try (.flush *out*) (.flush *err*) (catch Throwable _))",
|
|
1128
|
+
// An interrupt left pending by the code would end the wait at once, so
|
|
1129
|
+
// it is cleared for the query and restored afterwards, as is one that
|
|
1130
|
+
// arrives during the wait. The query is killed on every path.
|
|
1131
|
+
" (let [pi-repl-interrupted (volatile! (Thread/interrupted))",
|
|
1132
|
+
` pi-repl-query (try (.start (.redirectError ${builder} java.lang.ProcessBuilder$Redirect/DISCARD)) (catch Throwable _ nil))`,
|
|
1133
|
+
" pi-repl-column (when pi-repl-query",
|
|
1134
|
+
" (try",
|
|
1135
|
+
" (.close (.getOutputStream pi-repl-query))",
|
|
1136
|
+
" (when (and (.waitFor pi-repl-query 5 java.util.concurrent.TimeUnit/SECONDS) (zero? (.exitValue pi-repl-query)))",
|
|
1137
|
+
" (.trim ^String (slurp (.getInputStream pi-repl-query))))",
|
|
1138
|
+
" (catch InterruptedException _ (vreset! pi-repl-interrupted true) nil)",
|
|
1139
|
+
" (catch Throwable _ nil)",
|
|
1140
|
+
" (finally (.destroyForcibly pi-repl-query))))]",
|
|
1141
|
+
" (when @pi-repl-interrupted (.interrupt (Thread/currentThread)))",
|
|
1142
|
+
' (when-not (= pi-repl-column "0") (clojure.core/println))',
|
|
1143
|
+
...display.suffixLines.map((line) => ` (clojure.core/println ${JSON.stringify(line)})`),
|
|
1144
|
+
" nil)",
|
|
1145
|
+
];
|
|
1146
|
+
}
|
|
1068
1147
|
function buildClojureControlSource(code, doneFile, display) {
|
|
1069
|
-
const completion = display
|
|
1148
|
+
const completion = buildClojureFooter(display);
|
|
1070
1149
|
return [
|
|
1071
1150
|
"(let [code " + JSON.stringify(code) + "]",
|
|
1072
1151
|
...buildClojureDisplayStatements(display, " "),
|
package/package.json
CHANGED