@mcpjam/inspector 3.10.0 → 3.11.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.
@@ -35,7 +35,7 @@ import {
35
35
  supportsOwnershipProof,
36
36
  terminateOwnedProcess,
37
37
  terminateOwnedProcessGroup
38
- } from "./chunk-SPXMROZ2.js";
38
+ } from "./chunk-3I6NEQHV.js";
39
39
  import {
40
40
  ALLOWED_HOSTS,
41
41
  BROWSER_CONSENT_HEADER,
@@ -9664,182 +9664,40 @@ var init_host = __esm({
9664
9664
  };
9665
9665
  }
9666
9666
  });
9667
- var ToolDeclarationCapture = class {
9668
- snapshots = /* @__PURE__ */ new Map();
9669
- pending = /* @__PURE__ */ new Map();
9670
- generation = 0;
9671
- clear(serverId) {
9672
- this.snapshots.delete(serverId);
9673
- for (const [key, request3] of this.pending) {
9674
- if (request3.serverId === serverId) this.pending.delete(key);
9675
- }
9676
- }
9677
- read(serverId) {
9678
- const snapshot2 = this.snapshots.get(serverId);
9679
- return snapshot2 ? { tools: structuredClone(snapshot2.tools), capture: snapshot2.capture } : void 0;
9680
- }
9681
- observe(event) {
9682
- const message = event.message;
9683
- if (!message || typeof message !== "object" || message.id == null) return;
9684
- const key = JSON.stringify([event.serverId, typeof message.id, message.id]);
9685
- if (event.direction === "send") {
9686
- if (message.method !== "tools/list") return;
9687
- const params = message.params;
9688
- const cursor = params?.cursor;
9689
- let snapshot22 = this.snapshots.get(event.serverId);
9690
- if (cursor === void 0) {
9691
- snapshot22 = {
9692
- tools: [],
9693
- capture: "partial",
9694
- generation: ++this.generation,
9695
- cursors: /* @__PURE__ */ new Set(),
9696
- bytes: 0,
9697
- ambiguous: [...this.pending.values()].some(
9698
- (request22) => request22.serverId === event.serverId
9699
- )
9700
- };
9701
- this.snapshots.set(event.serverId, snapshot22);
9702
- } else if (!snapshot22 || snapshot22.capture === "complete" || snapshot22.nextCursor !== cursor || snapshot22.cursors.has(cursor)) {
9703
- return;
9704
- }
9705
- if (this.pending.size >= 512) {
9706
- this.clear(event.serverId);
9707
- return;
9708
- }
9709
- this.pending.set(key, {
9710
- serverId: event.serverId,
9711
- generation: snapshot22.generation,
9712
- cursor
9713
- });
9714
- if (cursor !== void 0) snapshot22.cursors.add(cursor);
9715
- return;
9716
- }
9717
- const request3 = this.pending.get(key);
9718
- if (!request3) return;
9719
- this.pending.delete(key);
9720
- const snapshot2 = this.snapshots.get(request3.serverId);
9721
- if (!snapshot2 || snapshot2.generation !== request3.generation) return;
9722
- const result = message.result;
9723
- if (message.error || !result || !Array.isArray(result.tools)) return;
9724
- const page3 = [];
9725
- for (const value of result.tools) {
9726
- if (!value || typeof value !== "object" || typeof value.name !== "string")
9727
- return;
9728
- const tool19 = {
9729
- name: value.name,
9730
- ...typeof value.description === "string" ? { description: value.description } : {},
9731
- ...value.inputSchema !== void 0 ? { inputSchema: value.inputSchema } : {},
9732
- ...value.outputSchema !== void 0 ? { outputSchema: value.outputSchema } : {},
9733
- ...value.annotations && typeof value.annotations === "object" && !Array.isArray(value.annotations) ? { annotations: value.annotations } : {}
9734
- };
9735
- snapshot2.bytes += new TextEncoder().encode(
9736
- JSON.stringify(tool19)
9737
- ).byteLength;
9738
- if (snapshot2.bytes > 4 * 1024 * 1024 || snapshot2.tools.length + page3.length >= 1e4)
9739
- return;
9740
- page3.push(structuredClone(tool19));
9741
- }
9742
- snapshot2.tools.push(...page3);
9743
- if (result.nextCursor === void 0) {
9744
- snapshot2.capture = snapshot2.ambiguous ? "partial" : "complete";
9745
- snapshot2.nextCursor = void 0;
9746
- } else if (typeof result.nextCursor === "string" && !snapshot2.cursors.has(result.nextCursor)) {
9747
- snapshot2.nextCursor = result.nextCursor;
9748
- } else {
9749
- snapshot2.nextCursor = void 0;
9750
- }
9751
- }
9752
- };
9753
- function isToolCall(body) {
9754
- if (typeof body !== "string") return false;
9755
- try {
9756
- return JSON.parse(body)?.method === "tools/call";
9757
- } catch {
9758
- return false;
9667
+ function extractNodeErrno(error, depth = 0) {
9668
+ if (!error || typeof error !== "object" || depth > 3) {
9669
+ return void 0;
9759
9670
  }
9760
- }
9761
- function wrapFetchForHttpErrors(fetchFn, hasAuthProvider) {
9762
- return (async (input, init2) => {
9763
- const response = await fetchFn(input, init2);
9764
- const method = init2?.method ?? (input instanceof Request ? input.method : "GET");
9765
- if (method.toUpperCase() !== "POST" || !isToolCall(init2?.body) || response.ok || // HTTP 400 can carry a JSON-RPC error the transport needs to dispatch.
9766
- response.status === 400 || // The transport must handle authentication and scope retries itself.
9767
- // It raises InsufficientScopeError for step-up even without a provider.
9768
- response.status === 403 && extractWWWAuthenticateParams(response).error === "insufficient_scope" || hasAuthProvider && (response.status === 401 || response.status === 403)) {
9769
- return response;
9770
- }
9771
- const text2 = await response.text().catch(() => null);
9772
- const statusLine = [response.status, response.statusText].filter(Boolean).join(" ");
9773
- const challenge = response.headers.get("www-authenticate");
9774
- const retryAfter = response.headers.get("retry-after");
9775
- const body = text2 === null ? "(unreadable body)" : text2 || "(empty body)";
9776
- throw new SdkHttpError(
9777
- SdkErrorCode.ClientHttpNotImplemented,
9778
- `Error POSTing to endpoint (HTTP ${statusLine}): ${body}${challenge ? `
9779
- WWW-Authenticate: ${challenge}` : ""}`,
9780
- {
9781
- status: response.status,
9782
- statusText: response.statusText,
9783
- text: text2,
9784
- ...retryAfter !== null ? { retryAfter } : {}
9785
- }
9786
- );
9787
- });
9788
- }
9789
- var DEFAULT_CLIENT_VERSION = "1.0.0";
9790
- var DEFAULT_TIMEOUT = DEFAULT_REQUEST_TIMEOUT_MSEC;
9791
- var HTTP_CONNECT_TIMEOUT = 3e3;
9792
- var DEFAULT_ELICITATION_TIMEOUT_EXTENSION_MS = 10 * 60 * 1e3;
9793
- function isMethodUnavailableError(error, method) {
9794
- if (!(error instanceof Error)) {
9795
- return false;
9671
+ const code = error.code;
9672
+ const ownCode = typeof code === "string" ? code : void 0;
9673
+ if (ownCode !== void 0 && looksLikeNodeErrno(ownCode)) {
9674
+ return ownCode;
9796
9675
  }
9797
- const message = error.message.toLowerCase();
9798
- const methodTokens = /* @__PURE__ */ new Set();
9799
- methodTokens.add(method.toLowerCase());
9800
- for (const part of method.split(/[/:._-]/)) {
9801
- if (part) {
9802
- methodTokens.add(part.toLowerCase());
9676
+ const cause = error.cause;
9677
+ if (cause !== void 0 && cause !== error) {
9678
+ const fromCause = extractNodeErrno(cause, depth + 1);
9679
+ if (fromCause !== void 0) {
9680
+ return fromCause;
9803
9681
  }
9804
9682
  }
9805
- const indicators = [
9806
- "method not found",
9807
- "not implemented",
9808
- "unsupported",
9809
- "does not support",
9810
- "unimplemented",
9811
- "unknown method",
9812
- "unknown mcp method"
9813
- ];
9814
- const indicatorMatch = indicators.some(
9815
- (indicator) => message.includes(indicator)
9816
- );
9817
- if (!indicatorMatch) {
9818
- return false;
9819
- }
9820
- if (Array.from(methodTokens).some((token) => message.includes(token))) {
9821
- return true;
9822
- }
9823
- return true;
9824
- }
9825
- var nonRetryableErrors = /* @__PURE__ */ new WeakSet();
9826
- function markNonRetryableError(error) {
9827
- nonRetryableErrors.add(error);
9828
- return error;
9829
- }
9830
- function isNonRetryableMarkedError(error) {
9831
- return typeof error === "object" && error !== null ? nonRetryableErrors.has(error) : false;
9683
+ return ownCode;
9832
9684
  }
9833
- function formatError(error) {
9834
- if (error instanceof Error) {
9835
- return error.message;
9836
- }
9837
- try {
9838
- return JSON.stringify(error);
9839
- } catch {
9840
- return String(error);
9841
- }
9685
+ function looksLikeNodeErrno(code) {
9686
+ return RETRYABLE_NODE_ERROR_CODES.has(code) || code.startsWith("UND_ERR_");
9842
9687
  }
9688
+ var RETRYABLE_NODE_ERROR_CODES = /* @__PURE__ */ new Set([
9689
+ "ECONNREFUSED",
9690
+ "ECONNRESET",
9691
+ "EAI_AGAIN",
9692
+ "ENETDOWN",
9693
+ "ENETUNREACH",
9694
+ "ENOTFOUND",
9695
+ "EPIPE",
9696
+ "ETIMEDOUT",
9697
+ "UND_ERR_CONNECT_TIMEOUT",
9698
+ "UND_ERR_HEADERS_TIMEOUT",
9699
+ "UND_ERR_SOCKET"
9700
+ ]);
9843
9701
  var MCPError = class extends Error {
9844
9702
  constructor(message, code, options) {
9845
9703
  super(message, options);
@@ -10060,40 +9918,212 @@ function isAuthError(error) {
10060
9918
  }
10061
9919
  return { isAuth: false };
10062
9920
  }
10063
- function extractNodeErrno(error, depth = 0) {
10064
- if (!error || typeof error !== "object" || depth > 3) {
10065
- return void 0;
9921
+ function httpStatus(error) {
9922
+ const seen = /* @__PURE__ */ new Set();
9923
+ let current = error;
9924
+ while (current && typeof current === "object" && !seen.has(current)) {
9925
+ seen.add(current);
9926
+ const record22 = current;
9927
+ for (const field2 of ["statusCode", "status", "code"]) {
9928
+ const value = record22[field2];
9929
+ if (typeof value === "number" && value >= 100 && value <= 599) {
9930
+ return value;
9931
+ }
9932
+ }
9933
+ const unwrapped = unwrapEraNegotiationCause(current);
9934
+ current = unwrapped !== current ? unwrapped : record22.cause;
10066
9935
  }
10067
- const code = error.code;
10068
- const ownCode = typeof code === "string" ? code : void 0;
10069
- if (ownCode !== void 0 && looksLikeNodeErrno(ownCode)) {
10070
- return ownCode;
9936
+ return void 0;
9937
+ }
9938
+ function connectionErrorMessage(url, errors, fallback) {
9939
+ const endpoint = `${url.origin}${url.pathname}`;
9940
+ const statuses = errors.map(httpStatus).filter((s) => s !== void 0);
9941
+ if (statuses.length > 0 && statuses.every((status) => status === 404)) {
9942
+ return `Server returned HTTP 404 at ${endpoint}. Check the MCP endpoint and server logs.`;
10071
9943
  }
10072
- const cause = error.cause;
10073
- if (cause !== void 0 && cause !== error) {
10074
- const fromCause = extractNodeErrno(cause, depth + 1);
10075
- if (fromCause !== void 0) {
10076
- return fromCause;
9944
+ if (statuses.length === 0 && errors.some(
9945
+ (error) => extractNodeErrno(unwrapEraNegotiationCause(error)) === "ECONNREFUSED"
9946
+ )) {
9947
+ return `Couldn't reach the server at ${endpoint}: connection refused (ECONNREFUSED). Check that it's running and that the host and port are correct.`;
9948
+ }
9949
+ return fallback;
9950
+ }
9951
+ var ToolDeclarationCapture = class {
9952
+ snapshots = /* @__PURE__ */ new Map();
9953
+ pending = /* @__PURE__ */ new Map();
9954
+ generation = 0;
9955
+ clear(serverId) {
9956
+ this.snapshots.delete(serverId);
9957
+ for (const [key, request3] of this.pending) {
9958
+ if (request3.serverId === serverId) this.pending.delete(key);
10077
9959
  }
10078
9960
  }
10079
- return ownCode;
9961
+ read(serverId) {
9962
+ const snapshot2 = this.snapshots.get(serverId);
9963
+ return snapshot2 ? { tools: structuredClone(snapshot2.tools), capture: snapshot2.capture } : void 0;
9964
+ }
9965
+ observe(event) {
9966
+ const message = event.message;
9967
+ if (!message || typeof message !== "object" || message.id == null) return;
9968
+ const key = JSON.stringify([event.serverId, typeof message.id, message.id]);
9969
+ if (event.direction === "send") {
9970
+ if (message.method !== "tools/list") return;
9971
+ const params = message.params;
9972
+ const cursor = params?.cursor;
9973
+ let snapshot22 = this.snapshots.get(event.serverId);
9974
+ if (cursor === void 0) {
9975
+ snapshot22 = {
9976
+ tools: [],
9977
+ capture: "partial",
9978
+ generation: ++this.generation,
9979
+ cursors: /* @__PURE__ */ new Set(),
9980
+ bytes: 0,
9981
+ ambiguous: [...this.pending.values()].some(
9982
+ (request22) => request22.serverId === event.serverId
9983
+ )
9984
+ };
9985
+ this.snapshots.set(event.serverId, snapshot22);
9986
+ } else if (!snapshot22 || snapshot22.capture === "complete" || snapshot22.nextCursor !== cursor || snapshot22.cursors.has(cursor)) {
9987
+ return;
9988
+ }
9989
+ if (this.pending.size >= 512) {
9990
+ this.clear(event.serverId);
9991
+ return;
9992
+ }
9993
+ this.pending.set(key, {
9994
+ serverId: event.serverId,
9995
+ generation: snapshot22.generation,
9996
+ cursor
9997
+ });
9998
+ if (cursor !== void 0) snapshot22.cursors.add(cursor);
9999
+ return;
10000
+ }
10001
+ const request3 = this.pending.get(key);
10002
+ if (!request3) return;
10003
+ this.pending.delete(key);
10004
+ const snapshot2 = this.snapshots.get(request3.serverId);
10005
+ if (!snapshot2 || snapshot2.generation !== request3.generation) return;
10006
+ const result = message.result;
10007
+ if (message.error || !result || !Array.isArray(result.tools)) return;
10008
+ const page3 = [];
10009
+ for (const value of result.tools) {
10010
+ if (!value || typeof value !== "object" || typeof value.name !== "string")
10011
+ return;
10012
+ const tool19 = {
10013
+ name: value.name,
10014
+ ...typeof value.description === "string" ? { description: value.description } : {},
10015
+ ...value.inputSchema !== void 0 ? { inputSchema: value.inputSchema } : {},
10016
+ ...value.outputSchema !== void 0 ? { outputSchema: value.outputSchema } : {},
10017
+ ...value.annotations && typeof value.annotations === "object" && !Array.isArray(value.annotations) ? { annotations: value.annotations } : {}
10018
+ };
10019
+ snapshot2.bytes += new TextEncoder().encode(
10020
+ JSON.stringify(tool19)
10021
+ ).byteLength;
10022
+ if (snapshot2.bytes > 4 * 1024 * 1024 || snapshot2.tools.length + page3.length >= 1e4)
10023
+ return;
10024
+ page3.push(structuredClone(tool19));
10025
+ }
10026
+ snapshot2.tools.push(...page3);
10027
+ if (result.nextCursor === void 0) {
10028
+ snapshot2.capture = snapshot2.ambiguous ? "partial" : "complete";
10029
+ snapshot2.nextCursor = void 0;
10030
+ } else if (typeof result.nextCursor === "string" && !snapshot2.cursors.has(result.nextCursor)) {
10031
+ snapshot2.nextCursor = result.nextCursor;
10032
+ } else {
10033
+ snapshot2.nextCursor = void 0;
10034
+ }
10035
+ }
10036
+ };
10037
+ function isToolCall(body) {
10038
+ if (typeof body !== "string") return false;
10039
+ try {
10040
+ return JSON.parse(body)?.method === "tools/call";
10041
+ } catch {
10042
+ return false;
10043
+ }
10080
10044
  }
10081
- function looksLikeNodeErrno(code) {
10082
- return RETRYABLE_NODE_ERROR_CODES.has(code) || code.startsWith("UND_ERR_");
10045
+ function wrapFetchForHttpErrors(fetchFn, hasAuthProvider) {
10046
+ return (async (input, init2) => {
10047
+ const response = await fetchFn(input, init2);
10048
+ const method = init2?.method ?? (input instanceof Request ? input.method : "GET");
10049
+ if (method.toUpperCase() !== "POST" || !isToolCall(init2?.body) || response.ok || // HTTP 400 can carry a JSON-RPC error the transport needs to dispatch.
10050
+ response.status === 400 || // The transport must handle authentication and scope retries itself.
10051
+ // It raises InsufficientScopeError for step-up even without a provider.
10052
+ response.status === 403 && extractWWWAuthenticateParams(response).error === "insufficient_scope" || hasAuthProvider && (response.status === 401 || response.status === 403)) {
10053
+ return response;
10054
+ }
10055
+ const text2 = await response.text().catch(() => null);
10056
+ const statusLine = [response.status, response.statusText].filter(Boolean).join(" ");
10057
+ const challenge = response.headers.get("www-authenticate");
10058
+ const retryAfter = response.headers.get("retry-after");
10059
+ const body = text2 === null ? "(unreadable body)" : text2 || "(empty body)";
10060
+ throw new SdkHttpError(
10061
+ SdkErrorCode.ClientHttpNotImplemented,
10062
+ `Error POSTing to endpoint (HTTP ${statusLine}): ${body}${challenge ? `
10063
+ WWW-Authenticate: ${challenge}` : ""}`,
10064
+ {
10065
+ status: response.status,
10066
+ statusText: response.statusText,
10067
+ text: text2,
10068
+ ...retryAfter !== null ? { retryAfter } : {}
10069
+ }
10070
+ );
10071
+ });
10072
+ }
10073
+ var DEFAULT_CLIENT_VERSION = "1.0.0";
10074
+ var DEFAULT_TIMEOUT = DEFAULT_REQUEST_TIMEOUT_MSEC;
10075
+ var HTTP_CONNECT_TIMEOUT = 3e3;
10076
+ var DEFAULT_ELICITATION_TIMEOUT_EXTENSION_MS = 10 * 60 * 1e3;
10077
+ function isMethodUnavailableError(error, method) {
10078
+ if (!(error instanceof Error)) {
10079
+ return false;
10080
+ }
10081
+ const message = error.message.toLowerCase();
10082
+ const methodTokens = /* @__PURE__ */ new Set();
10083
+ methodTokens.add(method.toLowerCase());
10084
+ for (const part of method.split(/[/:._-]/)) {
10085
+ if (part) {
10086
+ methodTokens.add(part.toLowerCase());
10087
+ }
10088
+ }
10089
+ const indicators = [
10090
+ "method not found",
10091
+ "not implemented",
10092
+ "unsupported",
10093
+ "does not support",
10094
+ "unimplemented",
10095
+ "unknown method",
10096
+ "unknown mcp method"
10097
+ ];
10098
+ const indicatorMatch = indicators.some(
10099
+ (indicator) => message.includes(indicator)
10100
+ );
10101
+ if (!indicatorMatch) {
10102
+ return false;
10103
+ }
10104
+ if (Array.from(methodTokens).some((token) => message.includes(token))) {
10105
+ return true;
10106
+ }
10107
+ return true;
10108
+ }
10109
+ var nonRetryableErrors = /* @__PURE__ */ new WeakSet();
10110
+ function markNonRetryableError(error) {
10111
+ nonRetryableErrors.add(error);
10112
+ return error;
10113
+ }
10114
+ function isNonRetryableMarkedError(error) {
10115
+ return typeof error === "object" && error !== null ? nonRetryableErrors.has(error) : false;
10116
+ }
10117
+ function formatError(error) {
10118
+ if (error instanceof Error) {
10119
+ return error.message;
10120
+ }
10121
+ try {
10122
+ return JSON.stringify(error);
10123
+ } catch {
10124
+ return String(error);
10125
+ }
10083
10126
  }
10084
- var RETRYABLE_NODE_ERROR_CODES = /* @__PURE__ */ new Set([
10085
- "ECONNREFUSED",
10086
- "ECONNRESET",
10087
- "EAI_AGAIN",
10088
- "ENETDOWN",
10089
- "ENETUNREACH",
10090
- "ENOTFOUND",
10091
- "EPIPE",
10092
- "ETIMEDOUT",
10093
- "UND_ERR_CONNECT_TIMEOUT",
10094
- "UND_ERR_HEADERS_TIMEOUT",
10095
- "UND_ERR_SOCKET"
10096
- ]);
10097
10127
  var DEFAULT_RETRY_POLICY = {
10098
10128
  retries: 0,
10099
10129
  retryDelayMs: 3e3
@@ -16613,9 +16643,11 @@ var MCPClientManager = class {
16613
16643
  ]);
16614
16644
  if (declaredPinFailure) throw declaredPinFailure;
16615
16645
  throw new Error(
16616
- `Failed to connect to MCP server "${serverId}" using Streamable HTTP, and this server's declared transport rules out the SSE fallback. Streamable HTTP error: ${formatError(
16617
- error
16618
- )}`,
16646
+ connectionErrorMessage(
16647
+ url,
16648
+ [error],
16649
+ `Failed to connect to MCP server "${serverId}" using Streamable HTTP, and this server's declared transport rules out the SSE fallback. Streamable HTTP error: ${formatError(error)}`
16650
+ ),
16619
16651
  { cause: error }
16620
16652
  );
16621
16653
  }
@@ -16675,7 +16707,11 @@ var MCPClientManager = class {
16675
16707
  }
16676
16708
  throw attachStreamableCause(
16677
16709
  new Error(
16678
- `Failed to connect to MCP server "${serverId}" using HTTP transports.${streamableMessage} SSE error: ${sseErrorMessage}.`,
16710
+ connectionErrorMessage(
16711
+ url,
16712
+ [streamableError, error],
16713
+ `Failed to connect to MCP server "${serverId}" using HTTP transports.${streamableMessage} SSE error: ${sseErrorMessage}.`
16714
+ ),
16679
16715
  { cause: error }
16680
16716
  ),
16681
16717
  streamableError
@@ -26479,7 +26515,7 @@ var noopPosthog = {
26479
26515
  var posthog = isTelemetryDisabled ? noopPosthog : new PostHog("phc_dTOPniyUNU2kD8Jx8yHMXSqiZHM8I91uWopTMX6EBE9", {
26480
26516
  host: "https://us.i.posthog.com"
26481
26517
  });
26482
- var SDK_VERSION = "8.14.0";
26518
+ var SDK_VERSION = "8.15.0";
26483
26519
  var SDK_RELEASE = `@mcpjam/sdk@${SDK_VERSION}`;
26484
26520
  var CAPTURED_ERROR_SYMBOL = Symbol.for("@mcpjam/sdk/captured-eval-error");
26485
26521
  init_internal();
@@ -26490,7 +26526,7 @@ init_eval_tool_execution();
26490
26526
  init_internal();
26491
26527
  init_internal();
26492
26528
  function readSdkVersion() {
26493
- return "8.14.0";
26529
+ return "8.15.0";
26494
26530
  }
26495
26531
  var DEFAULT_PLATFORM_USER_AGENT = `mcpjam-sdk/${readSdkVersion()}`;
26496
26532
  init_HostRunner();
@@ -74387,10 +74423,10 @@ function resolveSlug(error) {
74387
74423
  if (/\bout of MCPJam credits\b/i.test(message)) return { slug: "provider/mcpjam_limit" };
74388
74424
  const limitSlug = mcpjamLimitSlugForMessage(message);
74389
74425
  if (limitSlug) return { slug: limitSlug };
74390
- const httpStatus2 = httpStatusOf(error);
74391
- if (httpStatus2 !== void 0) {
74392
- const slug = classifyHttpStatus(httpStatus2);
74393
- if (slug) return { slug, rawCode: httpStatus2 };
74426
+ const httpStatus22 = httpStatusOf(error);
74427
+ if (httpStatus22 !== void 0) {
74428
+ const slug = classifyHttpStatus(httpStatus22);
74429
+ if (slug) return { slug, rawCode: httpStatus22 };
74394
74430
  }
74395
74431
  const oauthSlug = oauthBodySlug(error);
74396
74432
  if (oauthSlug) return { slug: oauthSlug };
@@ -83915,7 +83951,7 @@ var NEGATIVE_TEST_MODE_DETAILS = {
83915
83951
  }
83916
83952
  };
83917
83953
  function readSdkVersion2() {
83918
- return "8.14.0";
83954
+ return "8.15.0";
83919
83955
  }
83920
83956
  var CONFORMANCE_CHECKER_VERSION2 = readSdkVersion2();
83921
83957
  var MUST_POINTS2 = 95;
@@ -84546,6 +84582,27 @@ function fetchTokenizerCount(text2, model) {
84546
84582
  });
84547
84583
  }
84548
84584
 
84585
+ // server/utils/fetch-error-cause.ts
84586
+ function isFetchConnectionFailure(error) {
84587
+ return error instanceof TypeError && /fetch failed/i.test(error.message);
84588
+ }
84589
+ function getFetchErrorCause(error) {
84590
+ const cause = error?.cause?.code;
84591
+ return typeof cause === "string" ? cause : void 0;
84592
+ }
84593
+ function isFetchTimeout(error) {
84594
+ let current = error;
84595
+ for (let depth = 0; depth < 8; depth += 1) {
84596
+ if (!current || typeof current !== "object") return false;
84597
+ const name15 = current.name;
84598
+ if (name15 === "TimeoutError" || name15 === "AbortError") return true;
84599
+ const cause = current.cause;
84600
+ if (cause === void 0 || cause === current) return false;
84601
+ current = cause;
84602
+ }
84603
+ return false;
84604
+ }
84605
+
84549
84606
  // server/utils/tokenizer-helpers.ts
84550
84607
  var MODEL_ID_MAPPINGS = {
84551
84608
  // Anthropic models
@@ -84665,13 +84722,6 @@ function mapModelIdToTokenizerBackend(modelId) {
84665
84722
  function estimateTokensFromChars(text2) {
84666
84723
  return Math.ceil(text2.length / 4);
84667
84724
  }
84668
- function isFetchConnectionFailure(error) {
84669
- return error instanceof TypeError && /fetch failed/i.test(error.message);
84670
- }
84671
- function getFetchErrorCause(error) {
84672
- const cause = error?.cause?.code;
84673
- return typeof cause === "string" ? cause : void 0;
84674
- }
84675
84725
  var MAX_BACKEND_TOKENIZER_CHARS = 4 * 1024 * 1024;
84676
84726
  var tokenizerPeak = { chars: 0, oversizeSkips: 0 };
84677
84727
  function getTokenizerPeak() {
@@ -86234,6 +86284,13 @@ function startGuestAuthProvisioningInBackground() {
86234
86284
 
86235
86285
  // server/utils/guest-session-source.ts
86236
86286
  var DEFAULT_REMOTE_GUEST_SESSION_URL = "https://app.mcpjam.com/api/web/guest-session";
86287
+ function classifyThrown(error, signal, fallback) {
86288
+ if (isFetchTimeout(error)) return { reason: "timeout" };
86289
+ const networkCode = getFetchErrorCause(error);
86290
+ if (networkCode) return { reason: "network", networkCode };
86291
+ if (signal?.aborted) return { reason: "timeout" };
86292
+ return { reason: fallback };
86293
+ }
86237
86294
  function getConvexHttpUrl() {
86238
86295
  const convexHttpUrl3 = process.env.CONVEX_HTTP_URL;
86239
86296
  if (!convexHttpUrl3) {
@@ -86317,21 +86374,28 @@ async function performGuestSessionFetch(url, init2, source, mode) {
86317
86374
  kind: "error",
86318
86375
  status: response.status,
86319
86376
  setCookies,
86320
- ...retryAfterSeconds !== void 0 ? { retryAfterSeconds } : {}
86377
+ ...retryAfterSeconds !== void 0 ? { retryAfterSeconds } : {},
86378
+ reason: "upstream_status",
86379
+ upstreamStatus: response.status
86321
86380
  };
86322
86381
  }
86323
86382
  let body;
86324
86383
  try {
86325
86384
  body = await response.json();
86326
- } catch {
86327
- return { kind: "error", status: 503, setCookies };
86385
+ } catch (error) {
86386
+ const failure = classifyThrown(error, init2.signal, "bad_json");
86387
+ logger.warn(
86388
+ `[guest-auth] Failed to read ${source} guest session response`,
86389
+ failure
86390
+ );
86391
+ return { kind: "error", status: 503, setCookies, ...failure };
86328
86392
  }
86329
86393
  const session = parseSessionPayload(body);
86330
86394
  if (!session) {
86331
86395
  logger.warn(
86332
86396
  `[guest-auth] ${source} guest session response was missing token or expiresAt`
86333
86397
  );
86334
- return { kind: "error", status: 503, setCookies };
86398
+ return { kind: "error", status: 503, setCookies, reason: "bad_payload" };
86335
86399
  }
86336
86400
  logger.info(
86337
86401
  `[guest-auth] Fetched guest token from ${source} guest session`
@@ -86339,10 +86403,12 @@ async function performGuestSessionFetch(url, init2, source, mode) {
86339
86403
  return { kind: "session", session, setCookies };
86340
86404
  } catch (error) {
86341
86405
  const errMsg = error instanceof Error ? error.message : String(error);
86406
+ const failure = classifyThrown(error, init2.signal, "network");
86342
86407
  logger.warn(
86343
- `[guest-auth] Failed to fetch ${source} guest session: ${errMsg}`
86408
+ `[guest-auth] Failed to fetch ${source} guest session: ${errMsg}`,
86409
+ failure
86344
86410
  );
86345
- return { kind: "error", status: 503, setCookies: [] };
86411
+ return { kind: "error", status: 503, setCookies: [], ...failure };
86346
86412
  }
86347
86413
  }
86348
86414
  var DEFAULT_GUEST_FETCH_TIMEOUT_MS = 1e4;
@@ -86367,7 +86433,12 @@ async function fetchConvexGuestSession(context, timeoutMs = DEFAULT_GUEST_FETCH_
86367
86433
  logger.warn(
86368
86434
  `[guest-auth] Failed to provision Convex guest auth env: ${errMsg}`
86369
86435
  );
86370
- return { kind: "error", status: 503, setCookies: [] };
86436
+ return {
86437
+ kind: "error",
86438
+ status: 503,
86439
+ setCookies: [],
86440
+ reason: "provisioning"
86441
+ };
86371
86442
  }
86372
86443
  if (isConvexProvisioningUnavailable()) {
86373
86444
  return fetchRemoteGuestSession(context, timeoutMs);
@@ -102324,9 +102395,9 @@ function decodePaneCommand(res) {
102324
102395
 
102325
102396
  // server/services/browserd/browserd-codec.ts
102326
102397
  var BrowserdClientError = class extends Error {
102327
- constructor(message, httpStatus2) {
102398
+ constructor(message, httpStatus3) {
102328
102399
  super(message);
102329
- this.httpStatus = httpStatus2;
102400
+ this.httpStatus = httpStatus3;
102330
102401
  this.name = "BrowserdClientError";
102331
102402
  }
102332
102403
  };
@@ -155068,7 +155139,7 @@ function platformRefusalHint(refusal) {
155068
155139
  return refusal.canTopUp === false ? `${when} This is a usage limit: topping up credits does not lift it.` : when;
155069
155140
  }
155070
155141
  function readSdkVersion3() {
155071
- return "8.14.0";
155142
+ return "8.15.0";
155072
155143
  }
155073
155144
  var DEFAULT_PLATFORM_API_BASE_URL = "https://app.mcpjam.com/api/v1";
155074
155145
  function resolvePlatformRequestUrl(spec) {
@@ -187576,17 +187647,17 @@ function humanizeSwarmAttemptError(raw, errorCode2) {
187576
187647
  }
187577
187648
  if (!input) return { message: "The session failed for an unknown reason." };
187578
187649
  let body = input;
187579
- let httpStatus2;
187650
+ let httpStatus3;
187580
187651
  const envelope = AGENT_ERROR_ENVELOPE.exec(input);
187581
187652
  if (envelope) {
187582
- httpStatus2 = Number(envelope[1] ?? envelope[2]);
187653
+ httpStatus3 = Number(envelope[1] ?? envelope[2]);
187583
187654
  body = input.slice(envelope[0].length).trim();
187584
187655
  }
187585
187656
  if (looksLikeErrorPage(body)) {
187586
187657
  return {
187587
187658
  code: "upstream_error_page",
187588
- message: `The request was answered with an HTML error page instead of a response${httpStatus2 ? ` (HTTP ${httpStatus2})` : ""}. This usually means a proxy or CDN blocked it.`,
187589
- ...httpStatus2 !== void 0 ? { httpStatus: httpStatus2 } : {}
187659
+ message: `The request was answered with an HTML error page instead of a response${httpStatus3 ? ` (HTTP ${httpStatus3})` : ""}. This usually means a proxy or CDN blocked it.`,
187660
+ ...httpStatus3 !== void 0 ? { httpStatus: httpStatus3 } : {}
187590
187661
  };
187591
187662
  }
187592
187663
  const parsed = parseJsonObject(body);
@@ -187597,7 +187668,7 @@ function humanizeSwarmAttemptError(raw, errorCode2) {
187597
187668
  0,
187598
187669
  MAX_ATTEMPT_ERROR_CHARS
187599
187670
  ),
187600
- ...httpStatus2 !== void 0 ? { httpStatus: httpStatus2 } : {}
187671
+ ...httpStatus3 !== void 0 ? { httpStatus: httpStatus3 } : {}
187601
187672
  };
187602
187673
  }
187603
187674
  const headline = str(parsed.error) ?? str(parsed.message) ?? "The session could not run.";
@@ -187616,7 +187687,7 @@ function humanizeSwarmAttemptError(raw, errorCode2) {
187616
187687
  ...num(parsed.outstandingHolds) !== void 0 ? { outstandingHolds: num(parsed.outstandingHolds) } : {},
187617
187688
  ...retryAfterMs !== void 0 ? { retryAfterMs } : {},
187618
187689
  ...canTopUp ? { canTopUp } : {},
187619
- ...httpStatus2 !== void 0 ? { httpStatus: httpStatus2 } : {}
187690
+ ...httpStatus3 !== void 0 ? { httpStatus: httpStatus3 } : {}
187620
187691
  };
187621
187692
  }
187622
187693
  function humanizeSwarmAttemptErrorMessage(raw) {
@@ -195461,6 +195532,10 @@ function hostedCriterionId(predicate, scope) {
195461
195532
  ).slice(0, 12);
195462
195533
  return `${predicate.type}-${digest}`;
195463
195534
  }
195535
+ var HOSTED_RUBRIC_CHECKS_SCORER_PREFIX = "judge:rubricChecks:";
195536
+ function hostedRubricCheckScorerId(key) {
195537
+ return `${HOSTED_RUBRIC_CHECKS_SCORER_PREFIX}${key}`;
195538
+ }
195464
195539
 
195465
195540
  // server/services/evals/score-definitions.ts
195466
195541
  var HOSTED_PREDICATE_EVALUATOR_VERSION = "1";
@@ -195530,6 +195605,26 @@ function hostedJudgeScoreDefinition(args) {
195530
195605
  ...args.model ? { model: args.model } : {}
195531
195606
  };
195532
195607
  }
195608
+ var HOSTED_RUBRIC_CHECKS_PROJECTION_VERSION = "1";
195609
+ var HOSTED_RUBRIC_CHECKS_MODEL = "typesafe-ai/jev";
195610
+ function hostedRubricCheckScoreDefinition(args) {
195611
+ return {
195612
+ scorerId: hostedRubricCheckScorerId(args.key),
195613
+ idSource: "platform",
195614
+ scorerVersion: HOSTED_RUBRIC_CHECKS_PROJECTION_VERSION,
195615
+ implementationHash: export_canonicalDigest2({
195616
+ kind: args.kind,
195617
+ contentDigest: args.contentDigest,
195618
+ templateVersion: args.templateVersion ?? null,
195619
+ templateHash: args.templateHash ?? null
195620
+ }),
195621
+ label: `rubric check: ${args.label}`,
195622
+ deterministic: false,
195623
+ passThreshold: args.passThreshold,
195624
+ role: "advisory",
195625
+ model: HOSTED_RUBRIC_CHECKS_MODEL
195626
+ };
195627
+ }
195533
195628
  var HOSTED_AGENT_ACTIVITY_SCORER_ID = "platform:agentActivity";
195534
195629
  var HOSTED_AGENT_ACTIVITY_VERSION = "1";
195535
195630
  function hostedAgentActivityScoreDefinition() {
@@ -195567,6 +195662,9 @@ function buildHostedScoreDefinitions(inputs) {
195567
195662
  if (inputs.agentActivityFired) {
195568
195663
  definitions2.push(hostedAgentActivityScoreDefinition());
195569
195664
  }
195665
+ for (const question of inputs.rubricChecks ?? []) {
195666
+ definitions2.push(hostedRubricCheckScoreDefinition(question));
195667
+ }
195570
195668
  const byId = /* @__PURE__ */ new Map();
195571
195669
  for (const definition of definitions2) {
195572
195670
  const resolved = export_resolveScoreDefinition2(definition);
@@ -195581,6 +195679,42 @@ function buildHostedEvaluationConfig(inputs) {
195581
195679
  }
195582
195680
 
195583
195681
  // server/services/evals/score-rows.ts
195682
+ var RUBRIC_CHECK_KINDS = /* @__PURE__ */ new Set(["boolean", "choice", "score"]);
195683
+ function rubricCheckQuestionsFrom(verdict) {
195684
+ if (!verdict || !Array.isArray(verdict.questions)) return [];
195685
+ const templateVersion = isFiniteNumber(verdict.templateVersion) ? verdict.templateVersion : void 0;
195686
+ const templateHash = typeof verdict.templateHash === "string" ? verdict.templateHash : void 0;
195687
+ const seen = /* @__PURE__ */ new Set();
195688
+ const out = [];
195689
+ for (const raw of verdict.questions) {
195690
+ if (typeof raw !== "object" || raw === null) continue;
195691
+ const q = raw;
195692
+ if (typeof q.key !== "string" || !/^[cq]:[A-Za-z0-9_-]{1,64}$/.test(q.key) || seen.has(q.key) || typeof q.kind !== "string" || !RUBRIC_CHECK_KINDS.has(q.kind) || typeof q.contentDigest !== "string" || q.contentDigest.length === 0 || !isFiniteNumber(q.passThreshold)) {
195693
+ continue;
195694
+ }
195695
+ seen.add(q.key);
195696
+ const status = q.status === "scored" || q.status === "skipped" ? q.status : "error";
195697
+ out.push({
195698
+ key: q.key,
195699
+ kind: q.kind,
195700
+ label: typeof q.label === "string" ? q.label : q.key,
195701
+ contentDigest: q.contentDigest,
195702
+ passThreshold: q.passThreshold,
195703
+ ...templateVersion !== void 0 ? { templateVersion } : {},
195704
+ ...templateHash !== void 0 ? { templateHash } : {},
195705
+ status,
195706
+ ...isFiniteNumber(q.value) ? { value: q.value } : {},
195707
+ ...typeof q.error === "string" ? { error: q.error } : q.status !== status ? { error: `unknown status ${JSON.stringify(q.status)}` } : {},
195708
+ ...typeof q.rationale === "string" ? { rationale: q.rationale } : {},
195709
+ ...Array.isArray(q.evidence) ? {
195710
+ evidence: q.evidence.filter(
195711
+ (entry3) => typeof entry3 === "string"
195712
+ )
195713
+ } : {}
195714
+ });
195715
+ }
195716
+ return out;
195717
+ }
195584
195718
  function isFiniteNumber(value) {
195585
195719
  return typeof value === "number" && Number.isFinite(value);
195586
195720
  }
@@ -195592,6 +195726,7 @@ function judgeAbsenceStatus(verdict) {
195592
195726
  }
195593
195727
  function hostedScoreDefinitionInputs(inputs) {
195594
195728
  const judge = inputs.judgeVerdict;
195729
+ const rubricChecks = rubricCheckQuestionsFrom(inputs.rubricChecksVerdict);
195595
195730
  return {
195596
195731
  ...inputs.predicateResults?.length ? {
195597
195732
  predicates: inputs.predicateResults.map((result) => ({
@@ -195635,7 +195770,20 @@ function hostedScoreDefinitionInputs(inputs) {
195635
195770
  ...isRequiredRole(judge.role) ? { role: export_authoredRequiredRole() } : {}
195636
195771
  }
195637
195772
  } : {},
195638
- ...inputs.agentActivity?.status === "no_agent_activity" ? { agentActivityFired: true } : {}
195773
+ ...inputs.agentActivity?.status === "no_agent_activity" ? { agentActivityFired: true } : {},
195774
+ ...rubricChecks.length > 0 ? {
195775
+ rubricChecks: rubricChecks.map(
195776
+ ({ key, kind, label, contentDigest, passThreshold, ...rest }) => ({
195777
+ key,
195778
+ kind,
195779
+ label,
195780
+ contentDigest,
195781
+ passThreshold,
195782
+ ...rest.templateVersion !== void 0 ? { templateVersion: rest.templateVersion } : {},
195783
+ ...rest.templateHash !== void 0 ? { templateHash: rest.templateHash } : {}
195784
+ })
195785
+ )
195786
+ } : {}
195639
195787
  };
195640
195788
  }
195641
195789
  function buildHostedScoreRows(inputs, config) {
@@ -195715,6 +195863,39 @@ function buildHostedScoreRows(inputs, config) {
195715
195863
  );
195716
195864
  }
195717
195865
  }
195866
+ const rubricVerdict = inputs.rubricChecksVerdict;
195867
+ const answeredBy = typeof rubricVerdict?.model === "string" && rubricVerdict.model.length > 0 ? rubricVerdict.model : void 0;
195868
+ for (const question of rubricCheckQuestionsFrom(rubricVerdict)) {
195869
+ const definition = byId.get(hostedRubricCheckScorerId(question.key));
195870
+ if (!definition) continue;
195871
+ if (question.status === "skipped") {
195872
+ rows.push(
195873
+ export_skippedScoreResult2(
195874
+ definition,
195875
+ typeof rubricVerdict?.reason === "string" ? `rubric checks did not run: ${rubricVerdict.reason}` : "rubric checks did not run"
195876
+ )
195877
+ );
195878
+ continue;
195879
+ }
195880
+ if (question.status === "error" || question.value === void 0) {
195881
+ rows.push(
195882
+ export_errorScoreResult2(
195883
+ definition,
195884
+ question.error ?? (question.status === "scored" ? "rubric check reported no value" : "no_answer")
195885
+ )
195886
+ );
195887
+ continue;
195888
+ }
195889
+ rows.push(
195890
+ export_finalizeScoreResult2(definition, {
195891
+ kind: "scored",
195892
+ value: question.value,
195893
+ ...question.rationale ? { rationale: question.rationale } : {},
195894
+ ...question.evidence?.length ? { evidence: question.evidence } : {},
195895
+ ...answeredBy ? { model: answeredBy } : {}
195896
+ })
195897
+ );
195898
+ }
195718
195899
  return rows;
195719
195900
  }
195720
195901
  function describeToolMatch2(evaluation) {
@@ -212272,6 +212453,7 @@ function toCaseDto(testCase, vocabulary4 = 1) {
212272
212453
  updatedAt: testCase.updatedAt ?? null
212273
212454
  };
212274
212455
  }
212456
+ var PUBLIC_UNWRITABLE_JUDGE_SLOTS = ["groundedness", "rubricChecks"];
212275
212457
  function isCiOwnedSuiteDoc(suite) {
212276
212458
  const declared = suite.declaredSuiteId;
212277
212459
  return typeof declared === "string" && declared.length > 0 || suite.source === "sdk";
@@ -212740,6 +212922,12 @@ var suiteSettingsShape = {
212740
212922
  * while execution is unwired.
212741
212923
  */
212742
212924
  groundedness: z36.unknown().optional(),
212925
+ /**
212926
+ * App-only on day one (see the `judgeRubricChecks` manifest row).
212927
+ * Accepted here for the same reason as `groundedness`: a caller who
212928
+ * sends it gets a 400 naming the field, never a silent strip.
212929
+ */
212930
+ rubricChecks: z36.unknown().optional(),
212743
212931
  // The suite's own grading criteria, handed to the judge alongside
212744
212932
  // each case's expected output. `null` CLEARS them; an empty array is
212745
212933
  // refused because a rubric that asks nothing is not the absence of
@@ -212755,6 +212943,13 @@ var suiteSettingsShape = {
212755
212943
  message: "settings.judge.groundedness cannot be written while groundedness execution is not wired."
212756
212944
  });
212757
212945
  }
212946
+ if (judge.rubricChecks !== void 0) {
212947
+ ctx.addIssue({
212948
+ code: z36.ZodIssueCode.custom,
212949
+ path: ["rubricChecks"],
212950
+ message: "settings.judge.rubricChecks is authored in the app only; the criteria it grades are settings.judge.rubric."
212951
+ });
212952
+ }
212758
212953
  }).optional(),
212759
212954
  // ── The v2 verdict policy ────────────────────────────────────────────
212760
212955
  //
@@ -215941,10 +216136,12 @@ evals.patch("/projects/:projectId/eval-suites/:suiteId", async (c) => {
215941
216136
  delete goalCompletion.severity;
215942
216137
  }
215943
216138
  if (s.judge.rubric !== void 0) updateArgs.judgeRubric = s.judge.rubric;
215944
- updateArgs.judgeConfig = {
215945
- goalCompletion,
215946
- ...suite.judgeConfig?.groundedness ? { groundedness: suite.judgeConfig.groundedness } : {}
215947
- };
216139
+ const preserved = Object.fromEntries(
216140
+ PUBLIC_UNWRITABLE_JUDGE_SLOTS.filter(
216141
+ (slot) => suite.judgeConfig?.[slot]
216142
+ ).map((slot) => [slot, suite.judgeConfig[slot]])
216143
+ );
216144
+ updateArgs.judgeConfig = { goalCompletion, ...preserved };
215948
216145
  }
215949
216146
  applyVerdictPolicySettings(
215950
216147
  suite,
@@ -225182,7 +225379,7 @@ function classifyByStatus(error) {
225182
225379
  return null;
225183
225380
  }
225184
225381
  }
225185
- function httpStatus(refusal) {
225382
+ function httpStatus2(refusal) {
225186
225383
  return refusal.status;
225187
225384
  }
225188
225385
 
@@ -225510,7 +225707,7 @@ function webMcpErrorResponse(c, error, fallback) {
225510
225707
  logHostedRefusal(hostedRefusal);
225511
225708
  return c.json(
225512
225709
  { error: hostedRefusal.error, code: hostedRefusal.code },
225513
- httpStatus(hostedRefusal)
225710
+ httpStatus2(hostedRefusal)
225514
225711
  );
225515
225712
  }
225516
225713
  reportRouteFailure("[webmcp] unhandled route error", error, {
@@ -225711,7 +225908,7 @@ webmcpInspector.post("/sessions", async (c) => {
225711
225908
  logHostedRefusal(refusal);
225712
225909
  return c.json(
225713
225910
  { error: refusal.error, code: refusal.code },
225714
- httpStatus(refusal)
225911
+ httpStatus2(refusal)
225715
225912
  );
225716
225913
  }
225717
225914
  return webMcpErrorResponse(c, error, "Could not start your computer.");
@@ -240547,6 +240744,35 @@ var export_default2 = exporter2;
240547
240744
 
240548
240745
  // server/routes/web/guest-session.ts
240549
240746
  import { Hono as Hono57 } from "hono";
240747
+
240748
+ // shared/guest-session-failure.ts
240749
+ var GUEST_SESSION_FAILURE_REASONS = [
240750
+ "timeout",
240751
+ "network",
240752
+ "upstream_status",
240753
+ "bad_json",
240754
+ "bad_payload",
240755
+ "provisioning"
240756
+ ];
240757
+ var NETWORK_CODE_PATTERN = /^[A-Z][A-Z0-9_]{1,63}$/;
240758
+ function isFailureReason(value) {
240759
+ return typeof value === "string" && GUEST_SESSION_FAILURE_REASONS.includes(value);
240760
+ }
240761
+ function sanitizeGuestSessionFailureDetails(raw) {
240762
+ if (!raw || typeof raw !== "object") return void 0;
240763
+ const { reason, upstreamStatus, networkCode } = raw;
240764
+ if (!isFailureReason(reason)) return void 0;
240765
+ const details = { reason };
240766
+ if (typeof upstreamStatus === "number" && Number.isInteger(upstreamStatus) && upstreamStatus >= 100 && upstreamStatus <= 599) {
240767
+ details.upstreamStatus = upstreamStatus;
240768
+ }
240769
+ if (typeof networkCode === "string" && NETWORK_CODE_PATTERN.test(networkCode)) {
240770
+ details.networkCode = networkCode;
240771
+ }
240772
+ return details;
240773
+ }
240774
+
240775
+ // server/routes/web/guest-session.ts
240550
240776
  var guestSession = new Hono57();
240551
240777
  var MAX_LEGACY_TOKEN_LENGTH = 4096;
240552
240778
  var GUEST_SESSION_REFUSED_MESSAGE = "Too many guest sessions from your network today. Sign in to continue.";
@@ -240631,11 +240857,17 @@ guestSession.post("/", async (c) => {
240631
240857
  429
240632
240858
  );
240633
240859
  }
240860
+ const details = sanitizeGuestSessionFailureDetails({
240861
+ reason: result.reason,
240862
+ upstreamStatus: result.upstreamStatus,
240863
+ networkCode: result.networkCode
240864
+ });
240634
240865
  return webError(
240635
240866
  c,
240636
240867
  503,
240637
240868
  ErrorCode.INTERNAL_ERROR,
240638
- "Unable to obtain a guest session right now. Please try again."
240869
+ "Unable to obtain a guest session right now. Please try again.",
240870
+ details ? { ...details } : void 0
240639
240871
  );
240640
240872
  });
240641
240873
  function buildExpiredGuestSessionCookie() {
@@ -245640,6 +245872,10 @@ function readJudgeVerdict(metadata) {
245640
245872
  const verdict = metadata?.judgeVerdict;
245641
245873
  return typeof verdict === "object" && verdict !== null ? verdict : void 0;
245642
245874
  }
245875
+ function readRubricChecksVerdict(metadata) {
245876
+ const verdict = metadata?.rubricChecksVerdict;
245877
+ return typeof verdict === "object" && verdict !== null ? verdict : void 0;
245878
+ }
245643
245879
  function judgeEvidenceFromVerdict(verdict) {
245644
245880
  if (!verdict) return void 0;
245645
245881
  const status = verdict.status;
@@ -245788,7 +246024,8 @@ function deriveIterationPayload(args) {
245788
246024
  // same reason as `toolMatchAuthored`: an omitted definition leaves the
245789
246025
  // first pass's row unjoinable.
245790
246026
  ...storedAgentActivity ? { agentActivity: storedAgentActivity } : {},
245791
- ...judgeVerdict && isFiniteNumber3(judgeVerdict.threshold) ? { judgeVerdict } : {}
246027
+ ...judgeVerdict && isFiniteNumber3(judgeVerdict.threshold) ? { judgeVerdict } : {},
246028
+ ...args.rubricChecksVerdict ? { rubricChecksVerdict: args.rubricChecksVerdict } : {}
245792
246029
  });
245793
246030
  return scores.length > 0 ? { stage, scores, config: evaluationConfig } : { stage };
245794
246031
  }
@@ -245875,11 +246112,13 @@ async function runJudgeSecondPass(runId, ports = defaultPorts) {
245875
246112
  }
245876
246113
  let goalCompletionConfirmed = false;
245877
246114
  if (judgeVerdict && goalCompletionJobId !== void 0 && !goalCompletionFailed) {
246115
+ const rubricChecksVerdict = readRubricChecksVerdict(iteration.metadata);
245878
246116
  const { stage, scores, config } = deriveIterationPayload({
245879
246117
  iteration,
245880
246118
  mode,
245881
246119
  judgeVerdict,
245882
- attributionVerdict: void 0
246120
+ attributionVerdict: void 0,
246121
+ ...rubricChecksVerdict ? { rubricChecksVerdict } : {}
245883
246122
  });
245884
246123
  if (Object.keys(stage).length > 0) {
245885
246124
  const fields = stageFields(stage);