@shuffleio/shuffle-mcps 0.0.46 → 0.0.49

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 (3) hide show
  1. package/dist/index.js +109 -52
  2. package/dist/index.mjs +107 -50
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12062,7 +12062,7 @@ var subscribeLastOpenedAgentRun = (cb) => {
12062
12062
  var import_lucide_react15 = require("lucide-react");
12063
12063
 
12064
12064
  // ../Shuffle-Core/components/WorkflowRunExplorer.tsx
12065
- var import_react17 = __toESM(require("react"), 1);
12065
+ var import_react17 = __toESM(require("react"));
12066
12066
  var import_material20 = require("@mui/material");
12067
12067
  var import_icons_material = require("@mui/icons-material");
12068
12068
 
@@ -12130,14 +12130,43 @@ async function navigateToShuffleCore(destinationUrlOrPath, options) {
12130
12130
  const isSameDomain = Boolean(
12131
12131
  currentRoot && targetRoot && currentRoot === targetRoot
12132
12132
  );
12133
- if (!isCloudDomain3() && !isShuffleBackend || targetHost && currentHost && targetHost === currentHost || isSameDomain) {
12134
- if (popupWindow) {
12135
- popupWindow.location.href = targetUrl;
12133
+ function hasActiveSession2() {
12134
+ if (typeof window === "undefined") return false;
12135
+ const token = getSessionToken2();
12136
+ if (token && token.trim().length > 0) return true;
12137
+ try {
12138
+ const cookies = document.cookie || "";
12139
+ if (cookies.includes("session=") || cookies.includes("user_id=") || cookies.includes("token=")) {
12140
+ return true;
12141
+ }
12142
+ const userInfo = localStorage.getItem("shuffle_user_info") || localStorage.getItem("user_id");
12143
+ if (userInfo && userInfo.trim().length > 0 && userInfo !== "null") {
12144
+ return true;
12145
+ }
12146
+ } catch {
12147
+ }
12148
+ return false;
12149
+ }
12150
+ function directNavigate2(targetUrl2, popupWindow2) {
12151
+ if (popupWindow2) {
12152
+ try {
12153
+ popupWindow2.location.href = targetUrl2;
12154
+ } catch {
12155
+ if (typeof window !== "undefined") {
12156
+ window.location.href = targetUrl2;
12157
+ }
12158
+ }
12136
12159
  } else if (typeof window !== "undefined") {
12137
- window.location.href = targetUrl;
12160
+ window.location.href = targetUrl2;
12138
12161
  }
12139
12162
  return true;
12140
12163
  }
12164
+ if (!isCloudDomain3() && !isShuffleBackend || targetHost && currentHost && targetHost === currentHost || isSameDomain) {
12165
+ return directNavigate2(targetUrl, popupWindow);
12166
+ }
12167
+ if (!hasActiveSession2()) {
12168
+ return directNavigate2(targetUrl, popupWindow);
12169
+ }
12141
12170
  try {
12142
12171
  const isCloud2 = isCloudDomain3() || currentHost.endsWith(".shuffle.security") || currentHost === "shuffle.security";
12143
12172
  const handoffEndpoint = isCloud2 || isShuffleBackend ? UK_AUTH_HANDOFF_ENDPOINT : getApiUrl2("/api/v1/auth/handoff");
@@ -12155,25 +12184,17 @@ async function navigateToShuffleCore(destinationUrlOrPath, options) {
12155
12184
  headers
12156
12185
  });
12157
12186
  if (!response.ok) {
12158
- let reason = `Server error (${response.status})`;
12159
- try {
12160
- const errorData = await response.json();
12161
- if (errorData?.reason) {
12162
- reason = errorData.reason;
12163
- }
12164
- } catch {
12165
- }
12166
- if (popupWindow) popupWindow.close();
12167
- toast2.error(`Authentication handoff failed: ${reason}`);
12168
- return false;
12187
+ console.warn(
12188
+ `[authHandoff] Handoff ticket request returned ${response.status}, falling back to direct navigation`
12189
+ );
12190
+ return directNavigate2(targetUrl, popupWindow);
12169
12191
  }
12170
12192
  const data = await response.json();
12171
12193
  if (!data?.success || !data?.ticket) {
12172
- if (popupWindow) popupWindow.close();
12173
- toast2.error(
12174
- `Authentication handoff failed: ${data?.reason || "No ticket returned"}`
12194
+ console.warn(
12195
+ `[authHandoff] No ticket returned (${data?.reason || "unknown"}), falling back to direct navigation`
12175
12196
  );
12176
- return false;
12197
+ return directNavigate2(targetUrl, popupWindow);
12177
12198
  }
12178
12199
  let targetCoreBase = UK_SHUFFLE_CORE_BASE;
12179
12200
  if (!isShuffleBackend && !isCloud2) {
@@ -12219,15 +12240,16 @@ async function navigateToShuffleCore(destinationUrlOrPath, options) {
12219
12240
  }
12220
12241
  return true;
12221
12242
  } catch (err) {
12222
- if (popupWindow) popupWindow.close();
12223
- const msg = err instanceof Error ? err.message : "Network error";
12224
- toast2.error(`Failed to navigate to Shuffle Core: ${msg}`);
12225
- return false;
12243
+ console.warn(
12244
+ "[authHandoff] Error during handoff to Shuffle Core, falling back to direct navigation:",
12245
+ err
12246
+ );
12247
+ return directNavigate2(targetUrl, popupWindow);
12226
12248
  }
12227
12249
  }
12228
12250
 
12229
12251
  // ../Shuffle-Core/components/WorkflowRunExplorer.tsx
12230
- var import_react18_json_view3 = __toESM(require("react18-json-view"), 1);
12252
+ var import_react18_json_view3 = __toESM(require("react18-json-view"));
12231
12253
  var import_style3 = require("react18-json-view/src/style.css");
12232
12254
  var import_dark3 = require("react18-json-view/src/dark.css");
12233
12255
  var import_jsx_runtime24 = require("react/jsx-runtime");
@@ -14782,14 +14804,6 @@ var getDiagnosableScope = (parsed) => {
14782
14804
  (d) => d && typeof d === "object" && d.run_details ? d.run_details : null
14783
14805
  );
14784
14806
  if (runDetails.some((rd) => rd !== null)) scope.run_details = runDetails;
14785
- const finalDecisions = parsed.decisions.map((d) => {
14786
- if (!d || typeof d !== "object") return null;
14787
- const action = String(d.action || d.details?.action || "").toLowerCase();
14788
- const category = String(d.category || "").toLowerCase();
14789
- if (!["finish", "finalise"].includes(action) && !["finish", "finalise"].includes(category)) return null;
14790
- return { reason: d.reason };
14791
- });
14792
- if (finalDecisions.some((d) => d !== null)) scope.decisions = finalDecisions;
14793
14807
  }
14794
14808
  if (parsed.decision_string !== void 0) scope.decision_string = parsed.decision_string;
14795
14809
  return Object.keys(scope).length > 0 ? scope : null;
@@ -14804,11 +14818,11 @@ var extractDecisionIndex = (path) => {
14804
14818
  var isAiAuthText = (text) => {
14805
14819
  if (!text || typeof text !== "string") return false;
14806
14820
  const lower = text.toLowerCase();
14807
- const hasAuthSignal = /\b(401|unauthori[sz]ed|invalid[_\s-]*(api[_\s-]*key|credentials?)|incorrect\s+api\s+key|missing[_\s-]*(api[_\s-]*key|authorization)|authentication[_\s-]*(failed|required|error))\b/.test(
14821
+ const hasAuthSignal = /\b(401|unauthori[sz]ed|invalid[_\s-]*(api[_\s-]*key|credentials?|token|auth|key)|incorrect\s+api\s+key|missing[_\s-]*(api[_\s-]*key|authorization|credentials?)|authentication[_\s-]*(failed|required|error)|ai\s+credentials)\b/.test(
14808
14822
  lower
14809
- );
14823
+ ) || /check\s+your\s+ai\s+credentials/.test(lower);
14810
14824
  if (!hasAuthSignal) return false;
14811
- const hasAiSignal = /\b(failed\s+to\s+start\s+ai\s+agent|failed\s+to\s+run\s+ai\s+agent|ai\s+agent\s+(failed|error|crash)|runactionai|llm\s+request|failed\s+to\s+run\s+llm|no\s+llm|openai|anthropic|mistral|groq|deepseek|together\.ai|together\.xyz|openrouter|gemini|googleapis\.com|ollama|lm\s*studio|platform\.openai\.com|api\.openai\.com|local\s*llm)\b/.test(
14825
+ const hasAiSignal = /\b(failed\s+to\s+start\s+ai\s+agent|failed\s+to\s+run\s+ai(\s+(agent|query))?|failed\s+to\s+run\s+ai|ai\s+agent\s+(failed|error|crash|aborted)|ai\s+query|ai\s+credentials|shuffler\.io\/agents|runactionai|llm\s+request|failed\s+to\s+run\s+llm|no\s+llm|openai|anthropic|mistral|groq|deepseek|together\.ai|together\.xyz|openrouter|gemini|googleapis\.com|ollama|lm\s*studio|platform\.openai\.com|api\.openai\.com|local\s*llm)\b/.test(
14812
14826
  lower
14813
14827
  ) || /error\s+from\s+['"][^'"]*(openai|anthropic|mistral|groq|deepseek|together|openrouter|googleapis|ollama|lmstudio)/.test(
14814
14828
  lower
@@ -14874,13 +14888,19 @@ var diagnoseOutputWarning = (run) => {
14874
14888
  const isFinished = (run.status || "").toUpperCase() === "FINISHED";
14875
14889
  const hasSuccessfulFinish = (() => {
14876
14890
  if (!parsed || typeof parsed !== "object") return false;
14891
+ if (parsed.error && String(parsed.error).trim().length > 0) return false;
14892
+ if (parsed.success === false) return false;
14877
14893
  if (Array.isArray(parsed.decisions) && parsed.decisions.length > 0) {
14878
14894
  const last = parsed.decisions[parsed.decisions.length - 1];
14879
14895
  if (last && typeof last === "object") {
14880
14896
  const action = String(last.action || last.details?.action || "").toLowerCase();
14881
14897
  const category = String(last.category || "").toLowerCase();
14882
14898
  if (["finish", "finalise"].includes(action) || ["finish", "finalise"].includes(category)) {
14883
- return last.success !== false;
14899
+ if (last.success === false || last.status === "FAILED") return false;
14900
+ if (isAiAuthText(last.reason) || isAiAuthText(last.output) || isAiAuthText(last.details?.output)) return false;
14901
+ const reasonStr = String(last.reason || "").toLowerCase();
14902
+ if (reasonStr.startsWith("failed to") || reasonStr.includes("error,")) return false;
14903
+ return true;
14884
14904
  }
14885
14905
  }
14886
14906
  }
@@ -14893,17 +14913,22 @@ var diagnoseOutputWarning = (run) => {
14893
14913
  if (typeof parsed.error === "string") candidates.push(parsed.error);
14894
14914
  if (typeof parsed.reason === "string") candidates.push(parsed.reason);
14895
14915
  if (typeof parsed.message === "string") candidates.push(parsed.message);
14916
+ if (typeof parsed.output === "string") candidates.push(parsed.output);
14896
14917
  if (Array.isArray(parsed.decisions)) {
14897
14918
  for (const d of parsed.decisions) {
14898
14919
  if (typeof d?.run_details?.error === "string") candidates.push(d.run_details.error);
14899
- if (d?.success === false || d?.status === "FAILED") {
14900
- if (typeof d?.reason === "string") candidates.push(d.reason);
14901
- if (typeof d?.run_details?.result === "string") candidates.push(d.run_details.result);
14920
+ if (typeof d?.reason === "string") candidates.push(d.reason);
14921
+ if (typeof d?.run_details?.result === "string") candidates.push(d.run_details.result);
14922
+ if (typeof d?.output === "string") candidates.push(d.output);
14923
+ if (Array.isArray(d?.fields)) {
14924
+ for (const f of d.fields) {
14925
+ if (typeof f?.value === "string") candidates.push(f.value);
14926
+ }
14902
14927
  }
14903
14928
  }
14904
14929
  }
14905
14930
  }
14906
- if (raw && (!parsed || !Array.isArray(parsed.decisions) || parsed.decisions.length === 0)) {
14931
+ if (raw) {
14907
14932
  candidates.push(raw);
14908
14933
  }
14909
14934
  return candidates.find((v) => isAiAuthText(v)) || null;
@@ -15159,23 +15184,37 @@ var diagnoseOutputWarning = (run) => {
15159
15184
  var isAiAuthFailure = (run, extraText) => {
15160
15185
  if (isAiAuthText(extraText)) return true;
15161
15186
  if (!run) return false;
15162
- const status = (run.status || "").toUpperCase();
15163
- const isFinished = status === "FINISHED";
15164
- const fail = getFailureInfo(run);
15165
- if (fail && isAiAuthText(fail.reason)) return true;
15166
15187
  const diagnosis = diagnoseOutputWarning(run);
15167
15188
  if (diagnosis?.kind === "ai_auth" || diagnosis?.isAiAuth) return true;
15168
- if (isFinished) return false;
15169
- const decisions = run?.decisions;
15189
+ const fail = getFailureInfo(run);
15190
+ if (fail && isAiAuthText(fail.reason)) return true;
15191
+ const anyRun = run;
15192
+ if (typeof anyRun.result === "string" && isAiAuthText(anyRun.result)) return true;
15193
+ if (typeof anyRun.output === "string" && isAiAuthText(anyRun.output)) return true;
15194
+ if (typeof anyRun.error === "string" && isAiAuthText(anyRun.error)) return true;
15195
+ if (Array.isArray(run.results)) {
15196
+ for (const r of run.results) {
15197
+ if (typeof r?.result === "string" && isAiAuthText(r.result)) return true;
15198
+ if (typeof r?.error === "string" && isAiAuthText(r.error)) return true;
15199
+ }
15200
+ }
15201
+ const decisions = anyRun?.decisions;
15170
15202
  if (Array.isArray(decisions)) {
15171
15203
  for (const d of decisions) {
15204
+ if (isAiAuthText(d?.reason)) return true;
15205
+ if (typeof d?.output === "string" && isAiAuthText(d.output)) return true;
15172
15206
  if (typeof d?.run_details?.error === "string" && isAiAuthText(d.run_details.error)) return true;
15173
- if (d?.success === false || d?.status === "FAILED") {
15174
- if (isAiAuthText(d?.reason)) return true;
15175
- if (typeof d?.run_details?.result === "string" && isAiAuthText(d.run_details.result)) return true;
15207
+ if (typeof d?.run_details?.result === "string" && isAiAuthText(d.run_details.result)) return true;
15208
+ if (Array.isArray(d?.fields)) {
15209
+ for (const f of d.fields) {
15210
+ if (isAiAuthText(f?.value)) return true;
15211
+ }
15176
15212
  }
15177
15213
  }
15178
15214
  }
15215
+ const status = (run.status || "").toUpperCase();
15216
+ const isFinished = status === "FINISHED";
15217
+ if (isFinished) return false;
15179
15218
  return false;
15180
15219
  };
15181
15220
 
@@ -15307,6 +15346,21 @@ var AgentRunDiagnosisBanner = ({ run, sx, onJumpToEvidence, onFocusContinue, exe
15307
15346
  if (status === "FINISHED" && (diagnosis?.kind === "ai_auth" || diagnosis?.isAiAuth)) {
15308
15347
  return null;
15309
15348
  }
15349
+ if (status === "FINISHED" && diagnosis?.kind === "auth") {
15350
+ const firstEvidence2 = diagnosis?.evidence?.[0] || null;
15351
+ const jumpDecisionIndex2 = firstEvidence2 ? extractDecisionIndex(firstEvidence2.path) : null;
15352
+ if (jumpDecisionIndex2 === null) return null;
15353
+ const { parsed } = parseRunResult(run);
15354
+ const decs = parsed?.decisions || run?.decisions;
15355
+ if (Array.isArray(decs) && decs[jumpDecisionIndex2]) {
15356
+ const d = decs[jumpDecisionIndex2];
15357
+ const action = String(d?.action || d?.details?.action || "").toLowerCase();
15358
+ const category = String(d?.category || "").toLowerCase();
15359
+ if (["finish", "finalise"].includes(action) || ["finish", "finalise"].includes(category)) {
15360
+ return null;
15361
+ }
15362
+ }
15363
+ }
15310
15364
  const isCritical = !!failureInfo || diagnosis?.kind === "token_limit" || diagnosis?.kind === "ai_auth" || Boolean(diagnosis?.isAiAuth);
15311
15365
  const tone = isCritical ? "critical" : "medium";
15312
15366
  const Icon = isCritical ? import_lucide_react13.AlertTriangle : import_lucide_react13.HelpCircle;
@@ -20145,9 +20199,12 @@ var AgentUI = ({
20145
20199
  }
20146
20200
  }, [onChooseLLM]);
20147
20201
  const isAiAuthIssue = (0, import_react23.useMemo)(() => {
20148
- if (finishAnswer && finishAnswer.trim().length > 0) return false;
20202
+ if (finishAnswer && finishAnswer.trim().length > 0 && !isAiAuthText(finishAnswer)) {
20203
+ const diagnosable2 = execution?.results?.length ? execution : agentData;
20204
+ if (!isAiAuthFailure(diagnosable2, error || "")) return false;
20205
+ }
20149
20206
  const diagnosable = execution?.results?.length ? execution : agentData;
20150
- return isAiAuthFailure(diagnosable, error || "");
20207
+ return isAiAuthFailure(diagnosable, error || finishAnswer || "");
20151
20208
  }, [execution, agentData, finishAnswer, error]);
20152
20209
  const aiAuthSuggestionNode = isAiAuthIssue ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { sx: { mt: 1.5 }, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AiAuthSuggestion_default, { onOpenLocalLlm: openLocalLlmArea }) }) : null;
20153
20210
  (0, import_react23.useEffect)(() => {
package/dist/index.mjs CHANGED
@@ -11035,14 +11035,43 @@ async function navigateToShuffleCore(destinationUrlOrPath, options) {
11035
11035
  const isSameDomain = Boolean(
11036
11036
  currentRoot && targetRoot && currentRoot === targetRoot
11037
11037
  );
11038
- if (!isCloudDomain3() && !isShuffleBackend || targetHost && currentHost && targetHost === currentHost || isSameDomain) {
11039
- if (popupWindow) {
11040
- popupWindow.location.href = targetUrl;
11038
+ function hasActiveSession2() {
11039
+ if (typeof window === "undefined") return false;
11040
+ const token = getSessionToken();
11041
+ if (token && token.trim().length > 0) return true;
11042
+ try {
11043
+ const cookies = document.cookie || "";
11044
+ if (cookies.includes("session=") || cookies.includes("user_id=") || cookies.includes("token=")) {
11045
+ return true;
11046
+ }
11047
+ const userInfo = localStorage.getItem("shuffle_user_info") || localStorage.getItem("user_id");
11048
+ if (userInfo && userInfo.trim().length > 0 && userInfo !== "null") {
11049
+ return true;
11050
+ }
11051
+ } catch {
11052
+ }
11053
+ return false;
11054
+ }
11055
+ function directNavigate2(targetUrl2, popupWindow2) {
11056
+ if (popupWindow2) {
11057
+ try {
11058
+ popupWindow2.location.href = targetUrl2;
11059
+ } catch {
11060
+ if (typeof window !== "undefined") {
11061
+ window.location.href = targetUrl2;
11062
+ }
11063
+ }
11041
11064
  } else if (typeof window !== "undefined") {
11042
- window.location.href = targetUrl;
11065
+ window.location.href = targetUrl2;
11043
11066
  }
11044
11067
  return true;
11045
11068
  }
11069
+ if (!isCloudDomain3() && !isShuffleBackend || targetHost && currentHost && targetHost === currentHost || isSameDomain) {
11070
+ return directNavigate2(targetUrl, popupWindow);
11071
+ }
11072
+ if (!hasActiveSession2()) {
11073
+ return directNavigate2(targetUrl, popupWindow);
11074
+ }
11046
11075
  try {
11047
11076
  const isCloud2 = isCloudDomain3() || currentHost.endsWith(".shuffle.security") || currentHost === "shuffle.security";
11048
11077
  const handoffEndpoint = isCloud2 || isShuffleBackend ? UK_AUTH_HANDOFF_ENDPOINT : getApiUrl2("/api/v1/auth/handoff");
@@ -11060,25 +11089,17 @@ async function navigateToShuffleCore(destinationUrlOrPath, options) {
11060
11089
  headers
11061
11090
  });
11062
11091
  if (!response.ok) {
11063
- let reason = `Server error (${response.status})`;
11064
- try {
11065
- const errorData = await response.json();
11066
- if (errorData?.reason) {
11067
- reason = errorData.reason;
11068
- }
11069
- } catch {
11070
- }
11071
- if (popupWindow) popupWindow.close();
11072
- toast2.error(`Authentication handoff failed: ${reason}`);
11073
- return false;
11092
+ console.warn(
11093
+ `[authHandoff] Handoff ticket request returned ${response.status}, falling back to direct navigation`
11094
+ );
11095
+ return directNavigate2(targetUrl, popupWindow);
11074
11096
  }
11075
11097
  const data = await response.json();
11076
11098
  if (!data?.success || !data?.ticket) {
11077
- if (popupWindow) popupWindow.close();
11078
- toast2.error(
11079
- `Authentication handoff failed: ${data?.reason || "No ticket returned"}`
11099
+ console.warn(
11100
+ `[authHandoff] No ticket returned (${data?.reason || "unknown"}), falling back to direct navigation`
11080
11101
  );
11081
- return false;
11102
+ return directNavigate2(targetUrl, popupWindow);
11082
11103
  }
11083
11104
  let targetCoreBase = UK_SHUFFLE_CORE_BASE;
11084
11105
  if (!isShuffleBackend && !isCloud2) {
@@ -11124,10 +11145,11 @@ async function navigateToShuffleCore(destinationUrlOrPath, options) {
11124
11145
  }
11125
11146
  return true;
11126
11147
  } catch (err) {
11127
- if (popupWindow) popupWindow.close();
11128
- const msg = err instanceof Error ? err.message : "Network error";
11129
- toast2.error(`Failed to navigate to Shuffle Core: ${msg}`);
11130
- return false;
11148
+ console.warn(
11149
+ "[authHandoff] Error during handoff to Shuffle Core, falling back to direct navigation:",
11150
+ err
11151
+ );
11152
+ return directNavigate2(targetUrl, popupWindow);
11131
11153
  }
11132
11154
  }
11133
11155
 
@@ -13703,14 +13725,6 @@ var getDiagnosableScope = (parsed) => {
13703
13725
  (d) => d && typeof d === "object" && d.run_details ? d.run_details : null
13704
13726
  );
13705
13727
  if (runDetails.some((rd) => rd !== null)) scope.run_details = runDetails;
13706
- const finalDecisions = parsed.decisions.map((d) => {
13707
- if (!d || typeof d !== "object") return null;
13708
- const action = String(d.action || d.details?.action || "").toLowerCase();
13709
- const category = String(d.category || "").toLowerCase();
13710
- if (!["finish", "finalise"].includes(action) && !["finish", "finalise"].includes(category)) return null;
13711
- return { reason: d.reason };
13712
- });
13713
- if (finalDecisions.some((d) => d !== null)) scope.decisions = finalDecisions;
13714
13728
  }
13715
13729
  if (parsed.decision_string !== void 0) scope.decision_string = parsed.decision_string;
13716
13730
  return Object.keys(scope).length > 0 ? scope : null;
@@ -13725,11 +13739,11 @@ var extractDecisionIndex = (path) => {
13725
13739
  var isAiAuthText = (text) => {
13726
13740
  if (!text || typeof text !== "string") return false;
13727
13741
  const lower = text.toLowerCase();
13728
- const hasAuthSignal = /\b(401|unauthori[sz]ed|invalid[_\s-]*(api[_\s-]*key|credentials?)|incorrect\s+api\s+key|missing[_\s-]*(api[_\s-]*key|authorization)|authentication[_\s-]*(failed|required|error))\b/.test(
13742
+ const hasAuthSignal = /\b(401|unauthori[sz]ed|invalid[_\s-]*(api[_\s-]*key|credentials?|token|auth|key)|incorrect\s+api\s+key|missing[_\s-]*(api[_\s-]*key|authorization|credentials?)|authentication[_\s-]*(failed|required|error)|ai\s+credentials)\b/.test(
13729
13743
  lower
13730
- );
13744
+ ) || /check\s+your\s+ai\s+credentials/.test(lower);
13731
13745
  if (!hasAuthSignal) return false;
13732
- const hasAiSignal = /\b(failed\s+to\s+start\s+ai\s+agent|failed\s+to\s+run\s+ai\s+agent|ai\s+agent\s+(failed|error|crash)|runactionai|llm\s+request|failed\s+to\s+run\s+llm|no\s+llm|openai|anthropic|mistral|groq|deepseek|together\.ai|together\.xyz|openrouter|gemini|googleapis\.com|ollama|lm\s*studio|platform\.openai\.com|api\.openai\.com|local\s*llm)\b/.test(
13746
+ const hasAiSignal = /\b(failed\s+to\s+start\s+ai\s+agent|failed\s+to\s+run\s+ai(\s+(agent|query))?|failed\s+to\s+run\s+ai|ai\s+agent\s+(failed|error|crash|aborted)|ai\s+query|ai\s+credentials|shuffler\.io\/agents|runactionai|llm\s+request|failed\s+to\s+run\s+llm|no\s+llm|openai|anthropic|mistral|groq|deepseek|together\.ai|together\.xyz|openrouter|gemini|googleapis\.com|ollama|lm\s*studio|platform\.openai\.com|api\.openai\.com|local\s*llm)\b/.test(
13733
13747
  lower
13734
13748
  ) || /error\s+from\s+['"][^'"]*(openai|anthropic|mistral|groq|deepseek|together|openrouter|googleapis|ollama|lmstudio)/.test(
13735
13749
  lower
@@ -13795,13 +13809,19 @@ var diagnoseOutputWarning = (run) => {
13795
13809
  const isFinished = (run.status || "").toUpperCase() === "FINISHED";
13796
13810
  const hasSuccessfulFinish = (() => {
13797
13811
  if (!parsed || typeof parsed !== "object") return false;
13812
+ if (parsed.error && String(parsed.error).trim().length > 0) return false;
13813
+ if (parsed.success === false) return false;
13798
13814
  if (Array.isArray(parsed.decisions) && parsed.decisions.length > 0) {
13799
13815
  const last = parsed.decisions[parsed.decisions.length - 1];
13800
13816
  if (last && typeof last === "object") {
13801
13817
  const action = String(last.action || last.details?.action || "").toLowerCase();
13802
13818
  const category = String(last.category || "").toLowerCase();
13803
13819
  if (["finish", "finalise"].includes(action) || ["finish", "finalise"].includes(category)) {
13804
- return last.success !== false;
13820
+ if (last.success === false || last.status === "FAILED") return false;
13821
+ if (isAiAuthText(last.reason) || isAiAuthText(last.output) || isAiAuthText(last.details?.output)) return false;
13822
+ const reasonStr = String(last.reason || "").toLowerCase();
13823
+ if (reasonStr.startsWith("failed to") || reasonStr.includes("error,")) return false;
13824
+ return true;
13805
13825
  }
13806
13826
  }
13807
13827
  }
@@ -13814,17 +13834,22 @@ var diagnoseOutputWarning = (run) => {
13814
13834
  if (typeof parsed.error === "string") candidates.push(parsed.error);
13815
13835
  if (typeof parsed.reason === "string") candidates.push(parsed.reason);
13816
13836
  if (typeof parsed.message === "string") candidates.push(parsed.message);
13837
+ if (typeof parsed.output === "string") candidates.push(parsed.output);
13817
13838
  if (Array.isArray(parsed.decisions)) {
13818
13839
  for (const d of parsed.decisions) {
13819
13840
  if (typeof d?.run_details?.error === "string") candidates.push(d.run_details.error);
13820
- if (d?.success === false || d?.status === "FAILED") {
13821
- if (typeof d?.reason === "string") candidates.push(d.reason);
13822
- if (typeof d?.run_details?.result === "string") candidates.push(d.run_details.result);
13841
+ if (typeof d?.reason === "string") candidates.push(d.reason);
13842
+ if (typeof d?.run_details?.result === "string") candidates.push(d.run_details.result);
13843
+ if (typeof d?.output === "string") candidates.push(d.output);
13844
+ if (Array.isArray(d?.fields)) {
13845
+ for (const f of d.fields) {
13846
+ if (typeof f?.value === "string") candidates.push(f.value);
13847
+ }
13823
13848
  }
13824
13849
  }
13825
13850
  }
13826
13851
  }
13827
- if (raw && (!parsed || !Array.isArray(parsed.decisions) || parsed.decisions.length === 0)) {
13852
+ if (raw) {
13828
13853
  candidates.push(raw);
13829
13854
  }
13830
13855
  return candidates.find((v) => isAiAuthText(v)) || null;
@@ -14080,23 +14105,37 @@ var diagnoseOutputWarning = (run) => {
14080
14105
  var isAiAuthFailure = (run, extraText) => {
14081
14106
  if (isAiAuthText(extraText)) return true;
14082
14107
  if (!run) return false;
14083
- const status = (run.status || "").toUpperCase();
14084
- const isFinished = status === "FINISHED";
14085
- const fail = getFailureInfo(run);
14086
- if (fail && isAiAuthText(fail.reason)) return true;
14087
14108
  const diagnosis = diagnoseOutputWarning(run);
14088
14109
  if (diagnosis?.kind === "ai_auth" || diagnosis?.isAiAuth) return true;
14089
- if (isFinished) return false;
14090
- const decisions = run?.decisions;
14110
+ const fail = getFailureInfo(run);
14111
+ if (fail && isAiAuthText(fail.reason)) return true;
14112
+ const anyRun = run;
14113
+ if (typeof anyRun.result === "string" && isAiAuthText(anyRun.result)) return true;
14114
+ if (typeof anyRun.output === "string" && isAiAuthText(anyRun.output)) return true;
14115
+ if (typeof anyRun.error === "string" && isAiAuthText(anyRun.error)) return true;
14116
+ if (Array.isArray(run.results)) {
14117
+ for (const r of run.results) {
14118
+ if (typeof r?.result === "string" && isAiAuthText(r.result)) return true;
14119
+ if (typeof r?.error === "string" && isAiAuthText(r.error)) return true;
14120
+ }
14121
+ }
14122
+ const decisions = anyRun?.decisions;
14091
14123
  if (Array.isArray(decisions)) {
14092
14124
  for (const d of decisions) {
14125
+ if (isAiAuthText(d?.reason)) return true;
14126
+ if (typeof d?.output === "string" && isAiAuthText(d.output)) return true;
14093
14127
  if (typeof d?.run_details?.error === "string" && isAiAuthText(d.run_details.error)) return true;
14094
- if (d?.success === false || d?.status === "FAILED") {
14095
- if (isAiAuthText(d?.reason)) return true;
14096
- if (typeof d?.run_details?.result === "string" && isAiAuthText(d.run_details.result)) return true;
14128
+ if (typeof d?.run_details?.result === "string" && isAiAuthText(d.run_details.result)) return true;
14129
+ if (Array.isArray(d?.fields)) {
14130
+ for (const f of d.fields) {
14131
+ if (isAiAuthText(f?.value)) return true;
14132
+ }
14097
14133
  }
14098
14134
  }
14099
14135
  }
14136
+ const status = (run.status || "").toUpperCase();
14137
+ const isFinished = status === "FINISHED";
14138
+ if (isFinished) return false;
14100
14139
  return false;
14101
14140
  };
14102
14141
 
@@ -14228,6 +14267,21 @@ var AgentRunDiagnosisBanner = ({ run, sx, onJumpToEvidence, onFocusContinue, exe
14228
14267
  if (status === "FINISHED" && (diagnosis?.kind === "ai_auth" || diagnosis?.isAiAuth)) {
14229
14268
  return null;
14230
14269
  }
14270
+ if (status === "FINISHED" && diagnosis?.kind === "auth") {
14271
+ const firstEvidence2 = diagnosis?.evidence?.[0] || null;
14272
+ const jumpDecisionIndex2 = firstEvidence2 ? extractDecisionIndex(firstEvidence2.path) : null;
14273
+ if (jumpDecisionIndex2 === null) return null;
14274
+ const { parsed } = parseRunResult(run);
14275
+ const decs = parsed?.decisions || run?.decisions;
14276
+ if (Array.isArray(decs) && decs[jumpDecisionIndex2]) {
14277
+ const d = decs[jumpDecisionIndex2];
14278
+ const action = String(d?.action || d?.details?.action || "").toLowerCase();
14279
+ const category = String(d?.category || "").toLowerCase();
14280
+ if (["finish", "finalise"].includes(action) || ["finish", "finalise"].includes(category)) {
14281
+ return null;
14282
+ }
14283
+ }
14284
+ }
14231
14285
  const isCritical = !!failureInfo || diagnosis?.kind === "token_limit" || diagnosis?.kind === "ai_auth" || Boolean(diagnosis?.isAiAuth);
14232
14286
  const tone = isCritical ? "critical" : "medium";
14233
14287
  const Icon = isCritical ? AlertTriangle2 : HelpCircle;
@@ -19066,9 +19120,12 @@ var AgentUI = ({
19066
19120
  }
19067
19121
  }, [onChooseLLM]);
19068
19122
  const isAiAuthIssue = useMemo10(() => {
19069
- if (finishAnswer && finishAnswer.trim().length > 0) return false;
19123
+ if (finishAnswer && finishAnswer.trim().length > 0 && !isAiAuthText(finishAnswer)) {
19124
+ const diagnosable2 = execution?.results?.length ? execution : agentData;
19125
+ if (!isAiAuthFailure(diagnosable2, error || "")) return false;
19126
+ }
19070
19127
  const diagnosable = execution?.results?.length ? execution : agentData;
19071
- return isAiAuthFailure(diagnosable, error || "");
19128
+ return isAiAuthFailure(diagnosable, error || finishAnswer || "");
19072
19129
  }, [execution, agentData, finishAnswer, error]);
19073
19130
  const aiAuthSuggestionNode = isAiAuthIssue ? /* @__PURE__ */ jsx31(Box22, { sx: { mt: 1.5 }, children: /* @__PURE__ */ jsx31(AiAuthSuggestion_default, { onOpenLocalLlm: openLocalLlmArea }) }) : null;
19074
19131
  useEffect17(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shuffleio/shuffle-mcps",
3
- "version": "0.0.46",
3
+ "version": "0.0.49",
4
4
  "description": "Turn 3,000+ SaaS tools into MCP servers your agents can use. Headless React component for search, selection, and OAuth handoff.",
5
5
  "license": "MIT",
6
6
  "repository": {