castle-web-cli 0.4.35 → 0.4.36
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/agent.js +36 -27
- package/dist/chat-client.js +4 -1
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -543,13 +543,14 @@ function createTaskStore(opts) {
|
|
|
543
543
|
});
|
|
544
544
|
}
|
|
545
545
|
function spawnFromDirective(directive, originMessageId) {
|
|
546
|
-
// A fix/redo task sweeps the rows it obsoletes off the user's board.
|
|
547
|
-
// superseded task that
|
|
546
|
+
// A fix/redo task sweeps the rows it obsoletes off the user's board. Halt
|
|
547
|
+
// first -- a superseded task that is still running must have its process
|
|
548
|
+
// killed (not just hidden, which left an invisible zombie the rest of the
|
|
549
|
+
// board could depend on), and a waiting one must not start later.
|
|
548
550
|
for (const id of resolveDeps(tasks, directive.supersedes)) {
|
|
549
551
|
const old = tasks.get(id);
|
|
550
552
|
if (old && !old.acknowledged) {
|
|
551
|
-
|
|
552
|
-
old.status = 'interrupted';
|
|
553
|
+
haltTask(old);
|
|
553
554
|
old.acknowledged = true;
|
|
554
555
|
touch(old);
|
|
555
556
|
opts.onSuperseded(old);
|
|
@@ -620,6 +621,28 @@ function createTaskStore(opts) {
|
|
|
620
621
|
// stop everything still active. Waiting tasks are cancelled outright;
|
|
621
622
|
// running ones get their agent process killed and finalize as interrupted
|
|
622
623
|
// via the stopRequested path.
|
|
624
|
+
// Halt an active task: a waiting one is cancelled (-> interrupted); a
|
|
625
|
+
// running one gets its agent process killed and finalizes as interrupted
|
|
626
|
+
// via the stopRequested path. No-op on terminal tasks.
|
|
627
|
+
function haltTask(task) {
|
|
628
|
+
if (task.status === 'waiting') {
|
|
629
|
+
task.status = 'interrupted';
|
|
630
|
+
touch(task);
|
|
631
|
+
}
|
|
632
|
+
else if (task.status === 'running') {
|
|
633
|
+
stopRequested.add(task.id);
|
|
634
|
+
for (const child of children) {
|
|
635
|
+
if (child.pid === task.pid) {
|
|
636
|
+
try {
|
|
637
|
+
child.kill('SIGKILL');
|
|
638
|
+
}
|
|
639
|
+
catch {
|
|
640
|
+
/* already gone */
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
623
646
|
function stop(tokens) {
|
|
624
647
|
const ids = meansAll(tokens)
|
|
625
648
|
? [...tasks.values()]
|
|
@@ -628,25 +651,8 @@ function createTaskStore(opts) {
|
|
|
628
651
|
: resolveDeps(tasks, tokens);
|
|
629
652
|
for (const id of ids) {
|
|
630
653
|
const task = tasks.get(id);
|
|
631
|
-
if (
|
|
632
|
-
|
|
633
|
-
if (task.status === 'waiting') {
|
|
634
|
-
task.status = 'interrupted';
|
|
635
|
-
touch(task);
|
|
636
|
-
}
|
|
637
|
-
else if (task.status === 'running') {
|
|
638
|
-
stopRequested.add(task.id);
|
|
639
|
-
for (const child of children) {
|
|
640
|
-
if (child.pid === task.pid) {
|
|
641
|
-
try {
|
|
642
|
-
child.kill('SIGKILL');
|
|
643
|
-
}
|
|
644
|
-
catch {
|
|
645
|
-
/* already gone */
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
}
|
|
654
|
+
if (task)
|
|
655
|
+
haltTask(task);
|
|
650
656
|
}
|
|
651
657
|
}
|
|
652
658
|
return { sorted, get: (id) => tasks.get(id), spawnFromDirective, acknowledge, checkOff, stop, shutdown };
|
|
@@ -779,10 +785,13 @@ function runRouterTurnIn(ctx, instruction) {
|
|
|
779
785
|
messages: ctx.log.messages
|
|
780
786
|
.filter((m) => m.role !== 'log' && m.id !== message.id && m.status !== 'streaming')
|
|
781
787
|
.map((m) => ({ role: m.role, text: m.text })),
|
|
782
|
-
// Only the live board
|
|
783
|
-
//
|
|
784
|
-
//
|
|
785
|
-
tasks: ctx.taskStore
|
|
788
|
+
// Only the live board -- match what the user sees. Hide tasks that are
|
|
789
|
+
// BOTH acknowledged AND finished; an active (running/waiting) task always
|
|
790
|
+
// shows even if somehow acked, so nothing can ever go invisible mid-work.
|
|
791
|
+
tasks: ctx.taskStore
|
|
792
|
+
.sorted()
|
|
793
|
+
.filter((t) => !(t.acknowledged && isTerminal(t.status)))
|
|
794
|
+
.map(asPromptTask),
|
|
786
795
|
instruction,
|
|
787
796
|
});
|
|
788
797
|
const backend = ctx.backend();
|
package/dist/chat-client.js
CHANGED
|
@@ -227,7 +227,10 @@ function TaskRow(props) {
|
|
|
227
227
|
expanded && task.status !== 'running' ? (React.createElement("div", { className: "task-notes", dangerouslySetInnerHTML: renderMarkdown(notes) })) : null));
|
|
228
228
|
}
|
|
229
229
|
function TaskBoard(props) {
|
|
230
|
-
|
|
230
|
+
// Hide only tasks that are acknowledged AND finished. An active
|
|
231
|
+
// (running/waiting) task always shows, even if somehow acked -- a running
|
|
232
|
+
// task must never go invisible while it (and its dependents) are live.
|
|
233
|
+
const visible = props.tasks.filter((t) => !(t.acknowledged && TERMINAL_TASK_STATUSES.includes(t.status)));
|
|
231
234
|
if (visible.length === 0)
|
|
232
235
|
return null;
|
|
233
236
|
return (React.createElement("div", { id: "chat-strip" }, visible.map((task) => (React.createElement(TaskRow, { key: task.id, task: task, feed: props.feeds[task.id], onAck: props.onAck })))));
|