@synkro-sh/cli 1.10.9 → 1.10.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/dist/bootstrap.js +332 -93
- package/dist/bootstrap.js.map +1 -1
- package/package.json +18 -19
package/dist/bootstrap.js
CHANGED
|
@@ -147,7 +147,7 @@ function getIdentity() {
|
|
|
147
147
|
if (cached2) return cached2;
|
|
148
148
|
let cliVersion2 = "0.0.0";
|
|
149
149
|
try {
|
|
150
|
-
cliVersion2 = "1.10.
|
|
150
|
+
cliVersion2 = "1.10.10";
|
|
151
151
|
} catch {
|
|
152
152
|
}
|
|
153
153
|
const creds = loadCredentialsIdentity();
|
|
@@ -1645,10 +1645,9 @@ function installCCHooks(settingsPath, config) {
|
|
|
1645
1645
|
{
|
|
1646
1646
|
type: "command",
|
|
1647
1647
|
command: config.cvePrecheckScriptPath,
|
|
1648
|
-
//
|
|
1649
|
-
//
|
|
1650
|
-
|
|
1651
|
-
timeout: 15
|
|
1648
|
+
// Only a confirmed vulnerable runtime dependency reaches VEX triage. Codex can
|
|
1649
|
+
// take 13-17s for a valid answer, so match the bounded 25s gate plus its margin.
|
|
1650
|
+
timeout: 30
|
|
1652
1651
|
},
|
|
1653
1652
|
// skill-judge — its OWN system-message block, parallel with edit-precheck.
|
|
1654
1653
|
...config.skillJudgeScriptPath ? [{
|
|
@@ -1972,7 +1971,7 @@ function installCursorHooks(hooksJsonPath, config) {
|
|
|
1972
1971
|
matcher: "Write|Edit|StrReplace|MultiEdit|NotebookEdit|edit_file|reapply|edit_notebook|ApplyPatch|apply_patch"
|
|
1973
1972
|
});
|
|
1974
1973
|
pushCcHook(h, "preToolUse", config.cvePrecheckScriptPath, {
|
|
1975
|
-
timeout:
|
|
1974
|
+
timeout: 30,
|
|
1976
1975
|
matcher: "Write|Edit|StrReplace|MultiEdit|NotebookEdit|edit_file|reapply|edit_notebook|ApplyPatch|apply_patch"
|
|
1977
1976
|
});
|
|
1978
1977
|
pushCcHook(h, "preToolUse", config.agentJudgeScriptPath, {
|
|
@@ -2204,7 +2203,7 @@ function installCodexHooks(hooksJsonPath, config) {
|
|
|
2204
2203
|
push(h, "PreToolUse", [
|
|
2205
2204
|
cmd(config.editPrecheckScriptPath, 50, "Reviewing edit"),
|
|
2206
2205
|
cmd(config.cwePrecheckScriptPath, 50),
|
|
2207
|
-
cmd(config.cvePrecheckScriptPath,
|
|
2206
|
+
cmd(config.cvePrecheckScriptPath, 30),
|
|
2208
2207
|
...config.skillJudgeScriptPath ? [cmd(config.skillJudgeScriptPath, 50)] : []
|
|
2209
2208
|
], M_EDIT);
|
|
2210
2209
|
push(h, "PostToolUse", [
|
|
@@ -7934,7 +7933,7 @@ var init_dockerInstall = __esm({
|
|
|
7934
7933
|
HOST_PGLITE_PORT = parseInt(process.env.SYNKRO_HOST_PGLITE_PORT || "15433", 10);
|
|
7935
7934
|
CONTAINER_NAME = resolveContainerName();
|
|
7936
7935
|
defaultImageVersion = () => {
|
|
7937
|
-
if (true) return "1.10.
|
|
7936
|
+
if (true) return "1.10.10";
|
|
7938
7937
|
try {
|
|
7939
7938
|
const pkg = JSON.parse(readFileSync17(new URL("../../package.json", import.meta.url), "utf8"));
|
|
7940
7939
|
if (pkg.version) return pkg.version;
|
|
@@ -8994,7 +8993,7 @@ function writeConfigEnv(opts) {
|
|
|
8994
8993
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle2(credsPath)}`,
|
|
8995
8994
|
`SYNKRO_TIER=${shellQuoteSingle2(safeTier)}`,
|
|
8996
8995
|
`SYNKRO_INFERENCE=${shellQuoteSingle2(safeInference)}`,
|
|
8997
|
-
`SYNKRO_VERSION=${shellQuoteSingle2("1.10.
|
|
8996
|
+
`SYNKRO_VERSION=${shellQuoteSingle2("1.10.10")}`
|
|
8998
8997
|
];
|
|
8999
8998
|
if (safeSynkroBin) lines2.push(`SYNKRO_CLI_BIN=${shellQuoteSingle2(safeSynkroBin)}`);
|
|
9000
8999
|
if (safeUserId) lines2.push(`SYNKRO_USER_ID=${shellQuoteSingle2(safeUserId)}`);
|
|
@@ -9741,7 +9740,7 @@ async function installCommand(opts = {}) {
|
|
|
9741
9740
|
await setTelemetryState({ enabled: true, remoteFlushEnabled: telemetryConsent });
|
|
9742
9741
|
emit("install", {
|
|
9743
9742
|
phase: "started",
|
|
9744
|
-
cli_version_to: "1.10.
|
|
9743
|
+
cli_version_to: "1.10.10",
|
|
9745
9744
|
agents_detected: agents.map((a) => a.kind),
|
|
9746
9745
|
with_github: false,
|
|
9747
9746
|
with_local_cc: false,
|
|
@@ -15166,7 +15165,6 @@ async function styleOuterSession(bootPath, repoCwd, sidebarWidth) {
|
|
|
15166
15165
|
const tabPopup = "display-popup -E -w 60 -h 18 -S fg=colour111 " + shellQuote3(tabLauncher);
|
|
15167
15166
|
const dispatch = 'if-shell -F "#{==:#{mouse_status_range},tabmenu}" "' + tabPopup + '" "select-window -t="';
|
|
15168
15167
|
const style = [
|
|
15169
|
-
["set-option", "-t", UI_SESSION, "-q", "@synkro_build", buildStamp(bootPath)],
|
|
15170
15168
|
// Mouse: drag the pane border to resize the sidebar, click a pane to
|
|
15171
15169
|
// focus it, click rows/chips. Without this the fixed split reads as
|
|
15172
15170
|
// "blocked in".
|
|
@@ -15197,21 +15195,86 @@ async function styleOuterSession(bootPath, repoCwd, sidebarWidth) {
|
|
|
15197
15195
|
// Alt+s always returns focus to the sidebar (the leftmost pane).
|
|
15198
15196
|
["bind-key", "-n", "M-s", "select-pane", "-L"]
|
|
15199
15197
|
];
|
|
15200
|
-
for (const argv of style)
|
|
15201
|
-
|
|
15198
|
+
for (const argv of style) {
|
|
15199
|
+
if (!(await run(HOST, ["tmux", ...argv])).ok) return false;
|
|
15200
|
+
}
|
|
15201
|
+
for (const argv of buildClipboardBindings(UI_SESSION)) {
|
|
15202
|
+
if (!(await run(HOST, argv)).ok) return false;
|
|
15203
|
+
}
|
|
15204
|
+
return true;
|
|
15202
15205
|
}
|
|
15203
15206
|
function parseUiPanes(output) {
|
|
15204
|
-
return String(output || "").split("\n").map((line) => line.split("|")).filter((cols) => cols.length >=
|
|
15207
|
+
return String(output || "").split("\n").map((line) => line.split("|")).filter((cols) => cols.length >= 7).map(([window, pane, width, dead, remain, cwd, ...command]) => ({
|
|
15205
15208
|
window,
|
|
15206
15209
|
pane,
|
|
15207
15210
|
width: Number(width) || 0,
|
|
15211
|
+
dead: dead === "1",
|
|
15212
|
+
remain: remain === "on",
|
|
15213
|
+
cwd,
|
|
15208
15214
|
command: command.join("|")
|
|
15209
15215
|
})).filter((row2) => Boolean(row2.window && row2.pane));
|
|
15210
15216
|
}
|
|
15211
|
-
async function
|
|
15212
|
-
const
|
|
15213
|
-
|
|
15214
|
-
|
|
15217
|
+
async function ensureUiCenterPane(options) {
|
|
15218
|
+
const listed = await run(HOST, [
|
|
15219
|
+
"tmux",
|
|
15220
|
+
"list-panes",
|
|
15221
|
+
"-t",
|
|
15222
|
+
options.sidebarPane,
|
|
15223
|
+
"-F",
|
|
15224
|
+
"#{pane_id}|#{pane_dead}|#{remain-on-exit}|#{pane_start_command}"
|
|
15225
|
+
]);
|
|
15226
|
+
if (!listed.ok) return { ok: false, pane: "", created: false, recovered: false };
|
|
15227
|
+
const rows = listed.stdout.split("\n").map((line) => line.split("|")).filter((cols) => cols.length >= 4).map(([pane, dead, remain, ...command]) => ({
|
|
15228
|
+
pane,
|
|
15229
|
+
dead: dead === "1",
|
|
15230
|
+
remain: remain === "on",
|
|
15231
|
+
command: command.join("|")
|
|
15232
|
+
}));
|
|
15233
|
+
let center = rows.find((row2) => row2.pane !== options.sidebarPane);
|
|
15234
|
+
let created = false;
|
|
15235
|
+
if (!center) {
|
|
15236
|
+
const split = await run(HOST, [
|
|
15237
|
+
"tmux",
|
|
15238
|
+
"split-window",
|
|
15239
|
+
"-h",
|
|
15240
|
+
"-t",
|
|
15241
|
+
options.sidebarPane,
|
|
15242
|
+
"-c",
|
|
15243
|
+
options.cwd,
|
|
15244
|
+
"-P",
|
|
15245
|
+
"-F",
|
|
15246
|
+
"#{pane_id}",
|
|
15247
|
+
"tail -f /dev/null"
|
|
15248
|
+
]);
|
|
15249
|
+
const pane = split.stdout.trim();
|
|
15250
|
+
if (!split.ok || !pane) return { ok: false, pane: "", created: false, recovered: false };
|
|
15251
|
+
center = { pane, dead: false, remain: false, command: "tail -f /dev/null" };
|
|
15252
|
+
created = true;
|
|
15253
|
+
}
|
|
15254
|
+
const kept = await run(HOST, buildKeepPaneAfterExit(center.pane));
|
|
15255
|
+
if (!kept.ok) return { ok: false, pane: center.pane, created, recovered: false };
|
|
15256
|
+
const recovered = created || center.dead;
|
|
15257
|
+
if (recovered) {
|
|
15258
|
+
const command = options.terminalCommand === void 0 ? makeTerminalCommand(options.bootPath) : options.terminalCommand;
|
|
15259
|
+
const respawn = ["tmux", "respawn-pane", "-k", "-t", center.pane, "-c", options.cwd];
|
|
15260
|
+
if (command) respawn.push(command);
|
|
15261
|
+
const restored = await run(HOST, respawn);
|
|
15262
|
+
if (!restored.ok) return { ok: false, pane: center.pane, created, recovered: false };
|
|
15263
|
+
const spaceName = options.cwd.split("/").filter(Boolean).pop() || "space";
|
|
15264
|
+
const metadata = [
|
|
15265
|
+
["tmux", "set-option", "-t", center.pane, "-w", "-q", "@synkro_agent", ""],
|
|
15266
|
+
["tmux", "set-option", "-t", center.pane, "-w", "-q", "@synkro_cwd", options.cwd],
|
|
15267
|
+
["tmux", "set-option", "-t", center.pane, "-w", "-q", "@synkro_kind", "terminal"],
|
|
15268
|
+
["tmux", "set-option", "-t", center.pane, "-w", "automatic-rename", "off"],
|
|
15269
|
+
["tmux", "rename-window", "-t", center.pane, tabTitle("terminal", spaceName)]
|
|
15270
|
+
];
|
|
15271
|
+
for (const argv of metadata) {
|
|
15272
|
+
if (!(await run(HOST, argv)).ok) return { ok: false, pane: center.pane, created, recovered: false };
|
|
15273
|
+
}
|
|
15274
|
+
}
|
|
15275
|
+
return { ok: true, pane: center.pane, created, recovered };
|
|
15276
|
+
}
|
|
15277
|
+
async function reconcileUiShell(bootPath, repoCwd, options = {}) {
|
|
15215
15278
|
const listed = await run(HOST, [
|
|
15216
15279
|
"tmux",
|
|
15217
15280
|
"list-panes",
|
|
@@ -15219,18 +15282,64 @@ async function refreshUiShell(bootPath, repoCwd) {
|
|
|
15219
15282
|
"-t",
|
|
15220
15283
|
UI_SESSION,
|
|
15221
15284
|
"-F",
|
|
15222
|
-
"#{window_id}|#{pane_id}|#{pane_width}|#{pane_start_command}"
|
|
15285
|
+
"#{window_id}|#{pane_id}|#{pane_width}|#{pane_dead}|#{remain-on-exit}|#{@synkro_cwd}|#{pane_start_command}"
|
|
15223
15286
|
]);
|
|
15224
|
-
if (!listed.ok) return;
|
|
15287
|
+
if (!listed.ok) return { ok: false, changed: false };
|
|
15225
15288
|
const panes = parseUiPanes(listed.stdout);
|
|
15226
15289
|
const sidebars = panes.filter((row2) => row2.command.includes("--sidebar"));
|
|
15227
|
-
if (sidebars.length === 0) return;
|
|
15228
|
-
|
|
15290
|
+
if (sidebars.length === 0) return { ok: false, changed: false };
|
|
15291
|
+
let changed = false;
|
|
15229
15292
|
for (const sidebar of sidebars) {
|
|
15230
|
-
const
|
|
15231
|
-
|
|
15232
|
-
|
|
15293
|
+
const previous = panes.find((row2) => row2.window === sidebar.window && row2.pane !== sidebar.pane);
|
|
15294
|
+
const cwd = sidebar.cwd ? sidebar.cwd.startsWith("/") ? sidebar.cwd : join34(repoCwd, sidebar.cwd) : repoCwd;
|
|
15295
|
+
const center = await ensureUiCenterPane({
|
|
15296
|
+
sidebarPane: sidebar.pane,
|
|
15297
|
+
bootPath,
|
|
15298
|
+
cwd,
|
|
15299
|
+
terminalCommand: options.terminalCommand
|
|
15300
|
+
});
|
|
15301
|
+
if (!center.ok) return { ok: false, changed };
|
|
15302
|
+
if (sidebar.cwd !== cwd) {
|
|
15303
|
+
const migrated2 = await run(HOST, ["tmux", "set-option", "-t", sidebar.window, "-w", "-q", "@synkro_cwd", cwd]);
|
|
15304
|
+
if (!migrated2.ok) return { ok: false, changed };
|
|
15305
|
+
changed = true;
|
|
15306
|
+
}
|
|
15307
|
+
const staleBinding = !sidebar.command.includes("SYNKRO_UI_CENTER=" + center.pane + " ");
|
|
15308
|
+
if (options.refreshSidebars || center.recovered || staleBinding) {
|
|
15309
|
+
const rebound = await run(HOST, [
|
|
15310
|
+
"tmux",
|
|
15311
|
+
"respawn-pane",
|
|
15312
|
+
"-k",
|
|
15313
|
+
"-t",
|
|
15314
|
+
sidebar.pane,
|
|
15315
|
+
sidebarCommand(bootPath, center.pane, repoCwd)
|
|
15316
|
+
]);
|
|
15317
|
+
if (!rebound.ok) return { ok: false, changed };
|
|
15318
|
+
changed = true;
|
|
15319
|
+
}
|
|
15320
|
+
if (!previous?.remain || center.created || center.recovered) changed = true;
|
|
15321
|
+
}
|
|
15322
|
+
return { ok: true, changed };
|
|
15323
|
+
}
|
|
15324
|
+
async function refreshUiShell(bootPath, repoCwd, options = {}) {
|
|
15325
|
+
const expected = buildStamp(bootPath);
|
|
15326
|
+
const current = await run(HOST, ["tmux", "show-options", "-t", UI_SESSION, "-v", "@synkro_build"]);
|
|
15327
|
+
const buildChanged = !current.ok || current.stdout.trim() !== expected;
|
|
15328
|
+
if (buildChanged) {
|
|
15329
|
+
const width = await currentWindowColumns(UI_SESSION);
|
|
15330
|
+
if (!await styleOuterSession(bootPath, repoCwd, Number(sidebarColumns(width)))) return false;
|
|
15331
|
+
}
|
|
15332
|
+
const reconciled = await reconcileUiShell(bootPath, repoCwd, {
|
|
15333
|
+
terminalCommand: options.terminalCommand,
|
|
15334
|
+
refreshSidebars: buildChanged
|
|
15335
|
+
});
|
|
15336
|
+
if (!reconciled.ok) return false;
|
|
15337
|
+
if (reconciled.changed && options.persistLayout !== false) await snapshotTabs();
|
|
15338
|
+
if (buildChanged) {
|
|
15339
|
+
const stamped = await run(HOST, ["tmux", "set-option", "-t", UI_SESSION, "-q", "@synkro_build", expected]);
|
|
15340
|
+
if (!stamped.ok) return false;
|
|
15233
15341
|
}
|
|
15342
|
+
return true;
|
|
15234
15343
|
}
|
|
15235
15344
|
async function buildTab(bootPath, repoCwd, spec) {
|
|
15236
15345
|
await run(HOST, ["tmux", "set-option", "-g", "history-limit", "50000"]);
|
|
@@ -15238,8 +15347,20 @@ async function buildTab(bootPath, repoCwd, spec) {
|
|
|
15238
15347
|
if (!await uiSessionExists()) {
|
|
15239
15348
|
const cols = String(Number(process.stdout.columns || 0) || 220);
|
|
15240
15349
|
const rows = String(Number(process.stdout.rows || 0) || 55);
|
|
15241
|
-
const create = [
|
|
15242
|
-
|
|
15350
|
+
const create = [
|
|
15351
|
+
"tmux",
|
|
15352
|
+
"new-session",
|
|
15353
|
+
"-d",
|
|
15354
|
+
"-s",
|
|
15355
|
+
UI_SESSION,
|
|
15356
|
+
"-x",
|
|
15357
|
+
cols,
|
|
15358
|
+
"-y",
|
|
15359
|
+
rows,
|
|
15360
|
+
"-c",
|
|
15361
|
+
spec.cwd,
|
|
15362
|
+
"tail -f /dev/null"
|
|
15363
|
+
];
|
|
15243
15364
|
const made = await run(HOST, create);
|
|
15244
15365
|
if (!made.ok) {
|
|
15245
15366
|
throw new Error("tmux new-session failed: " + made.stderr.trim());
|
|
@@ -15249,14 +15370,26 @@ async function buildTab(bootPath, repoCwd, spec) {
|
|
|
15249
15370
|
const first = await run(HOST, ["tmux", "list-windows", "-t", UI_SESSION, "-F", "#{window_id}"]);
|
|
15250
15371
|
windowTarget = first.stdout.split("\n")[0]?.trim() || UI_SESSION + ":1";
|
|
15251
15372
|
} else {
|
|
15252
|
-
const create = [
|
|
15253
|
-
|
|
15373
|
+
const create = [
|
|
15374
|
+
"tmux",
|
|
15375
|
+
"new-window",
|
|
15376
|
+
"-t",
|
|
15377
|
+
UI_SESSION,
|
|
15378
|
+
"-P",
|
|
15379
|
+
"-F",
|
|
15380
|
+
"#{window_id}",
|
|
15381
|
+
"-c",
|
|
15382
|
+
spec.cwd,
|
|
15383
|
+
"tail -f /dev/null"
|
|
15384
|
+
];
|
|
15254
15385
|
const created = await run(HOST, create);
|
|
15255
15386
|
windowTarget = created.stdout.trim();
|
|
15256
15387
|
if (!created.ok || !windowTarget) return;
|
|
15257
15388
|
}
|
|
15258
15389
|
const sidebarCols = sidebarColumns(await currentWindowColumns(windowTarget));
|
|
15259
|
-
await styleOuterSession(bootPath, repoCwd, Number(sidebarCols))
|
|
15390
|
+
if (!await styleOuterSession(bootPath, repoCwd, Number(sidebarCols))) {
|
|
15391
|
+
throw new Error("tmux outer session styling failed");
|
|
15392
|
+
}
|
|
15260
15393
|
const split = await run(HOST, [
|
|
15261
15394
|
"tmux",
|
|
15262
15395
|
"split-window",
|
|
@@ -15271,18 +15404,35 @@ async function buildTab(bootPath, repoCwd, spec) {
|
|
|
15271
15404
|
"tail -f /dev/null"
|
|
15272
15405
|
]);
|
|
15273
15406
|
const sidebarPane = split.stdout.trim();
|
|
15407
|
+
if (!split.ok || !sidebarPane) throw new Error("tmux sidebar split failed: " + split.stderr.trim());
|
|
15274
15408
|
const panes = await run(HOST, ["tmux", "list-panes", "-t", windowTarget, "-F", "#{pane_id}"]);
|
|
15275
15409
|
const centerPane = panes.stdout.split("\n").map((line) => line.trim()).filter(Boolean).find((id) => id !== sidebarPane) || "";
|
|
15276
|
-
|
|
15410
|
+
if (!centerPane) throw new Error("tmux center pane was not created");
|
|
15411
|
+
const kept = await run(HOST, buildKeepPaneAfterExit(centerPane));
|
|
15412
|
+
if (!kept.ok) throw new Error("tmux center durability failed: " + kept.stderr.trim());
|
|
15277
15413
|
if (spec.agentSession) {
|
|
15278
15414
|
await run(HOST, ["tmux", "set-option", "-t", windowTarget, "-w", "-q", "@synkro_agent", spec.agentSession]);
|
|
15279
15415
|
}
|
|
15280
15416
|
await run(HOST, ["tmux", "set-option", "-t", windowTarget, "-w", "-q", "@synkro_cwd", spec.cwd]);
|
|
15281
15417
|
await run(HOST, ["tmux", "set-option", "-t", windowTarget, "-w", "-q", "@synkro_kind", spec.kind || "terminal"]);
|
|
15282
|
-
await run(HOST, [
|
|
15418
|
+
const sidebarStarted = await run(HOST, [
|
|
15419
|
+
"tmux",
|
|
15420
|
+
"respawn-pane",
|
|
15421
|
+
"-k",
|
|
15422
|
+
"-t",
|
|
15423
|
+
sidebarPane,
|
|
15424
|
+
sidebarCommand(bootPath, centerPane, repoCwd)
|
|
15425
|
+
]);
|
|
15426
|
+
if (!sidebarStarted.ok) throw new Error("tmux sidebar start failed: " + sidebarStarted.stderr.trim());
|
|
15427
|
+
const centerStart = ["tmux", "respawn-pane", "-k", "-t", centerPane, "-c", spec.cwd];
|
|
15428
|
+
if (spec.center) centerStart.push(spec.center);
|
|
15429
|
+
const centerStarted = await run(HOST, centerStart);
|
|
15430
|
+
if (!centerStarted.ok) throw new Error("tmux center start failed: " + centerStarted.stderr.trim());
|
|
15283
15431
|
const title = spec.title || tabTitle("terminal", spec.cwd.split("/").filter(Boolean).pop() || "space");
|
|
15284
15432
|
await run(HOST, ["tmux", "set-option", "-t", windowTarget, "-w", "automatic-rename", "off"]);
|
|
15285
15433
|
await run(HOST, ["tmux", "rename-window", "-t", windowTarget, title]);
|
|
15434
|
+
const stamped = await run(HOST, ["tmux", "set-option", "-t", UI_SESSION, "-q", "@synkro_build", buildStamp(bootPath)]);
|
|
15435
|
+
if (!stamped.ok) throw new Error("tmux build stamp failed: " + stamped.stderr.trim());
|
|
15286
15436
|
await snapshotTabs();
|
|
15287
15437
|
await run(HOST, ["tmux", "select-pane", "-t", spec.focus === "sidebar" ? sidebarPane : centerPane]);
|
|
15288
15438
|
}
|
|
@@ -15325,7 +15475,9 @@ async function launchUi(bootPath, repoCwd) {
|
|
|
15325
15475
|
if (!await uiSessionExists()) {
|
|
15326
15476
|
await buildTab(bootPath, repoCwd, { cwd: repoCwd, center: makeTerminalCommand(bootPath), focus: "sidebar" });
|
|
15327
15477
|
} else {
|
|
15328
|
-
await refreshUiShell(bootPath, repoCwd)
|
|
15478
|
+
if (!await refreshUiShell(bootPath, repoCwd)) {
|
|
15479
|
+
throw new Error("Synkro UI could not repair its tmux layout");
|
|
15480
|
+
}
|
|
15329
15481
|
}
|
|
15330
15482
|
await pruneCollapsedClients();
|
|
15331
15483
|
return runInherit(process.env.TMUX ? ["tmux", "switch-client", "-t", UI_SESSION] : ["tmux", "attach-session", "-t", UI_SESSION]);
|
|
@@ -15798,8 +15950,11 @@ var init_awake = __esm({
|
|
|
15798
15950
|
function runnerFor(backend) {
|
|
15799
15951
|
return backend === "container" ? { kind: "container", container: CONTAINER_NAME2 } : { kind: "host" };
|
|
15800
15952
|
}
|
|
15953
|
+
function hasLiveAgentCenter(paneOutput, session) {
|
|
15954
|
+
return String(paneOutput || "").split("\n").map((line) => line.split("|")).some(([dead, ...command]) => dead === "0" && !command.join("|").includes("--sidebar") && command.join("|").includes(session));
|
|
15955
|
+
}
|
|
15801
15956
|
async function runSidebar() {
|
|
15802
|
-
|
|
15957
|
+
let centerPane = process.env.SYNKRO_UI_CENTER || "";
|
|
15803
15958
|
const outerSession = process.env.SYNKRO_UI_OUTER || "synkro-ui";
|
|
15804
15959
|
const bootPath = process.env.SYNKRO_UI_BOOT || process.argv[1];
|
|
15805
15960
|
const repoCwd = process.env.SYNKRO_UI_REPO || process.cwd();
|
|
@@ -15967,53 +16122,114 @@ async function runSidebar() {
|
|
|
15967
16122
|
const agent = state.agents[state.agentIndex];
|
|
15968
16123
|
if (agent) await showAgent(agent);
|
|
15969
16124
|
}
|
|
16125
|
+
async function resolveCenterPane(cwd) {
|
|
16126
|
+
if (!ownPane || !cwd) return "";
|
|
16127
|
+
const resolved = await ensureUiCenterPane({ sidebarPane: ownPane, bootPath, cwd });
|
|
16128
|
+
if (!resolved.ok) {
|
|
16129
|
+
state.message = "could not restore this tab";
|
|
16130
|
+
return "";
|
|
16131
|
+
}
|
|
16132
|
+
centerPane = resolved.pane;
|
|
16133
|
+
if (resolved.recovered) {
|
|
16134
|
+
state.viewing = "";
|
|
16135
|
+
await snapshotTabs();
|
|
16136
|
+
stripWidth = -1;
|
|
16137
|
+
await syncChipStrip();
|
|
16138
|
+
}
|
|
16139
|
+
return centerPane;
|
|
16140
|
+
}
|
|
15970
16141
|
async function showWorkspaceTerminal(cwd) {
|
|
15971
|
-
|
|
16142
|
+
const pane = await resolveCenterPane(cwd);
|
|
16143
|
+
if (!pane) return false;
|
|
15972
16144
|
const command = makeTerminalCommand(bootPath);
|
|
15973
|
-
const argv = ["tmux", "respawn-pane", "-k", "-t",
|
|
16145
|
+
const argv = ["tmux", "respawn-pane", "-k", "-t", pane, "-c", cwd];
|
|
15974
16146
|
if (command) argv.push(command);
|
|
15975
16147
|
const respawned = await run(host, argv);
|
|
15976
16148
|
if (!respawned.ok) {
|
|
15977
16149
|
state.message = "could not restore workspace terminal";
|
|
15978
|
-
return;
|
|
16150
|
+
return false;
|
|
15979
16151
|
}
|
|
15980
16152
|
const spaceName = cwd.split("/").filter(Boolean).pop() || "space";
|
|
15981
|
-
|
|
15982
|
-
|
|
15983
|
-
|
|
15984
|
-
|
|
16153
|
+
const metadata = [
|
|
16154
|
+
["tmux", "set-option", "-t", pane, "-w", "-q", "@synkro_agent", ""],
|
|
16155
|
+
["tmux", "set-option", "-t", pane, "-w", "-q", "@synkro_cwd", cwd],
|
|
16156
|
+
["tmux", "set-option", "-t", pane, "-w", "-q", "@synkro_kind", "terminal"],
|
|
16157
|
+
["tmux", "rename-window", "-t", pane, tabTitle("terminal", spaceName)]
|
|
16158
|
+
];
|
|
16159
|
+
for (const commandArgv of metadata) {
|
|
16160
|
+
if (!(await run(host, commandArgv)).ok) {
|
|
16161
|
+
state.message = "could not update this tab";
|
|
16162
|
+
return false;
|
|
16163
|
+
}
|
|
16164
|
+
}
|
|
15985
16165
|
state.viewing = "";
|
|
15986
16166
|
await snapshotTabs();
|
|
16167
|
+
return true;
|
|
15987
16168
|
}
|
|
15988
|
-
async function
|
|
15989
|
-
if (!centerPane) return;
|
|
15990
|
-
if (agent.status === "offline") {
|
|
15991
|
-
await restoreSelected();
|
|
15992
|
-
return;
|
|
15993
|
-
}
|
|
16169
|
+
async function markAgentViewed(agent) {
|
|
15994
16170
|
const current = memory.get(agent.session);
|
|
15995
16171
|
memory.set(agent.session, { hash: current?.hash || "", wasWorking: false, seen: true });
|
|
15996
16172
|
if (agent.space) rememberLastAgent(await repoOf(agent.space), agent.session);
|
|
15997
16173
|
state.viewing = agent.session;
|
|
16174
|
+
}
|
|
16175
|
+
async function showAgent(agent) {
|
|
16176
|
+
if (agent.status === "offline") {
|
|
16177
|
+
await restoreSelected();
|
|
16178
|
+
return false;
|
|
16179
|
+
}
|
|
15998
16180
|
const windows = await run(host, ["tmux", "list-windows", "-t", outerSession, "-F", "#{window_id}|#{@synkro_agent}"]);
|
|
15999
16181
|
const holder = windows.stdout.split("\n").map((line) => line.split("|")).find((cols) => cols[1] === agent.session);
|
|
16000
16182
|
if (holder) {
|
|
16001
|
-
await run(host, [
|
|
16002
|
-
|
|
16003
|
-
|
|
16183
|
+
const holderPanes = await run(host, [
|
|
16184
|
+
"tmux",
|
|
16185
|
+
"list-panes",
|
|
16186
|
+
"-t",
|
|
16187
|
+
holder[0],
|
|
16188
|
+
"-F",
|
|
16189
|
+
"#{pane_dead}|#{pane_start_command}"
|
|
16190
|
+
]);
|
|
16191
|
+
const liveCenter = holderPanes.ok && hasLiveAgentCenter(holderPanes.stdout, agent.session);
|
|
16192
|
+
if (liveCenter) {
|
|
16193
|
+
const selected = await run(host, ["tmux", "select-window", "-t", holder[0]]);
|
|
16194
|
+
if (selected.ok) {
|
|
16195
|
+
await markAgentViewed(agent);
|
|
16196
|
+
state.message = agent.name;
|
|
16197
|
+
return true;
|
|
16198
|
+
}
|
|
16199
|
+
}
|
|
16200
|
+
await run(host, ["tmux", "set-option", "-t", holder[0], "-w", "-q", "@synkro_agent", ""]);
|
|
16004
16201
|
}
|
|
16202
|
+
const pane = await resolveCenterPane(agent.space || selectedSpace()?.path || repoCwd);
|
|
16203
|
+
if (!pane) return false;
|
|
16005
16204
|
await run(runnerFor(agent.backend), buildEnableMouse(agent.session));
|
|
16006
16205
|
for (const argv of buildClipboardBindings(agent.session)) {
|
|
16007
16206
|
await run(runnerFor(agent.backend), argv);
|
|
16008
16207
|
}
|
|
16009
16208
|
const command = buildCenterAttachCommand(runnerFor(agent.backend), agent.session);
|
|
16010
|
-
await run(host, ["tmux", "respawn-pane", "-k", "-t",
|
|
16209
|
+
const attached = await run(host, ["tmux", "respawn-pane", "-k", "-t", pane, command]);
|
|
16210
|
+
if (!attached.ok) {
|
|
16211
|
+
state.message = "could not open " + agent.name;
|
|
16212
|
+
await showWorkspaceTerminal(agent.space || selectedSpace()?.path || repoCwd);
|
|
16213
|
+
return false;
|
|
16214
|
+
}
|
|
16011
16215
|
const where = agent.space ? agent.space.split("/").filter(Boolean).pop() || "" : "";
|
|
16012
|
-
|
|
16013
|
-
|
|
16014
|
-
|
|
16216
|
+
const metadata = [
|
|
16217
|
+
["tmux", "set-option", "-t", pane, "-w", "-q", "@synkro_agent", agent.session],
|
|
16218
|
+
["tmux", "set-option", "-t", pane, "-w", "-q", "@synkro_cwd", agent.space || repoCwd],
|
|
16219
|
+
["tmux", "set-option", "-t", pane, "-w", "-q", "@synkro_kind", agent.harness],
|
|
16220
|
+
["tmux", "rename-window", "-t", pane, tabTitle(agent.harness, where)]
|
|
16221
|
+
];
|
|
16222
|
+
for (const commandArgv of metadata) {
|
|
16223
|
+
if (!(await run(host, commandArgv)).ok) {
|
|
16224
|
+
state.message = "could not update " + agent.name + " tab";
|
|
16225
|
+
await showWorkspaceTerminal(agent.space || selectedSpace()?.path || repoCwd);
|
|
16226
|
+
return false;
|
|
16227
|
+
}
|
|
16228
|
+
}
|
|
16229
|
+
await markAgentViewed(agent);
|
|
16015
16230
|
await snapshotTabs();
|
|
16016
16231
|
state.message = "attached " + agent.name;
|
|
16232
|
+
return true;
|
|
16017
16233
|
}
|
|
16018
16234
|
async function confirmKillAgent() {
|
|
16019
16235
|
const agent = state.agents[state.agentIndex];
|
|
@@ -16024,7 +16240,8 @@ async function runSidebar() {
|
|
|
16024
16240
|
if (allAgents.some((candidate) => candidate.session === agent.session && candidate.status !== "offline")) return;
|
|
16025
16241
|
state.message = "closed " + agent.name;
|
|
16026
16242
|
if (!wasViewing) return;
|
|
16027
|
-
await showWorkspaceTerminal(agent.space || selectedSpace()?.path || repoCwd);
|
|
16243
|
+
const restored = await showWorkspaceTerminal(agent.space || selectedSpace()?.path || repoCwd);
|
|
16244
|
+
if (!restored) return;
|
|
16028
16245
|
const successor = nextLiveAgent(allAgents, agent.repo || "");
|
|
16029
16246
|
if (successor) await showAgent(successor);
|
|
16030
16247
|
}
|
|
@@ -16940,6 +17157,42 @@ var init_dialog = __esm({
|
|
|
16940
17157
|
}
|
|
16941
17158
|
});
|
|
16942
17159
|
|
|
17160
|
+
// cli/harness/events.ts
|
|
17161
|
+
function fixPollIds(raw) {
|
|
17162
|
+
const text = String(raw || "");
|
|
17163
|
+
const ids = [
|
|
17164
|
+
...Array.from(text.matchAll(FIX_POLL_MARKERS), (match) => match[1]),
|
|
17165
|
+
...Array.from(text.matchAll(LEGACY_FIX_POLL_MARKERS), (match) => match[1])
|
|
17166
|
+
];
|
|
17167
|
+
return Array.from(new Set(ids.filter(Boolean)));
|
|
17168
|
+
}
|
|
17169
|
+
function fixPollId(raw) {
|
|
17170
|
+
return fixPollIds(raw)[0] || "";
|
|
17171
|
+
}
|
|
17172
|
+
function cleanGuardText(raw) {
|
|
17173
|
+
return String(raw || "").replace(FIX_POLL_MARKERS, "").replace(/\n*\s*SYNKRO FIX POLL[\s\S]*$/i, "").replace(/\n?\d{4}-\d\d-\d\dT[^\n]*\sERROR\s+codex_core::tools::router:[^\n]*/gi, "").replace(/\s*Checking command\s*$/i, "").trim();
|
|
17174
|
+
}
|
|
17175
|
+
function blockReason(raw) {
|
|
17176
|
+
const text = cleanGuardText(raw);
|
|
17177
|
+
if (!text) return "blocked by policy";
|
|
17178
|
+
const guardAt = text.lastIndexOf("Guard:");
|
|
17179
|
+
if (guardAt >= 0) return text.slice(guardAt + "Guard:".length).trim();
|
|
17180
|
+
const afterTag = text.match(/\[synkro:[^\]]*\]\s*(.+)/is);
|
|
17181
|
+
if (afterTag) return afterTag[1].trim();
|
|
17182
|
+
const afterHook = text.match(/blocked by a hook:\s*(.+)/is);
|
|
17183
|
+
if (afterHook) return afterHook[1].trim();
|
|
17184
|
+
return text;
|
|
17185
|
+
}
|
|
17186
|
+
var BLOCK_MARKER, FIX_POLL_MARKERS, LEGACY_FIX_POLL_MARKERS;
|
|
17187
|
+
var init_events = __esm({
|
|
17188
|
+
"cli/harness/events.ts"() {
|
|
17189
|
+
"use strict";
|
|
17190
|
+
BLOCK_MARKER = /blocked by a hook|\[synkro:/i;
|
|
17191
|
+
FIX_POLL_MARKERS = /\[synkro:fix-poll\s+item_id=\\*["']?([A-Za-z0-9_-]+)\\*["']?\s*\]/gi;
|
|
17192
|
+
LEGACY_FIX_POLL_MARKERS = /SYNKRO FIX POLL\s*\(item_id=([A-Za-z0-9_-]+)\)/gi;
|
|
17193
|
+
}
|
|
17194
|
+
});
|
|
17195
|
+
|
|
16943
17196
|
// cli/harness/render.ts
|
|
16944
17197
|
function spinnerFrame(tick) {
|
|
16945
17198
|
return SPINNER[Math.abs(tick) % SPINNER.length];
|
|
@@ -17001,10 +17254,11 @@ function renderEvent(event, width = 100) {
|
|
|
17001
17254
|
}
|
|
17002
17255
|
case "tool-end": {
|
|
17003
17256
|
if (event.blocked) {
|
|
17257
|
+
const reason = cleanGuardText(event.reason);
|
|
17004
17258
|
return [
|
|
17005
17259
|
S2.panel + S2.blocked + " \u29C9 Blocked" + S2.reset + S2.panel + S2.secondary + " " + clip3(terminalText(event.target), body - 21) + S2.reset,
|
|
17006
|
-
...wrap(terminalText(
|
|
17007
|
-
...wrap(blockNextStep(
|
|
17260
|
+
...wrap(terminalText(reason), body - 6).map((line, index) => index === 0 ? S2.blocked + " " + ELBOW + " " + S2.reset + S2.rule + line + S2.reset : S2.rule + " " + line + S2.reset),
|
|
17261
|
+
...wrap(blockNextStep(reason), body - 6).map((line) => S2.secondary + " " + line + S2.reset)
|
|
17008
17262
|
];
|
|
17009
17263
|
}
|
|
17010
17264
|
const timing = event.durationMs == null ? "" : " \xB7 " + seconds(event.durationMs);
|
|
@@ -17053,6 +17307,7 @@ var ESC2, color, S2, CLEAR_LINE, BULLET, ELBOW, SPINNER, TOOL_LABEL;
|
|
|
17053
17307
|
var init_render2 = __esm({
|
|
17054
17308
|
"cli/harness/render.ts"() {
|
|
17055
17309
|
"use strict";
|
|
17310
|
+
init_events();
|
|
17056
17311
|
ESC2 = "\x1B[";
|
|
17057
17312
|
color = (hex, plane = 38) => {
|
|
17058
17313
|
const [r, g, b] = hex.match(/../g).map((part) => Number.parseInt(part, 16));
|
|
@@ -17107,35 +17362,6 @@ var init_composer = __esm({
|
|
|
17107
17362
|
}
|
|
17108
17363
|
});
|
|
17109
17364
|
|
|
17110
|
-
// cli/harness/events.ts
|
|
17111
|
-
function fixPollId(raw) {
|
|
17112
|
-
const text = String(raw || "");
|
|
17113
|
-
return FIX_POLL_MARKER.exec(text)?.[1] || LEGACY_FIX_POLL_MARKER.exec(text)?.[1] || "";
|
|
17114
|
-
}
|
|
17115
|
-
function cleanGuardText(raw) {
|
|
17116
|
-
return String(raw || "").replace(FIX_POLL_MARKER, "").replace(/\n*\s*SYNKRO FIX POLL[\s\S]*$/i, "").replace(/\n?\d{4}-\d\d-\d\dT[^\n]*\sERROR\s+codex_core::tools::router:[^\n]*/gi, "").replace(/\s*Checking command\s*$/i, "").trim();
|
|
17117
|
-
}
|
|
17118
|
-
function blockReason(raw) {
|
|
17119
|
-
const text = cleanGuardText(raw);
|
|
17120
|
-
if (!text) return "blocked by policy";
|
|
17121
|
-
const guardAt = text.lastIndexOf("Guard:");
|
|
17122
|
-
if (guardAt >= 0) return text.slice(guardAt + "Guard:".length).trim();
|
|
17123
|
-
const afterTag = text.match(/\[synkro:[^\]]*\]\s*(.+)/is);
|
|
17124
|
-
if (afterTag) return afterTag[1].trim();
|
|
17125
|
-
const afterHook = text.match(/blocked by a hook:\s*(.+)/is);
|
|
17126
|
-
if (afterHook) return afterHook[1].trim();
|
|
17127
|
-
return text;
|
|
17128
|
-
}
|
|
17129
|
-
var BLOCK_MARKER, FIX_POLL_MARKER, LEGACY_FIX_POLL_MARKER;
|
|
17130
|
-
var init_events = __esm({
|
|
17131
|
-
"cli/harness/events.ts"() {
|
|
17132
|
-
"use strict";
|
|
17133
|
-
BLOCK_MARKER = /blocked by a hook|\[synkro:/i;
|
|
17134
|
-
FIX_POLL_MARKER = /\[synkro:fix-poll\s+item_id=\\?["']?([A-Za-z0-9_-]+)\\?["']?\]/i;
|
|
17135
|
-
LEGACY_FIX_POLL_MARKER = /SYNKRO FIX POLL\s*\(item_id=([A-Za-z0-9_-]+)\)/i;
|
|
17136
|
-
}
|
|
17137
|
-
});
|
|
17138
|
-
|
|
17139
17365
|
// cli/harness/changes.ts
|
|
17140
17366
|
import { lstatSync as lstatSync2, readFileSync as readFileSync33, readlinkSync } from "fs";
|
|
17141
17367
|
import { resolve as resolve6, relative } from "path";
|
|
@@ -17419,6 +17645,7 @@ function parseCursorLine(line, streamPartial = false) {
|
|
|
17419
17645
|
blocked,
|
|
17420
17646
|
reason: rejected ? blocked ? blockReason(rawReason) : rawReason || "rejected" : "",
|
|
17421
17647
|
pollId: blocked ? fixPollId(rawReason) : "",
|
|
17648
|
+
pollIds: blocked ? fixPollIds(rawReason) : [],
|
|
17422
17649
|
exitCode: success ? Number(success.exitCode ?? 0) : null,
|
|
17423
17650
|
output: String(success?.stdout || success?.stderr || ""),
|
|
17424
17651
|
fileChanges: completedFileChanges(body)
|
|
@@ -17761,6 +17988,11 @@ var init_run = __esm({
|
|
|
17761
17988
|
// cli/harness/codex.ts
|
|
17762
17989
|
import { spawn as spawn10 } from "child_process";
|
|
17763
17990
|
import { createInterface as createInterface6 } from "readline";
|
|
17991
|
+
function codexStderrNotice(raw, initialized) {
|
|
17992
|
+
const text = String(raw || "").trim();
|
|
17993
|
+
if (!text || initialized) return "";
|
|
17994
|
+
return /fatal|panic|authentication failed|not logged in/i.test(text) ? text.split("\n")[0].slice(0, 300) : "";
|
|
17995
|
+
}
|
|
17764
17996
|
function stringify(value) {
|
|
17765
17997
|
if (typeof value === "string") return value;
|
|
17766
17998
|
try {
|
|
@@ -17843,6 +18075,7 @@ function codexEvents(message) {
|
|
|
17843
18075
|
blocked,
|
|
17844
18076
|
reason: blocked ? blockReason(raw || status) : "",
|
|
17845
18077
|
pollId: blocked ? fixPollId(raw) : "",
|
|
18078
|
+
pollIds: blocked ? fixPollIds(raw) : [],
|
|
17846
18079
|
exitCode: typeof item.exitCode === "number" ? item.exitCode : null,
|
|
17847
18080
|
output: raw,
|
|
17848
18081
|
durationMs: typeof item.durationMs === "number" ? item.durationMs : null,
|
|
@@ -17864,6 +18097,7 @@ function codexEvents(message) {
|
|
|
17864
18097
|
exitCode: null,
|
|
17865
18098
|
output: reason,
|
|
17866
18099
|
pollId: fixPollId(reason),
|
|
18100
|
+
pollIds: fixPollIds(reason),
|
|
17867
18101
|
durationMs: typeof run2.durationMs === "number" ? run2.durationMs : null
|
|
17868
18102
|
}];
|
|
17869
18103
|
}
|
|
@@ -17898,6 +18132,7 @@ var init_codex = __esm({
|
|
|
17898
18132
|
cwd;
|
|
17899
18133
|
resumeId;
|
|
17900
18134
|
child = null;
|
|
18135
|
+
initialized = false;
|
|
17901
18136
|
nextId = 1;
|
|
17902
18137
|
pending = /* @__PURE__ */ new Map();
|
|
17903
18138
|
onEvent = null;
|
|
@@ -17974,7 +18209,7 @@ var init_codex = __esm({
|
|
|
17974
18209
|
}
|
|
17975
18210
|
});
|
|
17976
18211
|
this.child.stderr.on("data", (chunk) => {
|
|
17977
|
-
const message = String(chunk || "").
|
|
18212
|
+
const message = codexStderrNotice(String(chunk || ""), this.initialized);
|
|
17978
18213
|
if (message) this.onEvent?.({ type: "notice", text: message });
|
|
17979
18214
|
});
|
|
17980
18215
|
this.child.once("exit", (code) => {
|
|
@@ -17985,6 +18220,7 @@ var init_codex = __esm({
|
|
|
17985
18220
|
});
|
|
17986
18221
|
await this.request("initialize", { clientInfo: { name: "synkro-terminal", title: "Synkro", version: "1" }, capabilities: { experimentalApi: true } });
|
|
17987
18222
|
this.notify("initialized");
|
|
18223
|
+
this.initialized = true;
|
|
17988
18224
|
try {
|
|
17989
18225
|
const event = codexAccountUsageEvent(await this.request("account/rateLimits/read", null, 4e3));
|
|
17990
18226
|
if (event) this.accountUsage = event;
|
|
@@ -18321,11 +18557,13 @@ async function loadFixPoll(itemId, fetchImpl = fetch) {
|
|
|
18321
18557
|
const body = await response.json();
|
|
18322
18558
|
const candidates = Array.isArray(body.candidates) ? body.candidates.filter((candidate) => typeof candidate === "string").slice(0, 8) : [];
|
|
18323
18559
|
if (!candidates.length || body.status !== "pending") return null;
|
|
18560
|
+
const recommendedIdx = Number.isInteger(body.recommended_idx) && body.recommended_idx >= 0 && body.recommended_idx < candidates.length ? body.recommended_idx : -1;
|
|
18324
18561
|
return {
|
|
18325
18562
|
itemId,
|
|
18326
18563
|
filePath: String(body.file_path || ""),
|
|
18327
18564
|
ruleId: String(body.rule_id || ""),
|
|
18328
|
-
candidates
|
|
18565
|
+
candidates,
|
|
18566
|
+
recommendedIdx
|
|
18329
18567
|
};
|
|
18330
18568
|
}
|
|
18331
18569
|
async function recordFixPoll(itemId, chosenIdx, fetchImpl = fetch) {
|
|
@@ -18348,7 +18586,8 @@ function fixPollLines(poll, selected, width = 100) {
|
|
|
18348
18586
|
];
|
|
18349
18587
|
choices.forEach((choice, index) => {
|
|
18350
18588
|
const prefix = index === selected ? S2.user + " \u276F " : S2.dim + " ";
|
|
18351
|
-
const
|
|
18589
|
+
const recommendation = index === poll.recommendedIdx ? "Recommended: " : "";
|
|
18590
|
+
const text = wrap(index + 1 + ". " + recommendation + neutralizeTerminalControls(choice), max);
|
|
18352
18591
|
lines2.push(prefix + (text[0] || "") + S2.reset);
|
|
18353
18592
|
for (const continuation of text.slice(1)) lines2.push(" " + continuation);
|
|
18354
18593
|
});
|
|
@@ -18359,7 +18598,7 @@ async function pickFixPoll(poll, io = {}) {
|
|
|
18359
18598
|
const input = io.input || process.stdin;
|
|
18360
18599
|
const output = io.output || process.stdout;
|
|
18361
18600
|
if (!input.isTTY || !output.isTTY) return -1;
|
|
18362
|
-
let selected = 0;
|
|
18601
|
+
let selected = poll.recommendedIdx >= 0 && poll.recommendedIdx < poll.candidates.length ? poll.recommendedIdx : 0;
|
|
18363
18602
|
let rendered = 0;
|
|
18364
18603
|
const draw = () => {
|
|
18365
18604
|
if (rendered) output.write("\x1B[" + rendered + "A\x1B[J");
|
|
@@ -18396,7 +18635,7 @@ async function pickFixPoll(poll, io = {}) {
|
|
|
18396
18635
|
return choice;
|
|
18397
18636
|
}
|
|
18398
18637
|
async function resolveFixPolls(events, io = {}) {
|
|
18399
|
-
const ids = Array.from(new Set(events.filter((event) => event.type === "tool-end").
|
|
18638
|
+
const ids = Array.from(new Set(events.filter((event) => event.type === "tool-end").flatMap((event) => event.pollIds?.length ? event.pollIds : [event.pollId || ""]).filter(Boolean)));
|
|
18400
18639
|
const recorded = [];
|
|
18401
18640
|
for (const itemId of ids) {
|
|
18402
18641
|
const poll = await loadFixPoll(itemId, io.fetchImpl).catch(() => null);
|
|
@@ -19930,7 +20169,7 @@ function pseudonymousHostnameHash(installationId, host) {
|
|
|
19930
20169
|
}
|
|
19931
20170
|
function cliVersion() {
|
|
19932
20171
|
try {
|
|
19933
|
-
return "1.10.
|
|
20172
|
+
return "1.10.10";
|
|
19934
20173
|
} catch {
|
|
19935
20174
|
return "0.0.0";
|
|
19936
20175
|
}
|
|
@@ -20700,7 +20939,7 @@ var subArgs = args.slice(1);
|
|
|
20700
20939
|
var isDetachedChild = process.env.SYNKRO_TELEMETRY_DETACHED === "1";
|
|
20701
20940
|
var FLUSH_SKIP = /* @__PURE__ */ new Set(["grade", "inventory-sync", "version", "--version", "-v", "help", "--help", "-h", ""]);
|
|
20702
20941
|
function printVersion() {
|
|
20703
|
-
console.log("1.10.
|
|
20942
|
+
console.log("1.10.10");
|
|
20704
20943
|
}
|
|
20705
20944
|
function printHelp2() {
|
|
20706
20945
|
console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
|