@integrity-labs/agt-cli 0.28.1134 → 0.28.1136

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/mcp/index.js CHANGED
@@ -22443,6 +22443,25 @@ function kanbanAddResultText(data, submittedTitle, status) {
22443
22443
  ${first.duplicate_hint}` : added;
22444
22444
  }
22445
22445
 
22446
+ // src/assign-project-text.ts
22447
+ var TOOL = {
22448
+ artefact: { tool: "artefacts_assign_project", idArg: "artefact_id" },
22449
+ task: { tool: "kanban_assign_project", idArg: "kanban_item_id" }
22450
+ };
22451
+ function describeAssignProject(o) {
22452
+ const what = `${o.kind} ${o.leafId}`;
22453
+ const head = o.projectId ? `Assigned ${what} to project ${o.projectId}.` : `Cleared the project link on ${what}.`;
22454
+ if (o.previousProjectId === void 0) return head;
22455
+ const prev = o.previousProjectId;
22456
+ if (prev === o.projectId) {
22457
+ return `${head} No change: it was already ${prev ? `in project ${prev}` : "unfiled"}.`;
22458
+ }
22459
+ const { tool, idArg } = TOOL[o.kind];
22460
+ const from = prev ? `It was previously in project ${prev}.` : "It previously had no project.";
22461
+ const undoArg = prev ? `project_id="${prev}"` : "project_id=null";
22462
+ return `${head} ${from} To undo: ${tool} with ${idArg}="${o.leafId}", ${undoArg}.`;
22463
+ }
22464
+
22446
22465
  // src/kanban-assign-result.ts
22447
22466
  function kanbanAssignResultText(data, fallbackTargetAgent, fallbackTargetTeam) {
22448
22467
  if (!data.ok) return `Failed to assign task to ${fallbackTargetAgent}.`;
@@ -47077,7 +47096,9 @@ function renderKanbanItemLine(item, nowMs, suffix = "") {
47077
47096
  const res = item.result ? ` \u2713 ${item.result}` : "";
47078
47097
  const wait = renderWaitingClause(item, nowMs);
47079
47098
  const by = renderAssignerClause(item);
47080
- const head = `- [${pri}] ${item.title}${wait}${est}${del}${res}${by} (id: ${item.id})${suffix}`;
47099
+ const project = describeKanbanProject(item);
47100
+ const proj = project ? ` [project: ${project}]` : "";
47101
+ const head = `- [${pri}] ${item.title}${wait}${est}${del}${res}${by}${proj} (id: ${item.id})${suffix}`;
47081
47102
  const desc = renderDescriptionClause(item);
47082
47103
  return desc ? `${head}
47083
47104
  ${desc}` : head;
@@ -47147,6 +47168,10 @@ var BLOCKED_ON_ME_SECTION_HEADING = "You are blocking these (another agent has s
47147
47168
  var BLOCKED_ON_ME_SECTION_NOTE = "_Another agent has PARKED its own work until you act. These are not your cards and not pullable work \u2014 you cannot move, note or complete them, and they do not count toward your in-progress load. Do the thing named, then answer with `kanban_respond` (card_id + your answer) \u2014 that delivers it ON the parked card and un-parks it. Do NOT open a second card to carry the answer._";
47148
47169
  var HUMAN_ASSIGNED_SECTION_HEADING = "Assigned to a person (not yours to action)";
47149
47170
  var HUMAN_ASSIGNED_SECTION_NOTE = "_These belong to a person, not to you. You cannot move, note or complete them \u2014 every kanban write is refused. If the work is finished (or was never really theirs), use `kanban_recall` to pull the card back onto your board, then close it as normal._";
47171
+ function describeKanbanProject(item) {
47172
+ if (!item.project_id) return null;
47173
+ return item.project_name ? `${item.project_name} (${item.project_id})` : item.project_id;
47174
+ }
47150
47175
  function fullCardField(label, value) {
47151
47176
  if (value === null || value === void 0 || value === "") return null;
47152
47177
  return `${label}: ${value}`;
@@ -47192,6 +47217,10 @@ function renderKanbanFullCard(item, nowMs = Date.now(), frameToken = newFrameTok
47192
47217
  ].filter((l) => l !== null);
47193
47218
  if (source.length) lines.push(source.join(" \xB7 "));
47194
47219
  lines.push(`assigned by: ${describeKanbanAssigner(item, { always: true })}`);
47220
+ const project = describeKanbanProject(item);
47221
+ if (project) lines.push(`project: ${project}`);
47222
+ else if (Object.prototype.hasOwnProperty.call(item, "project_id")) lines.push("project: none (not filed under a project)");
47223
+ else lines.push("project: unknown (this API did not report it)");
47195
47224
  if (item.assignee_type && item.assignee_type !== "agent") {
47196
47225
  lines.push(`assigned to: ${item.assignee_type}${item.assignee_user_id ? ` (${item.assignee_user_id})` : ""}`);
47197
47226
  }
@@ -48658,6 +48687,8 @@ server.tool(
48658
48687
  - [${item.status}${via}, ${day}] ${item.title} (id: ${item.id})`);
48659
48688
  const assignedBy = renderKanbanSearchAssignerLine(item);
48660
48689
  if (assignedBy) lines.push(assignedBy);
48690
+ const project = describeKanbanProject(item);
48691
+ if (project) lines.push(` project: ${project}`);
48661
48692
  const descLines = renderKanbanSearchDescription(item, KANBAN_SEARCH_DESCRIPTION_MAX_CHARS);
48662
48693
  if (descLines) lines.push(descLines);
48663
48694
  if (item.deliverable) lines.push(` \u2192 ${item.deliverable}`);
@@ -52277,11 +52308,16 @@ async function assignArtefactProjectText(params) {
52277
52308
  `/host/artefact/${encodeURIComponent(params.artefact_id)}/assign-project`,
52278
52309
  { agent_id: AGT_AGENT_ID, project_id: params.project_id }
52279
52310
  );
52280
- return data.project_id ? `Assigned artefact ${data.artefact_id} to project ${data.project_id}.` : `Cleared the project link on artefact ${data.artefact_id}.`;
52311
+ return describeAssignProject({
52312
+ kind: "artefact",
52313
+ leafId: data.artefact_id,
52314
+ projectId: data.project_id,
52315
+ previousProjectId: data.previous_project_id
52316
+ });
52281
52317
  }
52282
52318
  server.tool(
52283
52319
  "artefacts_assign_project",
52284
- "Assign an already-published artefact to a project, or clear its project link. Pass the project_id from projects_list to assign, or null to remove the artefact from its current project. Use this to group existing work; to set a project when first publishing, pass project_id to the publish tool instead.",
52320
+ "Assign an already-published artefact to a project, or clear its project link. Pass the project_id from projects_list to assign, or null to remove the artefact from its current project. The reply names the project it was in before and the exact call to undo the move. Use this to group existing work; to set a project when first publishing, pass project_id to the publish tool instead.",
52285
52321
  {
52286
52322
  artefact_id: external_exports.string().uuid().describe("The artefact id returned by artefacts_list"),
52287
52323
  project_id: external_exports.string().uuid().nullable().describe("Project id to assign (from projects_list), or null to clear the link")
@@ -52295,11 +52331,16 @@ async function assignKanbanProjectText(params) {
52295
52331
  `/host/kanban/${encodeURIComponent(params.kanban_item_id)}/assign-project`,
52296
52332
  { agent_id: AGT_AGENT_ID, project_id: params.project_id }
52297
52333
  );
52298
- return data.project_id ? `Assigned task ${data.kanban_item_id} to project ${data.project_id}.` : `Cleared the project link on task ${data.kanban_item_id}.`;
52334
+ return describeAssignProject({
52335
+ kind: "task",
52336
+ leafId: data.kanban_item_id,
52337
+ projectId: data.project_id,
52338
+ previousProjectId: data.previous_project_id
52339
+ });
52299
52340
  }
52300
52341
  server.tool(
52301
52342
  "kanban_assign_project",
52302
- "Assign an existing kanban task to a project, or clear its project link. Pass the project_id from projects_list to assign, or null to remove the task from its current project. To set a project when first creating a task, pass project_id to kanban_add instead.",
52343
+ "Assign an existing kanban task to a project, or clear its project link. Pass the project_id from projects_list to assign, or null to remove the task from its current project. The reply names the project it was in before and the exact call to undo the move. kanban_get shows a task's current project. To set a project when first creating a task, pass project_id to kanban_add instead.",
52303
52344
  {
52304
52345
  kanban_item_id: external_exports.string().uuid().describe("The kanban task id returned by kanban_list"),
52305
52346
  project_id: external_exports.string().uuid().nullable().describe("Project id to assign (from projects_list), or null to clear the link")
@@ -22942,6 +22942,9 @@ function textNode(v) {
22942
22942
  }
22943
22943
  var RICH_TEXT_MAX_DEPTH = 64;
22944
22944
  function richTextToString(node, depth = 0) {
22945
+ return flattenRichText(node, depth).trim();
22946
+ }
22947
+ function flattenRichText(node, depth) {
22945
22948
  if (depth >= RICH_TEXT_MAX_DEPTH) return "[nested rich text truncated]";
22946
22949
  const rec = asRecord(node);
22947
22950
  if (!rec) return "";
@@ -22955,7 +22958,9 @@ function richTextToString(node, depth = 0) {
22955
22958
  const channelId = rec["channel_id"];
22956
22959
  if (typeof channelId === "string") parts.push(`<#${channelId}>`);
22957
22960
  const type = typeof rec["type"] === "string" ? rec["type"] : "";
22958
- const children = asArray(rec["elements"]).map((c) => richTextToString(c, depth + 1)).filter(Boolean);
22961
+ const inline = asArray(rec["elements"]).map((c) => flattenRichText(c, depth + 1)).filter(Boolean);
22962
+ const blockLevel = BLOCK_LEVEL_RICH_TEXT.has(type);
22963
+ const children = blockLevel ? inline.map((c) => c.trim()).filter(Boolean) : inline;
22959
22964
  if (children.length > 0) {
22960
22965
  if (type === "rich_text_table") parts.push(children.join("\n"));
22961
22966
  else if (type === "rich_text_table_row") parts.push(children.join(" | "));
@@ -22977,8 +22982,15 @@ ${body}
22977
22982
  ${fence}`);
22978
22983
  } else parts.push(children.join(""));
22979
22984
  }
22980
- return parts.join("").trim();
22985
+ return parts.join("");
22981
22986
  }
22987
+ var BLOCK_LEVEL_RICH_TEXT = /* @__PURE__ */ new Set([
22988
+ "rich_text_table",
22989
+ "rich_text_table_row",
22990
+ "rich_text_list",
22991
+ "rich_text_quote",
22992
+ "rich_text_preformatted"
22993
+ ]);
22982
22994
  function blockToString(block) {
22983
22995
  const b = asRecord(block);
22984
22996
  if (!b) return "";
@@ -23074,9 +23086,19 @@ function slackMessageBody(msg) {
23074
23086
  if (!rich) return top;
23075
23087
  if (!top) return rich;
23076
23088
  if (rich.startsWith(top)) return rich;
23089
+ if (!attachmentText && allRichText(msg.blocks) && sameWords(top, blockText)) return top;
23077
23090
  return `${top}
23078
23091
  ${rich}`;
23079
23092
  }
23093
+ function allRichText(blocks) {
23094
+ const list = asArray(blocks);
23095
+ return list.length > 0 && list.every((b) => asRecord(b)?.["type"] === "rich_text");
23096
+ }
23097
+ function sameWords(mrkdwn, plain) {
23098
+ const norm = (v) => v.replace(/<([^<>|]+)\|([^<>]*)>/g, "$2").replace(/<([^<>]+)>/g, "$1").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&").replace(/:[a-z0-9_+'-]+:/gi, "").toLowerCase().replace(/[^\p{L}\p{N}]+/gu, "");
23099
+ const a = norm(mrkdwn);
23100
+ return a.length > 0 && a === norm(plain);
23101
+ }
23080
23102
 
23081
23103
  // ../core/dist/channels/slack-rich-text.js
23082
23104
  var MAX_DEPTH = 12;
@@ -30377,6 +30399,14 @@ function humanEditedMessage(evt) {
30377
30399
  merged["edit_ts"] = evt.ts;
30378
30400
  return merged;
30379
30401
  }
30402
+ function isOwnNormalisedEdit(normalised, raw, botUserId2) {
30403
+ return normalised !== raw && !!botUserId2 && normalised.user === botUserId2;
30404
+ }
30405
+ function isSlackBotSender(evt, botUserId2) {
30406
+ if (typeof evt.bot_id === "string" && evt.bot_id.length > 0)
30407
+ return true;
30408
+ return !!botUserId2 && evt.user === botUserId2;
30409
+ }
30380
30410
  function decideSlackMessageForward(evt, thirdPartyBots) {
30381
30411
  if (evt.type !== "message") {
30382
30412
  return { forward: true };
@@ -30587,6 +30617,8 @@ function politeDeclineCopy(reason) {
30587
30617
  }
30588
30618
  }
30589
30619
  function isSlackDeclineAddressed(input) {
30620
+ if (input.isFromBot === true)
30621
+ return false;
30590
30622
  if (input.eventType === "app_mention")
30591
30623
  return true;
30592
30624
  if (typeof input.channelId === "string" && input.channelId.startsWith("D"))
@@ -51085,6 +51117,7 @@ async function connectSocketMode() {
51085
51117
  return;
51086
51118
  }
51087
51119
  const evt = humanEditedMessage(rawEvt) ?? rawEvt;
51120
+ if (isOwnNormalisedEdit(evt, rawEvt, botUserId)) return;
51088
51121
  const dedupId = slackInboundDedupId(evt);
51089
51122
  if (dedupId && markInboundDelivered("slack", dedupId)) {
51090
51123
  const isMention = evt.type === "app_mention";
@@ -51183,7 +51216,8 @@ async function connectSocketMode() {
51183
51216
  eventType: evt.type,
51184
51217
  channelId: evt.channel,
51185
51218
  text: evt.text,
51186
- botUserId
51219
+ botUserId,
51220
+ isFromBot: isSlackBotSender(evt, botUserId)
51187
51221
  })) {
51188
51222
  await maybeSendSenderPolicyDecline({
51189
51223
  channel: evt.channel,
@@ -68,8 +68,8 @@ import {
68
68
  writeDirectChatSessionState,
69
69
  writeEgressAllowlist,
70
70
  writePersistentClaudeWrapper
71
- } from "./chunk-HHLP37ZS.js";
72
- import "./chunk-4V3XZBB4.js";
71
+ } from "./chunk-PGTZFME3.js";
72
+ import "./chunk-773ZNDNR.js";
73
73
  import "./chunk-B6UYVEMD.js";
74
74
  import "./chunk-XWVM4KPK.js";
75
75
  import "./chunk-EL5MWGGH.js";
@@ -145,4 +145,4 @@ export {
145
145
  writeEgressAllowlist,
146
146
  writePersistentClaudeWrapper
147
147
  };
148
- //# sourceMappingURL=persistent-session-MNIZPA7A.js.map
148
+ //# sourceMappingURL=persistent-session-6W6PZGNB.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  paneLogPath
3
- } from "./chunk-HHLP37ZS.js";
4
- import "./chunk-4V3XZBB4.js";
3
+ } from "./chunk-PGTZFME3.js";
4
+ import "./chunk-773ZNDNR.js";
5
5
  import "./chunk-B6UYVEMD.js";
6
6
  import "./chunk-XWVM4KPK.js";
7
7
  import "./chunk-EL5MWGGH.js";
@@ -802,4 +802,4 @@ export {
802
802
  readAndResetSlackReplyBindingClassifications,
803
803
  readAndResetSlackReplyTargetClassifications
804
804
  };
805
- //# sourceMappingURL=responsiveness-probe-TJDREI5P.js.map
805
+ //# sourceMappingURL=responsiveness-probe-LLYHYZR7.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  sessionTranscriptDir
3
- } from "./chunk-4V3XZBB4.js";
3
+ } from "./chunk-773ZNDNR.js";
4
4
  import "./chunk-DGUM43GV.js";
5
5
 
6
6
  // src/lib/session-auth-dead.ts
@@ -204,4 +204,4 @@ export {
204
204
  decideSessionAuthState,
205
205
  probeSessionAuth
206
206
  };
207
- //# sourceMappingURL=session-auth-dead-WO7TZ2GV.js.map
207
+ //# sourceMappingURL=session-auth-dead-QZET5C3W.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.28.1134",
3
+ "version": "0.28.1136",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {