@iota-uz/sdk 0.4.25 → 0.4.27

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,20 @@ 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
+ const filtered = opts.filter((o) => typeof o === "string");
1834
+ if (filtered.length === 0) {
1835
+ return void 0;
1836
+ }
1837
+ return filtered;
1838
+ }
1794
1839
 
1795
1840
  // ui/src/bichat/machine/selectors.ts
1796
1841
  function deriveDebugMode(state) {
@@ -1807,8 +1852,11 @@ function deriveSessionSnapshot(state, methods) {
1807
1852
  debugMode: deriveDebugMode(state),
1808
1853
  sessionDebugUsage: getSessionDebugUsage(state.messaging.turns),
1809
1854
  debugLimits: state.session.debugLimits,
1855
+ reasoningEffort: state.session.reasoningEffort,
1856
+ reasoningEffortOptions: state.session.reasoningEffortOptions,
1810
1857
  setError: methods.setError,
1811
- retryFetchSession: methods.retryFetchSession
1858
+ retryFetchSession: methods.retryFetchSession,
1859
+ setReasoningEffort: methods.setReasoningEffort
1812
1860
  };
1813
1861
  }
1814
1862
  function deriveMessagingSnapshot(state, methods) {
@@ -1998,6 +2046,8 @@ var ChatMachine = class {
1998
2046
  this.sendingSessionId = null;
1999
2047
  this.fetchCancelled = false;
2000
2048
  this.disposed = false;
2049
+ this.reasoningEffortOptions = null;
2050
+ this.reasoningEffortOptionSet = null;
2001
2051
  /** Memoized sessionDebugUsage — avoids unnecessary session re-renders during streaming. */
2002
2052
  this.lastSessionDebugUsage = null;
2003
2053
  /** Interval handle for passive polling when another tab has an active stream. */
@@ -2029,7 +2079,8 @@ var ChatMachine = class {
2029
2079
  if (this.lastSessionSnapshotVersion !== this.sessionSnapshotVersion) {
2030
2080
  this.cachedSessionSnapshot = deriveSessionSnapshot(this.state, {
2031
2081
  setError: this.setError,
2032
- retryFetchSession: this.retryFetchSession
2082
+ retryFetchSession: this.retryFetchSession,
2083
+ setReasoningEffort: this.setReasoningEffort
2033
2084
  });
2034
2085
  this.lastSessionSnapshotVersion = this.sessionSnapshotVersion;
2035
2086
  }
@@ -2083,6 +2134,12 @@ var ChatMachine = class {
2083
2134
  this.dataSource = config.dataSource;
2084
2135
  this.rateLimiter = config.rateLimiter;
2085
2136
  this.onSessionCreated = config.onSessionCreated;
2137
+ this.reasoningEffortOptions = this.buildReasoningEffortOptions();
2138
+ this.reasoningEffortOptionSet = this.reasoningEffortOptions ? new Set(this.reasoningEffortOptions) : null;
2139
+ const initialReasoningEffort = this.sanitizeReasoningEffort(loadReasoningEffort() || void 0);
2140
+ if (!initialReasoningEffort) {
2141
+ clearReasoningEffort();
2142
+ }
2086
2143
  this.state = {
2087
2144
  session: {
2088
2145
  currentSessionId: void 0,
@@ -2091,7 +2148,9 @@ var ChatMachine = class {
2091
2148
  error: null,
2092
2149
  errorRetryable: false,
2093
2150
  debugModeBySession: {},
2094
- debugLimits: readDebugLimitsFromGlobalContext()
2151
+ debugLimits: readDebugLimitsFromGlobalContext(),
2152
+ reasoningEffort: initialReasoningEffort,
2153
+ reasoningEffortOptions: this.reasoningEffortOptions ?? void 0
2095
2154
  },
2096
2155
  messaging: {
2097
2156
  turns: [],
@@ -2133,6 +2192,21 @@ var ChatMachine = class {
2133
2192
  this.enqueueMessage = this._enqueueMessage.bind(this);
2134
2193
  this.removeQueueItem = this._removeQueueItem.bind(this);
2135
2194
  this.updateQueueItem = this._updateQueueItem.bind(this);
2195
+ this.setReasoningEffort = this._setReasoningEffort.bind(this);
2196
+ }
2197
+ buildReasoningEffortOptions() {
2198
+ const options = readReasoningEffortOptionsFromGlobalContext();
2199
+ if (!options || options.length === 0) {
2200
+ return null;
2201
+ }
2202
+ return options;
2203
+ }
2204
+ // Keep outbound payloads constrained to server-declared options.
2205
+ sanitizeReasoningEffort(effort) {
2206
+ if (!effort || !this.reasoningEffortOptionSet || this.reasoningEffortOptionSet.size === 0) {
2207
+ return void 0;
2208
+ }
2209
+ return this.reasoningEffortOptionSet.has(effort) ? effort : void 0;
2136
2210
  }
2137
2211
  // =====================================================================
2138
2212
  // Lifecycle
@@ -2253,6 +2327,15 @@ var ChatMachine = class {
2253
2327
  }
2254
2328
  });
2255
2329
  }
2330
+ _setReasoningEffort(effort) {
2331
+ const next = this.sanitizeReasoningEffort(effort);
2332
+ this._updateSession({ reasoningEffort: next });
2333
+ if (next) {
2334
+ saveReasoningEffort(next);
2335
+ return;
2336
+ }
2337
+ clearReasoningEffort();
2338
+ }
2256
2339
  // =====================================================================
2257
2340
  // Private — session fetch
2258
2341
  // =====================================================================
@@ -2680,6 +2763,7 @@ var ChatMachine = class {
2680
2763
  attachments,
2681
2764
  debugMode,
2682
2765
  replaceFromMessageID,
2766
+ reasoningEffort,
2683
2767
  tempTurnId
2684
2768
  } = params;
2685
2769
  let accumulatedContent = "";
@@ -2694,7 +2778,8 @@ var ChatMachine = class {
2694
2778
  this.abortController?.signal,
2695
2779
  {
2696
2780
  debugMode,
2697
- replaceFromMessageID
2781
+ replaceFromMessageID,
2782
+ reasoningEffort
2698
2783
  }
2699
2784
  )) {
2700
2785
  if (this.abortController?.signal.aborted) {
@@ -2891,6 +2976,7 @@ var ChatMachine = class {
2891
2976
  attachments,
2892
2977
  debugMode: curDebugMode,
2893
2978
  replaceFromMessageID,
2979
+ reasoningEffort: this.sanitizeReasoningEffort(this.state.session.reasoningEffort),
2894
2980
  tempTurnId: tempTurn.id
2895
2981
  });
2896
2982
  if (stopped) {
@@ -7087,21 +7173,15 @@ function calculateContextUsagePercent(promptTokens, effectiveMaxTokens) {
7087
7173
  }
7088
7174
  return promptTokens / effectiveMaxTokens * 100;
7089
7175
  }
7090
- function CopyPill({ text }) {
7176
+ function useCopyFeedback() {
7091
7177
  const [copied, setCopied] = React.useState(false);
7092
7178
  const timerRef = React.useRef(null);
7093
- React.useEffect(() => () => {
7094
- if (timerRef.current !== null) {
7095
- clearTimeout(timerRef.current);
7096
- }
7097
- }, []);
7098
- const handleCopy = async (e) => {
7099
- e.stopPropagation();
7179
+ const copy = React.useCallback(async (text) => {
7100
7180
  try {
7101
7181
  await navigator.clipboard.writeText(text);
7102
7182
  setCopied(true);
7103
7183
  if (timerRef.current !== null) {
7104
- clearTimeout(timerRef.current);
7184
+ window.clearTimeout(timerRef.current);
7105
7185
  }
7106
7186
  timerRef.current = window.setTimeout(() => {
7107
7187
  setCopied(false);
@@ -7110,6 +7190,19 @@ function CopyPill({ text }) {
7110
7190
  } catch (err) {
7111
7191
  console.error("Copy failed:", err);
7112
7192
  }
7193
+ }, []);
7194
+ React.useEffect(() => () => {
7195
+ if (timerRef.current !== null) {
7196
+ window.clearTimeout(timerRef.current);
7197
+ }
7198
+ }, []);
7199
+ return { copied, copy };
7200
+ }
7201
+ function CopyPill({ text }) {
7202
+ const { copied, copy } = useCopyFeedback();
7203
+ const handleCopy = async (e) => {
7204
+ e.stopPropagation();
7205
+ await copy(text);
7113
7206
  };
7114
7207
  return /* @__PURE__ */ jsxRuntime.jsxs(
7115
7208
  "button",
@@ -7127,6 +7220,25 @@ function CopyPill({ text }) {
7127
7220
  }
7128
7221
  );
7129
7222
  }
7223
+ function InlineCopyButton({ text }) {
7224
+ const { copied, copy } = useCopyFeedback();
7225
+ const handleCopy = async (e) => {
7226
+ e.stopPropagation();
7227
+ await copy(text);
7228
+ };
7229
+ return /* @__PURE__ */ jsxRuntime.jsx(
7230
+ "button",
7231
+ {
7232
+ onClick: handleCopy,
7233
+ "aria-label": copied ? "Copied" : "Copy",
7234
+ className: [
7235
+ "flex-shrink-0 p-1 rounded transition-colors duration-150",
7236
+ 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"
7237
+ ].join(" "),
7238
+ children: copied ? /* @__PURE__ */ jsxRuntime.jsx(react.Check, { size: 11, weight: "bold" }) : /* @__PURE__ */ jsxRuntime.jsx(react.Copy, { size: 11 })
7239
+ }
7240
+ );
7241
+ }
7130
7242
  function MetricChip({ icon, value, label }) {
7131
7243
  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
7244
  icon,
@@ -7225,7 +7337,7 @@ function ToolCard({ tool }) {
7225
7337
  }
7226
7338
  );
7227
7339
  }
7228
- function DebugPanel({ trace, debugLimits = null }) {
7340
+ function DebugPanel({ trace }) {
7229
7341
  const hasData = !!trace && hasDebugTrace(trace);
7230
7342
  const traceID = trace?.traceId?.trim() || "";
7231
7343
  const traceURL = trace?.traceUrl?.trim() || "";
@@ -7244,22 +7356,6 @@ function DebugPanel({ trace, debugLimits = null }) {
7244
7356
  }
7245
7357
  })();
7246
7358
  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
7359
  const metrics = [];
7264
7360
  if (hasData && trace) {
7265
7361
  if (trace.generationMs !== void 0) {
@@ -7312,34 +7408,36 @@ function DebugPanel({ trace, debugLimits = null }) {
7312
7408
  hasData && trace && /* @__PURE__ */ jsxRuntime.jsx(CopyPill, { text: JSON.stringify(trace, null, 2) })
7313
7409
  ] }),
7314
7410
  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 })
7411
+ (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: [
7412
+ traceID && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
7413
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-[10px] uppercase tracking-wider text-gray-400 dark:text-gray-500 w-14", children: "Trace" }),
7414
+ /* @__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 }),
7415
+ /* @__PURE__ */ jsxRuntime.jsx(InlineCopyButton, { text: traceID })
7322
7416
  ] }),
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 })
7417
+ trace.sessionId && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
7418
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-[10px] uppercase tracking-wider text-gray-400 dark:text-gray-500 w-14", children: "Session" }),
7419
+ /* @__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 }),
7420
+ /* @__PURE__ */ jsxRuntime.jsx(InlineCopyButton, { text: trace.sessionId })
7342
7421
  ] }),
7422
+ safeTraceURL && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0 pt-0.5", children: [
7423
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 w-14" }),
7424
+ /* @__PURE__ */ jsxRuntime.jsxs(
7425
+ "a",
7426
+ {
7427
+ href: safeTraceURL,
7428
+ target: "_blank",
7429
+ rel: "noopener noreferrer",
7430
+ "aria-label": "Open in Langfuse",
7431
+ 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",
7432
+ children: [
7433
+ /* @__PURE__ */ jsxRuntime.jsx(react.ArrowSquareOut, { size: 11, weight: "bold" }),
7434
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Open in Langfuse" })
7435
+ ]
7436
+ }
7437
+ )
7438
+ ] })
7439
+ ] }),
7440
+ (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
7441
  trace.observationReason && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[11px] text-amber-700 dark:text-amber-300", children: [
7344
7442
  "Observation: ",
7345
7443
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: trace.observationReason })
@@ -7379,30 +7477,6 @@ function DebugPanel({ trace, debugLimits = null }) {
7379
7477
  /* @__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
7478
  ] }),
7381
7479
  /* @__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
7480
  ] })
7407
7481
  ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-500 italic", children: "Debug info unavailable" })
7408
7482
  ] });
@@ -7464,8 +7538,7 @@ function AssistantMessage({
7464
7538
  hideAvatar = false,
7465
7539
  hideActions = false,
7466
7540
  hideTimestamp = false,
7467
- showDebug = false,
7468
- debugLimits = null
7541
+ showDebug = false
7469
7542
  }) {
7470
7543
  const { t } = useTranslation();
7471
7544
  const [explanationExpanded, setExplanationExpanded] = React.useState(false);
@@ -7656,7 +7729,7 @@ function AssistantMessage({
7656
7729
  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
7730
  ] })
7658
7731
  ) }),
7659
- showDebug && /* @__PURE__ */ jsxRuntime.jsx(DebugPanel, { trace: turn.debug, debugLimits })
7732
+ showDebug && /* @__PURE__ */ jsxRuntime.jsx(DebugPanel, { trace: turn.debug })
7660
7733
  ] }),
7661
7734
  turn.artifacts && turn.artifacts.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: classes.artifacts, children: renderSlot(
7662
7735
  slots?.artifacts,
@@ -7848,7 +7921,7 @@ function AssistantTurnView({
7848
7921
  hideTimestamp,
7849
7922
  allowRegenerate = true
7850
7923
  }) {
7851
- const { debugMode, debugLimits } = useChatSession();
7924
+ const { debugMode } = useChatSession();
7852
7925
  const { handleCopy, handleRegenerate, pendingQuestion, sendMessage: sendMessage2, loading } = useChatMessaging();
7853
7926
  const assistantTurn = turn.assistantTurn;
7854
7927
  if (!assistantTurn) {
@@ -7883,8 +7956,7 @@ function AssistantTurnView({
7883
7956
  hideAvatar,
7884
7957
  hideActions,
7885
7958
  hideTimestamp,
7886
- showDebug: debugMode,
7887
- debugLimits
7959
+ showDebug: debugMode
7888
7960
  }
7889
7961
  );
7890
7962
  }
@@ -9029,6 +9101,36 @@ function DebugStatsPanel({ debugSessionUsage, debugLimits }) {
9029
9101
  ] })
9030
9102
  ] });
9031
9103
  }
9104
+ var EFFORT_LABEL_KEYS = {
9105
+ low: "BiChat.Input.ReasoningEffortLow",
9106
+ medium: "BiChat.Input.ReasoningEffortMedium",
9107
+ high: "BiChat.Input.ReasoningEffortHigh",
9108
+ xhigh: "BiChat.Input.ReasoningEffortXHigh"
9109
+ };
9110
+ function ReasoningEffortSelector({ options, value, onChange, disabled }) {
9111
+ const { t } = useTranslation();
9112
+ const selected = value || options[1] || options[0];
9113
+ const label = t("BiChat.Input.ReasoningEffort");
9114
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 self-center flex items-center gap-1.5", children: [
9115
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-gray-400 dark:text-gray-500 font-medium whitespace-nowrap select-none", children: label }),
9116
+ /* @__PURE__ */ jsxRuntime.jsx(
9117
+ "select",
9118
+ {
9119
+ value: selected,
9120
+ disabled,
9121
+ onChange: (event) => onChange(event.target.value),
9122
+ className: [
9123
+ "cursor-pointer h-8 rounded-lg border border-gray-200 dark:border-gray-600",
9124
+ "bg-gray-50 dark:bg-gray-700/50 px-2.5 text-[11px] font-medium leading-none",
9125
+ "text-gray-700 dark:text-gray-200 focus:outline-none focus:ring-2 focus:ring-primary-500/25",
9126
+ "disabled:opacity-40 disabled:cursor-not-allowed"
9127
+ ].join(" "),
9128
+ "aria-label": label,
9129
+ children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt, children: t(EFFORT_LABEL_KEYS[opt] ?? opt) }, opt))
9130
+ }
9131
+ )
9132
+ ] });
9133
+ }
9032
9134
  var MAX_FILES_DEFAULT = 10;
9033
9135
  var MAX_FILE_SIZE_DEFAULT = 20 * 1024 * 1024;
9034
9136
  var MAX_HEIGHT = 192;
@@ -9055,7 +9157,10 @@ var MessageInput = React.forwardRef(
9055
9157
  maxFiles = MAX_FILES_DEFAULT,
9056
9158
  maxFileSize = MAX_FILE_SIZE_DEFAULT,
9057
9159
  containerClassName,
9058
- formClassName
9160
+ formClassName,
9161
+ reasoningEffortOptions,
9162
+ reasoningEffort,
9163
+ onReasoningEffortChange
9059
9164
  }, ref) => {
9060
9165
  const { t } = useTranslation();
9061
9166
  const [attachments, setAttachments] = React.useState([]);
@@ -9382,6 +9487,16 @@ var MessageInput = React.forwardRef(
9382
9487
  const canSubmit = !disabled && (message.trim() || attachments.length > 0);
9383
9488
  const visibleError = error || commandError;
9384
9489
  const visibleErrorText = visibleError ? t(visibleError) : "";
9490
+ const resolvedReasoningEffort = reasoningEffortOptions && reasoningEffortOptions.length > 0 ? reasoningEffortOptions.includes(reasoningEffort ?? "") ? reasoningEffort : reasoningEffortOptions[1] || reasoningEffortOptions[0] : void 0;
9491
+ React.useEffect(() => {
9492
+ if (!onReasoningEffortChange || !reasoningEffortOptions?.length) {
9493
+ return;
9494
+ }
9495
+ if (!resolvedReasoningEffort || resolvedReasoningEffort === reasoningEffort) {
9496
+ return;
9497
+ }
9498
+ onReasoningEffortChange(resolvedReasoningEffort);
9499
+ }, [reasoningEffort, onReasoningEffortChange, reasoningEffortOptions, resolvedReasoningEffort]);
9385
9500
  const defaultContainerClassName = "shrink-0 px-4 pt-4 pb-6";
9386
9501
  return /* @__PURE__ */ jsxRuntime.jsx(
9387
9502
  "div",
@@ -9504,16 +9619,25 @@ var MessageInput = React.forwardRef(
9504
9619
  "aria-label": t("BiChat.Input.MessageInput")
9505
9620
  }
9506
9621
  ) }),
9622
+ reasoningEffortOptions && reasoningEffortOptions.length > 0 && onReasoningEffortChange && /* @__PURE__ */ jsxRuntime.jsx(
9623
+ ReasoningEffortSelector,
9624
+ {
9625
+ options: reasoningEffortOptions,
9626
+ value: resolvedReasoningEffort,
9627
+ onChange: onReasoningEffortChange,
9628
+ disabled: disabled || loading
9629
+ }
9630
+ ),
9507
9631
  isStreaming && onCancelStreaming ? /* @__PURE__ */ jsxRuntime.jsx(
9508
9632
  "button",
9509
9633
  {
9510
9634
  type: "button",
9511
9635
  onClick: onCancelStreaming,
9512
9636
  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",
9637
+ 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
9638
  "aria-label": t("BiChat.Common.Cancel"),
9515
9639
  title: t("BiChat.Common.Cancel"),
9516
- children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 18, weight: "bold" })
9640
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.Stop, { size: 18, weight: "fill" })
9517
9641
  }
9518
9642
  ) : /* @__PURE__ */ jsxRuntime.jsx(
9519
9643
  "button",
@@ -11703,7 +11827,10 @@ function ChatSessionCore({
11703
11827
  debugLimits,
11704
11828
  currentSessionId,
11705
11829
  setError,
11706
- retryFetchSession
11830
+ retryFetchSession,
11831
+ reasoningEffort,
11832
+ setReasoningEffort,
11833
+ reasoningEffortOptions
11707
11834
  } = useChatSession();
11708
11835
  const {
11709
11836
  turns,
@@ -11998,7 +12125,10 @@ function ChatSessionCore({
11998
12125
  onUpdateQueueItem: updateQueueItem,
11999
12126
  onCancelStreaming: cancel,
12000
12127
  containerClassName: "pt-6 px-6",
12001
- formClassName: "mx-auto"
12128
+ formClassName: "mx-auto",
12129
+ reasoningEffortOptions,
12130
+ reasoningEffort,
12131
+ onReasoningEffortChange: setReasoningEffort
12002
12132
  }
12003
12133
  ),
12004
12134
  /* @__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 +12184,10 @@ function ChatSessionCore({
12054
12184
  onUnqueue: handleUnqueue,
12055
12185
  onRemoveQueueItem: removeQueueItem,
12056
12186
  onUpdateQueueItem: updateQueueItem,
12057
- onCancelStreaming: cancel
12187
+ onCancelStreaming: cancel,
12188
+ reasoningEffortOptions,
12189
+ reasoningEffort,
12190
+ onReasoningEffortChange: setReasoningEffort
12058
12191
  }
12059
12192
  )
12060
12193
  ] }) }),
@@ -18586,6 +18719,9 @@ async function* sendMessage(deps, sessionId, content, attachments = [], signal,
18586
18719
  replaceFromMessageId: options?.replaceFromMessageID,
18587
18720
  attachments: streamAttachments
18588
18721
  };
18722
+ if (options?.reasoningEffort) {
18723
+ payload.reasoningEffort = options.reasoningEffort;
18724
+ }
18589
18725
  const timeoutMs = deps.streamConnectTimeoutMs ?? 0;
18590
18726
  if (timeoutMs > 0) {
18591
18727
  connectionTimeoutID = setTimeout(() => {