@integrity-labs/agt-cli 0.15.6 → 0.15.8

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.
@@ -22,7 +22,7 @@ import {
22
22
  resolveChannels,
23
23
  resolveDmTarget,
24
24
  wrapScheduledTaskPrompt
25
- } from "../chunk-IGKAMH32.js";
25
+ } from "../chunk-32D5TUSD.js";
26
26
  import {
27
27
  findTaskByTemplate,
28
28
  getProjectDir,
@@ -1069,8 +1069,8 @@ function startRealtimeKanban(config2) {
1069
1069
  filter: filterStr
1070
1070
  }, (payload) => {
1071
1071
  const item = payload.new;
1072
- if (item.status === "today") {
1073
- log2(`[realtime] New kanban item in 'today': "${item.title}" for agent ${item.agent_id}`);
1072
+ if (item.status === "todo") {
1073
+ log2(`[realtime] New kanban item in 'todo': item_id=${item.id} agent=${item.agent_id}`);
1074
1074
  onTodayItem(item);
1075
1075
  }
1076
1076
  }).on("postgres_changes", {
@@ -1081,8 +1081,8 @@ function startRealtimeKanban(config2) {
1081
1081
  }, (payload) => {
1082
1082
  const item = payload.new;
1083
1083
  const old = payload.old;
1084
- if (item.status === "today" && old.status !== "today") {
1085
- log2(`[realtime] Kanban item moved to 'today': "${item.title}" for agent ${item.agent_id}`);
1084
+ if (item.status === "todo" && old.status !== "todo") {
1085
+ log2(`[realtime] Kanban item moved to 'todo': item_id=${item.id} agent=${item.agent_id}`);
1086
1086
  onTodayItem(item);
1087
1087
  }
1088
1088
  if (onCompletion && (item.status === "done" || item.status === "failed") && old.status !== item.status) {
@@ -3141,7 +3141,7 @@ async function processAgent(agent, agentStates) {
3141
3141
  } else if (agentFw === "claude-code") {
3142
3142
  if (sessionMode === "persistent") {
3143
3143
  if (isSessionHealthy(agent.code_name)) {
3144
- const todayItem = boardItems.find((b) => b.status === "today");
3144
+ const todayItem = boardItems.find((b) => b.status === "todo");
3145
3145
  const taskHint = todayItem ? ` Top item: "${todayItem.title}" (priority ${todayItem.priority}).` : "";
3146
3146
  injectMessage(agent.code_name, "task", `New work triggered. Check your kanban board with kanban_list and pick up the next item.${taskHint}`, {
3147
3147
  task_name: "kanban-work-trigger"
@@ -3467,7 +3467,7 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
3467
3467
  prompt = boardPrefix + prompt;
3468
3468
  }
3469
3469
  if (KANBAN_WORK_TEMPLATES.has(task.templateId)) {
3470
- const todayItem = boardItems.find((b) => b.status === "today");
3470
+ const todayItem = boardItems.find((b) => b.status === "todo");
3471
3471
  if (todayItem) {
3472
3472
  try {
3473
3473
  await api.post("/host/kanban", {
@@ -3489,9 +3489,42 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
3489
3489
  });
3490
3490
  }
3491
3491
  }
3492
+ async function startRun(opts) {
3493
+ try {
3494
+ const res = await api.post(
3495
+ "/host/runs/start",
3496
+ opts
3497
+ );
3498
+ return { run_id: res.run_id ?? null, kanban_item_id: res.kanban_item_id ?? null };
3499
+ } catch (err) {
3500
+ const errText = err instanceof Error ? err.message : String(err);
3501
+ const errId = createHash("sha256").update(errText).digest("hex").slice(0, 12);
3502
+ log(`[runs] start failed for agent_id=${opts.agent_id} source_type=${opts.source_type} error_id=${errId}`);
3503
+ return { run_id: null, kanban_item_id: null };
3504
+ }
3505
+ }
3506
+ async function finishRun(runId, outcome, options = {}) {
3507
+ try {
3508
+ await api.post("/host/runs/finish", {
3509
+ run_id: runId,
3510
+ outcome,
3511
+ outcome_message: options.outcomeMessage,
3512
+ metadata: options.metadata,
3513
+ complete_kanban_item_id: options.completeKanbanItemId ?? void 0,
3514
+ result: options.result
3515
+ });
3516
+ } catch (err) {
3517
+ const errText = err instanceof Error ? err.message : String(err);
3518
+ const errId = createHash("sha256").update(errText).digest("hex").slice(0, 12);
3519
+ log(`[runs] finish failed for run_id=${runId} outcome=${outcome} error_id=${errId}`);
3520
+ }
3521
+ }
3492
3522
  async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
3493
3523
  const projectDir = getProjectDir(codeName);
3494
3524
  const mcpConfigPath = join2(projectDir, ".mcp.json");
3525
+ let runId = null;
3526
+ let kanbanItemId = null;
3527
+ let taskResult;
3495
3528
  sanitizeMcpJson(mcpConfigPath, requireHost());
3496
3529
  prompt = wrapScheduledTaskPrompt(prompt);
3497
3530
  try {
@@ -3538,6 +3571,16 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
3538
3571
  log(`[claude-scheduler] Skipping task '${task.name}' for '${codeName}' \u2014 auth resolve failed: ${err.message}`);
3539
3572
  return;
3540
3573
  }
3574
+ const startResult = await startRun({
3575
+ agent_id: agentId,
3576
+ source_type: "scheduled_task",
3577
+ source_ref: task.taskId,
3578
+ metadata: { template_id: task.templateId, name: task.name },
3579
+ materialize_kanban: { title: task.name, priority: 2 }
3580
+ });
3581
+ runId = startResult.run_id;
3582
+ kanbanItemId = startResult.kanban_item_id;
3583
+ if (runId) childEnv["AGT_RUN_ID"] = runId;
3541
3584
  const { stdout, stderr } = await execFilePromiseLong(resolveClaudeBinary(), claudeArgs, {
3542
3585
  cwd: projectDir,
3543
3586
  timeout: 3e5,
@@ -3548,6 +3591,7 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
3548
3591
  log(`[claude-scheduler] Task '${task.name}' stderr for '${codeName}': ${stderr.slice(0, 500)}`);
3549
3592
  }
3550
3593
  const output = stdout.trim();
3594
+ taskResult = output.slice(0, 4e3) || void 0;
3551
3595
  log(`[claude-scheduler] Task '${task.name}' completed for '${codeName}' (${output.length} chars): ${output.slice(0, 300)}`);
3552
3596
  await processClaudeTaskResult(codeName, agentId, task.templateId, output, {
3553
3597
  mode: task.deliveryMode,
@@ -3555,6 +3599,13 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
3555
3599
  to: task.deliveryTo,
3556
3600
  taskId: task.taskId
3557
3601
  });
3602
+ if (runId) {
3603
+ await finishRun(runId, "completed", {
3604
+ metadata: { output_length: output.length },
3605
+ completeKanbanItemId: kanbanItemId,
3606
+ result: taskResult
3607
+ });
3608
+ }
3558
3609
  const updated = markTaskFired(codeName, task.taskId, "ok");
3559
3610
  claudeSchedulerStates.set(codeName, updated);
3560
3611
  if (task.scheduleKind === "at") {
@@ -3567,13 +3618,25 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
3567
3618
  const errMsg = err instanceof Error ? err.message : String(err);
3568
3619
  log(`[claude-scheduler] Task '${task.name}' failed for '${codeName}': ${errMsg}`);
3569
3620
  if (err instanceof ChildProcessError) {
3570
- if (err.stdout.trim()) {
3571
- log(`[claude-scheduler] Task '${task.name}' stdout for '${codeName}': ${err.stdout.trim().slice(0, 1e3)}`);
3621
+ const errStdout = err.stdout.trim();
3622
+ if (errStdout) {
3623
+ taskResult = errStdout.slice(0, 4e3) || taskResult;
3624
+ log(`[claude-scheduler] Task '${task.name}' stdout for '${codeName}': ${errStdout.slice(0, 1e3)}`);
3572
3625
  }
3573
3626
  if (err.stderr.trim()) {
3574
3627
  log(`[claude-scheduler] Task '${task.name}' stderr for '${codeName}': ${err.stderr.trim().slice(0, 1e3)}`);
3575
3628
  }
3576
3629
  }
3630
+ if (runId) {
3631
+ try {
3632
+ await finishRun(runId, "failed", {
3633
+ outcomeMessage: errMsg,
3634
+ completeKanbanItemId: kanbanItemId,
3635
+ result: taskResult
3636
+ });
3637
+ } catch {
3638
+ }
3639
+ }
3577
3640
  const updated = markTaskFired(codeName, task.taskId, "error");
3578
3641
  claudeSchedulerStates.set(codeName, updated);
3579
3642
  }
@@ -3821,7 +3884,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
3821
3884
  prompt = boardPrefix + prompt;
3822
3885
  }
3823
3886
  if (KANBAN_WORK_TEMPLATES.has(task.templateId)) {
3824
- const todayItem = boardItems.find((b) => b.status === "today");
3887
+ const todayItem = boardItems.find((b) => b.status === "todo");
3825
3888
  if (todayItem) {
3826
3889
  try {
3827
3890
  await api.post("/host/kanban", {
@@ -4216,7 +4279,7 @@ var TASK_UPDATE_TEMPLATES = /* @__PURE__ */ new Set(["hourly-status", "task-upda
4216
4279
  var PLAN_TEMPLATES = /* @__PURE__ */ new Set(["morning-plan"]);
4217
4280
  var KANBAN_WORK_TEMPLATES = /* @__PURE__ */ new Set(["kanban-work"]);
4218
4281
  var BOARD_INJECT_TEMPLATES = /* @__PURE__ */ new Set(["morning-plan", "task-update", "hourly-status", "end-of-day-summary", "kanban-work"]);
4219
- var ACTIONABLE_STATUSES = /* @__PURE__ */ new Set(["backlog", "today", "in_progress"]);
4282
+ var ACTIONABLE_STATUSES = /* @__PURE__ */ new Set(["backlog", "todo", "in_progress"]);
4220
4283
  function hasActionableItems(items) {
4221
4284
  return items.some((item) => ACTIONABLE_STATUSES.has(item.status));
4222
4285
  }
@@ -4349,8 +4412,8 @@ function parseStandupSummary(summary) {
4349
4412
  if (lower.includes("yesterday") || lower.includes("accomplished")) {
4350
4413
  currentSection = "yesterday";
4351
4414
  continue;
4352
- } else if (lower.includes("today") || lower.includes("working on")) {
4353
- currentSection = "today";
4415
+ } else if (lower.includes("todo") || lower.includes("working on")) {
4416
+ currentSection = "todo";
4354
4417
  continue;
4355
4418
  } else if (lower.includes("blocker")) {
4356
4419
  currentSection = "blockers";
@@ -4362,7 +4425,7 @@ function parseStandupSummary(summary) {
4362
4425
  case "yesterday":
4363
4426
  yesterday += (yesterday ? "\n" : "") + trimmed;
4364
4427
  break;
4365
- case "today":
4428
+ case "todo":
4366
4429
  today += (today ? "\n" : "") + trimmed;
4367
4430
  break;
4368
4431
  case "blockers":
@@ -4405,7 +4468,7 @@ function parsePlanItems(summary) {
4405
4468
  title,
4406
4469
  priority,
4407
4470
  estimated_minutes: estimatedMinutes,
4408
- status: "today"
4471
+ status: "todo"
4409
4472
  };
4410
4473
  } else if (currentItem && trimmed && !trimmed.match(/^(?:PLAN|---)/i)) {
4411
4474
  const descLine = sanitizeKanbanString(trimmed, MAX_KANBAN_NOTES_LENGTH);
@@ -4415,7 +4478,7 @@ function parsePlanItems(summary) {
4415
4478
  if (currentItem) items.push(currentItem);
4416
4479
  return items;
4417
4480
  }
4418
- var VALID_KANBAN_STATUSES = /* @__PURE__ */ new Set(["backlog", "today", "in_progress", "done"]);
4481
+ var VALID_KANBAN_STATUSES = /* @__PURE__ */ new Set(["backlog", "todo", "in_progress", "done"]);
4419
4482
  var MAX_KANBAN_TITLE_LENGTH = 500;
4420
4483
  var MAX_KANBAN_NOTES_LENGTH = 2e3;
4421
4484
  function sanitizeKanbanString(value, maxLen) {
@@ -4461,9 +4524,10 @@ function parseKanbanUpdates(summary) {
4461
4524
  const lines = kanbanSection.split("\n");
4462
4525
  for (const line of lines) {
4463
4526
  const trimmed = line.trim();
4464
- const match = trimmed.match(/^[-*•]\s*"([^"]+)":\s*(backlog|today|in_progress|done)(?:\s*\((.+)\))?/i);
4527
+ const match = trimmed.match(/^[-*•]\s*"([^"]+)":\s*(backlog|todo|today|in_progress|done)(?:\s*\((.+)\))?/i);
4465
4528
  if (match) {
4466
- const status = match[2].toLowerCase();
4529
+ const rawStatus = match[2].toLowerCase();
4530
+ const status = rawStatus === "today" ? "todo" : rawStatus;
4467
4531
  if (!VALID_KANBAN_STATUSES.has(status)) continue;
4468
4532
  const title = sanitizeKanbanString(match[1], MAX_KANBAN_TITLE_LENGTH);
4469
4533
  if (!title) continue;
@@ -4505,7 +4569,7 @@ function formatBoardForPrompt(items, template) {
4505
4569
  const lines = [];
4506
4570
  if (template === "morning-plan") {
4507
4571
  lines.push("=== CURRENT BOARD ===");
4508
- for (const [status, label] of [["backlog", "BACKLOG (carry-over)"], ["today", "TODAY"], ["in_progress", "IN PROGRESS"]]) {
4572
+ for (const [status, label] of [["backlog", "BACKLOG (carry-over)"], ["todo", "TO DO"], ["in_progress", "IN PROGRESS"]]) {
4509
4573
  const statusItems = grouped[status];
4510
4574
  if (statusItems && statusItems.length > 0) {
4511
4575
  lines.push(`${label}:`);
@@ -4517,13 +4581,13 @@ function formatBoardForPrompt(items, template) {
4517
4581
  lines.push("=====================");
4518
4582
  lines.push("");
4519
4583
  lines.push("Create today's plan. You may:");
4520
- lines.push('- Move backlog items to "today"');
4584
+ lines.push('- Move backlog items to "todo"');
4521
4585
  lines.push("- Add new items you've identified");
4522
4586
  lines.push("- Reprioritise existing items");
4523
4587
  lines.push("");
4524
4588
  } else {
4525
4589
  lines.push("=== YOUR KANBAN BOARD ===");
4526
- for (const [status, label] of [["today", "TODAY"], ["in_progress", "IN PROGRESS"], ["backlog", "BACKLOG"]]) {
4590
+ for (const [status, label] of [["todo", "TO DO"], ["in_progress", "IN PROGRESS"], ["backlog", "BACKLOG"]]) {
4527
4591
  const statusItems = grouped[status];
4528
4592
  if (statusItems && statusItems.length > 0) {
4529
4593
  lines.push(`${label}:`);