castle-web-cli 0.4.178 → 0.4.179
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
CHANGED
|
@@ -2269,6 +2269,8 @@ function persistTaskFile(tasksDir, task) {
|
|
|
2269
2269
|
// written whether or not the deck has the plan doc switched on: it is a disk
|
|
2270
2270
|
// receipt, never injected into a prompt, so it costs an off deck nothing.
|
|
2271
2271
|
const TASK_INDEX_FILE = 'index.md';
|
|
2272
|
+
const TASK_FEED_FILE = 'feed.json';
|
|
2273
|
+
const TASK_FEED_CAP = 80;
|
|
2272
2274
|
const TASK_INDEX_HEADER = '# tasks\n# <task-id> | <item> | <title> | <created> | <status> | <touching>\n';
|
|
2273
2275
|
// A pipe-delimited row can't carry a pipe. Titles come from the router's fence
|
|
2274
2276
|
// and can hold anything.
|
|
@@ -3224,8 +3226,27 @@ function asClientMessage(message, signPath) {
|
|
|
3224
3226
|
attachments: message.attachments.map((name) => clientUrl(`${AGENT_ATTACHMENT_PREFIX}${name}`, signPath)),
|
|
3225
3227
|
};
|
|
3226
3228
|
}
|
|
3227
|
-
function
|
|
3229
|
+
function loadTaskFeeds(tasksDir) {
|
|
3228
3230
|
const map = new Map();
|
|
3231
|
+
for (const entry of fs.existsSync(tasksDir) ? fs.readdirSync(tasksDir) : []) {
|
|
3232
|
+
const loaded = readJsonFile(path.join(tasksDir, entry, TASK_FEED_FILE));
|
|
3233
|
+
if (!Array.isArray(loaded))
|
|
3234
|
+
continue;
|
|
3235
|
+
const lines = loaded.filter((line) => typeof line === 'string');
|
|
3236
|
+
if (lines.length === 0)
|
|
3237
|
+
continue;
|
|
3238
|
+
map.set(entry, lines.slice(-TASK_FEED_CAP));
|
|
3239
|
+
}
|
|
3240
|
+
return map;
|
|
3241
|
+
}
|
|
3242
|
+
function createTaskFeeds(broadcast, tasksDir) {
|
|
3243
|
+
const map = loadTaskFeeds(tasksDir);
|
|
3244
|
+
function persist(task) {
|
|
3245
|
+
const feed = map.get(task.id);
|
|
3246
|
+
if (!feed || feed.length === 0)
|
|
3247
|
+
return;
|
|
3248
|
+
atomicWriteFileSync(path.join(tasksDir, task.id, TASK_FEED_FILE), JSON.stringify(feed, null, 2) + '\n');
|
|
3249
|
+
}
|
|
3229
3250
|
function push(task, entry) {
|
|
3230
3251
|
let feed = map.get(task.id);
|
|
3231
3252
|
if (!feed) {
|
|
@@ -3235,11 +3256,11 @@ function createTaskFeeds(broadcast) {
|
|
|
3235
3256
|
if (feed[feed.length - 1] === entry)
|
|
3236
3257
|
return;
|
|
3237
3258
|
feed.push(entry);
|
|
3238
|
-
if (feed.length >
|
|
3239
|
-
feed.splice(0, feed.length -
|
|
3259
|
+
if (feed.length > TASK_FEED_CAP)
|
|
3260
|
+
feed.splice(0, feed.length - TASK_FEED_CAP);
|
|
3240
3261
|
broadcast({ type: 'task-feed', id: task.id, entry });
|
|
3241
3262
|
}
|
|
3242
|
-
return { map, push };
|
|
3263
|
+
return { map, push, persist };
|
|
3243
3264
|
}
|
|
3244
3265
|
function createMessageThinking(broadcast) {
|
|
3245
3266
|
const map = new Map();
|
|
@@ -4399,7 +4420,7 @@ export function createAgentServer(opts) {
|
|
|
4399
4420
|
// Castle's), so the bar follows the change instead of the poll.
|
|
4400
4421
|
usageFeed.refresh();
|
|
4401
4422
|
};
|
|
4402
|
-
const taskFeeds = createTaskFeeds(broadcast);
|
|
4423
|
+
const taskFeeds = createTaskFeeds(broadcast, tasksDir);
|
|
4403
4424
|
const messageThinking = createMessageThinking(broadcast);
|
|
4404
4425
|
const taskStore = createTaskStore({
|
|
4405
4426
|
deckDir,
|
|
@@ -4421,7 +4442,7 @@ export function createAgentServer(opts) {
|
|
|
4421
4442
|
onUpdate: (task) => broadcast({ type: 'task-update', task: asClientTask(task, opts.signPath) }),
|
|
4422
4443
|
onStarted: () => undefined,
|
|
4423
4444
|
onRetry: (task, attempt) => addLog(`agent died, retrying (${attempt}/${MAX_TASK_ATTEMPTS}): ${task.title}`),
|
|
4424
|
-
onFinished: (task) => taskFeeds.
|
|
4445
|
+
onFinished: (task) => taskFeeds.persist(task),
|
|
4425
4446
|
onFeed: (task, entry) => taskFeeds.push(task, entry),
|
|
4426
4447
|
});
|
|
4427
4448
|
// The mid-run send queue (queue-by-default, "send now"/Stop interrupt, epoch
|