@thehammer/danx-dashboard-mcp 0.1.338 → 0.1.339

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/listen.js CHANGED
@@ -135,6 +135,9 @@ export function invalidEventReason(value) {
135
135
  case "comment_added": {
136
136
  if (!isCappedText(d.excerpt))
137
137
  return "detail.excerpt is not capped text";
138
+ // DX-5435: the line tells the agent which comment to signal on, so a person's comment must name it.
139
+ if (isPersonsComment(value) && typeof d.comment_id !== "number")
140
+ return "detail.comment_id is not a number";
138
141
  // DX-2906 — `problem` is OPTIONAL (only present when the comment named
139
142
  // one); absent is valid, but a present-and-malformed one is not.
140
143
  if (d.problem === undefined)
@@ -227,6 +230,19 @@ function actorLabel(event) {
227
230
  const via = event.viaKey === null ? "" : ` via ${event.viaKey.name}`;
228
231
  return `${event.actor}${via} (${event.origin})`;
229
232
  }
233
+ /** DX-5435: a comment a person wrote (not the session's own pause notice, not an agent's or the machine's): the one an agent should signal it is answering. */
234
+ function isPersonsComment(event) {
235
+ return event.origin === "operator" && event.release !== true;
236
+ }
237
+ /**
238
+ * DX-5435: what the agent does first with a person's comment. The responding signal shows the person "<agent> is responding..." under their comment in
239
+ * the Comments drawer until the agent's reply lands. The text is written here, with the line the agent reads, so every session that updates this package
240
+ * sends the signal without a plugin change.
241
+ */
242
+ export function respondingInstruction(cardId, commentId) {
243
+ const path = `/api/issues/${cardId}/comments/${commentId}/responding`;
244
+ return `If you will answer it, first call danxbot_api POST ${path} (no body) so the person sees you are on it; if you then decide no reply is needed, DELETE the same path`;
245
+ }
230
246
  /** Only ever called on an event `invalidEventReason` accepted, so its casts are checked. */
231
247
  function describe(event) {
232
248
  const d = event.detail;
@@ -240,9 +256,10 @@ function describe(event) {
240
256
  const problem = d.problem;
241
257
  if (event.release === true)
242
258
  return `${who} notice: ${quoted(d.excerpt)}`;
259
+ const respond = isPersonsComment(event) ? `. ${respondingInstruction(event.cardId, d.comment_id)}` : "";
243
260
  if (problem === undefined)
244
- return `${who} commented: ${quoted(d.excerpt)}`;
245
- return `${who} commented on problem ${quoted(problem.statement)}: ${quoted(d.excerpt)}`;
261
+ return `${who} commented: ${quoted(d.excerpt)}${respond}`;
262
+ return `${who} commented on problem ${quoted(problem.statement)}: ${quoted(d.excerpt)}${respond}`;
246
263
  }
247
264
  case "solution_answered": {
248
265
  // DX-2735: every answer answers ONE problem on a card that may carry several,
@@ -176,7 +176,7 @@ export class PlanEventRelay {
176
176
  this.start(cursor);
177
177
  if (this.buffer.length > 0)
178
178
  return this.answer();
179
- // DX-5415 / DX-4233: supersede where the waiter is installed, not before the pauses: calls resume in call order, so the newest always holds the slot and an older one that resumed late cannot orphan the waiter beneath it.
179
+ // DX-5415 / DX-4233: supersede where the waiter is installed, not only before the pauses, so an older call that resumed late cannot orphan the waiter beneath it. Calls resume in call order because a settle (capped at FINAL_SETTLE_BOUND_MS) ends before the idle window (HEARTBEAT_ACTIVITY_WINDOW_MS) can chain a second one; a wall-clock jump can break that order, costing the newer caller one early empty answer, never a second waiter.
180
180
  this.supersedeWaiter();
181
181
  return new Promise((resolve) => {
182
182
  const onAbort = () => this.supersedeWaiter();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thehammer/danx-dashboard-mcp",
3
- "version": "0.1.338",
3
+ "version": "0.1.339",
4
4
  "description": "Stdio MCP server fronting danxbot's dashboard API for agents (operator sessions and dispatched workers alike): the generic danxbot_api/danxbot_api_list/danxbot_api_spec tools reach any route the caller's credential may call, plus dedicated agent-specific tools (plan_connect, request_permission, attach_file, and danxbot_slack_reply) (DX-3465, PLN-11 R-25).",
5
5
  "license": "MIT",
6
6
  "type": "module",