@iota-uz/sdk 0.4.25 → 0.4.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -52,8 +52,8 @@ applet rpc gen --name <applet-name>
52
52
  applet rpc check --name <applet-name>
53
53
  applet rpc watch --name <applet-name>
54
54
  applet deps check
55
- applet sdk link --sdk-root ../../applets
56
- applet sdk unlink
55
+ applet sdk local --sdk-root ../../applets
56
+ applet sdk local --off
57
57
  applet check # deps + RPC drift for all applets
58
58
  applet schema export --name <applet>
59
59
  applet dev # start dev environment (all configured applets)
@@ -67,14 +67,15 @@ applet secrets delete --name <applet> --key OPENAI_API_KEY
67
67
 
68
68
  - **Specific version:** `go install github.com/iota-uz/applets/cmd/applet@v0.4.4`
69
69
  - **Shell completion:** `applet completion bash`, `applet completion zsh`, or `applet completion fish` — see `applet completion --help` for install instructions.
70
- - **Local SDK overrides:** `applet sdk link` writes local-only settings to `.applets/local.env` (gitignored) and avoids committing link overrides into package manifests/lockfiles.
70
+ - **Local SDK alias mode:** `applet sdk local` writes local-only settings to `.applets/local.env` (gitignored). `applet dev` then injects `IOTA_SDK_DIST` so Vite aliases `@iota-uz/sdk` to your local SDK dist.
71
71
 
72
72
  ---
73
73
 
74
74
  ## DX Migration Notes (Breaking)
75
75
 
76
76
  - `applets/` is the canonical source of `@iota-uz/sdk`; `iota-sdk/package.json` is no longer the publish source.
77
- - Local SDK iteration should use `applet sdk link --sdk-root ../../applets` and `applet sdk unlink` instead of committing `pnpm` overrides/workspace links.
77
+ - Local SDK iteration uses runtime alias mode only: `applet sdk local --sdk-root ../../applets` and `applet sdk local --off`.
78
+ - Never commit local `pnpm` overrides/workspace links for `@iota-uz/sdk`.
78
79
  - `applet dev` now detects `go.work` dependencies and automatically watches/restarts critical processes when dependency code changes.
79
80
  - Keep `.applets/local.env` local-only. It is intentionally gitignored and must not be committed.
80
81
 
@@ -1649,6 +1649,37 @@ function loadDebugMode(sessionId) {
1649
1649
  }
1650
1650
  }
1651
1651
 
1652
+ // ui/src/bichat/utils/reasoningEffortStorage.ts
1653
+ var STORAGE_KEY = "bichat.reasoningEffort";
1654
+ function saveReasoningEffort(effort) {
1655
+ if (typeof window === "undefined") {
1656
+ return;
1657
+ }
1658
+ try {
1659
+ window.sessionStorage.setItem(STORAGE_KEY, effort);
1660
+ } catch {
1661
+ }
1662
+ }
1663
+ function loadReasoningEffort() {
1664
+ if (typeof window === "undefined") {
1665
+ return null;
1666
+ }
1667
+ try {
1668
+ return window.sessionStorage.getItem(STORAGE_KEY);
1669
+ } catch {
1670
+ return null;
1671
+ }
1672
+ }
1673
+ function clearReasoningEffort() {
1674
+ if (typeof window === "undefined") {
1675
+ return;
1676
+ }
1677
+ try {
1678
+ window.sessionStorage.removeItem(STORAGE_KEY);
1679
+ } catch {
1680
+ }
1681
+ }
1682
+
1652
1683
  // ui/src/bichat/utils/debugTrace.ts
1653
1684
  function hasMeaningfulUsage(trace) {
1654
1685
  if (!trace) {
@@ -1791,6 +1822,16 @@ function readDebugLimitsFromGlobalContext() {
1791
1822
  completionReserveTokens
1792
1823
  };
1793
1824
  }
1825
+ function readReasoningEffortOptionsFromGlobalContext() {
1826
+ if (typeof window === "undefined") {
1827
+ return void 0;
1828
+ }
1829
+ const opts = window.__APPLET_CONTEXT__?.extensions?.llm?.reasoningEffortOptions;
1830
+ if (!Array.isArray(opts) || opts.length === 0) {
1831
+ return void 0;
1832
+ }
1833
+ return opts.filter((o) => typeof o === "string");
1834
+ }
1794
1835
 
1795
1836
  // ui/src/bichat/machine/selectors.ts
1796
1837
  function deriveDebugMode(state) {
@@ -1807,8 +1848,10 @@ function deriveSessionSnapshot(state, methods) {
1807
1848
  debugMode: deriveDebugMode(state),
1808
1849
  sessionDebugUsage: getSessionDebugUsage(state.messaging.turns),
1809
1850
  debugLimits: state.session.debugLimits,
1851
+ reasoningEffort: state.session.reasoningEffort,
1810
1852
  setError: methods.setError,
1811
- retryFetchSession: methods.retryFetchSession
1853
+ retryFetchSession: methods.retryFetchSession,
1854
+ setReasoningEffort: methods.setReasoningEffort
1812
1855
  };
1813
1856
  }
1814
1857
  function deriveMessagingSnapshot(state, methods) {
@@ -1998,6 +2041,7 @@ var ChatMachine = class {
1998
2041
  this.sendingSessionId = null;
1999
2042
  this.fetchCancelled = false;
2000
2043
  this.disposed = false;
2044
+ this.reasoningEffortOptions = null;
2001
2045
  /** Memoized sessionDebugUsage — avoids unnecessary session re-renders during streaming. */
2002
2046
  this.lastSessionDebugUsage = null;
2003
2047
  /** Interval handle for passive polling when another tab has an active stream. */
@@ -2029,7 +2073,8 @@ var ChatMachine = class {
2029
2073
  if (this.lastSessionSnapshotVersion !== this.sessionSnapshotVersion) {
2030
2074
  this.cachedSessionSnapshot = deriveSessionSnapshot(this.state, {
2031
2075
  setError: this.setError,
2032
- retryFetchSession: this.retryFetchSession
2076
+ retryFetchSession: this.retryFetchSession,
2077
+ setReasoningEffort: this.setReasoningEffort
2033
2078
  });
2034
2079
  this.lastSessionSnapshotVersion = this.sessionSnapshotVersion;
2035
2080
  }
@@ -2083,6 +2128,11 @@ var ChatMachine = class {
2083
2128
  this.dataSource = config.dataSource;
2084
2129
  this.rateLimiter = config.rateLimiter;
2085
2130
  this.onSessionCreated = config.onSessionCreated;
2131
+ this.reasoningEffortOptions = this.buildReasoningEffortOptions();
2132
+ const initialReasoningEffort = this.sanitizeReasoningEffort(loadReasoningEffort() || void 0);
2133
+ if (!initialReasoningEffort) {
2134
+ clearReasoningEffort();
2135
+ }
2086
2136
  this.state = {
2087
2137
  session: {
2088
2138
  currentSessionId: void 0,
@@ -2091,7 +2141,8 @@ var ChatMachine = class {
2091
2141
  error: null,
2092
2142
  errorRetryable: false,
2093
2143
  debugModeBySession: {},
2094
- debugLimits: readDebugLimitsFromGlobalContext()
2144
+ debugLimits: readDebugLimitsFromGlobalContext(),
2145
+ reasoningEffort: initialReasoningEffort
2095
2146
  },
2096
2147
  messaging: {
2097
2148
  turns: [],
@@ -2133,6 +2184,21 @@ var ChatMachine = class {
2133
2184
  this.enqueueMessage = this._enqueueMessage.bind(this);
2134
2185
  this.removeQueueItem = this._removeQueueItem.bind(this);
2135
2186
  this.updateQueueItem = this._updateQueueItem.bind(this);
2187
+ this.setReasoningEffort = this._setReasoningEffort.bind(this);
2188
+ }
2189
+ buildReasoningEffortOptions() {
2190
+ const options = readReasoningEffortOptionsFromGlobalContext();
2191
+ if (!options || options.length === 0) {
2192
+ return null;
2193
+ }
2194
+ return new Set(options);
2195
+ }
2196
+ // Keep outbound payloads constrained to server-declared options.
2197
+ sanitizeReasoningEffort(effort) {
2198
+ if (!effort || !this.reasoningEffortOptions || this.reasoningEffortOptions.size === 0) {
2199
+ return void 0;
2200
+ }
2201
+ return this.reasoningEffortOptions.has(effort) ? effort : void 0;
2136
2202
  }
2137
2203
  // =====================================================================
2138
2204
  // Lifecycle
@@ -2253,6 +2319,15 @@ var ChatMachine = class {
2253
2319
  }
2254
2320
  });
2255
2321
  }
2322
+ _setReasoningEffort(effort) {
2323
+ const next = this.sanitizeReasoningEffort(effort);
2324
+ this._updateSession({ reasoningEffort: next });
2325
+ if (next) {
2326
+ saveReasoningEffort(next);
2327
+ return;
2328
+ }
2329
+ clearReasoningEffort();
2330
+ }
2256
2331
  // =====================================================================
2257
2332
  // Private — session fetch
2258
2333
  // =====================================================================
@@ -2680,6 +2755,7 @@ var ChatMachine = class {
2680
2755
  attachments,
2681
2756
  debugMode,
2682
2757
  replaceFromMessageID,
2758
+ reasoningEffort,
2683
2759
  tempTurnId
2684
2760
  } = params;
2685
2761
  let accumulatedContent = "";
@@ -2694,7 +2770,8 @@ var ChatMachine = class {
2694
2770
  this.abortController?.signal,
2695
2771
  {
2696
2772
  debugMode,
2697
- replaceFromMessageID
2773
+ replaceFromMessageID,
2774
+ reasoningEffort
2698
2775
  }
2699
2776
  )) {
2700
2777
  if (this.abortController?.signal.aborted) {
@@ -2891,6 +2968,7 @@ var ChatMachine = class {
2891
2968
  attachments,
2892
2969
  debugMode: curDebugMode,
2893
2970
  replaceFromMessageID,
2971
+ reasoningEffort: this.sanitizeReasoningEffort(this.state.session.reasoningEffort),
2894
2972
  tempTurnId: tempTurn.id
2895
2973
  });
2896
2974
  if (stopped) {
@@ -7127,6 +7205,43 @@ function CopyPill({ text }) {
7127
7205
  }
7128
7206
  );
7129
7207
  }
7208
+ function InlineCopyButton({ text }) {
7209
+ const [copied, setCopied] = React.useState(false);
7210
+ const timerRef = React.useRef(null);
7211
+ React.useEffect(() => () => {
7212
+ if (timerRef.current !== null) {
7213
+ clearTimeout(timerRef.current);
7214
+ }
7215
+ }, []);
7216
+ const handleCopy = async (e) => {
7217
+ e.stopPropagation();
7218
+ try {
7219
+ await navigator.clipboard.writeText(text);
7220
+ setCopied(true);
7221
+ if (timerRef.current !== null) {
7222
+ clearTimeout(timerRef.current);
7223
+ }
7224
+ timerRef.current = window.setTimeout(() => {
7225
+ setCopied(false);
7226
+ timerRef.current = null;
7227
+ }, 2e3);
7228
+ } catch (err) {
7229
+ console.error("Copy failed:", err);
7230
+ }
7231
+ };
7232
+ return /* @__PURE__ */ jsxRuntime.jsx(
7233
+ "button",
7234
+ {
7235
+ onClick: handleCopy,
7236
+ "aria-label": copied ? "Copied" : "Copy",
7237
+ className: [
7238
+ "flex-shrink-0 p-1 rounded transition-colors duration-150",
7239
+ copied ? "text-emerald-500 dark:text-emerald-400" : "text-gray-300 dark:text-gray-600 hover:text-gray-500 dark:hover:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700/40"
7240
+ ].join(" "),
7241
+ children: copied ? /* @__PURE__ */ jsxRuntime.jsx(react.Check, { size: 11, weight: "bold" }) : /* @__PURE__ */ jsxRuntime.jsx(react.Copy, { size: 11 })
7242
+ }
7243
+ );
7244
+ }
7130
7245
  function MetricChip({ icon, value, label }) {
7131
7246
  return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1.5 px-2 py-1 rounded-md bg-gray-50 dark:bg-gray-800/40 text-[11px] tabular-nums", children: [
7132
7247
  icon,
@@ -7225,7 +7340,7 @@ function ToolCard({ tool }) {
7225
7340
  }
7226
7341
  );
7227
7342
  }
7228
- function DebugPanel({ trace, debugLimits = null }) {
7343
+ function DebugPanel({ trace }) {
7229
7344
  const hasData = !!trace && hasDebugTrace(trace);
7230
7345
  const traceID = trace?.traceId?.trim() || "";
7231
7346
  const traceURL = trace?.traceUrl?.trim() || "";
@@ -7244,22 +7359,6 @@ function DebugPanel({ trace, debugLimits = null }) {
7244
7359
  }
7245
7360
  })();
7246
7361
  const tokensPerSecond = calculateCompletionTokensPerSecond(trace?.usage, trace?.generationMs);
7247
- const effectiveMaxTokens = debugLimits?.effectiveMaxTokens ?? 0;
7248
- const promptTokens = trace?.usage?.promptTokens ?? 0;
7249
- const contextUsagePercent = calculateContextUsagePercent(promptTokens, effectiveMaxTokens);
7250
- const contextUsagePercentLabel = contextUsagePercent !== null ? contextUsagePercent.toFixed(1) : null;
7251
- const formatCompactTokens = (value) => {
7252
- if (!Number.isFinite(value) || value <= 0) {
7253
- return "0 tokens";
7254
- }
7255
- return `${new Intl.NumberFormat("en-US", {
7256
- notation: "compact",
7257
- maximumFractionDigits: value >= 1e5 ? 0 : 1
7258
- }).format(value)} tokens`;
7259
- };
7260
- const contextPercentValue = contextUsagePercent ?? 0;
7261
- const contextUsageToneClass = contextPercentValue > 75 ? "bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400" : contextPercentValue > 50 ? "bg-amber-100 dark:bg-amber-900/30 text-amber-600 dark:text-amber-400" : "bg-emerald-100 dark:bg-emerald-900/30 text-emerald-600 dark:text-emerald-400";
7262
- const contextUsageBarColor = contextPercentValue > 75 ? "#ef4444" : contextPercentValue > 50 ? "#f59e0b" : "#10b981";
7263
7362
  const metrics = [];
7264
7363
  if (hasData && trace) {
7265
7364
  if (trace.generationMs !== void 0) {
@@ -7312,34 +7411,36 @@ function DebugPanel({ trace, debugLimits = null }) {
7312
7411
  hasData && trace && /* @__PURE__ */ jsxRuntime.jsx(CopyPill, { text: JSON.stringify(trace, null, 2) })
7313
7412
  ] }),
7314
7413
  hasData && trace ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
7315
- (traceID || safeTraceURL) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-gray-200/60 dark:border-gray-700/40 bg-gray-50/50 dark:bg-gray-800/40 p-3 space-y-2", children: [
7316
- traceID && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
7317
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
7318
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] uppercase tracking-wider text-gray-500 dark:text-gray-400", children: "Trace ID" }),
7319
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-mono text-[11px] text-gray-800 dark:text-gray-200 break-all", children: traceID })
7320
- ] }),
7321
- /* @__PURE__ */ jsxRuntime.jsx(CopyPill, { text: traceID })
7414
+ (traceID || trace.sessionId) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-gray-200/60 dark:border-gray-700/40 bg-gray-50/50 dark:bg-gray-800/40 px-3 py-2 space-y-1.5", children: [
7415
+ traceID && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
7416
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-[10px] uppercase tracking-wider text-gray-400 dark:text-gray-500 w-14", children: "Trace" }),
7417
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 min-w-0 font-mono text-[11px] text-gray-700 dark:text-gray-300 truncate", title: traceID, children: traceID }),
7418
+ /* @__PURE__ */ jsxRuntime.jsx(InlineCopyButton, { text: traceID })
7322
7419
  ] }),
7323
- safeTraceURL && /* @__PURE__ */ jsxRuntime.jsxs(
7324
- "a",
7325
- {
7326
- href: safeTraceURL,
7327
- target: "_blank",
7328
- rel: "noopener noreferrer",
7329
- "aria-label": "View full trace in Langfuse (opens in new tab)",
7330
- className: "inline-flex items-center gap-1.5 text-[11px] font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300",
7331
- children: [
7332
- /* @__PURE__ */ jsxRuntime.jsx(react.ArrowSquareOut, { size: 12, weight: "bold" }),
7333
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Open in Langfuse" })
7334
- ]
7335
- }
7336
- )
7337
- ] }),
7338
- (trace.thinking || trace.observationReason || trace.sessionId) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-gray-200/60 dark:border-gray-700/40 bg-gray-50/50 dark:bg-gray-800/40 p-3 space-y-2", children: [
7339
- trace.sessionId && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[10px] uppercase tracking-wider text-gray-500 dark:text-gray-400", children: [
7340
- "Session: ",
7341
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono normal-case break-all", children: trace.sessionId })
7420
+ trace.sessionId && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
7421
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-[10px] uppercase tracking-wider text-gray-400 dark:text-gray-500 w-14", children: "Session" }),
7422
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 min-w-0 font-mono text-[11px] text-gray-700 dark:text-gray-300 truncate", title: trace.sessionId, children: trace.sessionId }),
7423
+ /* @__PURE__ */ jsxRuntime.jsx(InlineCopyButton, { text: trace.sessionId })
7342
7424
  ] }),
7425
+ safeTraceURL && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0 pt-0.5", children: [
7426
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 w-14" }),
7427
+ /* @__PURE__ */ jsxRuntime.jsxs(
7428
+ "a",
7429
+ {
7430
+ href: safeTraceURL,
7431
+ target: "_blank",
7432
+ rel: "noopener noreferrer",
7433
+ "aria-label": "Open in Langfuse",
7434
+ className: "inline-flex items-center gap-1.5 text-[11px] font-medium text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300 transition-colors duration-150",
7435
+ children: [
7436
+ /* @__PURE__ */ jsxRuntime.jsx(react.ArrowSquareOut, { size: 11, weight: "bold" }),
7437
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Open in Langfuse" })
7438
+ ]
7439
+ }
7440
+ )
7441
+ ] })
7442
+ ] }),
7443
+ (trace.thinking || trace.observationReason) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-gray-200/60 dark:border-gray-700/40 bg-gray-50/50 dark:bg-gray-800/40 p-3 space-y-2", children: [
7343
7444
  trace.observationReason && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[11px] text-amber-700 dark:text-amber-300", children: [
7344
7445
  "Observation: ",
7345
7446
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: trace.observationReason })
@@ -7379,30 +7480,6 @@ function DebugPanel({ trace, debugLimits = null }) {
7379
7480
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-1.5 py-0.5 rounded-full bg-gray-100 dark:bg-gray-800 text-[10px] font-mono font-medium text-gray-500 dark:text-gray-400 tabular-nums", children: trace.tools.length })
7380
7481
  ] }),
7381
7482
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: trace.tools.map((tool, idx) => /* @__PURE__ */ jsxRuntime.jsx(ToolCard, { tool }, `${tool.callId || tool.name}-${idx}`)) })
7382
- ] }),
7383
- contextUsagePercentLabel !== null && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-gray-200/60 dark:border-gray-700/40 bg-gray-50/50 dark:bg-gray-800/40 p-3 space-y-2", children: [
7384
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
7385
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase tracking-wider text-gray-500 dark:text-gray-400", children: "Context usage" }),
7386
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono text-[10px] text-gray-500 dark:text-gray-400 tabular-nums", children: [
7387
- formatCompactTokens(promptTokens),
7388
- " / ",
7389
- formatCompactTokens(effectiveMaxTokens)
7390
- ] }),
7391
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `px-1.5 py-0.5 rounded-full text-[10px] font-semibold tabular-nums ${contextUsageToneClass}`, children: [
7392
- contextUsagePercentLabel,
7393
- "%"
7394
- ] })
7395
- ] }),
7396
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1.5 rounded-full bg-gray-200/80 dark:bg-gray-700/50 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
7397
- "div",
7398
- {
7399
- className: "h-full rounded-full transition-all duration-700 ease-out",
7400
- style: {
7401
- width: `${Math.min(contextPercentValue, 100)}%`,
7402
- backgroundColor: contextUsageBarColor
7403
- }
7404
- }
7405
- ) })
7406
7483
  ] })
7407
7484
  ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-500 italic", children: "Debug info unavailable" })
7408
7485
  ] });
@@ -7464,8 +7541,7 @@ function AssistantMessage({
7464
7541
  hideAvatar = false,
7465
7542
  hideActions = false,
7466
7543
  hideTimestamp = false,
7467
- showDebug = false,
7468
- debugLimits = null
7544
+ showDebug = false
7469
7545
  }) {
7470
7546
  const { t } = useTranslation();
7471
7547
  const [explanationExpanded, setExplanationExpanded] = React.useState(false);
@@ -7656,7 +7732,7 @@ function AssistantMessage({
7656
7732
  explanationExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-3 text-sm text-gray-600 dark:text-gray-400", children: /* @__PURE__ */ jsxRuntime.jsx(React.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx("div", { children: t("BiChat.Common.Loading") }), children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownRenderer2, { content: turn.explanation }) }) })
7657
7733
  ] })
7658
7734
  ) }),
7659
- showDebug && /* @__PURE__ */ jsxRuntime.jsx(DebugPanel, { trace: turn.debug, debugLimits })
7735
+ showDebug && /* @__PURE__ */ jsxRuntime.jsx(DebugPanel, { trace: turn.debug })
7660
7736
  ] }),
7661
7737
  turn.artifacts && turn.artifacts.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: classes.artifacts, children: renderSlot(
7662
7738
  slots?.artifacts,
@@ -7848,7 +7924,7 @@ function AssistantTurnView({
7848
7924
  hideTimestamp,
7849
7925
  allowRegenerate = true
7850
7926
  }) {
7851
- const { debugMode, debugLimits } = useChatSession();
7927
+ const { debugMode } = useChatSession();
7852
7928
  const { handleCopy, handleRegenerate, pendingQuestion, sendMessage: sendMessage2, loading } = useChatMessaging();
7853
7929
  const assistantTurn = turn.assistantTurn;
7854
7930
  if (!assistantTurn) {
@@ -7883,8 +7959,7 @@ function AssistantTurnView({
7883
7959
  hideAvatar,
7884
7960
  hideActions,
7885
7961
  hideTimestamp,
7886
- showDebug: debugMode,
7887
- debugLimits
7962
+ showDebug: debugMode
7888
7963
  }
7889
7964
  );
7890
7965
  }
@@ -9029,6 +9104,36 @@ function DebugStatsPanel({ debugSessionUsage, debugLimits }) {
9029
9104
  ] })
9030
9105
  ] });
9031
9106
  }
9107
+ var EFFORT_LABEL_KEYS = {
9108
+ low: "BiChat.Input.ReasoningEffortLow",
9109
+ medium: "BiChat.Input.ReasoningEffortMedium",
9110
+ high: "BiChat.Input.ReasoningEffortHigh",
9111
+ xhigh: "BiChat.Input.ReasoningEffortXHigh"
9112
+ };
9113
+ function ReasoningEffortSelector({ options, value, onChange, disabled }) {
9114
+ const { t } = useTranslation();
9115
+ const selected = value || options[1] || options[0];
9116
+ const label = t("BiChat.Input.ReasoningEffort");
9117
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 self-center flex items-center gap-1.5", children: [
9118
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500 font-medium whitespace-nowrap select-none", children: label }),
9119
+ /* @__PURE__ */ jsxRuntime.jsx(
9120
+ "select",
9121
+ {
9122
+ value: selected,
9123
+ disabled,
9124
+ onChange: (event) => onChange(event.target.value),
9125
+ className: [
9126
+ "cursor-pointer h-8 rounded-lg border border-gray-200 dark:border-gray-600",
9127
+ "bg-gray-50 dark:bg-gray-700/50 px-2.5 text-[11px] font-medium leading-none",
9128
+ "text-gray-700 dark:text-gray-200 focus:outline-none focus:ring-2 focus:ring-primary-500/25",
9129
+ "disabled:opacity-40 disabled:cursor-not-allowed"
9130
+ ].join(" "),
9131
+ "aria-label": label,
9132
+ children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt, children: t(EFFORT_LABEL_KEYS[opt] ?? opt) }, opt))
9133
+ }
9134
+ )
9135
+ ] });
9136
+ }
9032
9137
  var MAX_FILES_DEFAULT = 10;
9033
9138
  var MAX_FILE_SIZE_DEFAULT = 20 * 1024 * 1024;
9034
9139
  var MAX_HEIGHT = 192;
@@ -9055,7 +9160,10 @@ var MessageInput = React.forwardRef(
9055
9160
  maxFiles = MAX_FILES_DEFAULT,
9056
9161
  maxFileSize = MAX_FILE_SIZE_DEFAULT,
9057
9162
  containerClassName,
9058
- formClassName
9163
+ formClassName,
9164
+ reasoningEffortOptions,
9165
+ reasoningEffort,
9166
+ onReasoningEffortChange
9059
9167
  }, ref) => {
9060
9168
  const { t } = useTranslation();
9061
9169
  const [attachments, setAttachments] = React.useState([]);
@@ -9504,16 +9612,25 @@ var MessageInput = React.forwardRef(
9504
9612
  "aria-label": t("BiChat.Input.MessageInput")
9505
9613
  }
9506
9614
  ) }),
9615
+ reasoningEffortOptions && reasoningEffortOptions.length > 0 && onReasoningEffortChange && /* @__PURE__ */ jsxRuntime.jsx(
9616
+ ReasoningEffortSelector,
9617
+ {
9618
+ options: reasoningEffortOptions,
9619
+ value: reasoningEffort,
9620
+ onChange: onReasoningEffortChange,
9621
+ disabled: disabled || loading
9622
+ }
9623
+ ),
9507
9624
  isStreaming && onCancelStreaming ? /* @__PURE__ */ jsxRuntime.jsx(
9508
9625
  "button",
9509
9626
  {
9510
9627
  type: "button",
9511
9628
  onClick: onCancelStreaming,
9512
9629
  disabled: disabled || fetching,
9513
- className: "cursor-pointer flex-shrink-0 self-center p-2 rounded-lg bg-red-600 hover:bg-red-700 active:bg-red-800 active:scale-95 text-white shadow-sm transition-all disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-red-600",
9630
+ className: "cursor-pointer flex-shrink-0 self-center p-2 rounded-lg bg-gray-900 hover:bg-gray-800 active:bg-black active:scale-95 text-white shadow-sm transition-all dark:bg-gray-100 dark:hover:bg-gray-200 dark:active:bg-white dark:text-gray-900 disabled:opacity-40 disabled:cursor-not-allowed",
9514
9631
  "aria-label": t("BiChat.Common.Cancel"),
9515
9632
  title: t("BiChat.Common.Cancel"),
9516
- children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 18, weight: "bold" })
9633
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.Stop, { size: 18, weight: "fill" })
9517
9634
  }
9518
9635
  ) : /* @__PURE__ */ jsxRuntime.jsx(
9519
9636
  "button",
@@ -11703,7 +11820,9 @@ function ChatSessionCore({
11703
11820
  debugLimits,
11704
11821
  currentSessionId,
11705
11822
  setError,
11706
- retryFetchSession
11823
+ retryFetchSession,
11824
+ reasoningEffort,
11825
+ setReasoningEffort
11707
11826
  } = useChatSession();
11708
11827
  const {
11709
11828
  turns,
@@ -11731,6 +11850,7 @@ function ChatSessionCore({
11731
11850
  const accessReadOnly = session?.access ? !session.access.canWrite : false;
11732
11851
  const effectiveReadOnly = Boolean(readOnly ?? isReadOnly) || isArchived || accessReadOnly;
11733
11852
  const [restoring, setRestoring] = React.useState(false);
11853
+ const [reasoningEffortOptions] = React.useState(() => readReasoningEffortOptionsFromGlobalContext());
11734
11854
  const handleRestore = React.useCallback(async () => {
11735
11855
  if (!session?.id) {
11736
11856
  return;
@@ -11998,7 +12118,10 @@ function ChatSessionCore({
11998
12118
  onUpdateQueueItem: updateQueueItem,
11999
12119
  onCancelStreaming: cancel,
12000
12120
  containerClassName: "pt-6 px-6",
12001
- formClassName: "mx-auto"
12121
+ formClassName: "mx-auto",
12122
+ reasoningEffortOptions,
12123
+ reasoningEffort,
12124
+ onReasoningEffortChange: setReasoningEffort
12002
12125
  }
12003
12126
  ),
12004
12127
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-4 pb-1 text-center text-xs text-gray-500 dark:text-gray-400", children: t("BiChat.Welcome.Disclaimer") })
@@ -12054,7 +12177,10 @@ function ChatSessionCore({
12054
12177
  onUnqueue: handleUnqueue,
12055
12178
  onRemoveQueueItem: removeQueueItem,
12056
12179
  onUpdateQueueItem: updateQueueItem,
12057
- onCancelStreaming: cancel
12180
+ onCancelStreaming: cancel,
12181
+ reasoningEffortOptions,
12182
+ reasoningEffort,
12183
+ onReasoningEffortChange: setReasoningEffort
12058
12184
  }
12059
12185
  )
12060
12186
  ] }) }),
@@ -18586,6 +18712,9 @@ async function* sendMessage(deps, sessionId, content, attachments = [], signal,
18586
18712
  replaceFromMessageId: options?.replaceFromMessageID,
18587
18713
  attachments: streamAttachments
18588
18714
  };
18715
+ if (options?.reasoningEffort) {
18716
+ payload.reasoningEffort = options.reasoningEffort;
18717
+ }
18589
18718
  const timeoutMs = deps.streamConnectTimeoutMs ?? 0;
18590
18719
  if (timeoutMs > 0) {
18591
18720
  connectionTimeoutID = setTimeout(() => {