@integrity-labs/agt-cli 0.13.0 → 0.14.0

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.
@@ -9,6 +9,7 @@ import {
9
9
  getIntegration,
10
10
  isParseError,
11
11
  isResolveError,
12
+ isSuppressOutput,
12
13
  parseDeliveryTarget,
13
14
  provision,
14
15
  provisionIsolationHook,
@@ -17,7 +18,7 @@ import {
17
18
  resolveChannels,
18
19
  resolveDmTarget,
19
20
  wrapScheduledTaskPrompt
20
- } from "../chunk-WNYQKTBP.js";
21
+ } from "../chunk-Y2ZGJIXI.js";
21
22
  import {
22
23
  findTaskByTemplate,
23
24
  getProjectDir,
@@ -637,6 +638,51 @@ function pickHintVariant(rng = Math.random) {
637
638
  return HINT_VARIANTS[idx];
638
639
  }
639
640
 
641
+ // src/lib/delivery-schedule-link.ts
642
+ function envSuffixFor2(codeName) {
643
+ return codeName.replace(/[^A-Za-z0-9]+/g, "_").toUpperCase();
644
+ }
645
+ function scheduleLinkFooterEnabled(codeName, env = process.env) {
646
+ if (codeName) {
647
+ const perAgent = env[`AGT_SCHEDULE_LINK_FOOTER_DISABLED__${envSuffixFor2(codeName)}`];
648
+ if (perAgent === "1") return false;
649
+ }
650
+ if (env["AGT_SCHEDULE_LINK_FOOTER_DISABLED"] === "1") return false;
651
+ return true;
652
+ }
653
+ function getConsoleUrl(env = process.env) {
654
+ const canonical = env["AGT_CONSOLE_URL"]?.trim();
655
+ if (canonical) return canonical.replace(/\/+$/, "");
656
+ const fallback = env["NEXT_PUBLIC_APP_URL"]?.trim();
657
+ if (fallback) return fallback.replace(/\/+$/, "");
658
+ return null;
659
+ }
660
+ function buildScheduleEditLink(consoleUrl, agentId, taskId) {
661
+ const base = consoleUrl.replace(/\/+$/, "");
662
+ return `${base}/agents/${encodeURIComponent(agentId)}/schedules/${encodeURIComponent(taskId)}`;
663
+ }
664
+ function formatScheduleLinkFooter(url, medium) {
665
+ if (medium === "slack") return `<${url}|Edit schedule>`;
666
+ if (medium === "telegram") return `Edit schedule: ${url}`;
667
+ return url;
668
+ }
669
+ function appendScheduleLinkFooter(body, url, medium) {
670
+ const footer = formatScheduleLinkFooter(url, medium);
671
+ const trimmed = body.replace(/\s+$/, "");
672
+ if (trimmed.endsWith(footer)) return trimmed;
673
+ return `${trimmed}
674
+
675
+ ${footer}`;
676
+ }
677
+ function withScheduleLinkFooter(opts) {
678
+ if (!opts.taskId) return opts.body;
679
+ if (!scheduleLinkFooterEnabled(opts.codeName, opts.env)) return opts.body;
680
+ const consoleUrl = getConsoleUrl(opts.env);
681
+ if (!consoleUrl) return opts.body;
682
+ const url = buildScheduleEditLink(consoleUrl, opts.agentId, opts.taskId);
683
+ return appendScheduleLinkFooter(opts.body, url, opts.medium);
684
+ }
685
+
640
686
  // src/lib/realtime-chat.ts
641
687
  import { createClient } from "@supabase/supabase-js";
642
688
  var client = null;
@@ -3162,6 +3208,16 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
3162
3208
  }
3163
3209
  async function processClaudeTaskResult(codeName, agentId, templateId, output, delivery) {
3164
3210
  try {
3211
+ if (isSuppressOutput(output)) {
3212
+ log(`[claude-scheduler] Suppressing delivery for '${codeName}' \u2014 output matched no-delivery sentinel or was empty`);
3213
+ if (delivery?.mode === "announce" && delivery.to) {
3214
+ await reportDeliveryStatus(agentId, delivery.taskId, {
3215
+ status: "skipped",
3216
+ error_code: "NO_CONTENT"
3217
+ });
3218
+ }
3219
+ return;
3220
+ }
3165
3221
  if (STANDUP_TEMPLATES.has(templateId)) {
3166
3222
  const standup = parseStandupSummary(output);
3167
3223
  await api.post("/host/agent-status", {
@@ -3195,7 +3251,7 @@ async function processClaudeTaskResult(codeName, agentId, templateId, output, de
3195
3251
  log(`[claude-scheduler] Kanban updates posted for '${codeName}' (${kanbanUpdates.length} updates)`);
3196
3252
  }
3197
3253
  }
3198
- if (delivery?.mode === "announce" && delivery.to && output) {
3254
+ if (delivery?.mode === "announce" && delivery.to) {
3199
3255
  await deliverScheduledTaskOutput(
3200
3256
  codeName,
3201
3257
  agentId,
@@ -4367,9 +4423,10 @@ ${a.detail}`;
4367
4423
  ${blocks.join("\n\n")}`);
4368
4424
  }
4369
4425
  async function deliverScheduledTaskOutput(agentCodeName, agentId, rawTarget, body, taskId) {
4426
+ const withLink = (b, medium) => withScheduleLinkFooter({ body: b, medium, codeName: agentCodeName, agentId, taskId });
4370
4427
  if (typeof rawTarget === "string") {
4371
4428
  if (rawTarget.startsWith("channel:")) {
4372
- const result = await sendTaskNotification(agentCodeName, "slack", rawTarget, body);
4429
+ const result = await sendTaskNotification(agentCodeName, "slack", rawTarget, withLink(body, "slack"));
4373
4430
  await reportDeliveryStatus(agentId, taskId, {
4374
4431
  status: result.ok ? "ok" : "failed",
4375
4432
  medium: "slack",
@@ -4378,7 +4435,7 @@ async function deliverScheduledTaskOutput(agentCodeName, agentId, rawTarget, bod
4378
4435
  return;
4379
4436
  }
4380
4437
  if (rawTarget.startsWith("chat:")) {
4381
- const result = await sendTaskNotification(agentCodeName, "telegram", rawTarget, body);
4438
+ const result = await sendTaskNotification(agentCodeName, "telegram", rawTarget, withLink(body, "telegram"));
4382
4439
  await reportDeliveryStatus(agentId, taskId, {
4383
4440
  status: result.ok ? "ok" : "failed",
4384
4441
  medium: "telegram",
@@ -4399,7 +4456,7 @@ async function deliverScheduledTaskOutput(agentCodeName, agentId, rawTarget, bod
4399
4456
  if (parsed.kind === "channel") {
4400
4457
  if (parsed.provider === "slack") {
4401
4458
  const channelId = parsed.channel_id ?? "";
4402
- const sent = await postSlackChannelMessage(agentCodeName, channelId, body);
4459
+ const sent = await postSlackChannelMessage(agentCodeName, channelId, withLink(body, "slack"));
4403
4460
  await reportDeliveryStatus(agentId, taskId, {
4404
4461
  status: sent.ok ? "ok" : "failed",
4405
4462
  medium: "slack",
@@ -4410,7 +4467,7 @@ async function deliverScheduledTaskOutput(agentCodeName, agentId, rawTarget, bod
4410
4467
  }
4411
4468
  const chatId = parsed.chat_id ?? "";
4412
4469
  const toStr = `chat:${chatId}`;
4413
- const result = await sendTaskNotification(agentCodeName, "telegram", toStr, body);
4470
+ const result = await sendTaskNotification(agentCodeName, "telegram", toStr, withLink(body, "telegram"));
4414
4471
  await reportDeliveryStatus(agentId, taskId, {
4415
4472
  status: result.ok ? "ok" : "failed",
4416
4473
  medium: "telegram",
@@ -4434,11 +4491,12 @@ async function deliverScheduledTaskOutput(agentCodeName, agentId, rawTarget, bod
4434
4491
  await reportDeliveryStatus(agentId, taskId, { status: "failed", error_code: resolved.code });
4435
4492
  return;
4436
4493
  }
4437
- const footeredBody = appendDmFooter(
4494
+ const attributionBody = appendDmFooter(
4438
4495
  body,
4439
4496
  agentRow.ownerTeamName,
4440
4497
  agentRow.agentDisplayName
4441
4498
  );
4499
+ const footeredBody = resolved.kind === "dm" ? withLink(attributionBody, resolved.medium === "slack" ? "slack" : "telegram") : attributionBody;
4442
4500
  if (resolved.kind === "dm" && resolved.medium === "slack") {
4443
4501
  const tokens = agentChannelTokens.get(agentCodeName);
4444
4502
  const botToken = tokens?.slack;