@mrrlin-dev/mcp 0.4.28 → 0.4.32

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.
Files changed (2) hide show
  1. package/dist/bin.cjs +87 -47
  2. package/package.json +5 -5
package/dist/bin.cjs CHANGED
@@ -37388,6 +37388,22 @@ function isRunnableProposal(item) {
37388
37388
  return true;
37389
37389
  }
37390
37390
 
37391
+ // ../../packages/schemas/dist/task-notes.js
37392
+ var TASK_NOTES_BRIEF_SECTIONS = [
37393
+ { heading: "Context", description: "why this task exists; link to parent/trigger task if follow-up." },
37394
+ { heading: "Scope", description: "concrete actions and acceptance criteria." },
37395
+ { heading: "References", description: "links, data, relevant findings (omit if nothing to reference)." }
37396
+ ];
37397
+ var TASK_NOTES_JOURNAL_SECTIONS = [
37398
+ { heading: "Result", description: "what was accomplished, key findings or metrics, follow-up tasks created." },
37399
+ {
37400
+ heading: "Recheck",
37401
+ dated: true,
37402
+ description: "what you checked, what you found, and what happens next."
37403
+ }
37404
+ ];
37405
+ var JOURNAL_HEADING_RE = new RegExp(`^##[ \\t]+(${TASK_NOTES_JOURNAL_SECTIONS.map((s) => s.heading).join("|")})\\b[ \\t]*(?:[\u2014\u2013-][ \\t]*(\\S.*?))?[ \\t]*$`);
37406
+
37391
37407
  // ../../packages/schemas/dist/index.js
37392
37408
  var mrrlinTaskStatusSchema = external_exports.enum([
37393
37409
  "backlog",
@@ -41328,24 +41344,30 @@ function createFailureLog(opts = {}) {
41328
41344
  const windowMs = opts.windowMs ?? failureLogWindowMs();
41329
41345
  const now = opts.now ?? Date.now;
41330
41346
  const lastEmit = /* @__PURE__ */ new Map();
41347
+ const KIND_NULL = "\0none";
41331
41348
  const counts = /* @__PURE__ */ new Map();
41332
41349
  let windowStartedAt = null;
41333
41350
  return {
41334
41351
  /** Decide whether this failure should be printed. Returns the suppressed count to include in
41335
41352
  * the line when it is. */
41336
41353
  shouldEmit(operation, kind) {
41337
- const prev = lastEmit.get(operation);
41338
- const sameKind = prev != null && prev.kind === kind;
41339
- const withinWindow = prev != null && now() - prev.at < windowMs;
41340
- if (sameKind && withinWindow) {
41354
+ const kindKey = kind ?? KIND_NULL;
41355
+ let byKind = lastEmit.get(operation);
41356
+ if (!byKind) {
41357
+ byKind = /* @__PURE__ */ new Map();
41358
+ lastEmit.set(operation, byKind);
41359
+ }
41360
+ const prev = byKind.get(kindKey);
41361
+ if (prev != null && now() - prev.at < windowMs) {
41341
41362
  prev.suppressed += 1;
41342
41363
  return { emit: false, suppressed: prev.suppressed };
41343
41364
  }
41344
- const suppressed = sameKind ? prev?.suppressed ?? 0 : 0;
41345
- lastEmit.set(operation, { kind, at: now(), suppressed: 0 });
41365
+ const suppressed = prev?.suppressed ?? 0;
41366
+ byKind.set(kindKey, { at: now(), suppressed: 0 });
41346
41367
  return { emit: true, suppressed };
41347
41368
  },
41348
- /** A success resets the operation's suppression state, so the next failure always prints. */
41369
+ /** A success resets the operation's suppression state for EVERY error kind, so the next failure
41370
+ * always prints regardless of which kind it is. */
41349
41371
  noteSuccess(operation) {
41350
41372
  lastEmit.delete(operation);
41351
41373
  },
@@ -41375,9 +41397,10 @@ function createFailureLog(opts = {}) {
41375
41397
  }
41376
41398
  };
41377
41399
  }
41378
- function failureLogLine(label, error51, suppressed) {
41400
+ function failureLogLine(label, error51, suppressed, note) {
41401
+ const noteText = note ? ` (${note})` : "";
41379
41402
  const tail2 = suppressed > 0 ? ` (${suppressed} identical suppressed since the last line)` : "";
41380
- return `[mrrlin-mcp director-bridge] ${label} failed: ${describeError(error51)}${tail2}
41403
+ return `[mrrlin-mcp director-bridge] ${label} failed${noteText}: ${describeError(error51)}${tail2}
41381
41404
  `;
41382
41405
  }
41383
41406
 
@@ -41397,15 +41420,12 @@ function createTokenRefresher(opts) {
41397
41420
  opts.failureLog?.noteSuccess("tokenRefresh");
41398
41421
  opts.onOk?.();
41399
41422
  } catch (error51) {
41400
- const label = "token refresh (will retry next tick)";
41423
+ const line = (suppressed) => failureLogLine("token refresh", error51, suppressed, "will retry next tick");
41401
41424
  if (opts.failureLog) {
41402
41425
  const { emit, suppressed } = opts.failureLog.shouldEmit("tokenRefresh", errorKind(error51));
41403
- if (emit) process.stderr.write(failureLogLine(label, error51, suppressed));
41426
+ if (emit) process.stderr.write(line(suppressed));
41404
41427
  } else {
41405
- process.stderr.write(
41406
- `[mrrlin-mcp director-bridge] token refresh failed (will retry next tick): ${describeError(error51)}
41407
- `
41408
- );
41428
+ process.stderr.write(line(0));
41409
41429
  }
41410
41430
  opts.onError?.(error51);
41411
41431
  }
@@ -41833,7 +41853,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
41833
41853
  }
41834
41854
 
41835
41855
  // src/_generated/version.ts
41836
- var PKG_VERSION = "0.4.28";
41856
+ var PKG_VERSION = "0.4.32";
41837
41857
 
41838
41858
  // src/api-base-url-migrate.ts
41839
41859
  var import_node_fs3 = __toESM(require("node:fs"), 1);
@@ -46035,6 +46055,30 @@ function isDeployGateRunStatus(status) {
46035
46055
  return status === "dev_deploy" || status === "prod_deploy";
46036
46056
  }
46037
46057
 
46058
+ // src/prompts/task-notes-contract.ts
46059
+ function renderTaskNotesContractLines() {
46060
+ const brief = TASK_NOTES_BRIEF_SECTIONS.map((s) => ` ## ${s.heading} \u2014 ${s.description}`);
46061
+ const [result, recheck] = TASK_NOTES_JOURNAL_SECTIONS;
46062
+ return [
46063
+ "- Notes (markdown): write for a human operator scanning a task list.",
46064
+ " First line: one plain-text sentence summarizing the task (no heading).",
46065
+ " Then scale the structure to complexity:",
46066
+ " For simple tasks \u2014 the one-line summary may be enough. No headings required.",
46067
+ " For non-trivial tasks, use these sections as needed:",
46068
+ ...brief,
46069
+ " When closing a task (update_task status=closed_done), APPEND a Result section:",
46070
+ ` ## ${result?.heading} \u2014 ${result?.description}`,
46071
+ " When you revisit a task that already has a Result \u2014 a later verification, a retry, a status",
46072
+ " re-check \u2014 APPEND a dated entry instead of rewriting Result:",
46073
+ ` ## ${recheck?.heading} \u2014 YYYY-MM-DD \u2014 ${recheck?.description}`,
46074
+ " Do NOT remove earlier sections \u2014 they remain useful for context.",
46075
+ " The sections above the first Result/Recheck are the brief (what the task IS); Result and",
46076
+ " Recheck are the execution journal (what HAPPENED). The task page renders them separately and",
46077
+ " collapses the journal, so keep each kind of content under the right heading.",
46078
+ " Adapt depth to the task: a one-line fix needs one sentence, not four headings."
46079
+ ];
46080
+ }
46081
+
46038
46082
  // src/turn-deadline.ts
46039
46083
  var DEFAULT_TURN_INTERRUPT_TIMEOUT_MS = 5e3;
46040
46084
  function withTimeout2(promise2, ms, message) {
@@ -46608,18 +46652,7 @@ var BASE_INSTRUCTIONS_PREFIX = [
46608
46652
  "- Title: short, actionable, human-readable. Describe what needs to happen, not internal jargon.",
46609
46653
  ' Good: "Audit crawled-not-indexed pages and fix 404 errors"',
46610
46654
  ' Bad: "GSC coverage triage crawled-not-indexed + 404"',
46611
- "- Notes (markdown): write for a human operator scanning a task list.",
46612
- " First line: one plain-text sentence summarizing the task (no heading).",
46613
- " Then scale the structure to complexity:",
46614
- " For simple tasks \u2014 the one-line summary may be enough. No headings required.",
46615
- " For non-trivial tasks, use these sections as needed:",
46616
- " ## Context \u2014 why this task exists; link to parent/trigger task if follow-up.",
46617
- " ## Scope \u2014 concrete actions and acceptance criteria.",
46618
- " ## References \u2014 links, data, relevant findings (omit if nothing to reference).",
46619
- " When closing a task (update_task status=closed_done), APPEND a Result section:",
46620
- " ## Result \u2014 what was accomplished, key findings or metrics, follow-up tasks created.",
46621
- " Do NOT remove earlier sections \u2014 they remain useful for context.",
46622
- " Adapt depth to the task: a one-line fix needs one sentence, not four headings.",
46655
+ ...renderTaskNotesContractLines(),
46623
46656
  "",
46624
46657
  // Slice 4 of token-efficient-execution-runs (D8). This is the ONLY way the reasoning behind a
46625
46658
  // decision survives past this conversation: a thread is retired once it has accumulated too many
@@ -48873,12 +48906,14 @@ async function compactChat(input, deps) {
48873
48906
  );
48874
48907
  if (exec.ok) {
48875
48908
  const summaryNorm = normalizeWhitespace(exec.text);
48909
+ const hasSomethingToVerify = operatorMessages.length > 0;
48876
48910
  const allPresent = operatorMessages.every((op) => {
48877
48911
  const opNorm = normalizeWhitespace(op);
48878
48912
  return summaryNorm.includes(opNorm);
48879
48913
  });
48914
+ const isBlank = exec.text.trim().length === 0;
48880
48915
  const withinBudget = Buffer.byteLength(exec.text, "utf8") <= input.budgetBytes;
48881
- if (allPresent && withinBudget) {
48916
+ if (hasSomethingToVerify && allPresent && !isBlank && withinBudget) {
48882
48917
  return { kind: "summary", seed: exec.text };
48883
48918
  }
48884
48919
  }
@@ -48902,6 +48937,9 @@ async function compactChat(input, deps) {
48902
48937
  };
48903
48938
  }
48904
48939
  const seed = kept.reverse().map(renderMessage).join("\n");
48940
+ if (seed.trim().length === 0) {
48941
+ return { kind: "no-seed", note: "No chat content could be carried forward." };
48942
+ }
48905
48943
  return { kind: "raw-tail", seed };
48906
48944
  }
48907
48945
 
@@ -54209,18 +54247,7 @@ function buildThreadStartParams(msg, config2, desiredModel) {
54209
54247
  "- Title: short, actionable, human-readable. Describe what needs to happen, not internal jargon.",
54210
54248
  ' Good: "Audit crawled-not-indexed pages and fix 404 errors"',
54211
54249
  ' Bad: "GSC coverage triage crawled-not-indexed + 404"',
54212
- "- Notes (markdown): write for a human operator scanning a task list.",
54213
- " First line: one plain-text sentence summarizing the task (no heading).",
54214
- " Then scale the structure to complexity:",
54215
- " For simple tasks \u2014 the one-line summary may be enough. No headings required.",
54216
- " For non-trivial tasks, use these sections as needed:",
54217
- " ## Context \u2014 why this task exists; link to parent/trigger task if follow-up.",
54218
- " ## Scope \u2014 concrete actions and acceptance criteria.",
54219
- " ## References \u2014 links, data, relevant findings (omit if nothing to reference).",
54220
- " When closing a task (update_task status=closed_done), APPEND a Result section:",
54221
- " ## Result \u2014 what was accomplished, key findings or metrics, follow-up tasks created.",
54222
- " Do NOT remove earlier sections \u2014 they remain useful for context.",
54223
- " Adapt depth to the task: a one-line fix needs one sentence, not four headings.",
54250
+ ...renderTaskNotesContractLines(),
54224
54251
  // early-intent-confirmation (design.md, "The chat contract"): the core block below is copied
54225
54252
  // VERBATIM from design.md, per tasks.md 10.1. It replaces an older sentence that also carried
54226
54253
  // "omit operatorSeedRequest only when there is genuinely no operator request behind the task
@@ -55182,13 +55209,15 @@ function createBridgeMessageHandler(deps) {
55182
55209
  provider: compactionSeat.id,
55183
55210
  weakModel: compactionSeat.models.weak
55184
55211
  });
55185
- const seed = result.kind === "no-seed" ? result.note : result.seed;
55212
+ const rawSeed = result.kind === "no-seed" ? result.note : result.seed;
55213
+ const seed = rawSeed.trim().length > 0 ? rawSeed : "No prior context could be carried forward.";
55186
55214
  sendForSpan({
55187
55215
  type: "compact-directive",
55188
55216
  directorSessionId: directorSessionId2,
55189
55217
  lineageId,
55190
55218
  resolvedSeat: compactionSeat.id,
55191
- seed
55219
+ seed,
55220
+ seedKind: result.kind
55192
55221
  });
55193
55222
  return;
55194
55223
  }
@@ -62626,6 +62655,17 @@ function compactProjectSnapshot(projectSlug, snapshot, maxItems) {
62626
62655
  }
62627
62656
  var ARTIFACT_PAYLOAD_BUDGET = 400;
62628
62657
  var COMMAND_OUTPUT_TAIL_LINES = 10;
62658
+ function asString(value) {
62659
+ return typeof value === "string" ? value : null;
62660
+ }
62661
+ function eventContentText(value) {
62662
+ if (typeof value === "string") return value;
62663
+ if (value === null || typeof value !== "object") return null;
62664
+ const blocks = Array.isArray(value) ? value : value.content;
62665
+ if (!Array.isArray(blocks)) return null;
62666
+ const texts = blocks.map((block) => block && typeof block === "object" ? asString(block.text) : null).filter((text) => text !== null);
62667
+ return texts.length > 0 ? texts.join("\n") : null;
62668
+ }
62629
62669
  function compactArtifactPayload(artifact) {
62630
62670
  const payload = artifact.payload ?? {};
62631
62671
  switch (artifact.kind) {
@@ -62641,10 +62681,10 @@ function compactArtifactPayload(artifact) {
62641
62681
  }
62642
62682
  case "command_output": {
62643
62683
  const event = payload.event ?? void 0;
62644
- const command = payload.command ?? event?.tool?.input?.command ?? null;
62645
- const cwd = payload.cwd ?? event?.tool?.input?.cwd ?? null;
62646
- const exitCode = payload.exitCode ?? null;
62647
- const rawOutput = payload.stdout ?? payload.output ?? event?.content ?? "";
62684
+ const command = asString(payload.command) ?? asString(event?.tool?.input?.command) ?? null;
62685
+ const cwd = asString(payload.cwd) ?? asString(event?.tool?.input?.cwd) ?? null;
62686
+ const exitCode = typeof payload.exitCode === "number" ? payload.exitCode : null;
62687
+ const rawOutput = eventContentText(payload.stdout) ?? eventContentText(payload.output) ?? eventContentText(event?.content) ?? "";
62648
62688
  const lines2 = rawOutput.split(/\r?\n/);
62649
62689
  const tail2 = lines2.slice(-COMMAND_OUTPUT_TAIL_LINES).join("\n");
62650
62690
  const firstError = lines2.find((l) => /error|fail/i.test(l)) ?? null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrrlin-dev/mcp",
3
- "version": "0.4.28",
3
+ "version": "0.4.32",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mrrlin-mcp": "dist/bin.cjs"
@@ -21,12 +21,12 @@
21
21
  "@types/ws": "^8.18.1",
22
22
  "esbuild": "^0.24.0",
23
23
  "tsx": "^4.22.3",
24
- "@mrrlin/agent-client": "0.0.0",
25
- "@mrrlin/director-e2e": "0.0.0",
26
24
  "@mrrlin/client": "0.0.0",
25
+ "@mrrlin/director-e2e": "0.0.0",
26
+ "@mrrlin/schemas": "0.0.0",
27
27
  "@mrrlin/tsconfig": "0.0.0",
28
- "@mrrlin/wiki": "0.0.0",
29
- "@mrrlin/schemas": "0.0.0"
28
+ "@mrrlin/agent-client": "0.0.0",
29
+ "@mrrlin/wiki": "0.0.0"
30
30
  },
31
31
  "dependencies": {
32
32
  "@iarna/toml": "^2.2.5",