doer-agent 0.5.4 → 0.5.5

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.
@@ -175,6 +175,10 @@ function pickSessionString(...values) {
175
175
  }
176
176
  return null;
177
177
  }
178
+ function toSortableTimestampMs(value) {
179
+ const parsed = Date.parse(value);
180
+ return Number.isFinite(parsed) ? parsed : 0;
181
+ }
178
182
  export async function collectSessionJsonlFiles(workspaceRoot) {
179
183
  const out = [];
180
184
  const stack = [getSessionsRootPath(workspaceRoot)];
@@ -233,8 +237,14 @@ async function readFirstLine(fileHandle, fileSize) {
233
237
  }
234
238
  return raw.trim();
235
239
  }
236
- function extractLastAgentMessage(candidateLines) {
237
- let fallback = null;
240
+ function normalizeSessionSummaryMessage(value) {
241
+ const message = toTrimmedStringOrNull(value);
242
+ if (!message || message.toLowerCase() === "empty") {
243
+ return null;
244
+ }
245
+ return message;
246
+ }
247
+ function extractLastSessionMessage(candidateLines) {
238
248
  for (const line of candidateLines) {
239
249
  const trimmed = line.trim();
240
250
  if (!trimmed) {
@@ -245,18 +255,13 @@ function extractLastAgentMessage(candidateLines) {
245
255
  if (parsed.type !== "event_msg" || !isObjectRecord(parsed.payload)) {
246
256
  continue;
247
257
  }
248
- if (parsed.payload.type === "agent_message" && typeof parsed.payload.message === "string" && parsed.payload.message.trim()) {
249
- return {
250
- message: parsed.payload.message.trim(),
251
- updatedAt: toTrimmedStringOrNull(parsed.timestamp),
252
- };
258
+ if (parsed.payload.type !== "agent_message" && parsed.payload.type !== "user_message") {
259
+ continue;
253
260
  }
254
- if (!fallback &&
255
- parsed.payload.type === "task_complete" &&
256
- typeof parsed.payload.last_agent_message === "string" &&
257
- parsed.payload.last_agent_message.trim()) {
258
- fallback = {
259
- message: parsed.payload.last_agent_message.trim(),
261
+ const message = normalizeSessionSummaryMessage(parsed.payload.message);
262
+ if (message) {
263
+ return {
264
+ message,
260
265
  updatedAt: toTrimmedStringOrNull(parsed.timestamp),
261
266
  };
262
267
  }
@@ -265,9 +270,9 @@ function extractLastAgentMessage(candidateLines) {
265
270
  // ignore malformed lines
266
271
  }
267
272
  }
268
- return fallback;
273
+ return null;
269
274
  }
270
- async function readLastAgentMessage(fileHandle, fileSize) {
275
+ async function readLastSessionMessage(fileHandle, fileSize) {
271
276
  const chunkBytes = 16_384;
272
277
  const maxScanBytes = 131_072;
273
278
  if (fileSize <= 0) {
@@ -288,12 +293,12 @@ async function readLastAgentMessage(fileHandle, fileSize) {
288
293
  const merged = buffer.toString("utf8", 0, bytesRead) + carry;
289
294
  const lines = merged.split(/\r?\n/);
290
295
  carry = lines.shift() || "";
291
- const found = extractLastAgentMessage(lines.reverse());
296
+ const found = extractLastSessionMessage(lines.reverse());
292
297
  if (found) {
293
298
  return found;
294
299
  }
295
300
  }
296
- return extractLastAgentMessage([carry]);
301
+ return extractLastSessionMessage([carry]);
297
302
  }
298
303
  function normalizeSessionMeta(rawMeta, filePath, mtimeMs) {
299
304
  const baseName = path.basename(filePath, path.extname(filePath));
@@ -315,7 +320,7 @@ async function readSessionSummary(filePath, mtimeMs) {
315
320
  fileHandle = await open(filePath, "r");
316
321
  const entryStat = await fileHandle.stat();
317
322
  const firstLine = await readFirstLine(fileHandle, entryStat.size);
318
- const tailSummary = await readLastAgentMessage(fileHandle, entryStat.size);
323
+ const tailSummary = await readLastSessionMessage(fileHandle, entryStat.size);
319
324
  let normalized = normalizeSessionMeta({}, filePath, mtimeMs);
320
325
  if (firstLine) {
321
326
  try {
@@ -365,7 +370,7 @@ async function listAgentSessions(workspaceRoot) {
365
370
  const files = await collectSessionJsonlFiles(workspaceRoot);
366
371
  files.sort((a, b) => b.mtimeMs - a.mtimeMs || a.filePath.localeCompare(b.filePath));
367
372
  const sessions = await Promise.all(files.slice(0, 10).map((file) => readSessionSummary(file.filePath, file.mtimeMs)));
368
- return sessions.sort((a, b) => Date.parse(b.updatedAt) - Date.parse(a.updatedAt) || b.filePath.localeCompare(a.filePath));
373
+ return sessions.sort((a, b) => toSortableTimestampMs(b.updatedAt) - toSortableTimestampMs(a.updatedAt) || b.filePath.localeCompare(a.filePath));
369
374
  }
370
375
  async function readSessionLineIndex(workspaceRoot, filePath) {
371
376
  const resolvedFile = resolveSessionFilePath(workspaceRoot, filePath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doer-agent",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "Reverse-polling agent runtime for doer",
5
5
  "type": "module",
6
6
  "main": "dist/agent.js",