aiterm-mcp 0.12.0 → 0.12.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/dist/codex-stop-hook.js +5 -1
- package/dist/core.js +30 -4
- package/dist/grok-stop-hook.js +5 -1
- package/package.json +1 -1
package/dist/codex-stop-hook.js
CHANGED
|
@@ -77,7 +77,11 @@ function appendEvent(file, event) {
|
|
|
77
77
|
if (!st.isFile() || st.uid !== uid() || st.nlink !== 1 || (st.mode & 0o077) !== 0) {
|
|
78
78
|
fail(`event file が安全ではありません: ${file}`);
|
|
79
79
|
}
|
|
80
|
-
fs.writeSync(fd, line, undefined, "utf8");
|
|
80
|
+
const written = fs.writeSync(fd, line, undefined, "utf8");
|
|
81
|
+
if (written < Buffer.byteLength(line, "utf8")) {
|
|
82
|
+
fs.ftruncateSync(fd, st.size);
|
|
83
|
+
fail(`event file への書込みが途中で終了しました: ${file}`);
|
|
84
|
+
}
|
|
81
85
|
}
|
|
82
86
|
finally {
|
|
83
87
|
fs.closeSync(fd);
|
package/dist/core.js
CHANGED
|
@@ -48,6 +48,8 @@ const AGENT_DONE_SCREEN_SETTLE_MAX_POLLS = 5;
|
|
|
48
48
|
const AGENT_DONE_SCREEN_SETTLE_MIN_SAMPLES = 3;
|
|
49
49
|
const AGENT_SUBMIT_DELAY_MS = 250;
|
|
50
50
|
const AGENT_EVENT_MAX_BYTES = 1024 * 1024;
|
|
51
|
+
const AGENT_EVENT_TAIL_BYTES = 64 * 1024;
|
|
52
|
+
const AGENT_METADATA_NEGATIVE_CACHE_TTL_MS = 2_000;
|
|
51
53
|
const AGENT_TUI_READY_TIMEOUT_MS = 30_000;
|
|
52
54
|
const AGENT_TUI_READY_POLL_MS = 500;
|
|
53
55
|
const AGENT_TUI_READY_LINES = 45;
|
|
@@ -318,6 +320,7 @@ function existingAgentsDir() {
|
|
|
318
320
|
}
|
|
319
321
|
function cleanupAgentState(name) {
|
|
320
322
|
assertSessionName(name);
|
|
323
|
+
agentMetadataNegativeCache.delete(name);
|
|
321
324
|
const dir = existingAgentsDir();
|
|
322
325
|
if (!dir)
|
|
323
326
|
return;
|
|
@@ -1053,10 +1056,12 @@ export function killAll() {
|
|
|
1053
1056
|
/* agent state dir 不在等は無視 */
|
|
1054
1057
|
}
|
|
1055
1058
|
}
|
|
1059
|
+
agentMetadataNegativeCache.clear();
|
|
1056
1060
|
return "killed all sessions on this socket";
|
|
1057
1061
|
}
|
|
1058
1062
|
const DEFAULT_AGENT_DONE_TIMEOUT = 600;
|
|
1059
1063
|
const agentWaitLocks = new Set();
|
|
1064
|
+
const agentMetadataNegativeCache = new Map();
|
|
1060
1065
|
function normalizeAgentLauncherWait(v) {
|
|
1061
1066
|
if (v == null || v === "none")
|
|
1062
1067
|
return "none";
|
|
@@ -1798,9 +1803,16 @@ function tryLoadAgentMetadata(name) {
|
|
|
1798
1803
|
}
|
|
1799
1804
|
function latestAgentDoneEvent(meta) {
|
|
1800
1805
|
const size = safeStatSize(meta.event_file);
|
|
1801
|
-
if (size === 0
|
|
1806
|
+
if (size === 0)
|
|
1802
1807
|
return null;
|
|
1803
|
-
const
|
|
1808
|
+
const isTailRead = size > AGENT_EVENT_TAIL_BYTES;
|
|
1809
|
+
let text = readFileRange(meta.event_file, isTailRead ? size - AGENT_EVENT_TAIL_BYTES : 0, size).toString("utf8");
|
|
1810
|
+
if (isTailRead) {
|
|
1811
|
+
const firstNewline = text.indexOf("\n");
|
|
1812
|
+
if (firstNewline === -1)
|
|
1813
|
+
return null;
|
|
1814
|
+
text = text.slice(firstNewline + 1);
|
|
1815
|
+
}
|
|
1804
1816
|
let latest = null;
|
|
1805
1817
|
for (const line of text.split("\n")) {
|
|
1806
1818
|
if (!line.trim() || Buffer.byteLength(line, "utf8") > 64 * 1024)
|
|
@@ -1966,9 +1978,21 @@ function inferAgentFrontend(name, meta, screen) {
|
|
|
1966
1978
|
return "unknown";
|
|
1967
1979
|
}
|
|
1968
1980
|
function agentReadMetadataSuffix(name, screen) {
|
|
1969
|
-
const
|
|
1970
|
-
|
|
1981
|
+
const now = Date.now();
|
|
1982
|
+
const negativeCacheUntil = agentMetadataNegativeCache.get(name);
|
|
1983
|
+
if (negativeCacheUntil && negativeCacheUntil > now)
|
|
1971
1984
|
return "";
|
|
1985
|
+
let meta;
|
|
1986
|
+
try {
|
|
1987
|
+
meta = loadAgentMetadata(name);
|
|
1988
|
+
}
|
|
1989
|
+
catch (e) {
|
|
1990
|
+
if (e instanceof AitermError && e.message.includes("agent_done 管理セッションではありません")) {
|
|
1991
|
+
agentMetadataNegativeCache.set(name, now + AGENT_METADATA_NEGATIVE_CACHE_TTL_MS);
|
|
1992
|
+
}
|
|
1993
|
+
return "";
|
|
1994
|
+
}
|
|
1995
|
+
agentMetadataNegativeCache.delete(name);
|
|
1972
1996
|
const ev = latestAgentDoneEvent(meta);
|
|
1973
1997
|
const bits = [
|
|
1974
1998
|
"agent",
|
|
@@ -2445,6 +2469,8 @@ export function openAgent(kind, opts = {}) {
|
|
|
2445
2469
|
? createCodexAgentMetadata(sid, cwd, opts.prompt ? "pending" : "none", { model, effort })
|
|
2446
2470
|
: createGrokAgentMetadata(kind, sid, cwd, opts.prompt ? "pending" : "none")
|
|
2447
2471
|
: null;
|
|
2472
|
+
if (meta)
|
|
2473
|
+
agentMetadataNegativeCache.delete(sid);
|
|
2448
2474
|
launchNote = buildAgentLaunchNote(kind, model, effort, meta);
|
|
2449
2475
|
const cmd = buildAgentCmd(kind, binForCmd, model, effort, opts.prompt ?? null, meta);
|
|
2450
2476
|
const envPrefix = agentEnvPrefix(meta, sid);
|
package/dist/grok-stop-hook.js
CHANGED
|
@@ -75,7 +75,11 @@ function appendEvent(file, event) {
|
|
|
75
75
|
if (!st.isFile() || st.uid !== uid() || st.nlink !== 1 || (st.mode & 0o077) !== 0) {
|
|
76
76
|
fail(`event file が安全ではありません: ${file}`);
|
|
77
77
|
}
|
|
78
|
-
fs.writeSync(fd, line, undefined, "utf8");
|
|
78
|
+
const written = fs.writeSync(fd, line, undefined, "utf8");
|
|
79
|
+
if (written < Buffer.byteLength(line, "utf8")) {
|
|
80
|
+
fs.ftruncateSync(fd, st.size);
|
|
81
|
+
fail(`event file への書込みが途中で終了しました: ${file}`);
|
|
82
|
+
}
|
|
79
83
|
}
|
|
80
84
|
finally {
|
|
81
85
|
fs.closeSync(fd);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"mcpName": "io.github.kitepon-rgb/aiterm-mcp",
|
|
5
5
|
"description": "AI-driven persistent terminal as a local stdio MCP server (tmux-backed). Holds one local PTY; SSH and containers are just commands you send into it. Also launches interactive Codex/Grok/Composer agent TUIs in a persistent terminal. Token-reducing reads.",
|
|
6
6
|
"keywords": [
|