whipped 0.7.0 → 0.8.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/cli.js
CHANGED
|
@@ -13562,7 +13562,10 @@ async function runLogs(options) {
|
|
|
13562
13562
|
process.exit(1);
|
|
13563
13563
|
}
|
|
13564
13564
|
if (options.follow) {
|
|
13565
|
-
const [cmd, args] = process.platform === "win32" ? [
|
|
13565
|
+
const [cmd, args] = process.platform === "win32" ? [
|
|
13566
|
+
"powershell",
|
|
13567
|
+
["-NoProfile", "-Command", `Get-Content -Path '${path2}' -Tail ${options.lines} -Wait`]
|
|
13568
|
+
] : ["tail", ["-f", "-n", String(options.lines), path2]];
|
|
13566
13569
|
const child = spawn2(cmd, args, {
|
|
13567
13570
|
stdio: "inherit"
|
|
13568
13571
|
});
|
|
@@ -13624,7 +13627,7 @@ import { existsSync as existsSync14, readFileSync as readFileSync8 } from "node:
|
|
|
13624
13627
|
import { createServer } from "node:http";
|
|
13625
13628
|
import { join as join22 } from "node:path";
|
|
13626
13629
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
13627
|
-
import * as
|
|
13630
|
+
import * as nodePty3 from "node-pty";
|
|
13628
13631
|
|
|
13629
13632
|
// node_modules/.pnpm/ws@8.20.0/node_modules/ws/wrapper.mjs
|
|
13630
13633
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -20478,11 +20481,12 @@ init_workspace_state();
|
|
|
20478
20481
|
init_workspace_state();
|
|
20479
20482
|
|
|
20480
20483
|
// src/daemon/scheduler.ts
|
|
20481
|
-
|
|
20484
|
+
var import_tree_kill2 = __toESM(require_tree_kill(), 1);
|
|
20482
20485
|
import { existsSync as existsSync10 } from "node:fs";
|
|
20483
20486
|
import { cp, link, mkdir as mkdir3, stat as stat2, symlink, unlink as unlink2 } from "node:fs/promises";
|
|
20484
20487
|
import { dirname as dirname6, join as join17, resolve as resolve2 } from "node:path";
|
|
20485
20488
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
20489
|
+
import * as nodePty2 from "node-pty";
|
|
20486
20490
|
init_api_contract();
|
|
20487
20491
|
init_logger();
|
|
20488
20492
|
|
|
@@ -21789,6 +21793,12 @@ var TaskScheduler = class {
|
|
|
21789
21793
|
planPhaseManuallyStopped = /* @__PURE__ */ new Set();
|
|
21790
21794
|
// Individual review stream IDs stopped by a manual stopTask() call.
|
|
21791
21795
|
manuallyStoppedStreams = /* @__PURE__ */ new Set();
|
|
21796
|
+
// Worktree-setup install commands currently running, keyed by taskId — so stopTask()
|
|
21797
|
+
// can kill the install PTY before the dev agent has even started.
|
|
21798
|
+
runningInstalls = /* @__PURE__ */ new Map();
|
|
21799
|
+
// Tasks whose install was manually stopped — signals the install runner to reset the
|
|
21800
|
+
// task to its initial state instead of proceeding to the agent.
|
|
21801
|
+
manuallyStoppedInstalls = /* @__PURE__ */ new Set();
|
|
21792
21802
|
// Shared worktree IDs currently in use by a dev agent — prevents sibling cards from
|
|
21793
21803
|
// running concurrently in the same worktree directory.
|
|
21794
21804
|
runningSharedWorktrees = /* @__PURE__ */ new Set();
|
|
@@ -22139,28 +22149,81 @@ ${assistantSystemPrompt}` : assistantSystemPrompt;
|
|
|
22139
22149
|
}
|
|
22140
22150
|
}
|
|
22141
22151
|
if (installCommand.trim()) {
|
|
22142
|
-
|
|
22152
|
+
const installCmd = installCommand.trim();
|
|
22153
|
+
await appendActivityLog(workspaceId, taskId, `Running: ${installCmd}`);
|
|
22154
|
+
const installStartedAt = Date.now();
|
|
22155
|
+
const installStreamId = `${taskId}-install-${installStartedAt}`;
|
|
22156
|
+
await appendTerminalSession(workspaceId, taskId, {
|
|
22157
|
+
streamId: installStreamId,
|
|
22158
|
+
type: "install",
|
|
22159
|
+
startedAt: installStartedAt,
|
|
22160
|
+
state: "running"
|
|
22161
|
+
});
|
|
22143
22162
|
stateHub.broadcastWorkspaceUpdate(workspaceId);
|
|
22144
|
-
|
|
22145
|
-
|
|
22146
|
-
|
|
22163
|
+
let installBuffer = "";
|
|
22164
|
+
const emitInstall = (data) => {
|
|
22165
|
+
installBuffer += data;
|
|
22166
|
+
stateHub.broadcastTerminalOutput(workspaceId, installStreamId, data);
|
|
22167
|
+
};
|
|
22168
|
+
emitInstall(`\x1B[1;36m$ ${installCmd}\x1B[0m\r
|
|
22169
|
+
`);
|
|
22170
|
+
const exitCode = await new Promise((resolveExit) => {
|
|
22171
|
+
const [shell, shellArgs] = getShellInvocation(installCmd);
|
|
22172
|
+
const proc = nodePty2.spawn(shell, shellArgs, {
|
|
22173
|
+
name: "xterm-256color",
|
|
22174
|
+
cols: 220,
|
|
22175
|
+
rows: 50,
|
|
22147
22176
|
cwd: worktree.path,
|
|
22148
|
-
|
|
22149
|
-
env: { ...process.env, REPO_PATH: repoPath }
|
|
22150
|
-
});
|
|
22151
|
-
proc.on("close", (code) => {
|
|
22152
|
-
if (code !== 0) {
|
|
22153
|
-
logger.error(`[scheduler] Install command failed (code ${code}) for task ${taskId}`);
|
|
22154
|
-
void appendActivityLog(
|
|
22155
|
-
workspaceId,
|
|
22156
|
-
taskId,
|
|
22157
|
-
`Install command failed (code ${code}) \u2014 proceeding anyway`
|
|
22158
|
-
);
|
|
22159
|
-
}
|
|
22160
|
-
resolve5();
|
|
22177
|
+
env: { ...process.env, REPO_PATH: repoPath, TERM: "xterm-256color" }
|
|
22161
22178
|
});
|
|
22179
|
+
this.runningInstalls.set(taskId, proc);
|
|
22180
|
+
proc.onData(emitInstall);
|
|
22181
|
+
proc.onExit(({ exitCode: exitCode2 }) => resolveExit(exitCode2 ?? 0));
|
|
22162
22182
|
});
|
|
22163
|
-
|
|
22183
|
+
this.runningInstalls.delete(taskId);
|
|
22184
|
+
this.setRecentBuffer(installStreamId, installBuffer);
|
|
22185
|
+
if (this.isShuttingDown) {
|
|
22186
|
+
await saveTerminalBuffer(workspaceId, installStreamId, installBuffer);
|
|
22187
|
+
return;
|
|
22188
|
+
}
|
|
22189
|
+
if (this.manuallyStoppedInstalls.delete(taskId)) {
|
|
22190
|
+
emitInstall("\r\n\x1B[1;33mInstall stopped \u2014 task reset\x1B[0m\r\n");
|
|
22191
|
+
await saveTerminalBuffer(workspaceId, installStreamId, installBuffer);
|
|
22192
|
+
await endTerminalSession(workspaceId, taskId, installStreamId, Date.now(), "stopped");
|
|
22193
|
+
if (hasSharedWorktree) this.runningSharedWorktrees.delete(effectiveWorktreeId);
|
|
22194
|
+
await removeWorktreeAsync(effectiveWorktreeId, repoPath, worktree.branch);
|
|
22195
|
+
await clearCardSession(workspaceId, taskId);
|
|
22196
|
+
await updateCard(workspaceId, taskId, { readyForDev: false });
|
|
22197
|
+
const stoppedBoard = await loadBoard(workspaceId);
|
|
22198
|
+
if (stoppedBoard.cards[taskId]?.columnId === "in_progress") {
|
|
22199
|
+
await moveCard(workspaceId, taskId, "todo");
|
|
22200
|
+
await appendActivityLog(workspaceId, taskId, "Moved back to Todo");
|
|
22201
|
+
}
|
|
22202
|
+
stateHub.broadcastWorkspaceUpdate(workspaceId);
|
|
22203
|
+
return;
|
|
22204
|
+
}
|
|
22205
|
+
if (exitCode !== 0) {
|
|
22206
|
+
logger.error(`[scheduler] Install command failed (code ${exitCode}) for task ${taskId}`);
|
|
22207
|
+
emitInstall(`\r
|
|
22208
|
+
\x1B[1;31mInstall command failed (code ${exitCode}) \u2014 proceeding anyway\x1B[0m\r
|
|
22209
|
+
`);
|
|
22210
|
+
await appendActivityLog(
|
|
22211
|
+
workspaceId,
|
|
22212
|
+
taskId,
|
|
22213
|
+
`Install command failed (code ${exitCode}) \u2014 proceeding anyway`
|
|
22214
|
+
);
|
|
22215
|
+
} else {
|
|
22216
|
+
emitInstall("\r\n\x1B[1;32mInstall complete\x1B[0m\r\n");
|
|
22217
|
+
await appendActivityLog(workspaceId, taskId, "Install complete");
|
|
22218
|
+
}
|
|
22219
|
+
await saveTerminalBuffer(workspaceId, installStreamId, installBuffer);
|
|
22220
|
+
await endTerminalSession(
|
|
22221
|
+
workspaceId,
|
|
22222
|
+
taskId,
|
|
22223
|
+
installStreamId,
|
|
22224
|
+
Date.now(),
|
|
22225
|
+
exitCode === 0 ? "completed" : "failed"
|
|
22226
|
+
);
|
|
22164
22227
|
stateHub.broadcastWorkspaceUpdate(workspaceId);
|
|
22165
22228
|
}
|
|
22166
22229
|
}
|
|
@@ -22412,6 +22475,15 @@ ${devSystemPromptResult.text}`;
|
|
|
22412
22475
|
}
|
|
22413
22476
|
}
|
|
22414
22477
|
stopTask(taskId) {
|
|
22478
|
+
const installProc = this.runningInstalls.get(taskId);
|
|
22479
|
+
if (installProc) {
|
|
22480
|
+
logger.info(`[scheduler] stopTask: install running \u2014 stopping task ${taskId}`);
|
|
22481
|
+
this.manuallyStoppedInstalls.add(taskId);
|
|
22482
|
+
this.runningInstalls.delete(taskId);
|
|
22483
|
+
killInstallProcess(installProc);
|
|
22484
|
+
void appendActivityLog(this.options.workspaceId, taskId, "Install stopped manually");
|
|
22485
|
+
return;
|
|
22486
|
+
}
|
|
22415
22487
|
const task = this.running.get(taskId);
|
|
22416
22488
|
if (task) {
|
|
22417
22489
|
logger.info(`[scheduler] stopTask: dev agent running \u2014 stopping task ${taskId}`);
|
|
@@ -22667,6 +22739,10 @@ ${devSystemPromptResult.text}`;
|
|
|
22667
22739
|
for (const [taskId] of this.running) {
|
|
22668
22740
|
this.stopTask(taskId);
|
|
22669
22741
|
}
|
|
22742
|
+
for (const proc of this.runningInstalls.values()) {
|
|
22743
|
+
killInstallProcess(proc);
|
|
22744
|
+
}
|
|
22745
|
+
this.runningInstalls.clear();
|
|
22670
22746
|
this.stopAssistantAgent();
|
|
22671
22747
|
}
|
|
22672
22748
|
// Call before stopAll() during graceful shutdown so onExit handlers bail out
|
|
@@ -22675,6 +22751,12 @@ ${devSystemPromptResult.text}`;
|
|
|
22675
22751
|
this.isShuttingDown = true;
|
|
22676
22752
|
}
|
|
22677
22753
|
};
|
|
22754
|
+
function killInstallProcess(proc) {
|
|
22755
|
+
try {
|
|
22756
|
+
(0, import_tree_kill2.default)(proc.pid, "SIGKILL");
|
|
22757
|
+
} catch {
|
|
22758
|
+
}
|
|
22759
|
+
}
|
|
22678
22760
|
async function shareIntoWorktree(src, dst) {
|
|
22679
22761
|
const isDir = (await stat2(src)).isDirectory();
|
|
22680
22762
|
if (process.platform !== "win32") {
|
|
@@ -27978,7 +28060,7 @@ async function createRuntimeServer(options) {
|
|
|
27978
28060
|
function startRun(workspaceId, cardId, command, cwd) {
|
|
27979
28061
|
stopRun(workspaceId);
|
|
27980
28062
|
const [shell, shellArgs] = getShellInvocation(command);
|
|
27981
|
-
const pty =
|
|
28063
|
+
const pty = nodePty3.spawn(shell, shellArgs, {
|
|
27982
28064
|
name: "xterm-256color",
|
|
27983
28065
|
cols: 120,
|
|
27984
28066
|
rows: 40,
|
|
@@ -28688,7 +28770,7 @@ process.on("uncaughtException", (err) => {
|
|
|
28688
28770
|
if (err.code === "EPIPE" || err.code === "ECONNRESET") return;
|
|
28689
28771
|
throw err;
|
|
28690
28772
|
});
|
|
28691
|
-
var VERSION9 = true ? "0.
|
|
28773
|
+
var VERSION9 = true ? "0.8.1" : "0.0.0-dev";
|
|
28692
28774
|
async function isPortAvailable(port, host) {
|
|
28693
28775
|
return new Promise((resolve5) => {
|
|
28694
28776
|
const probe = createServer2();
|
|
@@ -50181,6 +50181,9 @@ const AGENT_DISPLAY = {
|
|
|
50181
50181
|
dotColor: "bg-[#fb8147]"
|
|
50182
50182
|
}
|
|
50183
50183
|
};
|
|
50184
|
+
const SESSION_TYPE_LABELS = {
|
|
50185
|
+
install: "Install"
|
|
50186
|
+
};
|
|
50184
50187
|
function formatElapsed(sec) {
|
|
50185
50188
|
return `${Math.floor(sec / 60)}m ${(sec % 60).toString().padStart(2, "0")}s`;
|
|
50186
50189
|
}
|
|
@@ -50511,7 +50514,7 @@ function WorkflowPipeline({
|
|
|
50511
50514
|
/* Collapsed: icon-only timeline centered */
|
|
50512
50515
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col items-center pb-4 gap-0", children: sessions.length > 0 ? sessions.map((session, idx) => {
|
|
50513
50516
|
var _a3;
|
|
50514
|
-
const slotName = ((_a3 = workflowSlots == null ? void 0 : workflowSlots.find((s16) => s16.id === session.type)) == null ? void 0 : _a3.name) ?? session.type;
|
|
50517
|
+
const slotName = ((_a3 = workflowSlots == null ? void 0 : workflowSlots.find((s16) => s16.id === session.type)) == null ? void 0 : _a3.name) ?? SESSION_TYPE_LABELS[session.type] ?? session.type;
|
|
50515
50518
|
const status = sessionStatus(session);
|
|
50516
50519
|
const isFocused = activeStreamId === session.streamId;
|
|
50517
50520
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center", children: [
|
|
@@ -50546,7 +50549,7 @@ function WorkflowPipeline({
|
|
|
50546
50549
|
/* Expanded: full rows */
|
|
50547
50550
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col px-[18px] pb-4 max-h-72 overflow-y-auto", children: sessions.length > 0 ? sessions.map((session, idx) => {
|
|
50548
50551
|
var _a3;
|
|
50549
|
-
const slotName = ((_a3 = workflowSlots == null ? void 0 : workflowSlots.find((s16) => s16.id === session.type)) == null ? void 0 : _a3.name) ?? session.type;
|
|
50552
|
+
const slotName = ((_a3 = workflowSlots == null ? void 0 : workflowSlots.find((s16) => s16.id === session.type)) == null ? void 0 : _a3.name) ?? SESSION_TYPE_LABELS[session.type] ?? session.type;
|
|
50550
50553
|
const status = sessionStatus(session);
|
|
50551
50554
|
const duration2 = slotDuration(session.startedAt, session.endedAt);
|
|
50552
50555
|
const isFocused = activeStreamId === session.streamId;
|
|
@@ -76894,8 +76897,8 @@ function KanbanBoard({
|
|
|
76894
76897
|
const { trigger: stopAll } = useWrite((api) => api("cards/stop-all").POST());
|
|
76895
76898
|
const { trigger: resumeAll } = useWrite((api) => api("cards/resume-all").POST());
|
|
76896
76899
|
const currentBranch = (branchesData == null ? void 0 : branchesData.defaultBranch) ?? "";
|
|
76897
|
-
const openCard = (id) => navigate(`/${encodeURIComponent(workspaceId)}/board/${encodeURIComponent(id)}
|
|
76898
|
-
const closeCard = () => navigate(`/${encodeURIComponent(workspaceId)}/board
|
|
76900
|
+
const openCard = (id) => navigate(`/${encodeURIComponent(workspaceId)}/board/${encodeURIComponent(id)}`);
|
|
76901
|
+
const closeCard = () => navigate(`/${encodeURIComponent(workspaceId)}/board`);
|
|
76899
76902
|
const handleCardDelete = (card) => {
|
|
76900
76903
|
var _a4;
|
|
76901
76904
|
ConfirmDialog_default.show({
|
|
@@ -77279,7 +77282,7 @@ function BoardPage({ onOpenAgent }) {
|
|
|
77279
77282
|
if (projects.length === 0) return;
|
|
77280
77283
|
if (projects.some((p) => p.workspaceId === workspaceId)) return;
|
|
77281
77284
|
const id = (layout ? firstSortedProjectId(layout, projects) : null) ?? projects[0].workspaceId;
|
|
77282
|
-
navigate(`/${encodeURIComponent(id)}/board
|
|
77285
|
+
navigate(`/${encodeURIComponent(id)}/board`);
|
|
77283
77286
|
}, [projectList, layout, workspaceId, navigate]);
|
|
77284
77287
|
const switchProject = (wsId) => {
|
|
77285
77288
|
navigate(`/${encodeURIComponent(wsId)}/board`);
|
|
@@ -77290,7 +77293,7 @@ function BoardPage({ onOpenAgent }) {
|
|
|
77290
77293
|
if (wsId !== workspaceId) return;
|
|
77291
77294
|
const remaining = projects.filter((p) => p.workspaceId !== wsId);
|
|
77292
77295
|
const nextId = (layout ? firstSortedProjectId(layout, remaining) : null) ?? ((_a3 = remaining[0]) == null ? void 0 : _a3.workspaceId);
|
|
77293
|
-
navigate(nextId ? `/${encodeURIComponent(nextId)}/board` : "/"
|
|
77296
|
+
navigate(nextId ? `/${encodeURIComponent(nextId)}/board` : "/");
|
|
77294
77297
|
};
|
|
77295
77298
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-full overflow-hidden", children: [
|
|
77296
77299
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("nav", { className: "w-[220px] shrink-0 flex flex-col bg-[#141418] border-r border-[#2a2a35]", children: [
|
|
@@ -78079,7 +78082,7 @@ function RecurringAgentsPage() {
|
|
|
78079
78082
|
}, [list2.trigger]);
|
|
78080
78083
|
reactExports.useEffect(() => {
|
|
78081
78084
|
if (agentId || agents.length === 0) return;
|
|
78082
|
-
navigate(`/${encodeURIComponent(wsId)}/recurring-agents/${encodeURIComponent(agents[0].id)}
|
|
78085
|
+
navigate(`/${encodeURIComponent(wsId)}/recurring-agents/${encodeURIComponent(agents[0].id)}`);
|
|
78083
78086
|
}, [agentId, agents, wsId, navigate]);
|
|
78084
78087
|
const select = (id) => navigate(`/${encodeURIComponent(wsId)}/recurring-agents/${encodeURIComponent(id)}`);
|
|
78085
78088
|
const handleToggle = async (enabled) => {
|
package/dist/web-ui/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
|
7
7
|
<title>whipped</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-BMFVAmy4.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-CRXPsGTP.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|