@bolt-foundry/gambit 0.6.7 → 0.7.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.
@@ -16652,181 +16652,212 @@ var require_client = __commonJS({
16652
16652
 
16653
16653
  // simulator-ui/src/main.tsx
16654
16654
  var import_jsx_runtime2 = __toESM(require_jsx_runtime());
16655
- var import_react2 = __toESM(require__());
16655
+ var import_react = __toESM(require__());
16656
16656
  var import_client = __toESM(require_client());
16657
16657
 
16658
16658
  // simulator-ui/src/DocsPage.tsx
16659
16659
  var import_jsx_runtime = __toESM(require_jsx_runtime());
16660
- var import_react = __toESM(require__());
16661
16660
  var GAMBIT_PACKAGE_README = "https://github.com/bolt-foundry/gambit/blob/main/README.md";
16662
16661
  var GAMBIT_CLI_DOC = "https://github.com/bolt-foundry/gambit/blob/main/docs/cli.md";
16663
- function DocsPage(props) {
16664
- const { deckDisplayPath: deckDisplayPath2, deckAbsolutePath } = props;
16665
- const [deckSource, setDeckSource] = (0, import_react.useState)(null);
16666
- const [loading, setLoading] = (0, import_react.useState)(true);
16667
- const [error, setError] = (0, import_react.useState)(null);
16668
- const [copied, setCopied] = (0, import_react.useState)(false);
16669
- (0, import_react.useEffect)(() => {
16670
- let cancelled = false;
16671
- const load = async () => {
16672
- setLoading(true);
16673
- setError(null);
16674
- try {
16675
- const res = await fetch("/api/deck-source");
16676
- if (!res.ok) throw new Error(res.statusText);
16677
- const body = await res.json();
16678
- if (cancelled) return;
16679
- if (body.error) {
16680
- setError(body.error);
16681
- setDeckSource(body.content ?? null);
16682
- } else {
16683
- setDeckSource(body.content ?? "");
16684
- }
16685
- } catch (err) {
16686
- if (cancelled) return;
16687
- setError(err instanceof Error ? err.message : "Failed to load deck");
16688
- } finally {
16689
- if (!cancelled) setLoading(false);
16690
- }
16691
- };
16692
- load();
16693
- return () => {
16694
- cancelled = true;
16695
- };
16696
- }, []);
16697
- (0, import_react.useEffect)(() => {
16698
- if (!copied) return;
16699
- const handle = window.setTimeout(() => setCopied(false), 2e3);
16700
- return () => window.clearTimeout(handle);
16701
- }, [
16702
- copied
16703
- ]);
16704
- const handleCopyPath = (0, import_react.useCallback)(async () => {
16705
- try {
16706
- await navigator.clipboard?.writeText(deckAbsolutePath);
16707
- setCopied(true);
16708
- } catch {
16709
- setCopied(true);
16710
- }
16711
- }, [
16712
- deckAbsolutePath
16713
- ]);
16662
+ var DEFAULT_TEST_BOT_PATH = "/sessions/new/test-bot";
16663
+ var DEFAULT_DEBUG_PATH = "/sessions/new/debug";
16664
+ var DEFAULT_CALIBRATE_PATH = "/calibrate";
16665
+ function DocsPage() {
16714
16666
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
16715
16667
  className: "docs-shell",
16716
16668
  children: [
16717
16669
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
16718
16670
  className: "docs-hero",
16719
16671
  children: [
16720
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", {
16672
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
16673
+ className: "docs-eyebrow",
16721
16674
  children: "Gambit Simulator"
16722
16675
  }),
16723
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
16724
- children: [
16725
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", {
16726
- children: "Use the simulator to iterate fast and fix failures."
16727
- }),
16728
- " ",
16729
- "Run a test, capture why it failed, grade the result, and hand the evidence to Codex so it can help you update the deck."
16730
- ]
16676
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", {
16677
+ children: "Test an agent. See where it fails. Fix it fast."
16731
16678
  }),
16732
16679
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
16733
- children: "The simulator keeps the whole loop in one place: Test Bot to explore, Calibrate to grade, and Debug to inspect."
16680
+ className: "docs-subtitle",
16681
+ children: "Gambit is an open-source agent harness framework. It's designed to make it simple to create, debug, and fix AI workflows, agents and assistants."
16734
16682
  })
16735
16683
  ]
16736
16684
  }),
16737
16685
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
16738
- className: "docs-grid",
16686
+ className: "docs-callout",
16739
16687
  children: [
16740
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", {
16741
- className: "docs-card",
16742
- children: [
16743
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
16744
- children: "Run the test"
16745
- }),
16746
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
16747
- children: "Open Test Bot and try the scenario you care about. If the output looks wrong, add a rating and a short reason so the failure is captured."
16688
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("header", {
16689
+ className: "docs-callout-header",
16690
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
16691
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h2", {
16692
+ style: {
16693
+ display: "flex",
16694
+ flexDirection: "row",
16695
+ gap: 12,
16696
+ alignItems: "center"
16697
+ },
16698
+ children: [
16699
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
16700
+ className: "docs-icon",
16701
+ children: "\u{1F916}"
16702
+ }),
16703
+ "Start here:",
16704
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
16705
+ className: "docs-primary-btn",
16706
+ href: DEFAULT_TEST_BOT_PATH,
16707
+ children: "Open Test Bot"
16708
+ })
16709
+ ]
16748
16710
  })
16749
- ]
16711
+ })
16750
16712
  }),
16751
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", {
16752
- className: "docs-card",
16713
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
16714
+ className: "docs-callout-body",
16753
16715
  children: [
16716
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
16717
+ children: "The Test Bot lets you interact with your agent like a real user would."
16718
+ }),
16719
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
16720
+ className: "docs-divider"
16721
+ }),
16754
16722
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
16755
- children: "Grade"
16723
+ children: "What to do"
16724
+ }),
16725
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("ul", {
16726
+ children: [
16727
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
16728
+ children: "Some examples have a Test Bot input, these are usually optional."
16729
+ }),
16730
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
16731
+ children: 'Click "Run test bot" to start the conversation.'
16732
+ }),
16733
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
16734
+ children: "Review the agent's response."
16735
+ })
16736
+ ]
16756
16737
  }),
16757
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
16758
- children: "Run the grader in Calibrate. Copy a reference or the state file link for sharing."
16759
- })
16760
- ]
16761
- }),
16762
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", {
16763
- className: "docs-card",
16764
- children: [
16765
16738
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
16766
- children: "Fix + rerun"
16739
+ children: "If something looks wrong"
16767
16740
  }),
16768
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
16769
- children: "Paste the reference or state link into Codex and ask for help fixing the deck. Codex updates files, then you rerun the simulator to verify."
16741
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("ul", {
16742
+ children: [
16743
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
16744
+ children: "Leave a quick rating and a short note explaining why."
16745
+ }),
16746
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
16747
+ children: "Failures get captured for evaluation."
16748
+ })
16749
+ ]
16750
+ }),
16751
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
16752
+ children: "Calibrate the agent"
16753
+ }),
16754
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("ul", {
16755
+ children: [
16756
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
16757
+ children: 'Click the "Calibrate" tab to see all test bot runs.'
16758
+ }),
16759
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
16760
+ children: "Run graders to measure quality and identify issues."
16761
+ }),
16762
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
16763
+ children: "Flag grader results you want to keep track of."
16764
+ })
16765
+ ]
16766
+ }),
16767
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
16768
+ children: "Fix it"
16769
+ }),
16770
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("ul", {
16771
+ children: [
16772
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
16773
+ children: 'Click "Copy state path" to copy the state file location.'
16774
+ }),
16775
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
16776
+ children: "Share the state file with Codex, update the deck, then rerun."
16777
+ })
16778
+ ]
16770
16779
  })
16771
16780
  ]
16772
16781
  })
16773
16782
  ]
16774
16783
  }),
16775
16784
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
16776
- className: "deck-preview-shell",
16785
+ className: "docs-section docs-tabs",
16777
16786
  children: [
16778
16787
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
16788
+ className: "docs-section-header",
16789
+ children: [
16790
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
16791
+ className: "docs-icon",
16792
+ children: "\u{1F9ED}"
16793
+ }),
16794
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", {
16795
+ children: "When should I use each tab?"
16796
+ })
16797
+ ]
16798
+ }),
16799
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
16800
+ className: "docs-tab-card",
16779
16801
  children: [
16780
16802
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
16803
+ className: "docs-tab-row",
16781
16804
  children: [
16782
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
16783
- children: "Current deck"
16805
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
16806
+ className: "docs-tab-pill",
16807
+ href: DEFAULT_TEST_BOT_PATH,
16808
+ children: "Test Bot"
16784
16809
  }),
16785
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
16786
- children: "Edit this file in your editor. After changes, rerun or refresh the simulator."
16810
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
16811
+ children: [
16812
+ "Use this whenever you want to",
16813
+ " ",
16814
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", {
16815
+ children: "understand behavior"
16816
+ }),
16817
+ ". This is where almost everyone should start."
16818
+ ]
16787
16819
  })
16788
16820
  ]
16789
16821
  }),
16790
16822
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
16791
- className: "deck-preview-meta",
16823
+ className: "docs-tab-row",
16792
16824
  children: [
16793
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
16825
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
16826
+ className: "docs-tab-pill docs-tab-pill--gold",
16827
+ href: DEFAULT_CALIBRATE_PATH,
16828
+ children: "Calibrate"
16829
+ }),
16830
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
16794
16831
  children: [
16795
- "Path: ",
16796
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", {
16797
- children: deckDisplayPath2
16798
- })
16832
+ "Use this once you care about",
16833
+ " ",
16834
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", {
16835
+ children: "measuring quality"
16836
+ }),
16837
+ ", not just eyeballing it."
16799
16838
  ]
16800
- }),
16801
- " ",
16802
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
16803
- type: "button",
16804
- onClick: handleCopyPath,
16805
- children: copied ? "Copied" : "Copy path"
16806
16839
  })
16807
16840
  ]
16808
- })
16809
- ]
16810
- }),
16811
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
16812
- className: "deck-preview-body",
16813
- children: [
16814
- loading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
16815
- className: "placeholder",
16816
- children: "Loading deck\u2026"
16817
16841
  }),
16818
- !loading && error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
16819
- className: "error",
16842
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
16843
+ className: "docs-tab-row",
16820
16844
  children: [
16821
- "Failed to read deck: ",
16822
- error
16845
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", {
16846
+ className: "docs-tab-pill docs-tab-pill--indigo",
16847
+ href: DEFAULT_DEBUG_PATH,
16848
+ children: "Debug"
16849
+ }),
16850
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
16851
+ children: [
16852
+ "Use this when you need to understand",
16853
+ " ",
16854
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", {
16855
+ children: "why something failed"
16856
+ }),
16857
+ " at a deeper level."
16858
+ ]
16859
+ })
16823
16860
  ]
16824
- }),
16825
- !loading && !error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", {
16826
- className: "deck-preview",
16827
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", {
16828
- children: deckSource ?? ""
16829
- })
16830
16861
  })
16831
16862
  ]
16832
16863
  })
@@ -16915,7 +16946,208 @@ body {
16915
16946
  overflow: hidden;
16916
16947
  }
16917
16948
  .docs-shell {
16918
- padding: 12px 16px;
16949
+ padding: 32px 20px 64px;
16950
+ max-width: 1040px;
16951
+ margin: 0 auto;
16952
+ display: flex;
16953
+ flex-direction: column;
16954
+ gap: 28px;
16955
+ }
16956
+ .docs-eyebrow {
16957
+ text-transform: uppercase;
16958
+ letter-spacing: 0.16em;
16959
+ font-size: 11px;
16960
+ font-weight: 700;
16961
+ color: #64748b;
16962
+ margin: 0 0 10px 0;
16963
+ }
16964
+ .docs-subtitle {
16965
+ text-wrap: pretty;
16966
+ }
16967
+ .docs-hero h1 {
16968
+ margin: 0 0 12px 0;
16969
+ font-size: clamp(28px, 4vw, 40px);
16970
+ line-height: 1.2;
16971
+ color: #0f172a;
16972
+ }
16973
+ .docs-lede {
16974
+ margin: 0;
16975
+ font-size: 16px;
16976
+ max-width: 720px;
16977
+ color: #334155;
16978
+ }
16979
+ .docs-callout {
16980
+ background: white;
16981
+ border-radius: 18px;
16982
+ border: 1px solid #e2e8f0;
16983
+ padding: 20px;
16984
+ box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06);
16985
+ display: flex;
16986
+ flex-direction: column;
16987
+ gap: 16px;
16988
+ }
16989
+ .docs-callout-header {
16990
+ display: flex;
16991
+ gap: 14px;
16992
+ align-items: flex-start;
16993
+ }
16994
+ .docs-callout-header h2 {
16995
+ margin: 0 0 4px 0;
16996
+ font-size: 22px;
16997
+ }
16998
+ .docs-subtle {
16999
+ margin: 0;
17000
+ color: #475569;
17001
+ font-size: 14px;
17002
+ }
17003
+ .docs-primary-btn {
17004
+ border-radius: 12px;
17005
+ padding: 10px 18px;
17006
+ background: linear-gradient(135deg, #1d4ed8, #2563eb);
17007
+ color: white;
17008
+ font-weight: 600;
17009
+ text-decoration: none;
17010
+ display: inline-flex;
17011
+ align-items: center;
17012
+ justify-content: center;
17013
+ font-size: 14px;
17014
+ }
17015
+ .docs-primary-btn:hover {
17016
+ background: linear-gradient(135deg, #1e40af, #1d4ed8);
17017
+ }
17018
+ .docs-callout-body h3 {
17019
+ margin: 0 0 8px 0;
17020
+ font-size: 16px;
17021
+ }
17022
+ .docs-callout-body p {
17023
+ margin: 0 0 12px 0;
17024
+ color: #334155;
17025
+ }
17026
+ .docs-callout-body ul {
17027
+ margin: 0 0 12px 18px;
17028
+ color: #334155;
17029
+ padding: 0;
17030
+ }
17031
+ .docs-callout-body li {
17032
+ margin-bottom: 6px;
17033
+ }
17034
+ .docs-divider {
17035
+ height: 1px;
17036
+ background: #e2e8f0;
17037
+ margin: 8px 0 12px;
17038
+ }
17039
+ .docs-section {
17040
+ display: flex;
17041
+ flex-direction: column;
17042
+ gap: 12px;
17043
+ }
17044
+ .docs-section-header {
17045
+ display: flex;
17046
+ align-items: center;
17047
+ gap: 10px;
17048
+ }
17049
+ .docs-section-header h2 {
17050
+ margin: 0;
17051
+ font-size: 22px;
17052
+ }
17053
+ .docs-icon {
17054
+ display: inline-flex;
17055
+ align-items: center;
17056
+ justify-content: center;
17057
+ font-size: 28px;
17058
+ }
17059
+ .docs-loop {
17060
+ display: grid;
17061
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
17062
+ gap: 14px;
17063
+ }
17064
+ .docs-loop-step {
17065
+ border-radius: 16px;
17066
+ border: 1px solid #e2e8f0;
17067
+ background: #f8fafc;
17068
+ padding: 16px;
17069
+ display: flex;
17070
+ flex-direction: column;
17071
+ gap: 8px;
17072
+ }
17073
+ .docs-loop-step h3 {
17074
+ margin: 0;
17075
+ font-size: 16px;
17076
+ }
17077
+ .docs-loop-step p {
17078
+ margin: 0;
17079
+ color: #475569;
17080
+ font-size: 14px;
17081
+ }
17082
+ .docs-step-badge {
17083
+ align-self: flex-start;
17084
+ padding: 4px 10px;
17085
+ border-radius: 999px;
17086
+ background: #dbeafe;
17087
+ color: #1e40af;
17088
+ font-size: 12px;
17089
+ font-weight: 700;
17090
+ text-transform: uppercase;
17091
+ letter-spacing: 0.04em;
17092
+ }
17093
+ .docs-tabs .docs-tab-card {
17094
+ background: white;
17095
+ border-radius: 16px;
17096
+ border: 1px solid #e2e8f0;
17097
+ padding: 16px;
17098
+ display: flex;
17099
+ flex-direction: column;
17100
+ gap: 14px;
17101
+ }
17102
+ .docs-tab-row {
17103
+ display: grid;
17104
+ grid-template-columns: 120px 1fr;
17105
+ gap: 14px;
17106
+ align-items: center;
17107
+ }
17108
+ .docs-tab-row p {
17109
+ margin: 0;
17110
+ color: #334155;
17111
+ }
17112
+ .docs-tab-pill {
17113
+ display: inline-flex;
17114
+ align-items: center;
17115
+ justify-content: center;
17116
+ padding: 6px 12px;
17117
+ border-radius: 10px;
17118
+ background: #dbeafe;
17119
+ color: #1d4ed8;
17120
+ font-weight: 700;
17121
+ font-size: 12px;
17122
+ text-transform: uppercase;
17123
+ letter-spacing: 0.04em;
17124
+ text-decoration: none;
17125
+ border: none;
17126
+ cursor: pointer;
17127
+ }
17128
+ .docs-tab-pill--gold {
17129
+ background: #fef3c7;
17130
+ color: #92400e;
17131
+ }
17132
+ .docs-tab-pill--indigo {
17133
+ background: #e0e7ff;
17134
+ color: #3730a3;
17135
+ }
17136
+ .docs-links h3 {
17137
+ margin: 0 0 8px 0;
17138
+ }
17139
+ .docs-links ul {
17140
+ margin: 0;
17141
+ padding-left: 18px;
17142
+ }
17143
+ .docs-links li {
17144
+ margin-bottom: 6px;
17145
+ }
17146
+ @media (max-width: 720px) {
17147
+ .docs-tab-row {
17148
+ grid-template-columns: 1fr;
17149
+ align-items: flex-start;
17150
+ }
16919
17151
  }
16920
17152
  pre.deck-preview,
16921
17153
  pre.docs-command {
@@ -17180,6 +17412,12 @@ button.primary:disabled {
17180
17412
  border-top: none;
17181
17413
  padding-top: 0;
17182
17414
  }
17415
+ .calibrate-button-meta {
17416
+ font-size: 12px;
17417
+ text-wrap: pretty;
17418
+ margin: 0;
17419
+ margin-bottom: 0.5em;
17420
+ }
17183
17421
  .calibrate-drawer {
17184
17422
  background: #ffffff;
17185
17423
  border-radius: 16px;
@@ -17216,6 +17454,42 @@ button.primary:disabled {
17216
17454
  width: 100%;
17217
17455
  justify-content: center;
17218
17456
  }
17457
+ .calibrate-summary-list {
17458
+ display: flex;
17459
+ flex-direction: column;
17460
+ gap: 8px;
17461
+ }
17462
+ .calibrate-summary-card {
17463
+ border: 1px solid #e2e8f0;
17464
+ border-radius: 12px;
17465
+ padding: 8px;
17466
+ background: #f8fafc;
17467
+ display: flex;
17468
+ flex-direction: column;
17469
+ gap: 4px;
17470
+ }
17471
+ .calibrate-flag-card {
17472
+ border-color: #f59e0b;
17473
+ background: #fffbeb;
17474
+ }
17475
+ .calibrate-summary-title {
17476
+ font-size: 12px;
17477
+ font-weight: 700;
17478
+ color: #0f172a;
17479
+ }
17480
+ .ellipsis {
17481
+ text-overflow: ellipsis;
17482
+ white-space: nowrap;
17483
+ overflow: hidden;
17484
+ }
17485
+ .calibrate-summary-reason {
17486
+ font-size: 12px;
17487
+ color: #0f172a;
17488
+ }
17489
+ .calibrate-summary-meta {
17490
+ font-size: 11px;
17491
+ color: #64748b;
17492
+ }
17219
17493
  .chat-row {
17220
17494
  display: flex;
17221
17495
  justify-content: flex-start;
@@ -17628,6 +17902,17 @@ button.primary:disabled {
17628
17902
  padding: 4px 8px;
17629
17903
  font-size: 11px;
17630
17904
  }
17905
+ .calibrate-flag-btn {
17906
+ padding: 4px 8px;
17907
+ font-size: 11px;
17908
+ border-color: #f59e0b;
17909
+ color: #b45309;
17910
+ }
17911
+ .calibrate-flag-btn.active {
17912
+ background: #f59e0b;
17913
+ border-color: #f59e0b;
17914
+ color: #ffffff;
17915
+ }
17631
17916
  .trace-row-highlight {
17632
17917
  border-color: #0b93f6;
17633
17918
  box-shadow: 0 0 0 2px rgba(11, 147, 246, 0.15);
@@ -17651,6 +17936,26 @@ button.primary:disabled {
17651
17936
  flex-wrap: wrap;
17652
17937
  align-self: center;
17653
17938
  }
17939
+ .calibrate-flag-reason {
17940
+ margin-top: 8px;
17941
+ }
17942
+ .calibrate-flag-reason label {
17943
+ display: flex;
17944
+ flex-direction: column;
17945
+ gap: 4px;
17946
+ font-size: 12px;
17947
+ font-weight: 600;
17948
+ color: #475569;
17949
+ }
17950
+ .calibrate-flag-reason textarea {
17951
+ border: 1px solid #cbd5e1;
17952
+ border-radius: 10px;
17953
+ padding: 6px 8px;
17954
+ font-family: inherit;
17955
+ font-size: 12px;
17956
+ min-height: 70px;
17957
+ resize: vertical;
17958
+ }
17654
17959
  .trace-row-user {
17655
17960
  background: #0b93f6;
17656
17961
  border-color: #0b93f6;
@@ -18336,6 +18641,24 @@ function extractScoreAndReasonFromSample(sample) {
18336
18641
  reason: typeof sample.reason === "string" ? sample.reason : void 0
18337
18642
  };
18338
18643
  }
18644
+ function extractGradingFlags(meta) {
18645
+ if (!meta) return [];
18646
+ const flags = meta.gradingFlags;
18647
+ if (!Array.isArray(flags)) return [];
18648
+ return flags.filter((flag) => Boolean(flag && typeof flag === "object" && "refId" in flag));
18649
+ }
18650
+ function formatSnippet(value, maxLength = 140) {
18651
+ if (value === null || value === void 0) return "";
18652
+ const text = typeof value === "string" ? value : (() => {
18653
+ try {
18654
+ return JSON.stringify(value);
18655
+ } catch {
18656
+ return String(value);
18657
+ }
18658
+ })();
18659
+ if (text.length <= maxLength) return text;
18660
+ return `${text.slice(0, maxLength - 1)}\u2026`;
18661
+ }
18339
18662
  function getScoreClass(displayScore) {
18340
18663
  if (displayScore === void 0) return "calibrate-score--empty";
18341
18664
  if (displayScore > 0) return "calibrate-score--positive";
@@ -18427,7 +18750,7 @@ var deckDisplayPath = toRelativePath(normalizedDeckPath, repoRootPath) ?? normal
18427
18750
  var SESSIONS_BASE_PATH = "/sessions";
18428
18751
  var DOCS_PATH = "/docs";
18429
18752
  var DEFAULT_SESSION_PATH = `${SESSIONS_BASE_PATH}/new/debug`;
18430
- var DEFAULT_TEST_BOT_PATH = `${SESSIONS_BASE_PATH}/new/test-bot`;
18753
+ var DEFAULT_TEST_BOT_PATH2 = `${SESSIONS_BASE_PATH}/new/test-bot`;
18431
18754
  var CALIBRATE_PATH_SUFFIX = "/calibrate";
18432
18755
  var buildCalibratePath = (sessionId) => `${SESSIONS_BASE_PATH}/${encodeURIComponent(sessionId)}${CALIBRATE_PATH_SUFFIX}`;
18433
18756
  var DURABLE_STREAM_PREFIX = "/api/durable-streams/stream/";
@@ -18460,14 +18783,14 @@ var globalStyleEl = document.createElement("style");
18460
18783
  globalStyleEl.textContent = globalStyles;
18461
18784
  document.head.appendChild(globalStyleEl);
18462
18785
  function useSimulator() {
18463
- const [connectionStatus, setConnectionStatus] = (0, import_react2.useState)("connecting");
18464
- const [savedState, setSavedState] = (0, import_react2.useState)(null);
18465
- const [traceEvents, setTraceEvents] = (0, import_react2.useState)([]);
18466
- const [errors, setErrors] = (0, import_react2.useState)([]);
18467
- const [streamText, setStreamText] = (0, import_react2.useState)("");
18468
- const [isRunning, setIsRunning] = (0, import_react2.useState)(false);
18469
- const [connectSeq, setConnectSeq] = (0, import_react2.useState)(0);
18470
- (0, import_react2.useEffect)(() => {
18786
+ const [connectionStatus, setConnectionStatus] = (0, import_react.useState)("connecting");
18787
+ const [savedState, setSavedState] = (0, import_react.useState)(null);
18788
+ const [traceEvents, setTraceEvents] = (0, import_react.useState)([]);
18789
+ const [errors, setErrors] = (0, import_react.useState)([]);
18790
+ const [streamText, setStreamText] = (0, import_react.useState)("");
18791
+ const [isRunning, setIsRunning] = (0, import_react.useState)(false);
18792
+ const [connectSeq, setConnectSeq] = (0, import_react.useState)(0);
18793
+ (0, import_react.useEffect)(() => {
18471
18794
  const streamId = SIMULATOR_STREAM_ID;
18472
18795
  const streamUrl = buildDurableStreamUrl(streamId, getDurableStreamOffset(streamId));
18473
18796
  const source = new EventSource(streamUrl);
@@ -18536,7 +18859,7 @@ function useSimulator() {
18536
18859
  }, [
18537
18860
  connectSeq
18538
18861
  ]);
18539
- const run = (0, import_react2.useCallback)(async (opts) => {
18862
+ const run = (0, import_react.useCallback)(async (opts) => {
18540
18863
  setIsRunning(true);
18541
18864
  setStreamText("");
18542
18865
  const sessionId = opts.resetState ? void 0 : savedState?.meta?.sessionId;
@@ -18571,7 +18894,7 @@ function useSimulator() {
18571
18894
  }, [
18572
18895
  savedState?.meta?.sessionId
18573
18896
  ]);
18574
- const sendFeedback = (0, import_react2.useCallback)(async (messageRefId, score, reason) => {
18897
+ const sendFeedback = (0, import_react.useCallback)(async (messageRefId, score, reason) => {
18575
18898
  const sessionId = savedState?.meta?.sessionId;
18576
18899
  if (!sessionId) return;
18577
18900
  try {
@@ -18598,7 +18921,7 @@ function useSimulator() {
18598
18921
  }, [
18599
18922
  savedState?.meta?.sessionId
18600
18923
  ]);
18601
- const loadSession = (0, import_react2.useCallback)(async (sessionId) => {
18924
+ const loadSession = (0, import_react.useCallback)(async (sessionId) => {
18602
18925
  try {
18603
18926
  const res = await fetch("/api/simulator/load-session", {
18604
18927
  method: "POST",
@@ -18627,7 +18950,7 @@ function useSimulator() {
18627
18950
  ]);
18628
18951
  }
18629
18952
  }, []);
18630
- const saveNotes = (0, import_react2.useCallback)(async (text) => {
18953
+ const saveNotes = (0, import_react.useCallback)(async (text) => {
18631
18954
  const sessionId = savedState?.meta?.sessionId;
18632
18955
  if (!sessionId) return;
18633
18956
  try {
@@ -18652,7 +18975,7 @@ function useSimulator() {
18652
18975
  }, [
18653
18976
  savedState?.meta?.sessionId
18654
18977
  ]);
18655
- const saveSessionScore = (0, import_react2.useCallback)(async (score) => {
18978
+ const saveSessionScore = (0, import_react.useCallback)(async (score) => {
18656
18979
  const sessionId = savedState?.meta?.sessionId;
18657
18980
  if (!sessionId) return;
18658
18981
  try {
@@ -18677,10 +19000,10 @@ function useSimulator() {
18677
19000
  }, [
18678
19001
  savedState?.meta?.sessionId
18679
19002
  ]);
18680
- const reconnect = (0, import_react2.useCallback)(() => {
19003
+ const reconnect = (0, import_react.useCallback)(() => {
18681
19004
  setConnectSeq((prev) => prev + 1);
18682
19005
  }, []);
18683
- const resetLocal = (0, import_react2.useCallback)(() => {
19006
+ const resetLocal = (0, import_react.useCallback)(() => {
18684
19007
  setSavedState(null);
18685
19008
  setTraceEvents([]);
18686
19009
  setErrors([]);
@@ -18703,10 +19026,10 @@ function useSimulator() {
18703
19026
  };
18704
19027
  }
18705
19028
  function useSessions() {
18706
- const [sessions, setSessions] = (0, import_react2.useState)([]);
18707
- const [loading, setLoading] = (0, import_react2.useState)(false);
18708
- const [error, setError] = (0, import_react2.useState)(null);
18709
- const refresh = (0, import_react2.useCallback)(async () => {
19029
+ const [sessions, setSessions] = (0, import_react.useState)([]);
19030
+ const [loading, setLoading] = (0, import_react.useState)(false);
19031
+ const [error, setError] = (0, import_react.useState)(null);
19032
+ const refresh = (0, import_react.useCallback)(async () => {
18710
19033
  setLoading(true);
18711
19034
  setError(null);
18712
19035
  try {
@@ -18720,7 +19043,7 @@ function useSessions() {
18720
19043
  setLoading(false);
18721
19044
  }
18722
19045
  }, []);
18723
- const deleteSession = (0, import_react2.useCallback)(async (sessionId) => {
19046
+ const deleteSession = (0, import_react.useCallback)(async (sessionId) => {
18724
19047
  setLoading(true);
18725
19048
  setError(null);
18726
19049
  try {
@@ -18853,9 +19176,9 @@ function parseGradingRef(ref) {
18853
19176
  }
18854
19177
  function CopyBadge(props) {
18855
19178
  const { label, displayValue, copyValue, className } = props;
18856
- const [copied, setCopied] = (0, import_react2.useState)(false);
18857
- const timeoutRef = (0, import_react2.useRef)(void 0);
18858
- (0, import_react2.useEffect)(() => {
19179
+ const [copied, setCopied] = (0, import_react.useState)(false);
19180
+ const timeoutRef = (0, import_react.useRef)(void 0);
19181
+ (0, import_react.useEffect)(() => {
18859
19182
  return () => {
18860
19183
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
18861
19184
  };
@@ -18863,7 +19186,7 @@ function CopyBadge(props) {
18863
19186
  const copyTarget = copyValue ?? displayValue;
18864
19187
  if (!copyTarget) return null;
18865
19188
  const text = displayValue ?? copyTarget;
18866
- const handleCopy = (0, import_react2.useCallback)(async () => {
19189
+ const handleCopy = (0, import_react.useCallback)(async () => {
18867
19190
  try {
18868
19191
  if (navigator.clipboard?.writeText) {
18869
19192
  await navigator.clipboard.writeText(copyTarget);
@@ -19048,8 +19371,8 @@ function extractInitFromTraces(traces) {
19048
19371
  }
19049
19372
  function ConversationView(props) {
19050
19373
  const { messages, header, onScore, onReasonChange, emptyState } = props;
19051
- const containerRef = (0, import_react2.useRef)(null);
19052
- (0, import_react2.useEffect)(() => {
19374
+ const containerRef = (0, import_react.useRef)(null);
19375
+ (0, import_react.useEffect)(() => {
19053
19376
  const el = containerRef.current;
19054
19377
  if (!el) return;
19055
19378
  const frame = requestAnimationFrame(() => {
@@ -19124,12 +19447,12 @@ function renderMarkdown(text) {
19124
19447
  }
19125
19448
  function FeedbackControls(props) {
19126
19449
  const { messageRefId, feedback, onScore, onReasonChange } = props;
19127
- const [reason, setReason] = (0, import_react2.useState)(feedback?.reason ?? "");
19128
- const [opened, setOpened] = (0, import_react2.useState)(false);
19129
- const [localScore, setLocalScore] = (0, import_react2.useState)(null);
19130
- const [status, setStatus] = (0, import_react2.useState)("idle");
19131
- const lastSentRef = (0, import_react2.useRef)(null);
19132
- (0, import_react2.useEffect)(() => {
19450
+ const [reason, setReason] = (0, import_react.useState)(feedback?.reason ?? "");
19451
+ const [opened, setOpened] = (0, import_react.useState)(false);
19452
+ const [localScore, setLocalScore] = (0, import_react.useState)(null);
19453
+ const [status, setStatus] = (0, import_react.useState)("idle");
19454
+ const lastSentRef = (0, import_react.useRef)(null);
19455
+ (0, import_react.useEffect)(() => {
19133
19456
  setReason(feedback?.reason ?? "");
19134
19457
  if (feedback?.reason !== void 0) {
19135
19458
  setStatus("saved");
@@ -19139,7 +19462,7 @@ function FeedbackControls(props) {
19139
19462
  }, [
19140
19463
  feedback?.reason
19141
19464
  ]);
19142
- (0, import_react2.useEffect)(() => {
19465
+ (0, import_react.useEffect)(() => {
19143
19466
  if (typeof feedback?.score === "number") {
19144
19467
  setLocalScore(feedback.score);
19145
19468
  setOpened(true);
@@ -19148,7 +19471,7 @@ function FeedbackControls(props) {
19148
19471
  feedback?.score
19149
19472
  ]);
19150
19473
  const effectiveScore = typeof feedback?.score === "number" ? feedback.score : localScore;
19151
- (0, import_react2.useEffect)(() => {
19474
+ (0, import_react.useEffect)(() => {
19152
19475
  if (typeof effectiveScore !== "number") return;
19153
19476
  if (status !== "unsaved") return;
19154
19477
  const handle = window.setTimeout(() => {
@@ -19164,7 +19487,7 @@ function FeedbackControls(props) {
19164
19487
  onReasonChange,
19165
19488
  messageRefId
19166
19489
  ]);
19167
- (0, import_react2.useEffect)(() => {
19490
+ (0, import_react.useEffect)(() => {
19168
19491
  if (status !== "saving") return;
19169
19492
  if (feedback?.reason === reason && lastSentRef.current === reason) {
19170
19493
  setStatus("saved");
@@ -19225,8 +19548,8 @@ function FeedbackControls(props) {
19225
19548
  function TraceList(props) {
19226
19549
  const { traces } = props;
19227
19550
  const ordered = traces;
19228
- const panelRef = (0, import_react2.useRef)(null);
19229
- const entries = (0, import_react2.useMemo)(() => {
19551
+ const panelRef = (0, import_react.useRef)(null);
19552
+ const entries = (0, import_react.useMemo)(() => {
19230
19553
  const depthMap = /* @__PURE__ */ new Map();
19231
19554
  return ordered.map((trace) => {
19232
19555
  let depth = 0;
@@ -19253,7 +19576,7 @@ function TraceList(props) {
19253
19576
  }, [
19254
19577
  ordered
19255
19578
  ]);
19256
- (0, import_react2.useEffect)(() => {
19579
+ (0, import_react.useEffect)(() => {
19257
19580
  const el = panelRef.current;
19258
19581
  if (!el) return;
19259
19582
  const frame = requestAnimationFrame(() => {
@@ -19411,7 +19734,7 @@ function ToolCallField(props) {
19411
19734
  }
19412
19735
  function ToolCallBubble(props) {
19413
19736
  const { call } = props;
19414
- const [open, setOpen] = (0, import_react2.useState)(false);
19737
+ const [open, setOpen] = (0, import_react.useState)(false);
19415
19738
  const statusLabel = call.status === "completed" ? "Completed" : call.status === "error" ? "Error" : call.status === "running" ? "Running" : "Pending";
19416
19739
  const indentStyle = call.depth && call.depth > 0 ? {
19417
19740
  marginLeft: call.depth * 12
@@ -19621,10 +19944,10 @@ function RecentSessionsEmptyState(props) {
19621
19944
  });
19622
19945
  }
19623
19946
  function useHttpSchema() {
19624
- const [schemaResponse, setSchemaResponse] = (0, import_react2.useState)(null);
19625
- const [loading, setLoading] = (0, import_react2.useState)(false);
19626
- const [error, setError] = (0, import_react2.useState)(null);
19627
- const refresh = (0, import_react2.useCallback)(async () => {
19947
+ const [schemaResponse, setSchemaResponse] = (0, import_react.useState)(null);
19948
+ const [loading, setLoading] = (0, import_react.useState)(false);
19949
+ const [error, setError] = (0, import_react.useState)(null);
19950
+ const refresh = (0, import_react.useCallback)(async () => {
19628
19951
  setLoading(true);
19629
19952
  setError(null);
19630
19953
  try {
@@ -19638,7 +19961,7 @@ function useHttpSchema() {
19638
19961
  setLoading(false);
19639
19962
  }
19640
19963
  }, []);
19641
- (0, import_react2.useEffect)(() => {
19964
+ (0, import_react.useEffect)(() => {
19642
19965
  refresh();
19643
19966
  }, [
19644
19967
  refresh
@@ -19652,9 +19975,9 @@ function useHttpSchema() {
19652
19975
  }
19653
19976
  function JsonInputField(props) {
19654
19977
  const { value, optional, placeholder, onChange, onErrorChange } = props;
19655
- const onChangeRef = (0, import_react2.useRef)(onChange);
19656
- const onErrorChangeRef = (0, import_react2.useRef)(onErrorChange);
19657
- const [text, setText] = (0, import_react2.useState)(() => {
19978
+ const onChangeRef = (0, import_react.useRef)(onChange);
19979
+ const onErrorChangeRef = (0, import_react.useRef)(onErrorChange);
19980
+ const [text, setText] = (0, import_react.useState)(() => {
19658
19981
  if (value === void 0) return "";
19659
19982
  try {
19660
19983
  return JSON.stringify(value, null, 2);
@@ -19662,16 +19985,16 @@ function JsonInputField(props) {
19662
19985
  return String(value);
19663
19986
  }
19664
19987
  });
19665
- const [dirty, setDirty] = (0, import_react2.useState)(false);
19666
- const [error, setError] = (0, import_react2.useState)(null);
19667
- (0, import_react2.useEffect)(() => {
19988
+ const [dirty, setDirty] = (0, import_react.useState)(false);
19989
+ const [error, setError] = (0, import_react.useState)(null);
19990
+ (0, import_react.useEffect)(() => {
19668
19991
  onChangeRef.current = onChange;
19669
19992
  onErrorChangeRef.current = onErrorChange;
19670
19993
  }, [
19671
19994
  onChange,
19672
19995
  onErrorChange
19673
19996
  ]);
19674
- (0, import_react2.useEffect)(() => {
19997
+ (0, import_react.useEffect)(() => {
19675
19998
  if (dirty) return;
19676
19999
  if (value === void 0) {
19677
20000
  setText("");
@@ -19686,12 +20009,12 @@ function JsonInputField(props) {
19686
20009
  value,
19687
20010
  dirty
19688
20011
  ]);
19689
- (0, import_react2.useEffect)(() => {
20012
+ (0, import_react.useEffect)(() => {
19690
20013
  onErrorChangeRef.current?.(error);
19691
20014
  }, [
19692
20015
  error
19693
20016
  ]);
19694
- (0, import_react2.useEffect)(() => {
20017
+ (0, import_react.useEffect)(() => {
19695
20018
  if (!dirty) return;
19696
20019
  const handle = window.setTimeout(() => {
19697
20020
  const trimmed = text.trim();
@@ -19737,7 +20060,7 @@ function JsonInputField(props) {
19737
20060
  }
19738
20061
  function InitForm(props) {
19739
20062
  const { schema, value, onChange, onJsonErrorChange } = props;
19740
- const leaves = (0, import_react2.useMemo)(() => flattenSchemaLeaves(schema), [
20063
+ const leaves = (0, import_react.useMemo)(() => flattenSchemaLeaves(schema), [
19741
20064
  schema
19742
20065
  ]);
19743
20066
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
@@ -19971,41 +20294,41 @@ function SimulatorApp({ basePath }) {
19971
20294
  const sessionBasePath = rootPath === "/" ? SESSIONS_BASE_PATH : rootPath;
19972
20295
  const normalizedSessionBase = normalizeBasePath(sessionBasePath);
19973
20296
  const newSessionPath = `${normalizedSessionBase === "" ? "/sessions" : normalizedSessionBase}/new`.replace(/\/{2,}/g, "/");
19974
- const buildSessionUrl = (0, import_react2.useCallback)((sessionId2) => `${normalizedSessionBase === "" ? "/sessions" : normalizedSessionBase}/${encodeURIComponent(sessionId2)}/debug`.replace(/\/{2,}/g, "/"), [
20297
+ const buildSessionUrl = (0, import_react.useCallback)((sessionId2) => `${normalizedSessionBase === "" ? "/sessions" : normalizedSessionBase}/${encodeURIComponent(sessionId2)}/debug`.replace(/\/{2,}/g, "/"), [
19975
20298
  normalizedSessionBase
19976
20299
  ]);
19977
- const [sessionsOpen, setSessionsOpen] = (0, import_react2.useState)(false);
19978
- const [message, setMessage] = (0, import_react2.useState)("");
19979
- const [pendingReset, setPendingReset] = (0, import_react2.useState)(false);
19980
- const [initValue, setInitValue] = (0, import_react2.useState)(void 0);
19981
- const [initDirty, setInitDirty] = (0, import_react2.useState)(false);
19982
- const [initMode, setInitMode] = (0, import_react2.useState)("form");
19983
- const [initJsonText, setInitJsonText] = (0, import_react2.useState)("");
19984
- const [initJsonError, setInitJsonError] = (0, import_react2.useState)(null);
19985
- const [initOpen, setInitOpen] = (0, import_react2.useState)(false);
19986
- const [jsonErrors, setJsonErrors] = (0, import_react2.useState)({});
19987
- const [pendingSessionId, setPendingSessionId] = (0, import_react2.useState)(null);
19988
- const appliedSessionIdRef = (0, import_react2.useRef)(null);
19989
- const initializedRef = (0, import_react2.useRef)(false);
19990
- const currentDeckSlug = (0, import_react2.useMemo)(() => toDeckSlug(deckPath), []);
19991
- const [noteDraft, setNoteDraft] = (0, import_react2.useState)("");
19992
- const [noteStatus, setNoteStatus] = (0, import_react2.useState)("idle");
19993
- const pendingNoteRef = (0, import_react2.useRef)(null);
19994
- const [scoreStatus, setScoreStatus] = (0, import_react2.useState)("idle");
19995
- const pendingScoreRef = (0, import_react2.useRef)(null);
19996
- (0, import_react2.useEffect)(() => {
20300
+ const [sessionsOpen, setSessionsOpen] = (0, import_react.useState)(false);
20301
+ const [message, setMessage] = (0, import_react.useState)("");
20302
+ const [pendingReset, setPendingReset] = (0, import_react.useState)(false);
20303
+ const [initValue, setInitValue] = (0, import_react.useState)(void 0);
20304
+ const [initDirty, setInitDirty] = (0, import_react.useState)(false);
20305
+ const [initMode, setInitMode] = (0, import_react.useState)("form");
20306
+ const [initJsonText, setInitJsonText] = (0, import_react.useState)("");
20307
+ const [initJsonError, setInitJsonError] = (0, import_react.useState)(null);
20308
+ const [initOpen, setInitOpen] = (0, import_react.useState)(false);
20309
+ const [jsonErrors, setJsonErrors] = (0, import_react.useState)({});
20310
+ const [pendingSessionId, setPendingSessionId] = (0, import_react.useState)(null);
20311
+ const appliedSessionIdRef = (0, import_react.useRef)(null);
20312
+ const initializedRef = (0, import_react.useRef)(false);
20313
+ const currentDeckSlug = (0, import_react.useMemo)(() => toDeckSlug(deckPath), []);
20314
+ const [noteDraft, setNoteDraft] = (0, import_react.useState)("");
20315
+ const [noteStatus, setNoteStatus] = (0, import_react.useState)("idle");
20316
+ const pendingNoteRef = (0, import_react.useRef)(null);
20317
+ const [scoreStatus, setScoreStatus] = (0, import_react.useState)("idle");
20318
+ const pendingScoreRef = (0, import_react.useRef)(null);
20319
+ (0, import_react.useEffect)(() => {
19997
20320
  if (simulator.connectionStatus === "connecting") {
19998
20321
  appliedSessionIdRef.current = null;
19999
20322
  }
20000
20323
  }, [
20001
20324
  simulator.connectionStatus
20002
20325
  ]);
20003
- (0, import_react2.useEffect)(() => {
20326
+ (0, import_react.useEffect)(() => {
20004
20327
  refresh();
20005
20328
  }, [
20006
20329
  refresh
20007
20330
  ]);
20008
- (0, import_react2.useEffect)(() => {
20331
+ (0, import_react.useEffect)(() => {
20009
20332
  if (sessionsOpen) refresh();
20010
20333
  }, [
20011
20334
  sessionsOpen,
@@ -20016,7 +20339,7 @@ function SimulatorApp({ basePath }) {
20016
20339
  const schemaError = httpSchema.schemaResponse?.error ?? httpSchema.error ?? void 0;
20017
20340
  const conversationStarted = Boolean(simulator.savedState && simulator.savedState.messages.length > 0);
20018
20341
  const initEditable = Boolean(schema) && (!conversationStarted || pendingReset);
20019
- const lockedInitValue = (0, import_react2.useMemo)(() => {
20342
+ const lockedInitValue = (0, import_react.useMemo)(() => {
20020
20343
  const fromTraces = extractInitFromTraces(simulator.savedState?.traces);
20021
20344
  if (fromTraces !== void 0) return fromTraces;
20022
20345
  return schemaDefaults ?? deriveInitialFromSchema(schema);
@@ -20025,7 +20348,7 @@ function SimulatorApp({ basePath }) {
20025
20348
  schemaDefaults,
20026
20349
  schema
20027
20350
  ]);
20028
- (0, import_react2.useEffect)(() => {
20351
+ (0, import_react.useEffect)(() => {
20029
20352
  if (!schema) return;
20030
20353
  if (initDirty) return;
20031
20354
  if (schemaDefaults !== void 0) {
@@ -20038,7 +20361,7 @@ function SimulatorApp({ basePath }) {
20038
20361
  schemaDefaults,
20039
20362
  initDirty
20040
20363
  ]);
20041
- (0, import_react2.useEffect)(() => {
20364
+ (0, import_react.useEffect)(() => {
20042
20365
  if (initMode !== "json") return;
20043
20366
  if (initDirty) return;
20044
20367
  try {
@@ -20051,14 +20374,14 @@ function SimulatorApp({ basePath }) {
20051
20374
  initValue,
20052
20375
  initDirty
20053
20376
  ]);
20054
- (0, import_react2.useEffect)(() => {
20377
+ (0, import_react.useEffect)(() => {
20055
20378
  if (initEditable) {
20056
20379
  setInitOpen(true);
20057
20380
  }
20058
20381
  }, [
20059
20382
  initEditable
20060
20383
  ]);
20061
- const messages = (0, import_react2.useMemo)(() => {
20384
+ const messages = (0, import_react.useMemo)(() => {
20062
20385
  if (!simulator.savedState) return [];
20063
20386
  const feedbackByRef = new Map(simulator.savedState.feedback?.map((f) => [
20064
20387
  f.messageRefId,
@@ -20075,7 +20398,7 @@ function SimulatorApp({ basePath }) {
20075
20398
  }, [
20076
20399
  simulator.savedState
20077
20400
  ]);
20078
- const missingRequired = (0, import_react2.useMemo)(() => {
20401
+ const missingRequired = (0, import_react.useMemo)(() => {
20079
20402
  if (!schema || !initEditable) return [];
20080
20403
  return findMissingRequiredFields(schema, initValue);
20081
20404
  }, [
@@ -20083,13 +20406,13 @@ function SimulatorApp({ basePath }) {
20083
20406
  initEditable,
20084
20407
  initValue
20085
20408
  ]);
20086
- const jsonErrorCount = (0, import_react2.useMemo)(() => {
20409
+ const jsonErrorCount = (0, import_react.useMemo)(() => {
20087
20410
  return Object.values(jsonErrors).filter((v) => typeof v === "string" && v).length;
20088
20411
  }, [
20089
20412
  jsonErrors
20090
20413
  ]);
20091
20414
  const canStartWithInit = Boolean(schema) && initEditable && missingRequired.length === 0 && jsonErrorCount === 0;
20092
- const resetInitValue = (0, import_react2.useCallback)(() => {
20415
+ const resetInitValue = (0, import_react.useCallback)(() => {
20093
20416
  setInitJsonError(null);
20094
20417
  setJsonErrors((prev) => ({
20095
20418
  ...prev,
@@ -20107,7 +20430,7 @@ function SimulatorApp({ basePath }) {
20107
20430
  schema,
20108
20431
  schemaDefaults
20109
20432
  ]);
20110
- const startNewChat = (0, import_react2.useCallback)((opts) => {
20433
+ const startNewChat = (0, import_react.useCallback)((opts) => {
20111
20434
  const shouldPush = opts?.pushHistory ?? true;
20112
20435
  if (shouldPush) {
20113
20436
  if (opts?.replace) {
@@ -20137,14 +20460,14 @@ function SimulatorApp({ basePath }) {
20137
20460
  resetInitValue,
20138
20461
  newSessionPath
20139
20462
  ]);
20140
- const adoptSessionFromPath = (0, import_react2.useCallback)((sessionId2) => {
20463
+ const adoptSessionFromPath = (0, import_react.useCallback)((sessionId2) => {
20141
20464
  appliedSessionIdRef.current = null;
20142
20465
  setPendingSessionId(sessionId2);
20143
20466
  setPendingReset(false);
20144
20467
  setInitOpen(false);
20145
20468
  setInitDirty(true);
20146
20469
  }, []);
20147
- const navigateToSession = (0, import_react2.useCallback)((sessionId2, opts) => {
20470
+ const navigateToSession = (0, import_react.useCallback)((sessionId2, opts) => {
20148
20471
  const url = buildSessionUrl(sessionId2);
20149
20472
  if (opts?.replace) {
20150
20473
  window.history.replaceState({}, "", url);
@@ -20156,7 +20479,7 @@ function SimulatorApp({ basePath }) {
20156
20479
  adoptSessionFromPath,
20157
20480
  buildSessionUrl
20158
20481
  ]);
20159
- (0, import_react2.useEffect)(() => {
20482
+ (0, import_react.useEffect)(() => {
20160
20483
  if (initializedRef.current) return;
20161
20484
  initializedRef.current = true;
20162
20485
  const initialSession = getSessionIdFromPath(void 0, sessionBasePath) ?? getSessionIdFromPath();
@@ -20174,7 +20497,7 @@ function SimulatorApp({ basePath }) {
20174
20497
  startNewChat,
20175
20498
  sessionBasePath
20176
20499
  ]);
20177
- (0, import_react2.useEffect)(() => {
20500
+ (0, import_react.useEffect)(() => {
20178
20501
  const handler = () => {
20179
20502
  const sessionFromPath = getSessionIdFromPath(void 0, sessionBasePath) ?? getSessionIdFromPath();
20180
20503
  if (sessionFromPath) {
@@ -20192,7 +20515,7 @@ function SimulatorApp({ basePath }) {
20192
20515
  startNewChat,
20193
20516
  sessionBasePath
20194
20517
  ]);
20195
- (0, import_react2.useEffect)(() => {
20518
+ (0, import_react.useEffect)(() => {
20196
20519
  if (!pendingSessionId) return;
20197
20520
  if (simulator.connectionStatus !== "connected") return;
20198
20521
  if (appliedSessionIdRef.current === pendingSessionId) return;
@@ -20207,7 +20530,7 @@ function SimulatorApp({ basePath }) {
20207
20530
  const serverNotesUpdatedAt = simulator.savedState?.notes?.updatedAt;
20208
20531
  const serverScore = simulator.savedState?.conversationScore?.score ?? null;
20209
20532
  const serverScoreUpdatedAt = simulator.savedState?.conversationScore?.updatedAt;
20210
- (0, import_react2.useEffect)(() => {
20533
+ (0, import_react.useEffect)(() => {
20211
20534
  if (pendingNoteRef.current !== null) {
20212
20535
  if (serverNotesText === pendingNoteRef.current) {
20213
20536
  pendingNoteRef.current = null;
@@ -20220,7 +20543,7 @@ function SimulatorApp({ basePath }) {
20220
20543
  }, [
20221
20544
  serverNotesText
20222
20545
  ]);
20223
- (0, import_react2.useEffect)(() => {
20546
+ (0, import_react.useEffect)(() => {
20224
20547
  if (noteStatus !== "dirty") return;
20225
20548
  const handle = window.setTimeout(() => {
20226
20549
  setNoteStatus("saving");
@@ -20233,7 +20556,7 @@ function SimulatorApp({ basePath }) {
20233
20556
  noteDraft,
20234
20557
  simulator
20235
20558
  ]);
20236
- (0, import_react2.useEffect)(() => {
20559
+ (0, import_react.useEffect)(() => {
20237
20560
  if (pendingScoreRef.current !== null) {
20238
20561
  if (serverScore === pendingScoreRef.current) {
20239
20562
  pendingScoreRef.current = null;
@@ -20249,7 +20572,7 @@ function SimulatorApp({ basePath }) {
20249
20572
  }, [
20250
20573
  serverScore
20251
20574
  ]);
20252
- const handleSend = (0, import_react2.useCallback)(() => {
20575
+ const handleSend = (0, import_react.useCallback)(() => {
20253
20576
  const trimmed = message.trim();
20254
20577
  if (schema && initEditable) {
20255
20578
  if (!canStartWithInit) return;
@@ -20289,12 +20612,12 @@ function SimulatorApp({ basePath }) {
20289
20612
  canStartWithInit,
20290
20613
  initValue
20291
20614
  ]);
20292
- const handleScore = (0, import_react2.useCallback)((refId, score) => {
20615
+ const handleScore = (0, import_react.useCallback)((refId, score) => {
20293
20616
  simulator.sendFeedback(refId, score);
20294
20617
  }, [
20295
20618
  simulator
20296
20619
  ]);
20297
- const handleReason = (0, import_react2.useCallback)((refId, score, reason) => {
20620
+ const handleReason = (0, import_react.useCallback)((refId, score, reason) => {
20298
20621
  simulator.sendFeedback(refId, score, reason);
20299
20622
  }, [
20300
20623
  simulator
@@ -20304,7 +20627,7 @@ function SimulatorApp({ basePath }) {
20304
20627
  const sessionPermalink = sessionId ? buildSessionUrl(sessionId) : null;
20305
20628
  const sessionStatePath = typeof runMeta.sessionStatePath === "string" ? runMeta.sessionStatePath : typeof runMeta.sessionDir === "string" ? `${runMeta.sessionDir}/state.json` : void 0;
20306
20629
  const currentSessionScore = pendingScoreRef.current !== null ? pendingScoreRef.current : serverScore;
20307
- const deckSessions = (0, import_react2.useMemo)(() => {
20630
+ const deckSessions = (0, import_react.useMemo)(() => {
20308
20631
  return sessions.filter((session) => {
20309
20632
  if (!session) return false;
20310
20633
  if (session.deckSlug) return session.deckSlug === currentDeckSlug;
@@ -20587,19 +20910,23 @@ function SimulatorApp({ basePath }) {
20587
20910
  });
20588
20911
  }
20589
20912
  function CalibrateApp() {
20590
- const [loading, setLoading] = (0, import_react2.useState)(true);
20591
- const [error, setError] = (0, import_react2.useState)(null);
20592
- const [graders, setGraders] = (0, import_react2.useState)([]);
20593
- const [sessions, setSessions] = (0, import_react2.useState)([]);
20594
- const [selectedSessionId, setSelectedSessionId] = (0, import_react2.useState)(null);
20595
- const [selectedGraderId, setSelectedGraderId] = (0, import_react2.useState)(null);
20596
- const [running, setRunning] = (0, import_react2.useState)(false);
20597
- const initialCalibrateSessionRef = (0, import_react2.useRef)(getCalibrateSessionIdFromLocation());
20598
- const initialCalibrateRef = (0, import_react2.useRef)((() => {
20913
+ const [loading, setLoading] = (0, import_react.useState)(true);
20914
+ const [error, setError] = (0, import_react.useState)(null);
20915
+ const [graders, setGraders] = (0, import_react.useState)([]);
20916
+ const [sessions, setSessions] = (0, import_react.useState)([]);
20917
+ const [selectedSessionId, setSelectedSessionId] = (0, import_react.useState)(null);
20918
+ const [selectedGraderId, setSelectedGraderId] = (0, import_react.useState)(null);
20919
+ const [running, setRunning] = (0, import_react.useState)(false);
20920
+ const [sessionDetail, setSessionDetail] = (0, import_react.useState)(null);
20921
+ const [sessionDetailError, setSessionDetailError] = (0, import_react.useState)(null);
20922
+ const [sessionDetailLoading, setSessionDetailLoading] = (0, import_react.useState)(false);
20923
+ const [copiedStatePath, setCopiedStatePath] = (0, import_react.useState)(false);
20924
+ const initialCalibrateSessionRef = (0, import_react.useRef)(getCalibrateSessionIdFromLocation());
20925
+ const initialCalibrateRef = (0, import_react.useRef)((() => {
20599
20926
  const ref = getCalibrateRefFromLocation();
20600
20927
  return ref ? parseGradingRef(ref) : {};
20601
20928
  })());
20602
- const updateCalibratePath = (0, import_react2.useCallback)((sessionId, opts) => {
20929
+ const updateCalibratePath = (0, import_react.useCallback)((sessionId, opts) => {
20603
20930
  const targetPath = sessionId ? buildCalibratePath(sessionId) : "/calibrate";
20604
20931
  if (window.location.pathname === targetPath) return;
20605
20932
  const url = new URL(window.location.href);
@@ -20614,7 +20941,7 @@ function CalibrateApp() {
20614
20941
  }
20615
20942
  window.history.replaceState({}, "", url.toString());
20616
20943
  }, []);
20617
- const loadCalibrateData = (0, import_react2.useCallback)(async () => {
20944
+ const loadCalibrateData = (0, import_react.useCallback)(async () => {
20618
20945
  try {
20619
20946
  setLoading(true);
20620
20947
  const res = await fetch("/api/calibrate");
@@ -20648,12 +20975,12 @@ function CalibrateApp() {
20648
20975
  setLoading(false);
20649
20976
  }
20650
20977
  }, []);
20651
- (0, import_react2.useEffect)(() => {
20978
+ (0, import_react.useEffect)(() => {
20652
20979
  loadCalibrateData();
20653
20980
  }, [
20654
20981
  loadCalibrateData
20655
20982
  ]);
20656
- (0, import_react2.useEffect)(() => {
20983
+ (0, import_react.useEffect)(() => {
20657
20984
  const streamId = CALIBRATE_STREAM_ID;
20658
20985
  const streamUrl = buildDurableStreamUrl(streamId, getDurableStreamOffset(streamId));
20659
20986
  const source = new EventSource(streamUrl);
@@ -20688,7 +21015,7 @@ function CalibrateApp() {
20688
21015
  source.close();
20689
21016
  };
20690
21017
  }, []);
20691
- (0, import_react2.useEffect)(() => {
21018
+ (0, import_react.useEffect)(() => {
20692
21019
  if (selectedSessionId) {
20693
21020
  updateCalibratePath(selectedSessionId);
20694
21021
  } else {
@@ -20698,39 +21025,74 @@ function CalibrateApp() {
20698
21025
  selectedSessionId,
20699
21026
  updateCalibratePath
20700
21027
  ]);
20701
- const selectedSession = (0, import_react2.useMemo)(() => sessions.find((session) => session.id === selectedSessionId) ?? null, [
21028
+ (0, import_react.useEffect)(() => {
21029
+ if (!selectedSessionId) {
21030
+ setSessionDetail(null);
21031
+ setSessionDetailError(null);
21032
+ setSessionDetailLoading(false);
21033
+ return;
21034
+ }
21035
+ let active = true;
21036
+ const loadSessionDetail = async () => {
21037
+ try {
21038
+ setSessionDetailLoading(true);
21039
+ const res = await fetch(`/api/session?sessionId=${encodeURIComponent(selectedSessionId)}`);
21040
+ if (!res.ok) {
21041
+ const text = await res.text();
21042
+ throw new Error(text || res.statusText);
21043
+ }
21044
+ const data = await res.json();
21045
+ if (!active) return;
21046
+ setSessionDetail(data);
21047
+ setSessionDetailError(null);
21048
+ } catch (err) {
21049
+ if (!active) return;
21050
+ setSessionDetailError(err instanceof Error ? err.message : "Failed to load session details");
21051
+ setSessionDetail(null);
21052
+ } finally {
21053
+ if (active) setSessionDetailLoading(false);
21054
+ }
21055
+ };
21056
+ loadSessionDetail();
21057
+ return () => {
21058
+ active = false;
21059
+ };
21060
+ }, [
21061
+ selectedSessionId
21062
+ ]);
21063
+ const selectedSession = (0, import_react.useMemo)(() => sessions.find((session) => session.id === selectedSessionId) ?? null, [
20702
21064
  sessions,
20703
21065
  selectedSessionId
20704
21066
  ]);
20705
- const selectedGrader = (0, import_react2.useMemo)(() => graders.find((grader) => grader.id === selectedGraderId) ?? null, [
21067
+ const selectedGrader = (0, import_react.useMemo)(() => graders.find((grader) => grader.id === selectedGraderId) ?? null, [
20706
21068
  graders,
20707
21069
  selectedGraderId
20708
21070
  ]);
20709
- const sessionDeckDisplay = (0, import_react2.useMemo)(() => {
21071
+ const sessionDeckDisplay = (0, import_react.useMemo)(() => {
20710
21072
  if (!selectedSession?.deck) return null;
20711
21073
  return toRelativePath(selectedSession.deck, repoRootPath) ?? normalizeFsPath(selectedSession.deck);
20712
21074
  }, [
20713
21075
  selectedSession
20714
21076
  ]);
20715
- const sessionDirDisplay = (0, import_react2.useMemo)(() => {
21077
+ const sessionDirDisplay = (0, import_react.useMemo)(() => {
20716
21078
  if (!selectedSession?.sessionDir) return null;
20717
21079
  return toRelativePath(selectedSession.sessionDir, repoRootPath) ?? normalizeFsPath(selectedSession.sessionDir);
20718
21080
  }, [
20719
21081
  selectedSession
20720
21082
  ]);
20721
- const sessionStateDisplay = (0, import_react2.useMemo)(() => {
21083
+ const sessionStateDisplay = (0, import_react.useMemo)(() => {
20722
21084
  if (!selectedSession?.statePath) return null;
20723
21085
  return toRelativePath(selectedSession.statePath, repoRootPath) ?? normalizeFsPath(selectedSession.statePath);
20724
21086
  }, [
20725
21087
  selectedSession
20726
21088
  ]);
20727
- const sessionCreatedLabel = (0, import_react2.useMemo)(() => {
21089
+ const sessionCreatedLabel = (0, import_react.useMemo)(() => {
20728
21090
  return selectedSession?.createdAt ? formatTimestamp(selectedSession.createdAt) : null;
20729
21091
  }, [
20730
21092
  selectedSession
20731
21093
  ]);
20732
21094
  const sessionDebugHref = selectedSession ? `${SESSIONS_BASE_PATH}/${encodeURIComponent(selectedSession.id)}/debug` : null;
20733
- const sessionRuns = (0, import_react2.useMemo)(() => {
21095
+ const sessionRuns = (0, import_react.useMemo)(() => {
20734
21096
  if (!selectedSession?.gradingRuns) return [];
20735
21097
  return [
20736
21098
  ...selectedSession.gradingRuns
@@ -20738,7 +21100,7 @@ function CalibrateApp() {
20738
21100
  }, [
20739
21101
  selectedSession
20740
21102
  ]);
20741
- const runSections = (0, import_react2.useMemo)(() => {
21103
+ const runSections = (0, import_react.useMemo)(() => {
20742
21104
  return sessionRuns.map((run) => {
20743
21105
  const items = [];
20744
21106
  const result = run.result;
@@ -20827,16 +21189,85 @@ function CalibrateApp() {
20827
21189
  }, [
20828
21190
  sessionRuns
20829
21191
  ]);
20830
- const runItems = (0, import_react2.useMemo)(() => runSections.flatMap((section) => section.items), [
21192
+ const runItems = (0, import_react.useMemo)(() => runSections.flatMap((section) => section.items), [
21193
+ runSections
21194
+ ]);
21195
+ const runLabelById = (0, import_react.useMemo)(() => {
21196
+ const map = /* @__PURE__ */ new Map();
21197
+ runSections.forEach((section) => {
21198
+ map.set(section.run.id, section.label);
21199
+ });
21200
+ return map;
21201
+ }, [
20831
21202
  runSections
20832
21203
  ]);
20833
- const [expandedRunId, setExpandedRunId] = (0, import_react2.useState)(null);
20834
- const [expandedResults, setExpandedResults] = (0, import_react2.useState)({});
20835
- const [highlightedResult, setHighlightedResult] = (0, import_react2.useState)(null);
20836
- const [copiedRef, setCopiedRef] = (0, import_react2.useState)(null);
20837
- const [referenceDrafts, setReferenceDrafts] = (0, import_react2.useState)({});
20838
- const [showRawInputs, setShowRawInputs] = (0, import_react2.useState)({});
20839
- (0, import_react2.useEffect)(() => {
21204
+ const runItemByRefId = (0, import_react.useMemo)(() => {
21205
+ const map = /* @__PURE__ */ new Map();
21206
+ runItems.forEach((item) => {
21207
+ map.set(item.refId, item);
21208
+ });
21209
+ return map;
21210
+ }, [
21211
+ runItems
21212
+ ]);
21213
+ const gradingFlags = (0, import_react.useMemo)(() => extractGradingFlags(sessionDetail?.meta), [
21214
+ sessionDetail?.meta
21215
+ ]);
21216
+ const gradingFlagByRefId = (0, import_react.useMemo)(() => {
21217
+ const map = /* @__PURE__ */ new Map();
21218
+ gradingFlags.forEach((flag) => {
21219
+ map.set(flag.refId, flag);
21220
+ });
21221
+ return map;
21222
+ }, [
21223
+ gradingFlags
21224
+ ]);
21225
+ const flaggedRefSet = (0, import_react.useMemo)(() => {
21226
+ return new Set(gradingFlags.map((flag) => flag.refId));
21227
+ }, [
21228
+ gradingFlags
21229
+ ]);
21230
+ const messageByRefId = (0, import_react.useMemo)(() => {
21231
+ const map = /* @__PURE__ */ new Map();
21232
+ const refs = sessionDetail?.messageRefs ?? [];
21233
+ const messages = sessionDetail?.messages ?? [];
21234
+ refs.forEach((ref, idx) => {
21235
+ if (!ref?.id) return;
21236
+ const message = messages[idx];
21237
+ if (message) map.set(ref.id, message);
21238
+ });
21239
+ return map;
21240
+ }, [
21241
+ sessionDetail?.messageRefs,
21242
+ sessionDetail?.messages
21243
+ ]);
21244
+ const feedbackItems = (0, import_react.useMemo)(() => {
21245
+ const feedback = sessionDetail?.feedback ?? [];
21246
+ const items = feedback.map((entry) => {
21247
+ const message = messageByRefId.get(entry.messageRefId);
21248
+ return {
21249
+ entry,
21250
+ message
21251
+ };
21252
+ });
21253
+ return items.sort((a, b) => {
21254
+ const aKey = a.entry.createdAt ?? "";
21255
+ const bKey = b.entry.createdAt ?? "";
21256
+ return bKey.localeCompare(aKey);
21257
+ });
21258
+ }, [
21259
+ sessionDetail?.feedback,
21260
+ messageByRefId
21261
+ ]);
21262
+ const [expandedRunId, setExpandedRunId] = (0, import_react.useState)(null);
21263
+ const [expandedResults, setExpandedResults] = (0, import_react.useState)({});
21264
+ const [highlightedResult, setHighlightedResult] = (0, import_react.useState)(null);
21265
+ const [copiedRef, setCopiedRef] = (0, import_react.useState)(null);
21266
+ const [flagReasonDrafts, setFlagReasonDrafts] = (0, import_react.useState)({});
21267
+ const flagReasonTimeoutsRef = (0, import_react.useRef)({});
21268
+ const [referenceDrafts, setReferenceDrafts] = (0, import_react.useState)({});
21269
+ const [showRawInputs, setShowRawInputs] = (0, import_react.useState)({});
21270
+ (0, import_react.useEffect)(() => {
20840
21271
  const ref = initialCalibrateRef.current;
20841
21272
  if (!ref.runId) return;
20842
21273
  const match = runItems.find((item) => item.runId === ref.runId && (ref.turnIndex === void 0 || item.turnIndex === ref.turnIndex));
@@ -20850,7 +21281,7 @@ function CalibrateApp() {
20850
21281
  }, [
20851
21282
  runItems
20852
21283
  ]);
20853
- (0, import_react2.useEffect)(() => {
21284
+ (0, import_react.useEffect)(() => {
20854
21285
  const latestRunId = runSections[0]?.run.id ?? null;
20855
21286
  if (!latestRunId) {
20856
21287
  setExpandedRunId(null);
@@ -20860,7 +21291,130 @@ function CalibrateApp() {
20860
21291
  }, [
20861
21292
  runSections
20862
21293
  ]);
20863
- const runGrader = (0, import_react2.useCallback)(async () => {
21294
+ (0, import_react.useEffect)(() => {
21295
+ return () => {
21296
+ const timers = flagReasonTimeoutsRef.current;
21297
+ Object.values(timers).forEach((handle) => clearTimeout(handle));
21298
+ flagReasonTimeoutsRef.current = {};
21299
+ };
21300
+ }, []);
21301
+ const toggleFlag = (0, import_react.useCallback)(async (item) => {
21302
+ if (!selectedSessionId) return;
21303
+ try {
21304
+ const res = await fetch("/api/calibrate/flag", {
21305
+ method: "POST",
21306
+ headers: {
21307
+ "content-type": "application/json"
21308
+ },
21309
+ body: JSON.stringify({
21310
+ sessionId: selectedSessionId,
21311
+ refId: item.refId,
21312
+ runId: item.runId,
21313
+ turnIndex: item.turnIndex
21314
+ })
21315
+ });
21316
+ if (!res.ok) {
21317
+ const text = await res.text();
21318
+ throw new Error(text || res.statusText);
21319
+ }
21320
+ const data = await res.json();
21321
+ if (!data.flags) return;
21322
+ setSessionDetail((prev) => {
21323
+ if (!prev) return prev;
21324
+ return {
21325
+ ...prev,
21326
+ meta: {
21327
+ ...prev.meta ?? {},
21328
+ gradingFlags: data.flags
21329
+ }
21330
+ };
21331
+ });
21332
+ setFlagReasonDrafts((prev) => {
21333
+ const next = {
21334
+ ...prev
21335
+ };
21336
+ const isNowFlagged = data.flags?.some((flag2) => flag2.refId === item.refId);
21337
+ if (!isNowFlagged) {
21338
+ const timers = flagReasonTimeoutsRef.current;
21339
+ if (timers[item.refId]) {
21340
+ clearTimeout(timers[item.refId]);
21341
+ delete timers[item.refId];
21342
+ }
21343
+ delete next[item.refId];
21344
+ return next;
21345
+ }
21346
+ const flag = data.flags?.find((entry) => entry.refId === item.refId);
21347
+ if (flag?.reason) {
21348
+ next[item.refId] = flag.reason;
21349
+ } else {
21350
+ next[item.refId] = "";
21351
+ }
21352
+ return next;
21353
+ });
21354
+ } catch (err) {
21355
+ setError(err instanceof Error ? err.message : "Failed to flag grader");
21356
+ }
21357
+ }, [
21358
+ selectedSessionId
21359
+ ]);
21360
+ const updateFlagReason = (0, import_react.useCallback)(async (refId, reason) => {
21361
+ if (!selectedSessionId) return;
21362
+ try {
21363
+ const res = await fetch("/api/calibrate/flag/reason", {
21364
+ method: "POST",
21365
+ headers: {
21366
+ "content-type": "application/json"
21367
+ },
21368
+ body: JSON.stringify({
21369
+ sessionId: selectedSessionId,
21370
+ refId,
21371
+ reason
21372
+ })
21373
+ });
21374
+ if (!res.ok) {
21375
+ const text = await res.text();
21376
+ throw new Error(text || res.statusText);
21377
+ }
21378
+ const data = await res.json();
21379
+ if (!data.flags) return;
21380
+ setSessionDetail((prev) => {
21381
+ if (!prev) return prev;
21382
+ return {
21383
+ ...prev,
21384
+ meta: {
21385
+ ...prev.meta ?? {},
21386
+ gradingFlags: data.flags
21387
+ }
21388
+ };
21389
+ });
21390
+ } catch (err) {
21391
+ setError(err instanceof Error ? err.message : "Failed to save reason");
21392
+ }
21393
+ }, [
21394
+ selectedSessionId
21395
+ ]);
21396
+ const scheduleFlagReasonSave = (0, import_react.useCallback)((refId, reason) => {
21397
+ const timers = flagReasonTimeoutsRef.current;
21398
+ if (timers[refId]) {
21399
+ clearTimeout(timers[refId]);
21400
+ }
21401
+ timers[refId] = window.setTimeout(() => {
21402
+ updateFlagReason(refId, reason);
21403
+ delete timers[refId];
21404
+ }, 650);
21405
+ }, [
21406
+ updateFlagReason
21407
+ ]);
21408
+ const handleCopyStatePath = (0, import_react.useCallback)(() => {
21409
+ const target = selectedSession?.statePath ?? null;
21410
+ if (!target) return;
21411
+ navigator.clipboard?.writeText(target);
21412
+ setCopiedStatePath(true);
21413
+ window.setTimeout(() => setCopiedStatePath(false), 1200);
21414
+ }, [
21415
+ selectedSession?.statePath
21416
+ ]);
21417
+ const runGrader = (0, import_react.useCallback)(async () => {
20864
21418
  if (!selectedSessionId || !selectedGraderId) return;
20865
21419
  try {
20866
21420
  setRunning(true);
@@ -21196,6 +21750,7 @@ function CalibrateApp() {
21196
21750
  const scoreClass = getScoreClass(displayScore);
21197
21751
  const isOpen = !isPending && Boolean(expandedResults[item.key]);
21198
21752
  const draft = referenceDrafts[item.key];
21753
+ const isFlagged = flaggedRefSet.has(item.refId);
21199
21754
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
21200
21755
  className: `calibrate-run-section${highlightedResult === item.key ? " trace-row-highlight" : ""}`,
21201
21756
  children: [
@@ -21261,6 +21816,16 @@ function CalibrateApp() {
21261
21816
  !isPending && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
21262
21817
  className: "calibrate-result-actions",
21263
21818
  children: [
21819
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", {
21820
+ type: "button",
21821
+ className: classNames("ghost-btn", "calibrate-flag-btn", isFlagged && "active"),
21822
+ onClick: () => toggleFlag({
21823
+ refId: item.refId,
21824
+ runId: item.runId,
21825
+ turnIndex: item.turnIndex
21826
+ }),
21827
+ children: isFlagged ? "Flagged" : "Flag"
21828
+ }),
21264
21829
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", {
21265
21830
  type: "button",
21266
21831
  className: "ghost-btn calibrate-ref-copy",
@@ -21302,6 +21867,29 @@ function CalibrateApp() {
21302
21867
  })
21303
21868
  ]
21304
21869
  }),
21870
+ isFlagged && !isPending && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
21871
+ className: "calibrate-flag-reason",
21872
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", {
21873
+ children: [
21874
+ "Reason",
21875
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("textarea", {
21876
+ value: flagReasonDrafts[item.refId] ?? gradingFlagByRefId.get(item.refId)?.reason ?? "",
21877
+ placeholder: "Why is this flagged?",
21878
+ onChange: (e) => {
21879
+ const nextReason = e.target.value;
21880
+ setFlagReasonDrafts((prev) => ({
21881
+ ...prev,
21882
+ [item.refId]: nextReason
21883
+ }));
21884
+ scheduleFlagReasonSave(item.refId, nextReason);
21885
+ },
21886
+ onBlur: (e) => {
21887
+ scheduleFlagReasonSave(item.refId, e.target.value);
21888
+ }
21889
+ })
21890
+ ]
21891
+ })
21892
+ }),
21305
21893
  item.error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
21306
21894
  className: "error",
21307
21895
  children: item.error
@@ -21626,6 +22214,104 @@ function CalibrateApp() {
21626
22214
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", {
21627
22215
  children: "Deck & session"
21628
22216
  }),
22217
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
22218
+ className: "drawer-section",
22219
+ children: [
22220
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", {
22221
+ children: "Ratings & flags"
22222
+ }),
22223
+ selectedSession?.statePath && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, {
22224
+ children: [
22225
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", {
22226
+ type: "button",
22227
+ className: "primary",
22228
+ onClick: handleCopyStatePath,
22229
+ children: copiedStatePath ? "Copied" : "Copy state path"
22230
+ }),
22231
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", {
22232
+ className: "calibrate-button-meta",
22233
+ children: "Paste this in your coding assistant to debug the agent."
22234
+ })
22235
+ ]
22236
+ }),
22237
+ sessionDetailLoading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22238
+ className: "placeholder",
22239
+ children: "Loading ratings and flags\u2026"
22240
+ }),
22241
+ sessionDetailError && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22242
+ className: "error",
22243
+ children: sessionDetailError
22244
+ }),
22245
+ !sessionDetailLoading && !sessionDetailError && feedbackItems.length === 0 && gradingFlags.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22246
+ className: "placeholder",
22247
+ children: "No ratings or flags yet."
22248
+ }),
22249
+ feedbackItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22250
+ className: "calibrate-summary-list",
22251
+ children: feedbackItems.map(({ entry, message }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
22252
+ className: "calibrate-summary-card",
22253
+ children: [
22254
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
22255
+ className: "calibrate-summary-title",
22256
+ children: [
22257
+ "Rating ",
22258
+ entry.score
22259
+ ]
22260
+ }),
22261
+ entry.reason && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22262
+ className: "calibrate-summary-reason ellipsis",
22263
+ children: entry.reason
22264
+ }),
22265
+ message?.content && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22266
+ className: "calibrate-summary-meta ellipsis",
22267
+ children: formatSnippet(message.content)
22268
+ }),
22269
+ entry.createdAt && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22270
+ className: "calibrate-summary-meta ellipsis",
22271
+ children: formatTimestampShort(entry.createdAt)
22272
+ })
22273
+ ]
22274
+ }, `${entry.id}-${entry.messageRefId}`))
22275
+ }),
22276
+ gradingFlags.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22277
+ className: "calibrate-summary-list",
22278
+ children: gradingFlags.map((flag) => {
22279
+ const runLabel = flag.runId ? runLabelById.get(flag.runId) : void 0;
22280
+ const flaggedItem = runItemByRefId.get(flag.refId);
22281
+ const turnLabel = flaggedItem?.turnNumber ? `Turn ${flaggedItem.turnNumber}` : void 0;
22282
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
22283
+ className: "calibrate-summary-card calibrate-flag-card",
22284
+ children: [
22285
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22286
+ className: "calibrate-summary-title",
22287
+ children: "Flagged grader"
22288
+ }),
22289
+ runLabel && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22290
+ className: "calibrate-summary-meta ellipsis",
22291
+ children: runLabel
22292
+ }),
22293
+ turnLabel && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22294
+ className: "calibrate-summary-meta ellipsis",
22295
+ children: turnLabel
22296
+ }),
22297
+ !runLabel && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22298
+ className: "calibrate-summary-meta ellipsis",
22299
+ children: flag.refId
22300
+ }),
22301
+ flag.reason && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22302
+ className: "calibrate-summary-reason ellipsis",
22303
+ children: flag.reason
22304
+ }),
22305
+ flag.createdAt && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22306
+ className: "calibrate-summary-meta ellipsis ",
22307
+ children: formatTimestampShort(flag.createdAt)
22308
+ })
22309
+ ]
22310
+ }, flag.id);
22311
+ })
22312
+ })
22313
+ ]
22314
+ }),
21629
22315
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
21630
22316
  className: "drawer-section",
21631
22317
  children: [
@@ -21697,35 +22383,35 @@ function CalibrateApp() {
21697
22383
  function TestBotApp(props) {
21698
22384
  const { onNavigateToSession, onReplaceTestBotSession, onResetTestBotSession, activeSessionId } = props;
21699
22385
  const deckStorageKey = "gambit:test-bot:selected-deck";
21700
- const [testDecks, setTestDecks] = (0, import_react2.useState)([]);
21701
- const [selectedDeckId, setSelectedDeckId] = (0, import_react2.useState)(null);
21702
- const [botLabel, setBotLabel] = (0, import_react2.useState)(null);
21703
- const [botDescription, setBotDescription] = (0, import_react2.useState)(null);
21704
- const [botInputSchema, setBotInputSchema] = (0, import_react2.useState)(null);
21705
- const [botInputSchemaError, setBotInputSchemaError] = (0, import_react2.useState)(null);
21706
- const [botInputValue, setBotInputValue] = (0, import_react2.useState)(void 0);
21707
- const [botInputDirty, setBotInputDirty] = (0, import_react2.useState)(false);
21708
- const [botInputJsonErrors, setBotInputJsonErrors] = (0, import_react2.useState)({});
21709
- const [botInputDefaults, setBotInputDefaults] = (0, import_react2.useState)(void 0);
21710
- const [initialUserMessage, setInitialUserMessage] = (0, import_react2.useState)("");
21711
- const [run, setRun] = (0, import_react2.useState)({
22386
+ const [testDecks, setTestDecks] = (0, import_react.useState)([]);
22387
+ const [selectedDeckId, setSelectedDeckId] = (0, import_react.useState)(null);
22388
+ const [botLabel, setBotLabel] = (0, import_react.useState)(null);
22389
+ const [botDescription, setBotDescription] = (0, import_react.useState)(null);
22390
+ const [botInputSchema, setBotInputSchema] = (0, import_react.useState)(null);
22391
+ const [botInputSchemaError, setBotInputSchemaError] = (0, import_react.useState)(null);
22392
+ const [botInputValue, setBotInputValue] = (0, import_react.useState)(void 0);
22393
+ const [botInputDirty, setBotInputDirty] = (0, import_react.useState)(false);
22394
+ const [botInputJsonErrors, setBotInputJsonErrors] = (0, import_react.useState)({});
22395
+ const [botInputDefaults, setBotInputDefaults] = (0, import_react.useState)(void 0);
22396
+ const [initialUserMessage, setInitialUserMessage] = (0, import_react.useState)("");
22397
+ const [run, setRun] = (0, import_react.useState)({
21712
22398
  status: "idle",
21713
22399
  messages: [],
21714
22400
  traces: [],
21715
22401
  toolInserts: []
21716
22402
  });
21717
- const runRef = (0, import_react2.useRef)({
22403
+ const runRef = (0, import_react.useRef)({
21718
22404
  status: "idle",
21719
22405
  messages: [],
21720
22406
  traces: [],
21721
22407
  toolInserts: []
21722
22408
  });
21723
- const lastRunMessageCountRef = (0, import_react2.useRef)(0);
21724
- const [toolCallsOpen, setToolCallsOpen] = (0, import_react2.useState)({});
21725
- const [latencyByTurn, setLatencyByTurn] = (0, import_react2.useState)({});
21726
- const lastUserEndByTurnRef = (0, import_react2.useRef)({});
21727
- const firstAssistantTokenByTurnRef = (0, import_react2.useRef)({});
21728
- (0, import_react2.useEffect)(() => {
22409
+ const lastRunMessageCountRef = (0, import_react.useRef)(0);
22410
+ const [toolCallsOpen, setToolCallsOpen] = (0, import_react.useState)({});
22411
+ const [latencyByTurn, setLatencyByTurn] = (0, import_react.useState)({});
22412
+ const lastUserEndByTurnRef = (0, import_react.useRef)({});
22413
+ const firstAssistantTokenByTurnRef = (0, import_react.useRef)({});
22414
+ (0, import_react.useEffect)(() => {
21729
22415
  lastRunMessageCountRef.current = 0;
21730
22416
  setToolCallsOpen({});
21731
22417
  setLatencyByTurn({});
@@ -21734,20 +22420,20 @@ function TestBotApp(props) {
21734
22420
  }, [
21735
22421
  run.id
21736
22422
  ]);
21737
- const [streamingUser, setStreamingUser] = (0, import_react2.useState)(null);
21738
- const [streamingAssistant, setStreamingAssistant] = (0, import_react2.useState)(null);
22423
+ const [streamingUser, setStreamingUser] = (0, import_react.useState)(null);
22424
+ const [streamingAssistant, setStreamingAssistant] = (0, import_react.useState)(null);
21739
22425
  const deckSchema = useHttpSchema();
21740
22426
  const deckInputSchema = deckSchema.schemaResponse?.schema;
21741
22427
  const deckSchemaDefaults = deckSchema.schemaResponse?.defaults;
21742
22428
  const deckSchemaError = deckSchema.schemaResponse?.error ?? deckSchema.error ?? void 0;
21743
- const [deckInitValue, setDeckInitValue] = (0, import_react2.useState)(void 0);
21744
- const [deckInitDirty, setDeckInitDirty] = (0, import_react2.useState)(false);
21745
- const [deckJsonErrors, setDeckJsonErrors] = (0, import_react2.useState)({});
21746
- const [botPath, setBotPath] = (0, import_react2.useState)(null);
21747
- const pollRef = (0, import_react2.useRef)(null);
21748
- const transcriptRef = (0, import_react2.useRef)(null);
21749
- const runIdRef = (0, import_react2.useRef)(void 0);
21750
- const loadTestBot = (0, import_react2.useCallback)(async (opts) => {
22429
+ const [deckInitValue, setDeckInitValue] = (0, import_react.useState)(void 0);
22430
+ const [deckInitDirty, setDeckInitDirty] = (0, import_react.useState)(false);
22431
+ const [deckJsonErrors, setDeckJsonErrors] = (0, import_react.useState)({});
22432
+ const [botPath, setBotPath] = (0, import_react.useState)(null);
22433
+ const pollRef = (0, import_react.useRef)(null);
22434
+ const transcriptRef = (0, import_react.useRef)(null);
22435
+ const runIdRef = (0, import_react.useRef)(void 0);
22436
+ const loadTestBot = (0, import_react.useCallback)(async (opts) => {
21751
22437
  let storedDeckId = null;
21752
22438
  try {
21753
22439
  storedDeckId = localStorage.getItem(deckStorageKey);
@@ -21798,12 +22484,12 @@ function TestBotApp(props) {
21798
22484
  }, [
21799
22485
  deckStorageKey
21800
22486
  ]);
21801
- (0, import_react2.useEffect)(() => {
22487
+ (0, import_react.useEffect)(() => {
21802
22488
  loadTestBot();
21803
22489
  }, [
21804
22490
  loadTestBot
21805
22491
  ]);
21806
- (0, import_react2.useEffect)(() => {
22492
+ (0, import_react.useEffect)(() => {
21807
22493
  runIdRef.current = run.id;
21808
22494
  runRef.current = run;
21809
22495
  setStreamingUser(null);
@@ -21811,14 +22497,14 @@ function TestBotApp(props) {
21811
22497
  }, [
21812
22498
  run.id
21813
22499
  ]);
21814
- (0, import_react2.useEffect)(() => {
22500
+ (0, import_react.useEffect)(() => {
21815
22501
  if (!run.sessionId) return;
21816
22502
  onReplaceTestBotSession(run.sessionId);
21817
22503
  }, [
21818
22504
  onReplaceTestBotSession,
21819
22505
  run.sessionId
21820
22506
  ]);
21821
- (0, import_react2.useEffect)(() => {
22507
+ (0, import_react.useEffect)(() => {
21822
22508
  if (!selectedDeckId) return;
21823
22509
  try {
21824
22510
  localStorage.setItem(deckStorageKey, selectedDeckId);
@@ -21828,12 +22514,12 @@ function TestBotApp(props) {
21828
22514
  deckStorageKey,
21829
22515
  selectedDeckId
21830
22516
  ]);
21831
- (0, import_react2.useEffect)(() => {
22517
+ (0, import_react.useEffect)(() => {
21832
22518
  runRef.current = run;
21833
22519
  }, [
21834
22520
  run
21835
22521
  ]);
21836
- (0, import_react2.useEffect)(() => {
22522
+ (0, import_react.useEffect)(() => {
21837
22523
  const streamId = TEST_BOT_STREAM_ID;
21838
22524
  const streamUrl = buildDurableStreamUrl(streamId, getDurableStreamOffset(streamId));
21839
22525
  const source = new EventSource(streamUrl);
@@ -21935,7 +22621,7 @@ function TestBotApp(props) {
21935
22621
  source.close();
21936
22622
  };
21937
22623
  }, []);
21938
- const refreshStatus = (0, import_react2.useCallback)(async (opts) => {
22624
+ const refreshStatus = (0, import_react.useCallback)(async (opts) => {
21939
22625
  try {
21940
22626
  const runId = opts?.runId ?? run.id;
21941
22627
  const sessionId = opts?.sessionId;
@@ -21966,12 +22652,12 @@ function TestBotApp(props) {
21966
22652
  selectedDeckId,
21967
22653
  testDecks
21968
22654
  ]);
21969
- (0, import_react2.useEffect)(() => {
22655
+ (0, import_react.useEffect)(() => {
21970
22656
  refreshStatus();
21971
22657
  }, [
21972
22658
  refreshStatus
21973
22659
  ]);
21974
- (0, import_react2.useEffect)(() => {
22660
+ (0, import_react.useEffect)(() => {
21975
22661
  if (!activeSessionId) return;
21976
22662
  refreshStatus({
21977
22663
  sessionId: activeSessionId
@@ -21980,7 +22666,7 @@ function TestBotApp(props) {
21980
22666
  activeSessionId,
21981
22667
  refreshStatus
21982
22668
  ]);
21983
- (0, import_react2.useEffect)(() => {
22669
+ (0, import_react.useEffect)(() => {
21984
22670
  if (!deckInputSchema) return;
21985
22671
  if (deckInitDirty) return;
21986
22672
  const nextInit = deckSchemaDefaults !== void 0 ? cloneValue(deckSchemaDefaults) : deriveInitialFromSchema(deckInputSchema);
@@ -21990,7 +22676,7 @@ function TestBotApp(props) {
21990
22676
  deckSchemaDefaults,
21991
22677
  deckInitDirty
21992
22678
  ]);
21993
- (0, import_react2.useEffect)(() => {
22679
+ (0, import_react.useEffect)(() => {
21994
22680
  if (!botInputSchema) return;
21995
22681
  if (botInputDirty) return;
21996
22682
  const nextBotInput = botInputDefaults !== void 0 ? cloneValue(botInputDefaults) : deriveInitialFromSchema(botInputSchema);
@@ -22000,34 +22686,34 @@ function TestBotApp(props) {
22000
22686
  botInputDirty,
22001
22687
  botInputDefaults
22002
22688
  ]);
22003
- const missingBotInput = (0, import_react2.useMemo)(() => {
22689
+ const missingBotInput = (0, import_react.useMemo)(() => {
22004
22690
  if (!botInputSchema) return [];
22005
22691
  return findMissingRequiredFields(botInputSchema, botInputValue);
22006
22692
  }, [
22007
22693
  botInputSchema,
22008
22694
  botInputValue
22009
22695
  ]);
22010
- const botJsonErrorCount = (0, import_react2.useMemo)(() => {
22696
+ const botJsonErrorCount = (0, import_react.useMemo)(() => {
22011
22697
  return Object.values(botInputJsonErrors).filter((v) => typeof v === "string" && v).length;
22012
22698
  }, [
22013
22699
  botInputJsonErrors
22014
22700
  ]);
22015
- const missingDeckInit = (0, import_react2.useMemo)(() => {
22701
+ const missingDeckInit = (0, import_react.useMemo)(() => {
22016
22702
  if (!deckInputSchema) return [];
22017
22703
  return findMissingRequiredFields(deckInputSchema, deckInitValue);
22018
22704
  }, [
22019
22705
  deckInputSchema,
22020
22706
  deckInitValue
22021
22707
  ]);
22022
- const deckJsonErrorCount = (0, import_react2.useMemo)(() => {
22708
+ const deckJsonErrorCount = (0, import_react.useMemo)(() => {
22023
22709
  return Object.values(deckJsonErrors).filter((v) => typeof v === "string" && v).length;
22024
22710
  }, [
22025
22711
  deckJsonErrors
22026
22712
  ]);
22027
- const toolCallSummaries = (0, import_react2.useMemo)(() => summarizeToolCalls(run.traces ?? []), [
22713
+ const toolCallSummaries = (0, import_react.useMemo)(() => summarizeToolCalls(run.traces ?? []), [
22028
22714
  run.traces
22029
22715
  ]);
22030
- const toolBuckets = (0, import_react2.useMemo)(() => {
22716
+ const toolBuckets = (0, import_react.useMemo)(() => {
22031
22717
  const deriveInsertsFromTraces = (traces, messageCount) => {
22032
22718
  const inserts2 = [];
22033
22719
  let messageIndex = 0;
@@ -22098,7 +22784,7 @@ function TestBotApp(props) {
22098
22784
  run.traces,
22099
22785
  run.messages.length
22100
22786
  ]);
22101
- const assistantLatencyByMessageIndex = (0, import_react2.useMemo)(() => {
22787
+ const assistantLatencyByMessageIndex = (0, import_react.useMemo)(() => {
22102
22788
  const map = {};
22103
22789
  let assistantTurn = 0;
22104
22790
  run.messages.forEach((msg, index) => {
@@ -22117,7 +22803,7 @@ function TestBotApp(props) {
22117
22803
  const canRunPersona = testDecks.length > 0;
22118
22804
  const hasPersonaSelection = canRunPersona && Boolean(selectedDeckId);
22119
22805
  const canStart = hasPersonaSelection && (!botInputSchema || missingBotInput.length === 0) && (!deckInputSchema || missingDeckInit.length === 0) && botJsonErrorCount === 0 && deckJsonErrorCount === 0;
22120
- (0, import_react2.useEffect)(() => {
22806
+ (0, import_react.useEffect)(() => {
22121
22807
  if (run.status !== "running") {
22122
22808
  if (pollRef.current) window.clearInterval(pollRef.current);
22123
22809
  return;
@@ -22132,7 +22818,7 @@ function TestBotApp(props) {
22132
22818
  run.status,
22133
22819
  refreshStatus
22134
22820
  ]);
22135
- (0, import_react2.useEffect)(() => {
22821
+ (0, import_react.useEffect)(() => {
22136
22822
  if (streamingUser?.expectedUserCount !== void 0 && streamingUser.runId === run.id && countUserMessages(run.messages) >= streamingUser.expectedUserCount) {
22137
22823
  setStreamingUser(null);
22138
22824
  }
@@ -22155,7 +22841,7 @@ function TestBotApp(props) {
22155
22841
  streamingUser,
22156
22842
  streamingAssistant?.text
22157
22843
  ]);
22158
- const startRun = (0, import_react2.useCallback)(async () => {
22844
+ const startRun = (0, import_react.useCallback)(async () => {
22159
22845
  try {
22160
22846
  const res = await fetch("/api/test-bot/run", {
22161
22847
  method: "POST",
@@ -22198,7 +22884,7 @@ function TestBotApp(props) {
22198
22884
  refreshStatus,
22199
22885
  selectedDeckId
22200
22886
  ]);
22201
- const stopRun = (0, import_react2.useCallback)(async () => {
22887
+ const stopRun = (0, import_react.useCallback)(async () => {
22202
22888
  if (!run.id) return;
22203
22889
  try {
22204
22890
  await fetch("/api/test-bot/stop", {
@@ -22221,7 +22907,7 @@ function TestBotApp(props) {
22221
22907
  refreshStatus,
22222
22908
  run.id
22223
22909
  ]);
22224
- const handleNewChat = (0, import_react2.useCallback)(async () => {
22910
+ const handleNewChat = (0, import_react.useCallback)(async () => {
22225
22911
  if (run.status === "running") {
22226
22912
  await stopRun();
22227
22913
  }
@@ -22237,7 +22923,7 @@ function TestBotApp(props) {
22237
22923
  run.status,
22238
22924
  stopRun
22239
22925
  ]);
22240
- const saveTestBotFeedback = (0, import_react2.useCallback)(async (messageRefId, score, reason) => {
22926
+ const saveTestBotFeedback = (0, import_react.useCallback)(async (messageRefId, score, reason) => {
22241
22927
  if (!run.sessionId) return;
22242
22928
  try {
22243
22929
  const res = await fetch("/api/session/feedback", {
@@ -22269,17 +22955,17 @@ function TestBotApp(props) {
22269
22955
  }, [
22270
22956
  run.sessionId
22271
22957
  ]);
22272
- const handleTestBotScore = (0, import_react2.useCallback)((messageRefId, score) => {
22958
+ const handleTestBotScore = (0, import_react.useCallback)((messageRefId, score) => {
22273
22959
  saveTestBotFeedback(messageRefId, score);
22274
22960
  }, [
22275
22961
  saveTestBotFeedback
22276
22962
  ]);
22277
- const handleTestBotReason = (0, import_react2.useCallback)((messageRefId, score, reason) => {
22963
+ const handleTestBotReason = (0, import_react.useCallback)((messageRefId, score, reason) => {
22278
22964
  saveTestBotFeedback(messageRefId, score, reason);
22279
22965
  }, [
22280
22966
  saveTestBotFeedback
22281
22967
  ]);
22282
- const handleDeckSelection = (0, import_react2.useCallback)(async (nextId) => {
22968
+ const handleDeckSelection = (0, import_react.useCallback)(async (nextId) => {
22283
22969
  if (!nextId) return;
22284
22970
  if (nextId === selectedDeckId) return;
22285
22971
  await handleNewChat();
@@ -22490,12 +23176,6 @@ function TestBotApp(props) {
22490
23176
  disabled: run.status !== "running",
22491
23177
  "data-testid": "testbot-stop",
22492
23178
  children: "Stop"
22493
- }),
22494
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", {
22495
- type: "button",
22496
- className: "ghost-btn",
22497
- onClick: () => refreshStatus(),
22498
- children: "Refresh"
22499
23179
  })
22500
23180
  ]
22501
23181
  })
@@ -22720,10 +23400,10 @@ function normalizeAppPath(input) {
22720
23400
  return DOCS_PATH;
22721
23401
  }
22722
23402
  if (trimmed === "/test-bot") {
22723
- if (window.location.pathname !== DEFAULT_TEST_BOT_PATH) {
22724
- window.history.replaceState({}, "", DEFAULT_TEST_BOT_PATH);
23403
+ if (window.location.pathname !== DEFAULT_TEST_BOT_PATH2) {
23404
+ window.history.replaceState({}, "", DEFAULT_TEST_BOT_PATH2);
22725
23405
  }
22726
- return DEFAULT_TEST_BOT_PATH;
23406
+ return DEFAULT_TEST_BOT_PATH2;
22727
23407
  }
22728
23408
  if (trimmed === "/debug" || trimmed === "/simulate" || trimmed === SESSIONS_BASE_PATH) {
22729
23409
  if (window.location.pathname !== DEFAULT_SESSION_PATH) {
@@ -22757,15 +23437,15 @@ function normalizeAppPath(input) {
22757
23437
  }
22758
23438
  function App() {
22759
23439
  const simulatorBasePath = SESSIONS_BASE_PATH;
22760
- const [path, setPath] = (0, import_react2.useState)(() => normalizeAppPath(window.location.pathname));
22761
- const [bundleStamp, setBundleStamp] = (0, import_react2.useState)(null);
23440
+ const [path, setPath] = (0, import_react.useState)(() => normalizeAppPath(window.location.pathname));
23441
+ const [bundleStamp, setBundleStamp] = (0, import_react.useState)(null);
22762
23442
  const activeSessionId = getSessionIdFromPath(path);
22763
- (0, import_react2.useEffect)(() => {
23443
+ (0, import_react.useEffect)(() => {
22764
23444
  const handler = () => setPath(normalizeAppPath(window.location.pathname));
22765
23445
  window.addEventListener("popstate", handler);
22766
23446
  return () => window.removeEventListener("popstate", handler);
22767
23447
  }, []);
22768
- (0, import_react2.useEffect)(() => {
23448
+ (0, import_react.useEffect)(() => {
22769
23449
  const loadBundleStamp = async () => {
22770
23450
  try {
22771
23451
  const res = await fetch("/ui/bundle.js", {
@@ -22781,14 +23461,14 @@ function App() {
22781
23461
  };
22782
23462
  loadBundleStamp();
22783
23463
  }, []);
22784
- const navigate = (0, import_react2.useCallback)((next) => {
23464
+ const navigate = (0, import_react.useCallback)((next) => {
22785
23465
  if (next === path) return;
22786
23466
  window.history.pushState({}, "", next);
22787
23467
  setPath(next);
22788
23468
  }, [
22789
23469
  path
22790
23470
  ]);
22791
- const replacePath = (0, import_react2.useCallback)((next) => {
23471
+ const replacePath = (0, import_react.useCallback)((next) => {
22792
23472
  if (next === path) return;
22793
23473
  window.history.replaceState({}, "", next);
22794
23474
  setPath(next);
@@ -22799,7 +23479,7 @@ function App() {
22799
23479
  const isTestBot = !isDocs && /\/test-bot$/.test(path);
22800
23480
  const isCalibrate = !isDocs && (path.startsWith("/calibrate") || /^\/sessions\/[^/]+\/calibrate/.test(path));
22801
23481
  const currentPage = isDocs ? "docs" : isTestBot ? "test-bot" : isCalibrate ? "calibrate" : "debug";
22802
- const testBotPath = activeSessionId ? `${SESSIONS_BASE_PATH}/${encodeURIComponent(activeSessionId)}/test-bot` : DEFAULT_TEST_BOT_PATH;
23482
+ const testBotPath = activeSessionId ? `${SESSIONS_BASE_PATH}/${encodeURIComponent(activeSessionId)}/test-bot` : DEFAULT_TEST_BOT_PATH2;
22803
23483
  const debugPath = activeSessionId ? `${SESSIONS_BASE_PATH}/${encodeURIComponent(activeSessionId)}/debug` : DEFAULT_SESSION_PATH;
22804
23484
  const calibratePath = activeSessionId ? buildCalibratePath(activeSessionId) : "/calibrate";
22805
23485
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, {
@@ -22856,15 +23536,12 @@ function App() {
22856
23536
  }),
22857
23537
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
22858
23538
  className: "page-shell",
22859
- children: currentPage === "docs" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DocsPage, {
22860
- deckDisplayPath,
22861
- deckAbsolutePath: normalizedDeckPath
22862
- }) : currentPage === "debug" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SimulatorApp, {
23539
+ children: currentPage === "docs" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DocsPage, {}) : currentPage === "debug" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SimulatorApp, {
22863
23540
  basePath: simulatorBasePath
22864
23541
  }) : currentPage === "test-bot" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TestBotApp, {
22865
23542
  onNavigateToSession: (sessionId) => navigate(`${simulatorBasePath}/${encodeURIComponent(sessionId)}/debug`),
22866
23543
  onReplaceTestBotSession: (sessionId) => replacePath(`${simulatorBasePath}/${encodeURIComponent(sessionId)}/test-bot`),
22867
- onResetTestBotSession: () => replacePath(DEFAULT_TEST_BOT_PATH),
23544
+ onResetTestBotSession: () => replacePath(DEFAULT_TEST_BOT_PATH2),
22868
23545
  activeSessionId
22869
23546
  }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CalibrateApp, {})
22870
23547
  })
@@ -22872,7 +23549,7 @@ function App() {
22872
23549
  })
22873
23550
  });
22874
23551
  }
22875
- (0, import_client.createRoot)(document.getElementById("root")).render(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react2.default.StrictMode, {
23552
+ (0, import_client.createRoot)(document.getElementById("root")).render(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react.default.StrictMode, {
22876
23553
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(App, {})
22877
23554
  }));
22878
23555
  /**