@productbrain/mcp 0.0.1-beta.5642 → 0.0.1-beta.5663

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.
@@ -202,6 +202,9 @@ function classifyError(err) {
202
202
  }
203
203
  return { code: "INTERNAL_ERROR", message: message || "An unexpected error occurred." };
204
204
  }
205
+ function retryIsFutile(code) {
206
+ return code === "VALIDATION_ERROR";
207
+ }
205
208
 
206
209
  // src/envelope.ts
207
210
  function success(summary, data, next) {
@@ -15561,7 +15564,7 @@ ${lines.join("\n")}${truncationNote}`;
15561
15564
  function questionErrorResult(err, action, params = {}) {
15562
15565
  const classified = classifyError(err);
15563
15566
  const definedParams = Object.fromEntries(Object.entries(params).filter(([, v]) => v !== void 0));
15564
- const fallbackActions = classified.code === "VALIDATION_ERROR" ? void 0 : [{ tool: "question", description: `Retry ${action}`, parameters: { action, ...definedParams } }];
15567
+ const fallbackActions = retryIsFutile(classified.code) ? void 0 : [{ tool: "question", description: `Retry ${action}`, parameters: { action, ...definedParams } }];
15565
15568
  return failureResult(
15566
15569
  classified.message,
15567
15570
  classified.code,
@@ -15625,12 +15628,13 @@ var ROLE_ACTION_SPECS = {
15625
15628
  };
15626
15629
  function formatRow(row) {
15627
15630
  const id = row.entryId ?? row.id;
15628
- return ` ${id} ${sanitizeSingleLineField(row.name)} [${row.canonicalKey ?? "?"}/${row.status}]`;
15631
+ const statusDisplay = row.workflowStatus ? `${row.status} / ${sanitizeSingleLineField(row.workflowStatus)}` : row.status;
15632
+ return ` ${id} ${sanitizeSingleLineField(row.name)} [${row.canonicalKey ?? "?"}/${statusDisplay}]`;
15629
15633
  }
15630
15634
  function formatSection(label, rows, truncated, cursorHint) {
15631
- if (rows.length === 0) return [` ${label}: not recorded yet`];
15632
- const lines = [` ${label}:`, ...rows.map(formatRow)];
15633
- if (truncated) lines.push(` (more exist \u2014 ${cursorHint ?? "raise limit (capped at 200, no cursor for this list)"})`);
15635
+ if (rows.length === 0 && !truncated) return [` ${label}: not recorded yet`];
15636
+ const lines = rows.length === 0 ? [` ${label}: not recorded yet, but the scan is incomplete`] : [` ${label}:`, ...rows.map(formatRow)];
15637
+ if (truncated) lines.push(` (scan incomplete, more may exist \u2014 ${cursorHint ?? "raise limit (capped at 200, no cursor for this list)"})`);
15634
15638
  return lines;
15635
15639
  }
15636
15640
  function formatRoleAccountable(result2) {
@@ -15656,12 +15660,13 @@ async function handleRoleAccountable(roleId, canonicalKey, limit, cursor) {
15656
15660
  function roleErrorResult(err, action, params = {}) {
15657
15661
  const classified = classifyError(err);
15658
15662
  const definedParams = Object.fromEntries(Object.entries(params).filter(([, v]) => v !== void 0));
15663
+ const fallbackActions = retryIsFutile(classified.code) ? void 0 : [{ tool: "role", description: `Retry ${action}`, parameters: { action, ...definedParams } }];
15659
15664
  return failureResult(
15660
15665
  classified.message,
15661
15666
  classified.code,
15662
15667
  classified.message,
15663
15668
  classified.recovery ?? "Use action='accountable' with roleId set to a real role's chain id or entry id.",
15664
- classified.availableActions ?? [{ tool: "role", description: `Retry ${action}`, parameters: { action, ...definedParams } }],
15669
+ classified.availableActions ?? fallbackActions,
15665
15670
  classified.diagnostics
15666
15671
  );
15667
15672
  }
@@ -15698,7 +15703,13 @@ var outcomeSchema = z35.object({
15698
15703
  "'record': record a reading (evidence, not a verdict). 'list': list readings, newest first. 'show': the derived view \u2014 current, progress, pace, staleness, recorded completion."
15699
15704
  ),
15700
15705
  entryId: z35.string().max(200).optional().describe("The key result (or other outcome-bearing) entry, by its chain id. Required for all three actions."),
15701
- value: z35.number().optional().describe("'record': the measured value. Required for 'record'."),
15706
+ // PR #858 review round 3 (Codex P2, PRRT_kwDORS4ils6gXHj9): a JSON number that overflows to
15707
+ // `Infinity` (e.g. `1e400`) parses fine in JS and passes a plain `z.number()`, but
15708
+ // `callGateway()` serializes it with `JSON.stringify`, which turns `Infinity` into `null` —
15709
+ // the backend's `v.number()` validator then rejects a call this tool's own schema accepted.
15710
+ // `.finite()` rejects it here, matching the explicit finite-value checks the CLI/other outcome
15711
+ // entry surfaces already use.
15712
+ value: z35.number().finite().optional().describe("'record': the measured value. Required for 'record'."),
15702
15713
  valueText: z35.string().max(500).optional().describe("'record': verbatim as-reported form when the source was not clean, e.g. '~62%'. Display only."),
15703
15714
  asOf: z35.string().max(64).optional().describe("'record': when the world was in this state, as a parseable date (default: now). Back-dating a backfill is legitimate \u2014 it shows up as asOf earlier than recordedAt."),
15704
15715
  kind: z35.enum(READING_KINDS).optional().describe("'record': measurement | estimate | correction (default: measurement)."),
@@ -15711,7 +15722,7 @@ var outcomeSchema = z35.object({
15711
15722
  var recordVariant = z35.object({
15712
15723
  action: z35.literal("record"),
15713
15724
  entryId: z35.string().max(200),
15714
- value: z35.number(),
15725
+ value: z35.number().finite(),
15715
15726
  valueText: z35.string().max(500).optional(),
15716
15727
  asOf: z35.string().max(64).optional(),
15717
15728
  kind: z35.enum(READING_KINDS).optional(),
@@ -15735,6 +15746,10 @@ var OUTCOME_ACTION_SPECS = {
15735
15746
  list: { params: ["entryId", "limit"], description: "entryId is required; limit is optional." },
15736
15747
  show: { params: ["entryId"], description: "entryId is required." }
15737
15748
  };
15749
+ function safeDateSlice(ms) {
15750
+ const d = new Date(ms);
15751
+ return Number.isNaN(d.getTime()) ? "invalid-date" : d.toISOString().slice(0, 10);
15752
+ }
15738
15753
  function formatRecordReceipt(numericValue, entryId, valueText, receipt) {
15739
15754
  const tier = receipt.independenceTier ?? "unknown";
15740
15755
  const lines = [
@@ -15751,7 +15766,7 @@ function formatReadingsList(entryId, result2) {
15751
15766
  const rows = result2?.readings ?? [];
15752
15767
  if (rows.length === 0) return `No readings recorded on ${safeEntryId} yet.`;
15753
15768
  const lines = rows.map((row) => {
15754
- const when = new Date(row.asOf).toISOString().slice(0, 10);
15769
+ const when = safeDateSlice(row.asOf);
15755
15770
  const superseded = row.supersededByReadingId ? ` <- superseded by ${row.supersededByReadingId}` : "";
15756
15771
  const text = row.valueText ? ` ("${sanitizeSingleLineField(row.valueText)}")` : "";
15757
15772
  const note = row.note ? ` - ${sanitizeSingleLineField(row.note)}` : "";
@@ -15774,7 +15789,7 @@ function formatOutcomeShow(result2) {
15774
15789
  ` progress ${pct(o.progressPct)} direction ${o.direction}`,
15775
15790
  ` pace ${pct(o.pacePct)} ${o.pacePct === void 0 ? "(no cycle end set)" : o.pacePct >= 0 ? "(ahead of pace)" : "(behind pace)"}`,
15776
15791
  ` state ${o.state}${o.hasNoReadings ? " \u2014 never read" : ""}${o.overdueByMs ? ` (by ${Math.floor(o.overdueByMs / 864e5)}d)` : ""}`,
15777
- ` next due ${o.nextDueAt ? new Date(o.nextDueAt).toISOString().slice(0, 10) : "no cadence set"}`,
15792
+ ` next due ${o.nextDueAt ? safeDateSlice(o.nextDueAt) : "no cadence set"}`,
15778
15793
  ` owner ${roleLabel(o.ownerRole)}`,
15779
15794
  ` reporter ${roleLabel(o.reporterRole)}`,
15780
15795
  ` completion recorded as ${o.completion} (source: ${o.completionProvenance})`,
@@ -15792,16 +15807,17 @@ function outcomeErrorResult(err, action, entryId, params = {}) {
15792
15807
  const classified = classifyError(err);
15793
15808
  const definedParams = Object.fromEntries(Object.entries(params).filter(([, v]) => v !== void 0));
15794
15809
  const isUnverifiedRecordTimeout = action === "record" && classified.code === "GATEWAY_TIMEOUT";
15810
+ const isMissingCorrectionTarget = action === "record" && classified.code === "NOT_FOUND" && classified.message.startsWith("Reading not found");
15795
15811
  const defaultActions = isUnverifiedRecordTimeout ? [
15796
15812
  { tool: "outcome", description: "Check whether the reading already landed", parameters: { action: "list", entryId } },
15797
15813
  { tool: "outcome", description: "Check the derived view", parameters: { action: "show", entryId } }
15798
- ] : [{ tool: "outcome", description: `Retry ${action}`, parameters: { action, ...definedParams } }];
15814
+ ] : isMissingCorrectionTarget ? [{ tool: "outcome", description: "List readings for this entry to find a valid correctsReadingId", parameters: { action: "list", entryId } }] : retryIsFutile(classified.code) ? void 0 : [{ tool: "outcome", description: `Retry ${action}`, parameters: { action, ...definedParams } }];
15799
15815
  return failureResult(
15800
15816
  classified.message,
15801
15817
  classified.code,
15802
15818
  classified.message,
15803
- classified.recovery ?? "Use action='show' or action='list' with a valid entryId to check the key result exists.",
15804
- classified.availableActions ?? defaultActions,
15819
+ isMissingCorrectionTarget ? `Reading correctsReadingId not found for entryId='${entryId}'. Use action='list' to see valid reading ids.` : classified.recovery ?? "Use action='show' or action='list' with a valid entryId to check the key result exists.",
15820
+ isMissingCorrectionTarget ? defaultActions : classified.availableActions ?? defaultActions,
15805
15821
  classified.diagnostics
15806
15822
  );
15807
15823
  }
@@ -16841,4 +16857,4 @@ export {
16841
16857
  createProductBrainServer,
16842
16858
  initFeatureFlags
16843
16859
  };
16844
- //# sourceMappingURL=chunk-C5BIZH5N.js.map
16860
+ //# sourceMappingURL=chunk-A4WEYWDI.js.map