agent-board-runner 0.1.17 → 0.1.18
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/cli.js +135 -22
- package/dist/index.js +135 -22
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2103,7 +2103,22 @@ function parseGitDiffNameStatus(output) {
|
|
|
2103
2103
|
const columns = line.split(" ");
|
|
2104
2104
|
const status = columns[0].slice(0, 1);
|
|
2105
2105
|
const path = columns[columns.length - 1];
|
|
2106
|
-
return { path, status };
|
|
2106
|
+
return { path, status, additions: null, deletions: null, binary: false };
|
|
2107
|
+
});
|
|
2108
|
+
}
|
|
2109
|
+
function parseGitDiffNumstat(output) {
|
|
2110
|
+
return output.split("\n").filter((line) => line.length > 0).map((line) => {
|
|
2111
|
+
const [added, deleted, path] = line.split(" ");
|
|
2112
|
+
const binary = added === "-" && deleted === "-";
|
|
2113
|
+
return { path, additions: binary ? null : Number(added), deletions: binary ? null : Number(deleted), binary };
|
|
2114
|
+
});
|
|
2115
|
+
}
|
|
2116
|
+
function mergeNumstat(files, numstat) {
|
|
2117
|
+
const byPath = new Map(numstat.map((entry) => [entry.path, entry]));
|
|
2118
|
+
return files.map((file) => {
|
|
2119
|
+
const stat = byPath.get(file.path);
|
|
2120
|
+
if (!stat) return file;
|
|
2121
|
+
return { ...file, additions: stat.additions, deletions: stat.deletions, binary: stat.binary };
|
|
2107
2122
|
});
|
|
2108
2123
|
}
|
|
2109
2124
|
async function getRepoDiffForTarget(label, cwd) {
|
|
@@ -2137,14 +2152,84 @@ async function getRepoDiffForTarget(label, cwd) {
|
|
|
2137
2152
|
files = parseGitDiffNameStatus(stdout);
|
|
2138
2153
|
} catch (err) {
|
|
2139
2154
|
const message = err instanceof Error ? err.message : String(err);
|
|
2140
|
-
return { label, files: [], diff: "", error: message };
|
|
2155
|
+
return { label, files: [], diff: "", branch, error: message };
|
|
2156
|
+
}
|
|
2157
|
+
if (files.length === 0) return { label, files, diff: "", branch };
|
|
2158
|
+
try {
|
|
2159
|
+
const { stdout: numstatOut } = await execFileAsync2("git", ["diff", "--numstat", remoteRef, "HEAD"], { ...DIFF_EXEC_OPTIONS, cwd });
|
|
2160
|
+
files = mergeNumstat(files, parseGitDiffNumstat(numstatOut));
|
|
2161
|
+
} catch {
|
|
2141
2162
|
}
|
|
2142
|
-
if (files.length === 0) return { label, files, diff: "" };
|
|
2143
2163
|
try {
|
|
2144
2164
|
const { stdout } = await execFileAsync2("git", ["diff", remoteRef, "HEAD"], { ...DIFF_EXEC_OPTIONS, cwd });
|
|
2145
|
-
return { label, files, diff: stdout };
|
|
2165
|
+
return { label, files, diff: stdout, branch };
|
|
2166
|
+
} catch {
|
|
2167
|
+
return { label, files, diff: "", branch };
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
async function resolveDiffTargetCwd(entry, projectId, label) {
|
|
2171
|
+
if (!label) return entry.repoRoot;
|
|
2172
|
+
if (!statuslineSupabase) throw new HttpError(400, "Reposit\xF3rio filho n\xE3o dispon\xEDvel.");
|
|
2173
|
+
const children = await getProjectRepos(statuslineSupabase, projectId);
|
|
2174
|
+
const child2 = children.find((candidate) => candidate.subpath === label);
|
|
2175
|
+
if (!child2) throw new HttpError(400, "Reposit\xF3rio filho desconhecido.");
|
|
2176
|
+
return join9(entry.repoRoot, child2.subpath);
|
|
2177
|
+
}
|
|
2178
|
+
async function readFileAtRevision(cwd, ref, relPath) {
|
|
2179
|
+
try {
|
|
2180
|
+
const { stdout } = await execFileAsync2("git", ["show", `${ref}:${relPath}`], {
|
|
2181
|
+
cwd,
|
|
2182
|
+
maxBuffer: DIFF_EXEC_OPTIONS.maxBuffer,
|
|
2183
|
+
encoding: "buffer"
|
|
2184
|
+
});
|
|
2185
|
+
return stdout;
|
|
2146
2186
|
} catch {
|
|
2147
|
-
return
|
|
2187
|
+
return null;
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
function toFileRevisionJson(buffer, imageContentType) {
|
|
2191
|
+
if (buffer === null) return { exists: false, content: null, binary: false };
|
|
2192
|
+
if (looksBinary(buffer)) {
|
|
2193
|
+
return {
|
|
2194
|
+
exists: true,
|
|
2195
|
+
content: null,
|
|
2196
|
+
binary: true,
|
|
2197
|
+
...imageContentType ? { imageBase64: buffer.toString("base64"), imageContentType } : {}
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2200
|
+
return { exists: true, content: buffer.toString("utf8"), binary: false };
|
|
2201
|
+
}
|
|
2202
|
+
async function handleDiffFileRequest(entry, res, projectId, relPath, label) {
|
|
2203
|
+
if (!relPath) {
|
|
2204
|
+
sendJson(res, 400, { error: "Par\xE2metro path \xE9 obrigat\xF3rio." });
|
|
2205
|
+
return;
|
|
2206
|
+
}
|
|
2207
|
+
try {
|
|
2208
|
+
const cwd = await resolveDiffTargetCwd(entry, projectId, label);
|
|
2209
|
+
resolveWithinRepo(cwd, relPath);
|
|
2210
|
+
const { stdout: branchOut } = await execFileAsync2("git", ["branch", "--show-current"], { cwd });
|
|
2211
|
+
const branch = branchOut.trim();
|
|
2212
|
+
if (!branch) {
|
|
2213
|
+
sendJson(res, 400, { error: "HEAD destacado: sem branch local para comparar com a origin." });
|
|
2214
|
+
return;
|
|
2215
|
+
}
|
|
2216
|
+
const [originalBuffer, modifiedBuffer] = await Promise.all([
|
|
2217
|
+
readFileAtRevision(cwd, `origin/${branch}`, relPath),
|
|
2218
|
+
readFileAtRevision(cwd, "HEAD", relPath)
|
|
2219
|
+
]);
|
|
2220
|
+
const ext = relPath.split(".").pop()?.toLowerCase() ?? "";
|
|
2221
|
+
const imageContentType = MIME_TYPES_BY_EXT[ext];
|
|
2222
|
+
sendJson(res, 200, {
|
|
2223
|
+
original: toFileRevisionJson(originalBuffer, imageContentType),
|
|
2224
|
+
modified: toFileRevisionJson(modifiedBuffer, imageContentType)
|
|
2225
|
+
});
|
|
2226
|
+
} catch (err) {
|
|
2227
|
+
if (err instanceof HttpError) {
|
|
2228
|
+
sendJson(res, err.status, { error: err.message });
|
|
2229
|
+
return;
|
|
2230
|
+
}
|
|
2231
|
+
logger.runner.error("FILES", "Unexpected error handling a diff-file request:", err);
|
|
2232
|
+
sendJson(res, 500, { error: "Erro interno do runner." });
|
|
2148
2233
|
}
|
|
2149
2234
|
}
|
|
2150
2235
|
async function handleDiffRequest(entry, res, projectId) {
|
|
@@ -2329,6 +2414,12 @@ function handleRequest(req, res) {
|
|
|
2329
2414
|
void handleDiffRequest(entry, res, projectId);
|
|
2330
2415
|
return;
|
|
2331
2416
|
}
|
|
2417
|
+
if (pathname === "/diff-file") {
|
|
2418
|
+
const projectId = typeof query.projectId === "string" ? query.projectId : "";
|
|
2419
|
+
const label = typeof query.label === "string" ? query.label : null;
|
|
2420
|
+
void handleDiffFileRequest(entry, res, projectId, relPath, label);
|
|
2421
|
+
return;
|
|
2422
|
+
}
|
|
2332
2423
|
try {
|
|
2333
2424
|
if (pathname === "/tree") {
|
|
2334
2425
|
sendJson(res, 200, { entries: listDirectory(entry.repoRoot, relPath) });
|
|
@@ -2577,13 +2668,49 @@ function toSessionName(title) {
|
|
|
2577
2668
|
// src/agentSession.ts
|
|
2578
2669
|
var TUI_IDLE_MS = 1500;
|
|
2579
2670
|
var TUI_READY_TIMEOUT_MS = 6e4;
|
|
2580
|
-
var
|
|
2671
|
+
var PASTE_SETTLE_MS = 200;
|
|
2672
|
+
var PASTE_SETTLE_TIMEOUT_MS = 5e3;
|
|
2581
2673
|
var PASTE_START = "\x1B[200~";
|
|
2582
2674
|
var PASTE_END = "\x1B[201~";
|
|
2583
2675
|
var SHIFT_TAB = "\x1B[Z";
|
|
2584
2676
|
var SHIFT_TAB_PRESSES_TO_PLAN_MODE = 4;
|
|
2585
2677
|
var SHIFT_TAB_DELAY_MS = 400;
|
|
2586
2678
|
var PLAN_MODE_INDICATOR = /plan mode on/i;
|
|
2679
|
+
function writePasteAndSubmit(pty, cardId, message, context) {
|
|
2680
|
+
pty.write(`${PASTE_START}${message}${PASTE_END}`);
|
|
2681
|
+
let settleTimer;
|
|
2682
|
+
let ceilingTimer;
|
|
2683
|
+
let dataSubscription;
|
|
2684
|
+
let exitSubscription;
|
|
2685
|
+
let submitted = false;
|
|
2686
|
+
const submit = () => {
|
|
2687
|
+
if (submitted) return;
|
|
2688
|
+
submitted = true;
|
|
2689
|
+
clearTimeout(settleTimer);
|
|
2690
|
+
clearTimeout(ceilingTimer);
|
|
2691
|
+
dataSubscription?.dispose();
|
|
2692
|
+
exitSubscription?.dispose();
|
|
2693
|
+
try {
|
|
2694
|
+
pty.write("\r");
|
|
2695
|
+
} catch (err) {
|
|
2696
|
+
logger.card.error(cardId, `Failed to submit ${context} to the agent:`, err);
|
|
2697
|
+
}
|
|
2698
|
+
};
|
|
2699
|
+
const cancel = () => {
|
|
2700
|
+
submitted = true;
|
|
2701
|
+
clearTimeout(settleTimer);
|
|
2702
|
+
clearTimeout(ceilingTimer);
|
|
2703
|
+
dataSubscription?.dispose();
|
|
2704
|
+
exitSubscription?.dispose();
|
|
2705
|
+
};
|
|
2706
|
+
dataSubscription = pty.onData(() => {
|
|
2707
|
+
clearTimeout(settleTimer);
|
|
2708
|
+
settleTimer = setTimeout(submit, PASTE_SETTLE_MS);
|
|
2709
|
+
});
|
|
2710
|
+
settleTimer = setTimeout(submit, PASTE_SETTLE_MS);
|
|
2711
|
+
ceilingTimer = setTimeout(submit, PASTE_SETTLE_TIMEOUT_MS);
|
|
2712
|
+
exitSubscription = pty.onExit(cancel);
|
|
2713
|
+
}
|
|
2587
2714
|
function spawnAgentPty(repoPath, cardId, cardTitle, instructions, sessionId, ticket, planFirst) {
|
|
2588
2715
|
ensureDirTrusted(repoPath);
|
|
2589
2716
|
ensureMcpServersTrusted(repoPath);
|
|
@@ -2627,14 +2754,7 @@ function sendMessageWhenIdle(pty, cardId, message, planFirst) {
|
|
|
2627
2754
|
if (!stopWaiting()) return;
|
|
2628
2755
|
if (planFirst) await enterPlanMode(pty, cardId);
|
|
2629
2756
|
try {
|
|
2630
|
-
pty
|
|
2631
|
-
setTimeout(() => {
|
|
2632
|
-
try {
|
|
2633
|
-
pty.write("\r");
|
|
2634
|
-
} catch (err) {
|
|
2635
|
-
logger.card.error(cardId, "Failed to submit the card instructions to the agent:", err);
|
|
2636
|
-
}
|
|
2637
|
-
}, SUBMIT_DELAY_MS);
|
|
2757
|
+
writePasteAndSubmit(pty, cardId, message, "the card instructions");
|
|
2638
2758
|
} catch (err) {
|
|
2639
2759
|
logger.card.error(cardId, "Failed to send the card instructions to the agent:", err);
|
|
2640
2760
|
}
|
|
@@ -2670,14 +2790,7 @@ async function enterPlanMode(pty, cardId) {
|
|
|
2670
2790
|
}
|
|
2671
2791
|
function sendMessageToIdleSession(pty, cardId, message) {
|
|
2672
2792
|
try {
|
|
2673
|
-
pty
|
|
2674
|
-
setTimeout(() => {
|
|
2675
|
-
try {
|
|
2676
|
-
pty.write("\r");
|
|
2677
|
-
} catch (err) {
|
|
2678
|
-
logger.card.error(cardId, "Failed to submit a message to the idle session:", err);
|
|
2679
|
-
}
|
|
2680
|
-
}, SUBMIT_DELAY_MS);
|
|
2793
|
+
writePasteAndSubmit(pty, cardId, message, "a message");
|
|
2681
2794
|
} catch (err) {
|
|
2682
2795
|
logger.card.error(cardId, "Failed to send a message to the idle session:", err);
|
|
2683
2796
|
}
|
package/dist/index.js
CHANGED
|
@@ -1823,7 +1823,22 @@ function parseGitDiffNameStatus(output) {
|
|
|
1823
1823
|
const columns = line.split(" ");
|
|
1824
1824
|
const status = columns[0].slice(0, 1);
|
|
1825
1825
|
const path = columns[columns.length - 1];
|
|
1826
|
-
return { path, status };
|
|
1826
|
+
return { path, status, additions: null, deletions: null, binary: false };
|
|
1827
|
+
});
|
|
1828
|
+
}
|
|
1829
|
+
function parseGitDiffNumstat(output) {
|
|
1830
|
+
return output.split("\n").filter((line) => line.length > 0).map((line) => {
|
|
1831
|
+
const [added, deleted, path] = line.split(" ");
|
|
1832
|
+
const binary = added === "-" && deleted === "-";
|
|
1833
|
+
return { path, additions: binary ? null : Number(added), deletions: binary ? null : Number(deleted), binary };
|
|
1834
|
+
});
|
|
1835
|
+
}
|
|
1836
|
+
function mergeNumstat(files, numstat) {
|
|
1837
|
+
const byPath = new Map(numstat.map((entry) => [entry.path, entry]));
|
|
1838
|
+
return files.map((file) => {
|
|
1839
|
+
const stat = byPath.get(file.path);
|
|
1840
|
+
if (!stat) return file;
|
|
1841
|
+
return { ...file, additions: stat.additions, deletions: stat.deletions, binary: stat.binary };
|
|
1827
1842
|
});
|
|
1828
1843
|
}
|
|
1829
1844
|
async function getRepoDiffForTarget(label, cwd) {
|
|
@@ -1857,14 +1872,84 @@ async function getRepoDiffForTarget(label, cwd) {
|
|
|
1857
1872
|
files = parseGitDiffNameStatus(stdout);
|
|
1858
1873
|
} catch (err) {
|
|
1859
1874
|
const message = err instanceof Error ? err.message : String(err);
|
|
1860
|
-
return { label, files: [], diff: "", error: message };
|
|
1875
|
+
return { label, files: [], diff: "", branch, error: message };
|
|
1876
|
+
}
|
|
1877
|
+
if (files.length === 0) return { label, files, diff: "", branch };
|
|
1878
|
+
try {
|
|
1879
|
+
const { stdout: numstatOut } = await execFileAsync2("git", ["diff", "--numstat", remoteRef, "HEAD"], { ...DIFF_EXEC_OPTIONS, cwd });
|
|
1880
|
+
files = mergeNumstat(files, parseGitDiffNumstat(numstatOut));
|
|
1881
|
+
} catch {
|
|
1861
1882
|
}
|
|
1862
|
-
if (files.length === 0) return { label, files, diff: "" };
|
|
1863
1883
|
try {
|
|
1864
1884
|
const { stdout } = await execFileAsync2("git", ["diff", remoteRef, "HEAD"], { ...DIFF_EXEC_OPTIONS, cwd });
|
|
1865
|
-
return { label, files, diff: stdout };
|
|
1885
|
+
return { label, files, diff: stdout, branch };
|
|
1886
|
+
} catch {
|
|
1887
|
+
return { label, files, diff: "", branch };
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
async function resolveDiffTargetCwd(entry, projectId, label) {
|
|
1891
|
+
if (!label) return entry.repoRoot;
|
|
1892
|
+
if (!statuslineSupabase) throw new HttpError(400, "Reposit\xF3rio filho n\xE3o dispon\xEDvel.");
|
|
1893
|
+
const children = await getProjectRepos(statuslineSupabase, projectId);
|
|
1894
|
+
const child2 = children.find((candidate) => candidate.subpath === label);
|
|
1895
|
+
if (!child2) throw new HttpError(400, "Reposit\xF3rio filho desconhecido.");
|
|
1896
|
+
return join7(entry.repoRoot, child2.subpath);
|
|
1897
|
+
}
|
|
1898
|
+
async function readFileAtRevision(cwd, ref, relPath) {
|
|
1899
|
+
try {
|
|
1900
|
+
const { stdout } = await execFileAsync2("git", ["show", `${ref}:${relPath}`], {
|
|
1901
|
+
cwd,
|
|
1902
|
+
maxBuffer: DIFF_EXEC_OPTIONS.maxBuffer,
|
|
1903
|
+
encoding: "buffer"
|
|
1904
|
+
});
|
|
1905
|
+
return stdout;
|
|
1866
1906
|
} catch {
|
|
1867
|
-
return
|
|
1907
|
+
return null;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
function toFileRevisionJson(buffer, imageContentType) {
|
|
1911
|
+
if (buffer === null) return { exists: false, content: null, binary: false };
|
|
1912
|
+
if (looksBinary(buffer)) {
|
|
1913
|
+
return {
|
|
1914
|
+
exists: true,
|
|
1915
|
+
content: null,
|
|
1916
|
+
binary: true,
|
|
1917
|
+
...imageContentType ? { imageBase64: buffer.toString("base64"), imageContentType } : {}
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1920
|
+
return { exists: true, content: buffer.toString("utf8"), binary: false };
|
|
1921
|
+
}
|
|
1922
|
+
async function handleDiffFileRequest(entry, res, projectId, relPath, label) {
|
|
1923
|
+
if (!relPath) {
|
|
1924
|
+
sendJson(res, 400, { error: "Par\xE2metro path \xE9 obrigat\xF3rio." });
|
|
1925
|
+
return;
|
|
1926
|
+
}
|
|
1927
|
+
try {
|
|
1928
|
+
const cwd = await resolveDiffTargetCwd(entry, projectId, label);
|
|
1929
|
+
resolveWithinRepo(cwd, relPath);
|
|
1930
|
+
const { stdout: branchOut } = await execFileAsync2("git", ["branch", "--show-current"], { cwd });
|
|
1931
|
+
const branch = branchOut.trim();
|
|
1932
|
+
if (!branch) {
|
|
1933
|
+
sendJson(res, 400, { error: "HEAD destacado: sem branch local para comparar com a origin." });
|
|
1934
|
+
return;
|
|
1935
|
+
}
|
|
1936
|
+
const [originalBuffer, modifiedBuffer] = await Promise.all([
|
|
1937
|
+
readFileAtRevision(cwd, `origin/${branch}`, relPath),
|
|
1938
|
+
readFileAtRevision(cwd, "HEAD", relPath)
|
|
1939
|
+
]);
|
|
1940
|
+
const ext = relPath.split(".").pop()?.toLowerCase() ?? "";
|
|
1941
|
+
const imageContentType = MIME_TYPES_BY_EXT[ext];
|
|
1942
|
+
sendJson(res, 200, {
|
|
1943
|
+
original: toFileRevisionJson(originalBuffer, imageContentType),
|
|
1944
|
+
modified: toFileRevisionJson(modifiedBuffer, imageContentType)
|
|
1945
|
+
});
|
|
1946
|
+
} catch (err) {
|
|
1947
|
+
if (err instanceof HttpError) {
|
|
1948
|
+
sendJson(res, err.status, { error: err.message });
|
|
1949
|
+
return;
|
|
1950
|
+
}
|
|
1951
|
+
logger.runner.error("FILES", "Unexpected error handling a diff-file request:", err);
|
|
1952
|
+
sendJson(res, 500, { error: "Erro interno do runner." });
|
|
1868
1953
|
}
|
|
1869
1954
|
}
|
|
1870
1955
|
async function handleDiffRequest(entry, res, projectId) {
|
|
@@ -2049,6 +2134,12 @@ function handleRequest(req, res) {
|
|
|
2049
2134
|
void handleDiffRequest(entry, res, projectId);
|
|
2050
2135
|
return;
|
|
2051
2136
|
}
|
|
2137
|
+
if (pathname === "/diff-file") {
|
|
2138
|
+
const projectId = typeof query.projectId === "string" ? query.projectId : "";
|
|
2139
|
+
const label = typeof query.label === "string" ? query.label : null;
|
|
2140
|
+
void handleDiffFileRequest(entry, res, projectId, relPath, label);
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
2052
2143
|
try {
|
|
2053
2144
|
if (pathname === "/tree") {
|
|
2054
2145
|
sendJson(res, 200, { entries: listDirectory(entry.repoRoot, relPath) });
|
|
@@ -2465,13 +2556,49 @@ function toSessionName(title) {
|
|
|
2465
2556
|
// src/agentSession.ts
|
|
2466
2557
|
var TUI_IDLE_MS = 1500;
|
|
2467
2558
|
var TUI_READY_TIMEOUT_MS = 6e4;
|
|
2468
|
-
var
|
|
2559
|
+
var PASTE_SETTLE_MS = 200;
|
|
2560
|
+
var PASTE_SETTLE_TIMEOUT_MS = 5e3;
|
|
2469
2561
|
var PASTE_START = "\x1B[200~";
|
|
2470
2562
|
var PASTE_END = "\x1B[201~";
|
|
2471
2563
|
var SHIFT_TAB = "\x1B[Z";
|
|
2472
2564
|
var SHIFT_TAB_PRESSES_TO_PLAN_MODE = 4;
|
|
2473
2565
|
var SHIFT_TAB_DELAY_MS = 400;
|
|
2474
2566
|
var PLAN_MODE_INDICATOR = /plan mode on/i;
|
|
2567
|
+
function writePasteAndSubmit(pty, cardId, message, context) {
|
|
2568
|
+
pty.write(`${PASTE_START}${message}${PASTE_END}`);
|
|
2569
|
+
let settleTimer;
|
|
2570
|
+
let ceilingTimer;
|
|
2571
|
+
let dataSubscription;
|
|
2572
|
+
let exitSubscription;
|
|
2573
|
+
let submitted = false;
|
|
2574
|
+
const submit = () => {
|
|
2575
|
+
if (submitted) return;
|
|
2576
|
+
submitted = true;
|
|
2577
|
+
clearTimeout(settleTimer);
|
|
2578
|
+
clearTimeout(ceilingTimer);
|
|
2579
|
+
dataSubscription?.dispose();
|
|
2580
|
+
exitSubscription?.dispose();
|
|
2581
|
+
try {
|
|
2582
|
+
pty.write("\r");
|
|
2583
|
+
} catch (err) {
|
|
2584
|
+
logger.card.error(cardId, `Failed to submit ${context} to the agent:`, err);
|
|
2585
|
+
}
|
|
2586
|
+
};
|
|
2587
|
+
const cancel = () => {
|
|
2588
|
+
submitted = true;
|
|
2589
|
+
clearTimeout(settleTimer);
|
|
2590
|
+
clearTimeout(ceilingTimer);
|
|
2591
|
+
dataSubscription?.dispose();
|
|
2592
|
+
exitSubscription?.dispose();
|
|
2593
|
+
};
|
|
2594
|
+
dataSubscription = pty.onData(() => {
|
|
2595
|
+
clearTimeout(settleTimer);
|
|
2596
|
+
settleTimer = setTimeout(submit, PASTE_SETTLE_MS);
|
|
2597
|
+
});
|
|
2598
|
+
settleTimer = setTimeout(submit, PASTE_SETTLE_MS);
|
|
2599
|
+
ceilingTimer = setTimeout(submit, PASTE_SETTLE_TIMEOUT_MS);
|
|
2600
|
+
exitSubscription = pty.onExit(cancel);
|
|
2601
|
+
}
|
|
2475
2602
|
function spawnAgentPty(repoPath, cardId, cardTitle, instructions, sessionId, ticket, planFirst) {
|
|
2476
2603
|
ensureDirTrusted(repoPath);
|
|
2477
2604
|
ensureMcpServersTrusted(repoPath);
|
|
@@ -2515,14 +2642,7 @@ function sendMessageWhenIdle(pty, cardId, message, planFirst) {
|
|
|
2515
2642
|
if (!stopWaiting()) return;
|
|
2516
2643
|
if (planFirst) await enterPlanMode(pty, cardId);
|
|
2517
2644
|
try {
|
|
2518
|
-
pty
|
|
2519
|
-
setTimeout(() => {
|
|
2520
|
-
try {
|
|
2521
|
-
pty.write("\r");
|
|
2522
|
-
} catch (err) {
|
|
2523
|
-
logger.card.error(cardId, "Failed to submit the card instructions to the agent:", err);
|
|
2524
|
-
}
|
|
2525
|
-
}, SUBMIT_DELAY_MS);
|
|
2645
|
+
writePasteAndSubmit(pty, cardId, message, "the card instructions");
|
|
2526
2646
|
} catch (err) {
|
|
2527
2647
|
logger.card.error(cardId, "Failed to send the card instructions to the agent:", err);
|
|
2528
2648
|
}
|
|
@@ -2558,14 +2678,7 @@ async function enterPlanMode(pty, cardId) {
|
|
|
2558
2678
|
}
|
|
2559
2679
|
function sendMessageToIdleSession(pty, cardId, message) {
|
|
2560
2680
|
try {
|
|
2561
|
-
pty
|
|
2562
|
-
setTimeout(() => {
|
|
2563
|
-
try {
|
|
2564
|
-
pty.write("\r");
|
|
2565
|
-
} catch (err) {
|
|
2566
|
-
logger.card.error(cardId, "Failed to submit a message to the idle session:", err);
|
|
2567
|
-
}
|
|
2568
|
-
}, SUBMIT_DELAY_MS);
|
|
2681
|
+
writePasteAndSubmit(pty, cardId, message, "a message");
|
|
2569
2682
|
} catch (err) {
|
|
2570
2683
|
logger.card.error(cardId, "Failed to send a message to the idle session:", err);
|
|
2571
2684
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-board-runner",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"description": "Local runner for Agent Board — signs in with your own Supabase account (no shared secrets) and drives Claude Code against repos under your local repos root.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|