@flanksource/clicky-ui 0.3.23 → 0.3.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/data/ai/AdvancedChatConfig.cjs +3 -0
  2. package/dist/data/ai/AdvancedChatConfig.cjs.map +1 -1
  3. package/dist/data/ai/AdvancedChatConfig.d.ts +2 -1
  4. package/dist/data/ai/AdvancedChatConfig.d.ts.map +1 -1
  5. package/dist/data/ai/AdvancedChatConfig.js +3 -0
  6. package/dist/data/ai/AdvancedChatConfig.js.map +1 -1
  7. package/dist/data/ai/ChatWindow.cjs +77 -4
  8. package/dist/data/ai/ChatWindow.cjs.map +1 -1
  9. package/dist/data/ai/ChatWindow.d.ts.map +1 -1
  10. package/dist/data/ai/ChatWindow.js +78 -5
  11. package/dist/data/ai/ChatWindow.js.map +1 -1
  12. package/dist/data/ai/ChatWindow.runtime.cjs +19 -4
  13. package/dist/data/ai/ChatWindow.runtime.cjs.map +1 -1
  14. package/dist/data/ai/ChatWindow.runtime.d.ts +2 -0
  15. package/dist/data/ai/ChatWindow.runtime.d.ts.map +1 -1
  16. package/dist/data/ai/ChatWindow.runtime.js +19 -4
  17. package/dist/data/ai/ChatWindow.runtime.js.map +1 -1
  18. package/dist/data/ai/ChatWindow.test-utils.d.ts +2 -1
  19. package/dist/data/ai/ChatWindow.test-utils.d.ts.map +1 -1
  20. package/dist/data/ai/ToolPreferences.cjs +8 -1
  21. package/dist/data/ai/ToolPreferences.cjs.map +1 -1
  22. package/dist/data/ai/ToolPreferences.d.ts +2 -1
  23. package/dist/data/ai/ToolPreferences.d.ts.map +1 -1
  24. package/dist/data/ai/ToolPreferences.js +8 -1
  25. package/dist/data/ai/ToolPreferences.js.map +1 -1
  26. package/dist/data/chat/Chat.cjs +34 -7
  27. package/dist/data/chat/Chat.cjs.map +1 -1
  28. package/dist/data/chat/Chat.d.ts +9 -1
  29. package/dist/data/chat/Chat.d.ts.map +1 -1
  30. package/dist/data/chat/Chat.js +34 -7
  31. package/dist/data/chat/Chat.js.map +1 -1
  32. package/dist/data/chat/ChatRuntimeToolbar.cjs +13 -7
  33. package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
  34. package/dist/data/chat/ChatRuntimeToolbar.d.ts +2 -1
  35. package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
  36. package/dist/data/chat/ChatRuntimeToolbar.js +13 -7
  37. package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
  38. package/dist/data/chat/ContextMeter.cjs +64 -27
  39. package/dist/data/chat/ContextMeter.cjs.map +1 -1
  40. package/dist/data/chat/ContextMeter.d.ts +11 -4
  41. package/dist/data/chat/ContextMeter.d.ts.map +1 -1
  42. package/dist/data/chat/ContextMeter.js +64 -27
  43. package/dist/data/chat/ContextMeter.js.map +1 -1
  44. package/dist/data/chat/Message.cjs +36 -1
  45. package/dist/data/chat/Message.cjs.map +1 -1
  46. package/dist/data/chat/Message.d.ts +1 -1
  47. package/dist/data/chat/Message.d.ts.map +1 -1
  48. package/dist/data/chat/Message.js +37 -2
  49. package/dist/data/chat/Message.js.map +1 -1
  50. package/dist/data/chat/approval.cjs +17 -0
  51. package/dist/data/chat/approval.cjs.map +1 -1
  52. package/dist/data/chat/approval.d.ts +5 -0
  53. package/dist/data/chat/approval.d.ts.map +1 -1
  54. package/dist/data/chat/approval.js +17 -0
  55. package/dist/data/chat/approval.js.map +1 -1
  56. package/dist/data/chat/fork-seed.cjs +22 -0
  57. package/dist/data/chat/fork-seed.cjs.map +1 -0
  58. package/dist/data/chat/fork-seed.d.ts +8 -0
  59. package/dist/data/chat/fork-seed.d.ts.map +1 -0
  60. package/dist/data/chat/fork-seed.js +22 -0
  61. package/dist/data/chat/fork-seed.js.map +1 -0
  62. package/dist/data/chat/types.cjs.map +1 -1
  63. package/dist/data/chat/types.d.ts +19 -0
  64. package/dist/data/chat/types.d.ts.map +1 -1
  65. package/dist/data/chat/types.js.map +1 -1
  66. package/dist/data/chat/usage-snapshot.cjs +10 -1
  67. package/dist/data/chat/usage-snapshot.cjs.map +1 -1
  68. package/dist/data/chat/usage-snapshot.d.ts.map +1 -1
  69. package/dist/data/chat/usage-snapshot.js +10 -1
  70. package/dist/data/chat/usage-snapshot.js.map +1 -1
  71. package/dist/data/runtime/RuntimeBar.cjs +3 -0
  72. package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
  73. package/dist/data/runtime/RuntimeBar.d.ts +3 -1
  74. package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
  75. package/dist/data/runtime/RuntimeBar.js +3 -0
  76. package/dist/data/runtime/RuntimeBar.js.map +1 -1
  77. package/dist/data/runtime/RuntimeBarCombo.cjs +15 -1
  78. package/dist/data/runtime/RuntimeBarCombo.cjs.map +1 -1
  79. package/dist/data/runtime/RuntimeBarCombo.d.ts +2 -1
  80. package/dist/data/runtime/RuntimeBarCombo.d.ts.map +1 -1
  81. package/dist/data/runtime/RuntimeBarCombo.js +15 -1
  82. package/dist/data/runtime/RuntimeBarCombo.js.map +1 -1
  83. package/dist/data/runtime/RuntimeBarSegments.cjs +7 -0
  84. package/dist/data/runtime/RuntimeBarSegments.cjs.map +1 -1
  85. package/dist/data/runtime/RuntimeBarSegments.d.ts +2 -1
  86. package/dist/data/runtime/RuntimeBarSegments.d.ts.map +1 -1
  87. package/dist/data/runtime/RuntimeBarSegments.js +7 -0
  88. package/dist/data/runtime/RuntimeBarSegments.js.map +1 -1
  89. package/dist/data/version-info.cjs +3 -3
  90. package/dist/data/version-info.js +3 -3
  91. package/dist/styles.css +1 -1
  92. package/package.json +1 -1
@@ -12,6 +12,7 @@ function ChatRuntimeToolbar({
12
12
  selectedModel,
13
13
  usage,
14
14
  threadId,
15
+ locked = false,
15
16
  onRuntimeChange
16
17
  }) {
17
18
  const showRuntimeBar = Boolean(
@@ -19,9 +20,9 @@ function ChatRuntimeToolbar({
19
20
  );
20
21
  const showContextMeter = Boolean(threadId || selectedModel || usage);
21
22
  if (!showRuntimeBar && !showContextMeter) return null;
22
- const contextWindow = (selectedModel == null ? void 0 : selectedModel.contextWindow) ?? (usage == null ? void 0 : usage.maxTokens) ?? 0;
23
+ const contextWindow = (usage == null ? void 0 : usage.maxTokens) ?? 0;
23
24
  const usedTokens = (usage == null ? void 0 : usage.usedTokens) ?? 0;
24
- const ModelGlyph = providerIcons.providerIcon(selectedModel == null ? void 0 : selectedModel.provider);
25
+ const ModelGlyph = providerIcons.providerIcon(usage == null ? void 0 : usage.backend);
25
26
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 items-center gap-2", children: [
26
27
  showRuntimeBar && /* @__PURE__ */ jsxRuntime.jsx(
27
28
  RuntimeBar.RuntimeBar,
@@ -31,6 +32,7 @@ function ChatRuntimeToolbar({
31
32
  onChange: onRuntimeChange,
32
33
  models,
33
34
  reasoningEfforts,
35
+ locked,
34
36
  ...runtimeFamilies ? { families: runtimeFamilies } : {}
35
37
  }
36
38
  ),
@@ -45,13 +47,17 @@ function ChatRuntimeToolbar({
45
47
  ...contextWindow > 0 ? { windowTokens: contextWindow } : {},
46
48
  ...(usage == null ? void 0 : usage.messageCount) != null ? { messageCount: usage.messageCount } : {},
47
49
  ...(usage == null ? void 0 : usage.cost) != null ? { cost: { total: usage.cost } } : {},
48
- ...threadId ? { sessionId: threadId } : {},
49
- ...(selectedModel == null ? void 0 : selectedModel.label) ? { model: selectedModel.label } : (usage == null ? void 0 : usage.modelLabel) ? { model: usage.modelLabel } : {},
50
+ ...(usage == null ? void 0 : usage.backend) ? { backend: usage.backend } : {},
51
+ ...(usage == null ? void 0 : usage.executionMode) ? { executionMode: usage.executionMode } : {},
52
+ ...(usage == null ? void 0 : usage.model) ? { model: usage.model } : (usage == null ? void 0 : usage.modelLabel) ? { model: usage.modelLabel } : {},
53
+ ...(usage == null ? void 0 : usage.captainSessionId) ? { captainSessionId: usage.captainSessionId } : {},
54
+ ...(usage == null ? void 0 : usage.providerSessionId) ? { providerSessionId: usage.providerSessionId } : {},
55
+ ...(usage == null ? void 0 : usage.threadId) ? { threadId: usage.threadId } : {},
56
+ ...(usage == null ? void 0 : usage.turnId) ? { turnId: usage.turnId } : {},
50
57
  ...runtime.effort ? { effort: runtime.effort } : {},
51
- ...runtime.mode ? { executionMode: runtime.mode } : {},
52
58
  ...ModelGlyph ? { modelIcon: ModelGlyph } : {},
53
- ...(selectedModel == null ? void 0 : selectedModel.provider) ? {
54
- modelIconClassName: providerIcons.providerIconColor(selectedModel.provider)
59
+ ...(usage == null ? void 0 : usage.backend) ? {
60
+ modelIconClassName: providerIcons.providerIconColor(usage.backend)
55
61
  } : {}
56
62
  }
57
63
  )
@@ -1 +1 @@
1
- {"version":3,"file":"ChatRuntimeToolbar.cjs","sources":["../../../src/data/chat/ChatRuntimeToolbar.tsx"],"sourcesContent":["import { ContextMeter } from \"./ContextMeter\";\nimport { providerIcon, providerIconColor } from \"./provider-icons\";\nimport type { ChatModel, ChatModelRuntime, ChatUsageSummary } from \"./types\";\nimport { RuntimeBar } from \"../runtime/RuntimeBar\";\nimport type { SpecRuntimeFamily } from \"../runtime/runtime-mode\";\n\nexport type ChatRuntimeToolbarProps = {\n models: ChatModel[];\n runtime: ChatModelRuntime;\n runtimeFamilies?: SpecRuntimeFamily[] | undefined;\n reasoningEfforts: string[];\n selectedModel?: ChatModel | undefined;\n usage?: ChatUsageSummary | null | undefined;\n threadId?: string | undefined;\n onRuntimeChange: (runtime: ChatModelRuntime) => void;\n};\n\nexport function ChatRuntimeToolbar({\n models,\n runtime,\n runtimeFamilies,\n reasoningEfforts,\n selectedModel,\n usage,\n threadId,\n onRuntimeChange,\n}: ChatRuntimeToolbarProps) {\n const showRuntimeBar = Boolean(\n runtimeFamilies?.length ||\n models.length ||\n runtime.backend ||\n runtime.id ||\n runtime.model,\n );\n const showContextMeter = Boolean(threadId || selectedModel || usage);\n if (!showRuntimeBar && !showContextMeter) return null;\n\n const contextWindow = selectedModel?.contextWindow ?? usage?.maxTokens ?? 0;\n const usedTokens = usage?.usedTokens ?? 0;\n const ModelGlyph = providerIcon(selectedModel?.provider);\n\n return (\n <div className=\"flex flex-1 items-center gap-2\">\n {showRuntimeBar && (\n <RuntimeBar\n variant=\"combo\"\n value={runtime}\n onChange={onRuntimeChange}\n models={models}\n reasoningEfforts={reasoningEfforts}\n {...(runtimeFamilies ? { families: runtimeFamilies } : {})}\n />\n )}\n {showContextMeter && (\n <>\n <div className=\"flex-1\" />\n <ContextMeter\n mode=\"gauge\"\n usedPercent={\n contextWindow > 0\n ? Math.round((usedTokens / contextWindow) * 100)\n : 0\n }\n usedTokens={usedTokens}\n {...(contextWindow > 0 ? { windowTokens: contextWindow } : {})}\n {...(usage?.messageCount != null\n ? { messageCount: usage.messageCount }\n : {})}\n {...(usage?.cost != null ? { cost: { total: usage.cost } } : {})}\n {...(threadId ? { sessionId: threadId } : {})}\n {...(selectedModel?.label\n ? { model: selectedModel.label }\n : usage?.modelLabel\n ? { model: usage.modelLabel }\n : {})}\n {...(runtime.effort ? { effort: runtime.effort } : {})}\n {...(runtime.mode ? { executionMode: runtime.mode } : {})}\n {...(ModelGlyph ? { modelIcon: ModelGlyph } : {})}\n {...(selectedModel?.provider\n ? {\n modelIconClassName: providerIconColor(selectedModel.provider),\n }\n : {})}\n />\n </>\n )}\n </div>\n );\n}\n"],"names":["providerIcon","jsxs","jsx","RuntimeBar","Fragment","ContextMeter","providerIconColor"],"mappings":";;;;;;AAiBO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,iBAAiB;AAAA,KACrB,mDAAiB,WACjB,OAAO,UACP,QAAQ,WACR,QAAQ,MACR,QAAQ;AAAA,EAAA;AAEV,QAAM,mBAAmB,QAAQ,YAAY,iBAAiB,KAAK;AACnE,MAAI,CAAC,kBAAkB,CAAC,iBAAkB,QAAO;AAEjD,QAAM,iBAAgB,+CAAe,mBAAiB,+BAAO,cAAa;AAC1E,QAAM,cAAa,+BAAO,eAAc;AACxC,QAAM,aAAaA,cAAAA,aAAa,+CAAe,QAAQ;AAEvD,SACEC,2BAAAA,KAAC,OAAA,EAAI,WAAU,kCACZ,UAAA;AAAA,IAAA,kBACCC,2BAAAA;AAAAA,MAACC,WAAAA;AAAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,OAAO;AAAA,QACP,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACC,GAAI,kBAAkB,EAAE,UAAU,oBAAoB,CAAA;AAAA,MAAC;AAAA,IAAA;AAAA,IAG3D,oBACCF,2BAAAA,KAAAG,qBAAA,EACE,UAAA;AAAA,MAAAF,2BAAAA,IAAC,OAAA,EAAI,WAAU,SAAA,CAAS;AAAA,MACxBA,2BAAAA;AAAAA,QAACG,aAAAA;AAAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,aACE,gBAAgB,IACZ,KAAK,MAAO,aAAa,gBAAiB,GAAG,IAC7C;AAAA,UAEN;AAAA,UACC,GAAI,gBAAgB,IAAI,EAAE,cAAc,cAAA,IAAkB,CAAA;AAAA,UAC1D,IAAI,+BAAO,iBAAgB,OACxB,EAAE,cAAc,MAAM,aAAA,IACtB,CAAA;AAAA,UACH,IAAI,+BAAO,SAAQ,OAAO,EAAE,MAAM,EAAE,OAAO,MAAM,KAAA,EAAK,IAAM,CAAA;AAAA,UAC5D,GAAI,WAAW,EAAE,WAAW,SAAA,IAAa,CAAA;AAAA,UACzC,IAAI,+CAAe,SAChB,EAAE,OAAO,cAAc,MAAA,KACvB,+BAAO,cACL,EAAE,OAAO,MAAM,WAAA,IACf,CAAA;AAAA,UACL,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAA,IAAW,CAAA;AAAA,UAClD,GAAI,QAAQ,OAAO,EAAE,eAAe,QAAQ,KAAA,IAAS,CAAA;AAAA,UACrD,GAAI,aAAa,EAAE,WAAW,WAAA,IAAe,CAAA;AAAA,UAC7C,IAAI,+CAAe,YAChB;AAAA,YACE,oBAAoBC,cAAAA,kBAAkB,cAAc,QAAQ;AAAA,UAAA,IAE9D,CAAA;AAAA,QAAC;AAAA,MAAA;AAAA,IACP,EAAA,CACF;AAAA,EAAA,GAEJ;AAEJ;;"}
1
+ {"version":3,"file":"ChatRuntimeToolbar.cjs","sources":["../../../src/data/chat/ChatRuntimeToolbar.tsx"],"sourcesContent":["import { ContextMeter } from \"./ContextMeter\";\nimport { providerIcon, providerIconColor } from \"./provider-icons\";\nimport type { ChatModel, ChatModelRuntime, ChatUsageSummary } from \"./types\";\nimport { RuntimeBar } from \"../runtime/RuntimeBar\";\nimport type { SpecRuntimeFamily } from \"../runtime/runtime-mode\";\n\nexport type ChatRuntimeToolbarProps = {\n models: ChatModel[];\n runtime: ChatModelRuntime;\n runtimeFamilies?: SpecRuntimeFamily[] | undefined;\n reasoningEfforts: string[];\n selectedModel?: ChatModel | undefined;\n usage?: ChatUsageSummary | null | undefined;\n threadId?: string | undefined;\n locked?: boolean | undefined;\n onRuntimeChange: (runtime: ChatModelRuntime) => void;\n};\n\nexport function ChatRuntimeToolbar({\n models,\n runtime,\n runtimeFamilies,\n reasoningEfforts,\n selectedModel,\n usage,\n threadId,\n locked = false,\n onRuntimeChange,\n}: ChatRuntimeToolbarProps) {\n const showRuntimeBar = Boolean(\n runtimeFamilies?.length ||\n models.length ||\n runtime.backend ||\n runtime.id ||\n runtime.model,\n );\n const showContextMeter = Boolean(threadId || selectedModel || usage);\n if (!showRuntimeBar && !showContextMeter) return null;\n\n const contextWindow = usage?.maxTokens ?? 0;\n const usedTokens = usage?.usedTokens ?? 0;\n const ModelGlyph = providerIcon(usage?.backend);\n\n return (\n <div className=\"flex flex-1 items-center gap-2\">\n {showRuntimeBar && (\n <RuntimeBar\n variant=\"combo\"\n value={runtime}\n onChange={onRuntimeChange}\n models={models}\n reasoningEfforts={reasoningEfforts}\n locked={locked}\n {...(runtimeFamilies ? { families: runtimeFamilies } : {})}\n />\n )}\n {showContextMeter && (\n <>\n <div className=\"flex-1\" />\n <ContextMeter\n mode=\"gauge\"\n usedPercent={\n contextWindow > 0\n ? Math.round((usedTokens / contextWindow) * 100)\n : 0\n }\n usedTokens={usedTokens}\n {...(contextWindow > 0 ? { windowTokens: contextWindow } : {})}\n {...(usage?.messageCount != null\n ? { messageCount: usage.messageCount }\n : {})}\n {...(usage?.cost != null ? { cost: { total: usage.cost } } : {})}\n {...(usage?.backend ? { backend: usage.backend } : {})}\n {...(usage?.executionMode\n ? { executionMode: usage.executionMode }\n : {})}\n {...(usage?.model\n ? { model: usage.model }\n : usage?.modelLabel\n ? { model: usage.modelLabel }\n : {})}\n {...(usage?.captainSessionId\n ? { captainSessionId: usage.captainSessionId }\n : {})}\n {...(usage?.providerSessionId\n ? { providerSessionId: usage.providerSessionId }\n : {})}\n {...(usage?.threadId ? { threadId: usage.threadId } : {})}\n {...(usage?.turnId ? { turnId: usage.turnId } : {})}\n {...(runtime.effort ? { effort: runtime.effort } : {})}\n {...(ModelGlyph ? { modelIcon: ModelGlyph } : {})}\n {...(usage?.backend\n ? {\n modelIconClassName: providerIconColor(usage.backend),\n }\n : {})}\n />\n </>\n )}\n </div>\n );\n}\n"],"names":["providerIcon","jsxs","jsx","RuntimeBar","Fragment","ContextMeter","providerIconColor"],"mappings":";;;;;;AAkBO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AACF,GAA4B;AAC1B,QAAM,iBAAiB;AAAA,KACrB,mDAAiB,WACjB,OAAO,UACP,QAAQ,WACR,QAAQ,MACR,QAAQ;AAAA,EAAA;AAEV,QAAM,mBAAmB,QAAQ,YAAY,iBAAiB,KAAK;AACnE,MAAI,CAAC,kBAAkB,CAAC,iBAAkB,QAAO;AAEjD,QAAM,iBAAgB,+BAAO,cAAa;AAC1C,QAAM,cAAa,+BAAO,eAAc;AACxC,QAAM,aAAaA,cAAAA,aAAa,+BAAO,OAAO;AAE9C,SACEC,2BAAAA,KAAC,OAAA,EAAI,WAAU,kCACZ,UAAA;AAAA,IAAA,kBACCC,2BAAAA;AAAAA,MAACC,WAAAA;AAAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,OAAO;AAAA,QACP,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACC,GAAI,kBAAkB,EAAE,UAAU,oBAAoB,CAAA;AAAA,MAAC;AAAA,IAAA;AAAA,IAG3D,oBACCF,2BAAAA,KAAAG,qBAAA,EACE,UAAA;AAAA,MAAAF,2BAAAA,IAAC,OAAA,EAAI,WAAU,SAAA,CAAS;AAAA,MACxBA,2BAAAA;AAAAA,QAACG,aAAAA;AAAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,aACE,gBAAgB,IACZ,KAAK,MAAO,aAAa,gBAAiB,GAAG,IAC7C;AAAA,UAEN;AAAA,UACC,GAAI,gBAAgB,IAAI,EAAE,cAAc,cAAA,IAAkB,CAAA;AAAA,UAC1D,IAAI,+BAAO,iBAAgB,OACxB,EAAE,cAAc,MAAM,aAAA,IACtB,CAAA;AAAA,UACH,IAAI,+BAAO,SAAQ,OAAO,EAAE,MAAM,EAAE,OAAO,MAAM,KAAA,EAAK,IAAM,CAAA;AAAA,UAC5D,IAAI,+BAAO,WAAU,EAAE,SAAS,MAAM,QAAA,IAAY,CAAA;AAAA,UAClD,IAAI,+BAAO,iBACR,EAAE,eAAe,MAAM,cAAA,IACvB,CAAA;AAAA,UACH,IAAI,+BAAO,SACR,EAAE,OAAO,MAAM,MAAA,KACf,+BAAO,cACL,EAAE,OAAO,MAAM,WAAA,IACf,CAAA;AAAA,UACL,IAAI,+BAAO,oBACR,EAAE,kBAAkB,MAAM,iBAAA,IAC1B,CAAA;AAAA,UACH,IAAI,+BAAO,qBACR,EAAE,mBAAmB,MAAM,kBAAA,IAC3B,CAAA;AAAA,UACH,IAAI,+BAAO,YAAW,EAAE,UAAU,MAAM,SAAA,IAAa,CAAA;AAAA,UACrD,IAAI,+BAAO,UAAS,EAAE,QAAQ,MAAM,OAAA,IAAW,CAAA;AAAA,UAC/C,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAA,IAAW,CAAA;AAAA,UAClD,GAAI,aAAa,EAAE,WAAW,WAAA,IAAe,CAAA;AAAA,UAC7C,IAAI,+BAAO,WACR;AAAA,YACE,oBAAoBC,cAAAA,kBAAkB,MAAM,OAAO;AAAA,UAAA,IAErD,CAAA;AAAA,QAAC;AAAA,MAAA;AAAA,IACP,EAAA,CACF;AAAA,EAAA,GAEJ;AAEJ;;"}
@@ -8,7 +8,8 @@ export type ChatRuntimeToolbarProps = {
8
8
  selectedModel?: ChatModel | undefined;
9
9
  usage?: ChatUsageSummary | null | undefined;
10
10
  threadId?: string | undefined;
11
+ locked?: boolean | undefined;
11
12
  onRuntimeChange: (runtime: ChatModelRuntime) => void;
12
13
  };
13
- export declare function ChatRuntimeToolbar({ models, runtime, runtimeFamilies, reasoningEfforts, selectedModel, usage, threadId, onRuntimeChange, }: ChatRuntimeToolbarProps): import("react/jsx-runtime").JSX.Element | null;
14
+ export declare function ChatRuntimeToolbar({ models, runtime, runtimeFamilies, reasoningEfforts, selectedModel, usage, threadId, locked, onRuntimeChange, }: ChatRuntimeToolbarProps): import("react/jsx-runtime").JSX.Element | null;
14
15
  //# sourceMappingURL=ChatRuntimeToolbar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatRuntimeToolbar.d.ts","sourceRoot":"","sources":["../../../src/data/chat/ChatRuntimeToolbar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE7E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,eAAe,CAAC,EAAE,iBAAiB,EAAE,GAAG,SAAS,CAAC;IAClD,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACtC,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,eAAe,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,OAAO,EACP,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,KAAK,EACL,QAAQ,EACR,eAAe,GAChB,EAAE,uBAAuB,kDA8DzB"}
1
+ {"version":3,"file":"ChatRuntimeToolbar.d.ts","sourceRoot":"","sources":["../../../src/data/chat/ChatRuntimeToolbar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE7E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,eAAe,CAAC,EAAE,iBAAiB,EAAE,GAAG,SAAS,CAAC;IAClD,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACtC,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,eAAe,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,OAAO,EACP,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,KAAK,EACL,QAAQ,EACR,MAAc,EACd,eAAe,GAChB,EAAE,uBAAuB,kDAyEzB"}
@@ -10,6 +10,7 @@ function ChatRuntimeToolbar({
10
10
  selectedModel,
11
11
  usage,
12
12
  threadId,
13
+ locked = false,
13
14
  onRuntimeChange
14
15
  }) {
15
16
  const showRuntimeBar = Boolean(
@@ -17,9 +18,9 @@ function ChatRuntimeToolbar({
17
18
  );
18
19
  const showContextMeter = Boolean(threadId || selectedModel || usage);
19
20
  if (!showRuntimeBar && !showContextMeter) return null;
20
- const contextWindow = (selectedModel == null ? void 0 : selectedModel.contextWindow) ?? (usage == null ? void 0 : usage.maxTokens) ?? 0;
21
+ const contextWindow = (usage == null ? void 0 : usage.maxTokens) ?? 0;
21
22
  const usedTokens = (usage == null ? void 0 : usage.usedTokens) ?? 0;
22
- const ModelGlyph = providerIcon(selectedModel == null ? void 0 : selectedModel.provider);
23
+ const ModelGlyph = providerIcon(usage == null ? void 0 : usage.backend);
23
24
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 items-center gap-2", children: [
24
25
  showRuntimeBar && /* @__PURE__ */ jsx(
25
26
  RuntimeBar,
@@ -29,6 +30,7 @@ function ChatRuntimeToolbar({
29
30
  onChange: onRuntimeChange,
30
31
  models,
31
32
  reasoningEfforts,
33
+ locked,
32
34
  ...runtimeFamilies ? { families: runtimeFamilies } : {}
33
35
  }
34
36
  ),
@@ -43,13 +45,17 @@ function ChatRuntimeToolbar({
43
45
  ...contextWindow > 0 ? { windowTokens: contextWindow } : {},
44
46
  ...(usage == null ? void 0 : usage.messageCount) != null ? { messageCount: usage.messageCount } : {},
45
47
  ...(usage == null ? void 0 : usage.cost) != null ? { cost: { total: usage.cost } } : {},
46
- ...threadId ? { sessionId: threadId } : {},
47
- ...(selectedModel == null ? void 0 : selectedModel.label) ? { model: selectedModel.label } : (usage == null ? void 0 : usage.modelLabel) ? { model: usage.modelLabel } : {},
48
+ ...(usage == null ? void 0 : usage.backend) ? { backend: usage.backend } : {},
49
+ ...(usage == null ? void 0 : usage.executionMode) ? { executionMode: usage.executionMode } : {},
50
+ ...(usage == null ? void 0 : usage.model) ? { model: usage.model } : (usage == null ? void 0 : usage.modelLabel) ? { model: usage.modelLabel } : {},
51
+ ...(usage == null ? void 0 : usage.captainSessionId) ? { captainSessionId: usage.captainSessionId } : {},
52
+ ...(usage == null ? void 0 : usage.providerSessionId) ? { providerSessionId: usage.providerSessionId } : {},
53
+ ...(usage == null ? void 0 : usage.threadId) ? { threadId: usage.threadId } : {},
54
+ ...(usage == null ? void 0 : usage.turnId) ? { turnId: usage.turnId } : {},
48
55
  ...runtime.effort ? { effort: runtime.effort } : {},
49
- ...runtime.mode ? { executionMode: runtime.mode } : {},
50
56
  ...ModelGlyph ? { modelIcon: ModelGlyph } : {},
51
- ...(selectedModel == null ? void 0 : selectedModel.provider) ? {
52
- modelIconClassName: providerIconColor(selectedModel.provider)
57
+ ...(usage == null ? void 0 : usage.backend) ? {
58
+ modelIconClassName: providerIconColor(usage.backend)
53
59
  } : {}
54
60
  }
55
61
  )
@@ -1 +1 @@
1
- {"version":3,"file":"ChatRuntimeToolbar.js","sources":["../../../src/data/chat/ChatRuntimeToolbar.tsx"],"sourcesContent":["import { ContextMeter } from \"./ContextMeter\";\nimport { providerIcon, providerIconColor } from \"./provider-icons\";\nimport type { ChatModel, ChatModelRuntime, ChatUsageSummary } from \"./types\";\nimport { RuntimeBar } from \"../runtime/RuntimeBar\";\nimport type { SpecRuntimeFamily } from \"../runtime/runtime-mode\";\n\nexport type ChatRuntimeToolbarProps = {\n models: ChatModel[];\n runtime: ChatModelRuntime;\n runtimeFamilies?: SpecRuntimeFamily[] | undefined;\n reasoningEfforts: string[];\n selectedModel?: ChatModel | undefined;\n usage?: ChatUsageSummary | null | undefined;\n threadId?: string | undefined;\n onRuntimeChange: (runtime: ChatModelRuntime) => void;\n};\n\nexport function ChatRuntimeToolbar({\n models,\n runtime,\n runtimeFamilies,\n reasoningEfforts,\n selectedModel,\n usage,\n threadId,\n onRuntimeChange,\n}: ChatRuntimeToolbarProps) {\n const showRuntimeBar = Boolean(\n runtimeFamilies?.length ||\n models.length ||\n runtime.backend ||\n runtime.id ||\n runtime.model,\n );\n const showContextMeter = Boolean(threadId || selectedModel || usage);\n if (!showRuntimeBar && !showContextMeter) return null;\n\n const contextWindow = selectedModel?.contextWindow ?? usage?.maxTokens ?? 0;\n const usedTokens = usage?.usedTokens ?? 0;\n const ModelGlyph = providerIcon(selectedModel?.provider);\n\n return (\n <div className=\"flex flex-1 items-center gap-2\">\n {showRuntimeBar && (\n <RuntimeBar\n variant=\"combo\"\n value={runtime}\n onChange={onRuntimeChange}\n models={models}\n reasoningEfforts={reasoningEfforts}\n {...(runtimeFamilies ? { families: runtimeFamilies } : {})}\n />\n )}\n {showContextMeter && (\n <>\n <div className=\"flex-1\" />\n <ContextMeter\n mode=\"gauge\"\n usedPercent={\n contextWindow > 0\n ? Math.round((usedTokens / contextWindow) * 100)\n : 0\n }\n usedTokens={usedTokens}\n {...(contextWindow > 0 ? { windowTokens: contextWindow } : {})}\n {...(usage?.messageCount != null\n ? { messageCount: usage.messageCount }\n : {})}\n {...(usage?.cost != null ? { cost: { total: usage.cost } } : {})}\n {...(threadId ? { sessionId: threadId } : {})}\n {...(selectedModel?.label\n ? { model: selectedModel.label }\n : usage?.modelLabel\n ? { model: usage.modelLabel }\n : {})}\n {...(runtime.effort ? { effort: runtime.effort } : {})}\n {...(runtime.mode ? { executionMode: runtime.mode } : {})}\n {...(ModelGlyph ? { modelIcon: ModelGlyph } : {})}\n {...(selectedModel?.provider\n ? {\n modelIconClassName: providerIconColor(selectedModel.provider),\n }\n : {})}\n />\n </>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":";;;;AAiBO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,iBAAiB;AAAA,KACrB,mDAAiB,WACjB,OAAO,UACP,QAAQ,WACR,QAAQ,MACR,QAAQ;AAAA,EAAA;AAEV,QAAM,mBAAmB,QAAQ,YAAY,iBAAiB,KAAK;AACnE,MAAI,CAAC,kBAAkB,CAAC,iBAAkB,QAAO;AAEjD,QAAM,iBAAgB,+CAAe,mBAAiB,+BAAO,cAAa;AAC1E,QAAM,cAAa,+BAAO,eAAc;AACxC,QAAM,aAAa,aAAa,+CAAe,QAAQ;AAEvD,SACE,qBAAC,OAAA,EAAI,WAAU,kCACZ,UAAA;AAAA,IAAA,kBACC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,OAAO;AAAA,QACP,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACC,GAAI,kBAAkB,EAAE,UAAU,oBAAoB,CAAA;AAAA,MAAC;AAAA,IAAA;AAAA,IAG3D,oBACC,qBAAA,UAAA,EACE,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,SAAA,CAAS;AAAA,MACxB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,aACE,gBAAgB,IACZ,KAAK,MAAO,aAAa,gBAAiB,GAAG,IAC7C;AAAA,UAEN;AAAA,UACC,GAAI,gBAAgB,IAAI,EAAE,cAAc,cAAA,IAAkB,CAAA;AAAA,UAC1D,IAAI,+BAAO,iBAAgB,OACxB,EAAE,cAAc,MAAM,aAAA,IACtB,CAAA;AAAA,UACH,IAAI,+BAAO,SAAQ,OAAO,EAAE,MAAM,EAAE,OAAO,MAAM,KAAA,EAAK,IAAM,CAAA;AAAA,UAC5D,GAAI,WAAW,EAAE,WAAW,SAAA,IAAa,CAAA;AAAA,UACzC,IAAI,+CAAe,SAChB,EAAE,OAAO,cAAc,MAAA,KACvB,+BAAO,cACL,EAAE,OAAO,MAAM,WAAA,IACf,CAAA;AAAA,UACL,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAA,IAAW,CAAA;AAAA,UAClD,GAAI,QAAQ,OAAO,EAAE,eAAe,QAAQ,KAAA,IAAS,CAAA;AAAA,UACrD,GAAI,aAAa,EAAE,WAAW,WAAA,IAAe,CAAA;AAAA,UAC7C,IAAI,+CAAe,YAChB;AAAA,YACE,oBAAoB,kBAAkB,cAAc,QAAQ;AAAA,UAAA,IAE9D,CAAA;AAAA,QAAC;AAAA,MAAA;AAAA,IACP,EAAA,CACF;AAAA,EAAA,GAEJ;AAEJ;"}
1
+ {"version":3,"file":"ChatRuntimeToolbar.js","sources":["../../../src/data/chat/ChatRuntimeToolbar.tsx"],"sourcesContent":["import { ContextMeter } from \"./ContextMeter\";\nimport { providerIcon, providerIconColor } from \"./provider-icons\";\nimport type { ChatModel, ChatModelRuntime, ChatUsageSummary } from \"./types\";\nimport { RuntimeBar } from \"../runtime/RuntimeBar\";\nimport type { SpecRuntimeFamily } from \"../runtime/runtime-mode\";\n\nexport type ChatRuntimeToolbarProps = {\n models: ChatModel[];\n runtime: ChatModelRuntime;\n runtimeFamilies?: SpecRuntimeFamily[] | undefined;\n reasoningEfforts: string[];\n selectedModel?: ChatModel | undefined;\n usage?: ChatUsageSummary | null | undefined;\n threadId?: string | undefined;\n locked?: boolean | undefined;\n onRuntimeChange: (runtime: ChatModelRuntime) => void;\n};\n\nexport function ChatRuntimeToolbar({\n models,\n runtime,\n runtimeFamilies,\n reasoningEfforts,\n selectedModel,\n usage,\n threadId,\n locked = false,\n onRuntimeChange,\n}: ChatRuntimeToolbarProps) {\n const showRuntimeBar = Boolean(\n runtimeFamilies?.length ||\n models.length ||\n runtime.backend ||\n runtime.id ||\n runtime.model,\n );\n const showContextMeter = Boolean(threadId || selectedModel || usage);\n if (!showRuntimeBar && !showContextMeter) return null;\n\n const contextWindow = usage?.maxTokens ?? 0;\n const usedTokens = usage?.usedTokens ?? 0;\n const ModelGlyph = providerIcon(usage?.backend);\n\n return (\n <div className=\"flex flex-1 items-center gap-2\">\n {showRuntimeBar && (\n <RuntimeBar\n variant=\"combo\"\n value={runtime}\n onChange={onRuntimeChange}\n models={models}\n reasoningEfforts={reasoningEfforts}\n locked={locked}\n {...(runtimeFamilies ? { families: runtimeFamilies } : {})}\n />\n )}\n {showContextMeter && (\n <>\n <div className=\"flex-1\" />\n <ContextMeter\n mode=\"gauge\"\n usedPercent={\n contextWindow > 0\n ? Math.round((usedTokens / contextWindow) * 100)\n : 0\n }\n usedTokens={usedTokens}\n {...(contextWindow > 0 ? { windowTokens: contextWindow } : {})}\n {...(usage?.messageCount != null\n ? { messageCount: usage.messageCount }\n : {})}\n {...(usage?.cost != null ? { cost: { total: usage.cost } } : {})}\n {...(usage?.backend ? { backend: usage.backend } : {})}\n {...(usage?.executionMode\n ? { executionMode: usage.executionMode }\n : {})}\n {...(usage?.model\n ? { model: usage.model }\n : usage?.modelLabel\n ? { model: usage.modelLabel }\n : {})}\n {...(usage?.captainSessionId\n ? { captainSessionId: usage.captainSessionId }\n : {})}\n {...(usage?.providerSessionId\n ? { providerSessionId: usage.providerSessionId }\n : {})}\n {...(usage?.threadId ? { threadId: usage.threadId } : {})}\n {...(usage?.turnId ? { turnId: usage.turnId } : {})}\n {...(runtime.effort ? { effort: runtime.effort } : {})}\n {...(ModelGlyph ? { modelIcon: ModelGlyph } : {})}\n {...(usage?.backend\n ? {\n modelIconClassName: providerIconColor(usage.backend),\n }\n : {})}\n />\n </>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":";;;;AAkBO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AACF,GAA4B;AAC1B,QAAM,iBAAiB;AAAA,KACrB,mDAAiB,WACjB,OAAO,UACP,QAAQ,WACR,QAAQ,MACR,QAAQ;AAAA,EAAA;AAEV,QAAM,mBAAmB,QAAQ,YAAY,iBAAiB,KAAK;AACnE,MAAI,CAAC,kBAAkB,CAAC,iBAAkB,QAAO;AAEjD,QAAM,iBAAgB,+BAAO,cAAa;AAC1C,QAAM,cAAa,+BAAO,eAAc;AACxC,QAAM,aAAa,aAAa,+BAAO,OAAO;AAE9C,SACE,qBAAC,OAAA,EAAI,WAAU,kCACZ,UAAA;AAAA,IAAA,kBACC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,OAAO;AAAA,QACP,UAAU;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACC,GAAI,kBAAkB,EAAE,UAAU,oBAAoB,CAAA;AAAA,MAAC;AAAA,IAAA;AAAA,IAG3D,oBACC,qBAAA,UAAA,EACE,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,SAAA,CAAS;AAAA,MACxB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,aACE,gBAAgB,IACZ,KAAK,MAAO,aAAa,gBAAiB,GAAG,IAC7C;AAAA,UAEN;AAAA,UACC,GAAI,gBAAgB,IAAI,EAAE,cAAc,cAAA,IAAkB,CAAA;AAAA,UAC1D,IAAI,+BAAO,iBAAgB,OACxB,EAAE,cAAc,MAAM,aAAA,IACtB,CAAA;AAAA,UACH,IAAI,+BAAO,SAAQ,OAAO,EAAE,MAAM,EAAE,OAAO,MAAM,KAAA,EAAK,IAAM,CAAA;AAAA,UAC5D,IAAI,+BAAO,WAAU,EAAE,SAAS,MAAM,QAAA,IAAY,CAAA;AAAA,UAClD,IAAI,+BAAO,iBACR,EAAE,eAAe,MAAM,cAAA,IACvB,CAAA;AAAA,UACH,IAAI,+BAAO,SACR,EAAE,OAAO,MAAM,MAAA,KACf,+BAAO,cACL,EAAE,OAAO,MAAM,WAAA,IACf,CAAA;AAAA,UACL,IAAI,+BAAO,oBACR,EAAE,kBAAkB,MAAM,iBAAA,IAC1B,CAAA;AAAA,UACH,IAAI,+BAAO,qBACR,EAAE,mBAAmB,MAAM,kBAAA,IAC3B,CAAA;AAAA,UACH,IAAI,+BAAO,YAAW,EAAE,UAAU,MAAM,SAAA,IAAa,CAAA;AAAA,UACrD,IAAI,+BAAO,UAAS,EAAE,QAAQ,MAAM,OAAA,IAAW,CAAA;AAAA,UAC/C,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAA,IAAW,CAAA;AAAA,UAClD,GAAI,aAAa,EAAE,WAAW,WAAA,IAAe,CAAA;AAAA,UAC7C,IAAI,+BAAO,WACR;AAAA,YACE,oBAAoB,kBAAkB,MAAM,OAAO;AAAA,UAAA,IAErD,CAAA;AAAA,QAAC;AAAA,MAAA;AAAA,IACP,EAAA,CACF;AAAA,EAAA,GAEJ;AAEJ;"}
@@ -79,6 +79,11 @@ function ContextMeter({
79
79
  windowTokens,
80
80
  messageCount,
81
81
  sessionId,
82
+ captainSessionId,
83
+ providerSessionId,
84
+ threadId,
85
+ turnId,
86
+ backend,
82
87
  executionMode,
83
88
  model,
84
89
  modelIcon: Glyph,
@@ -104,17 +109,38 @@ function ContextMeter({
104
109
  const totalCost = (cost == null ? void 0 : cost.total) ?? 0;
105
110
  const EffortGlyph = effort ? effortIcons.effortLevelIcon(effort) : void 0;
106
111
  const effortColor = effort ? effortIcons.effortLevelColor(effort) : void 0;
107
- const copyStatus = copyResult && copyResult.sessionId === sessionId ? copyResult.status : void 0;
108
- const copySessionId = async () => {
109
- if (!sessionId) return;
112
+ const identities = [
113
+ sessionId ? { key: "session", label: "Session", value: sessionId } : void 0,
114
+ captainSessionId ? {
115
+ key: "captain-session",
116
+ label: "Captain session",
117
+ value: captainSessionId
118
+ } : void 0,
119
+ providerSessionId ? {
120
+ key: "provider-session",
121
+ label: "Provider session",
122
+ value: providerSessionId
123
+ } : void 0,
124
+ threadId ? { key: "thread", label: "Thread", value: threadId } : void 0,
125
+ turnId ? { key: "turn", label: "Turn", value: turnId } : void 0
126
+ ].filter((identity) => identity !== void 0);
127
+ const copyIdentity = async (identity) => {
110
128
  if (copyResetTimer.current !== void 0) {
111
129
  window.clearTimeout(copyResetTimer.current);
112
130
  }
113
131
  try {
114
- await navigator.clipboard.writeText(sessionId);
115
- setCopyResult({ sessionId, status: "copied" });
132
+ await navigator.clipboard.writeText(identity.value);
133
+ setCopyResult({
134
+ identity: identity.key,
135
+ value: identity.value,
136
+ status: "copied"
137
+ });
116
138
  } catch {
117
- setCopyResult({ sessionId, status: "failed" });
139
+ setCopyResult({
140
+ identity: identity.key,
141
+ value: identity.value,
142
+ status: "failed"
143
+ });
118
144
  }
119
145
  copyResetTimer.current = window.setTimeout(
120
146
  () => setCopyResult(void 0),
@@ -262,33 +288,44 @@ function ContextMeter({
262
288
  }
263
289
  ) : null
264
290
  ] }),
265
- (sessionId || executionMode) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5 border-b border-border pb-2", children: [
266
- sessionId ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4", children: [
267
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Session" }),
268
- /* @__PURE__ */ jsxRuntime.jsxs(
269
- "button",
291
+ (identities.length > 0 || backend || executionMode) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5 border-b border-border pb-2", children: [
292
+ identities.map((identity) => {
293
+ const copyStatus = (copyResult == null ? void 0 : copyResult.identity) === identity.key && copyResult.value === identity.value ? copyResult.status : void 0;
294
+ return /* @__PURE__ */ jsxRuntime.jsxs(
295
+ "div",
270
296
  {
271
- type: "button",
272
- "aria-label": copyStatus === "copied" ? "Session ID copied" : copyStatus === "failed" ? "Session ID copy failed" : "Copy session ID",
273
- title: sessionId,
274
- className: utils.cn(
275
- "flex min-w-0 max-w-48 items-center gap-1.5 font-medium hover:text-foreground",
276
- copyStatus === "failed" && "text-destructive"
277
- ),
278
- onClick: () => void copySessionId(),
297
+ className: "flex items-center justify-between gap-4",
279
298
  children: [
280
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-mono", children: sessionId }),
281
- /* @__PURE__ */ jsxRuntime.jsx(
282
- Icon.Icon,
299
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: identity.label }),
300
+ /* @__PURE__ */ jsxRuntime.jsxs(
301
+ "button",
283
302
  {
284
- icon: copyStatus === "copied" ? UiCheck.UiCheck : UiCopy.UiCopy,
285
- className: "size-3.5 shrink-0"
303
+ type: "button",
304
+ "aria-label": copyStatus === "copied" ? `${identity.label} ID copied` : copyStatus === "failed" ? `${identity.label} ID copy failed` : `Copy ${identity.label.toLowerCase()} ID`,
305
+ title: identity.value,
306
+ className: utils.cn(
307
+ "flex min-w-0 max-w-48 items-center gap-1.5 font-medium hover:text-foreground",
308
+ copyStatus === "failed" && "text-destructive"
309
+ ),
310
+ onClick: () => void copyIdentity(identity),
311
+ children: [
312
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-mono", children: identity.value }),
313
+ /* @__PURE__ */ jsxRuntime.jsx(
314
+ Icon.Icon,
315
+ {
316
+ icon: copyStatus === "copied" ? UiCheck.UiCheck : UiCopy.UiCopy,
317
+ className: "size-3.5 shrink-0"
318
+ }
319
+ )
320
+ ]
286
321
  }
287
322
  )
288
323
  ]
289
- }
290
- )
291
- ] }) : null,
324
+ },
325
+ identity.key
326
+ );
327
+ }),
328
+ backend ? /* @__PURE__ */ jsxRuntime.jsx(Row, { label: "Backend", value: backend }) : null,
292
329
  executionMode ? /* @__PURE__ */ jsxRuntime.jsx(Row, { label: "Mode", value: executionMode }) : null
293
330
  ] }),
294
331
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMeter.cjs","sources":["../../../src/data/chat/ContextMeter.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { compactTokens, formatCost } from \"../../lib/tokens\";\nimport { UiCheck, UiCopy } from \"../../icons\";\nimport { Icon, type StaticIconComponent } from \"../Icon\";\nimport { HoverCard } from \"../../overlay/HoverCard\";\nimport {\n effortLevelColor,\n effortLevelIcon,\n effortLevelLabel,\n} from \"./effort-icons\";\n\nexport type ContextMeterMode = \"bar\" | \"gauge\";\n\nexport type ContextMeterTokens = {\n input?: number | undefined;\n output?: number | undefined;\n reasoning?: number | undefined;\n cacheRead?: number | undefined;\n cacheWrite?: number | undefined;\n total?: number | undefined;\n};\n\nexport type ContextMeterCost = {\n input?: number | undefined;\n output?: number | undefined;\n reasoning?: number | undefined;\n cacheRead?: number | undefined;\n cacheWrite?: number | undefined;\n total?: number | undefined;\n};\n\nexport type ContextMeterBudget = {\n used?: number | undefined;\n total?: number | undefined;\n remaining?: number | undefined;\n};\n\nexport type ContextMeterProps = {\n /** Trigger shape: a compact `bar` (session header) or a circular `gauge`\n * (chat toolbar). Both open the same hover popover. */\n mode?: ContextMeterMode;\n /** Share of the context window used, 0–100 — drives the fill and tone. */\n usedPercent: number;\n /** Context-window tokens shown in the popover. */\n usedTokens?: number | undefined;\n windowTokens?: number | undefined;\n /** Message count shown in the popover (chat). */\n messageCount?: number | undefined;\n /** Session identifier exposed as a click-to-copy value in the popover. */\n sessionId?: string | undefined;\n /** Runtime mechanism used to execute the session, such as api or cmux. */\n executionMode?: string | undefined;\n /** Model id/label and its brand glyph. */\n model?: string | undefined;\n modelIcon?: StaticIconComponent | undefined;\n modelIconClassName?: string | undefined;\n /** Reasoning effort shown with its semantic glyph and color in the hover card. */\n effort?: string | undefined;\n /** Per-bucket token counts for the popover breakdown. */\n tokens?: ContextMeterTokens | undefined;\n /** Per-bucket costs (USD) for the popover breakdown. */\n cost?: ContextMeterCost | undefined;\n budget?: ContextMeterBudget | undefined;\n className?: string | undefined;\n};\n\nconst COPY_STATUS_RESET_MS = 2000;\nconst GAUGE_RADIUS = 15;\nconst GAUGE_CIRCUMFERENCE = 2 * Math.PI * GAUGE_RADIUS;\n\nfunction barTone(pct: number): string {\n return pct > 80\n ? \"bg-red-600 [[data-theme=dark]_&]:bg-red-400\"\n : pct > 50\n ? \"bg-amber-700 [[data-theme=dark]_&]:bg-amber-400\"\n : \"bg-emerald-600 [[data-theme=dark]_&]:bg-emerald-400\";\n}\n\nfunction ringTone(pct: number): string {\n return pct > 80\n ? \"text-red-600 [[data-theme=dark]_&]:text-red-400\"\n : pct > 50\n ? \"text-amber-700 [[data-theme=dark]_&]:text-amber-400\"\n : \"text-emerald-600 [[data-theme=dark]_&]:text-emerald-400\";\n}\n\nfunction textTone(pct: number): string {\n return pct > 80\n ? \"text-red-700 [[data-theme=dark]_&]:text-red-400\"\n : pct > 50\n ? \"text-amber-700 [[data-theme=dark]_&]:text-amber-400\"\n : \"text-emerald-700 [[data-theme=dark]_&]:text-emerald-400\";\n}\n\nfunction Row({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"flex justify-between gap-4\">\n <span className=\"text-muted-foreground\">{label}</span>\n <span className=\"font-medium tabular-nums\">{value}</span>\n </div>\n );\n}\n\nfunction anyPositive(...values: (number | undefined)[]): boolean {\n return values.some((v) => v != null && v > 0);\n}\n\ntype BucketRow = {\n label: string;\n tokens?: number | undefined;\n cost?: number | undefined;\n};\n\n/** One row per token/cost bucket, kept only when it carries a token or cost\n * value. Cache stays split into read and write on both axes. */\nfunction bucketRows(\n tokens?: ContextMeterTokens,\n cost?: ContextMeterCost,\n): BucketRow[] {\n const rows: BucketRow[] = [\n { label: \"Input\", tokens: tokens?.input, cost: cost?.input },\n { label: \"Output\", tokens: tokens?.output, cost: cost?.output },\n { label: \"Reasoning\", tokens: tokens?.reasoning, cost: cost?.reasoning },\n { label: \"Cache read\", tokens: tokens?.cacheRead, cost: cost?.cacheRead },\n {\n label: \"Cache write\",\n tokens: tokens?.cacheWrite,\n cost: cost?.cacheWrite,\n },\n ];\n return rows.filter((row) => (row.tokens ?? 0) > 0 || (row.cost ?? 0) > 0);\n}\n\nfunction UsageTable({\n rows,\n totalTokens,\n totalCost,\n showTokens,\n showCost,\n}: {\n rows: BucketRow[];\n totalTokens: number;\n totalCost: number;\n showTokens: boolean;\n showCost: boolean;\n}) {\n const numCell = \"px-1 py-0.5 text-right tabular-nums\";\n return (\n <table className=\"w-full border-collapse\">\n <thead>\n <tr className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">\n <th className=\"px-1 py-0.5 text-left font-medium\" />\n {showTokens && (\n <th className=\"px-1 py-0.5 text-right font-medium\">Tokens</th>\n )}\n {showCost && (\n <th className=\"px-1 py-0.5 text-right font-medium\">Cost</th>\n )}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row.label}>\n <td className=\"px-1 py-0.5 text-left text-muted-foreground\">\n {row.label}\n </td>\n {showTokens && (\n <td className={numCell}>\n {row.tokens ? (\n compactTokens(row.tokens)\n ) : (\n <span className=\"text-muted-foreground/50\">—</span>\n )}\n </td>\n )}\n {showCost && (\n <td className={numCell}>\n {row.cost ? (\n formatCost(row.cost)\n ) : (\n <span className=\"text-muted-foreground/50\">—</span>\n )}\n </td>\n )}\n </tr>\n ))}\n <tr className=\"border-t border-border font-medium\">\n <td className=\"px-1 py-0.5 text-left\">Total</td>\n {showTokens && (\n <td className={numCell}>{compactTokens(totalTokens)}</td>\n )}\n {showCost && <td className={numCell}>{formatCost(totalCost)}</td>}\n </tr>\n </tbody>\n </table>\n );\n}\n\n/** Unified context-window meter. Renders as a compact progress `bar` or a\n * circular `gauge`; hovering or focusing it opens a popover with the model, the\n * copyable session id, execution mode, context-window breakdown, per-bucket\n * token usage and the cost + budget detail. Domain-agnostic — callers feed\n * plain values. */\nexport function ContextMeter({\n mode = \"bar\",\n usedPercent,\n usedTokens,\n windowTokens,\n messageCount,\n sessionId,\n executionMode,\n model,\n modelIcon: Glyph,\n modelIconClassName,\n effort,\n tokens,\n cost,\n budget,\n className,\n}: ContextMeterProps) {\n const [copyResult, setCopyResult] = useState<\n { sessionId: string; status: \"copied\" | \"failed\" } | undefined\n >();\n const copyResetTimer = useRef<number | undefined>(undefined);\n useEffect(\n () => () => {\n if (copyResetTimer.current !== undefined) {\n window.clearTimeout(copyResetTimer.current);\n }\n },\n [],\n );\n const pct = Math.min(100, Math.max(0, Math.round(usedPercent)));\n const totalTokens = tokens?.total ?? 0;\n const totalCost = cost?.total ?? 0;\n const EffortGlyph = effort ? effortLevelIcon(effort) : undefined;\n const effortColor = effort ? effortLevelColor(effort) : undefined;\n const copyStatus =\n copyResult && copyResult.sessionId === sessionId\n ? copyResult.status\n : undefined;\n // The status is transient feedback for the click that produced it — without\n // this it would greet every later hover of the same session.\n const copySessionId = async () => {\n if (!sessionId) return;\n if (copyResetTimer.current !== undefined) {\n window.clearTimeout(copyResetTimer.current);\n }\n try {\n await navigator.clipboard.writeText(sessionId);\n setCopyResult({ sessionId, status: \"copied\" });\n } catch {\n setCopyResult({ sessionId, status: \"failed\" });\n }\n copyResetTimer.current = window.setTimeout(\n () => setCopyResult(undefined),\n COPY_STATUS_RESET_MS,\n );\n };\n\n const trigger =\n mode === \"gauge\" ? (\n <span\n className={cn(\n \"inline-flex items-center rounded-md px-2.5 py-1.5 text-xs text-muted-foreground transition-colors hover:bg-accent hover:text-foreground\",\n className,\n )}\n aria-label={`Context ${pct}% used`}\n >\n <span className=\"relative inline-flex size-9 shrink-0 items-center justify-center\">\n <svg\n data-context-gauge-ring\n aria-hidden=\"true\"\n width=\"36\"\n height=\"36\"\n viewBox=\"0 0 36 36\"\n className={cn(\"absolute inset-0\", ringTone(pct))}\n >\n <circle\n cx=\"18\"\n cy=\"18\"\n r={GAUGE_RADIUS}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n opacity=\"0.15\"\n />\n <circle\n cx=\"18\"\n cy=\"18\"\n r={GAUGE_RADIUS}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeDasharray={GAUGE_CIRCUMFERENCE}\n strokeDashoffset={(1 - pct / 100) * GAUGE_CIRCUMFERENCE}\n strokeLinecap=\"round\"\n transform=\"rotate(-90 18 18)\"\n />\n </svg>\n {Glyph ? (\n <Icon\n icon={Glyph}\n className={cn(\"relative size-5\", modelIconClassName)}\n />\n ) : (\n <span\n className={cn(\n \"relative text-[9px] font-semibold tabular-nums\",\n textTone(pct),\n )}\n >\n {pct}\n </span>\n )}\n </span>\n </span>\n ) : (\n <span\n className={cn(\n \"inline-flex items-center gap-1.5 rounded border border-border px-1.5 py-0.5 text-[11px] text-muted-foreground\",\n className,\n )}\n aria-label={`Context ${pct}% used`}\n >\n <span className=\"shrink-0\">ctx</span>\n <span className=\"h-1.5 w-16 overflow-hidden rounded-full bg-muted\">\n <span\n className={cn(\n \"block h-full rounded-full transition-all\",\n barTone(pct),\n )}\n style={{ width: `${pct}%` }}\n />\n </span>\n <span\n className={cn(\"shrink-0 font-medium tabular-nums\", textTone(pct))}\n >\n {pct}%\n </span>\n </span>\n );\n\n return (\n <HoverCard\n trigger={trigger}\n placement=\"bottom\"\n delay={200}\n cardClassName=\"w-72 p-3\"\n >\n <div className=\"space-y-2.5 text-xs\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"font-semibold\">Context usage</span>\n <span className={cn(\"font-semibold tabular-nums\", textTone(pct))}>\n {pct}%\n </span>\n </div>\n\n {(model || effort) && (\n <div className=\"flex items-center justify-between gap-3 border-b border-border pb-2\">\n {model ? (\n <div className=\"flex min-w-0 items-center gap-2\">\n {Glyph && (\n <Icon\n icon={Glyph}\n className={cn(\"size-4 shrink-0\", modelIconClassName)}\n />\n )}\n <span className=\"truncate font-medium\" title={model}>\n {model}\n </span>\n </div>\n ) : null}\n {effort ? (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center gap-1 font-medium\",\n effortColor,\n )}\n >\n {EffortGlyph ? <EffortGlyph className=\"size-3.5\" /> : null}\n {effortLevelLabel(effort)} effort\n </span>\n ) : null}\n </div>\n )}\n\n {(sessionId || executionMode) && (\n <div className=\"space-y-1.5 border-b border-border pb-2\">\n {sessionId ? (\n <div className=\"flex items-center justify-between gap-4\">\n <span className=\"text-muted-foreground\">Session</span>\n <button\n type=\"button\"\n aria-label={\n copyStatus === \"copied\"\n ? \"Session ID copied\"\n : copyStatus === \"failed\"\n ? \"Session ID copy failed\"\n : \"Copy session ID\"\n }\n title={sessionId}\n className={cn(\n \"flex min-w-0 max-w-48 items-center gap-1.5 font-medium hover:text-foreground\",\n copyStatus === \"failed\" && \"text-destructive\",\n )}\n onClick={() => void copySessionId()}\n >\n <span className=\"truncate font-mono\">{sessionId}</span>\n <Icon\n icon={copyStatus === \"copied\" ? UiCheck : UiCopy}\n className=\"size-3.5 shrink-0\"\n />\n </button>\n </div>\n ) : null}\n {executionMode ? <Row label=\"Mode\" value={executionMode} /> : null}\n </div>\n )}\n\n <div className=\"space-y-1.5\">\n <div className=\"h-1.5 overflow-hidden rounded-full bg-muted\">\n <div\n className={cn(\"h-full rounded-full\", barTone(pct))}\n style={{ width: `${pct}%` }}\n />\n </div>\n {windowTokens ? (\n <>\n <Row\n label=\"Window\"\n value={`${compactTokens(usedTokens ?? 0)} / ${compactTokens(windowTokens)}`}\n />\n <Row label=\"Free\" value={`${100 - pct}%`} />\n </>\n ) : (\n <Row label=\"Used\" value={`${pct}%`} />\n )}\n {messageCount != null ? (\n <Row label=\"Messages\" value={String(messageCount)} />\n ) : null}\n </div>\n\n {(totalTokens > 0 || totalCost > 0 || budget) && (\n <div className=\"space-y-1.5 border-t border-border pt-2\">\n {(totalTokens > 0 || totalCost > 0) && (\n <UsageTable\n rows={bucketRows(tokens, cost)}\n totalTokens={totalTokens}\n totalCost={totalCost}\n showTokens={totalTokens > 0}\n showCost={totalCost > 0}\n />\n )}\n {budget?.total != null && budget.total > 0 ? (\n <Row\n label=\"Budget\"\n value={`${formatCost(budget.used ?? 0)} / ${formatCost(budget.total)}`}\n />\n ) : budget?.remaining != null ? (\n <Row label=\"Budget left\" value={formatCost(budget.remaining)} />\n ) : anyPositive(budget?.used) ? (\n <Row label=\"Budget\" value={formatCost(budget?.used ?? 0)} />\n ) : null}\n </div>\n )}\n </div>\n </HoverCard>\n );\n}\n"],"names":["jsxs","jsx","tokens","compactTokens","formatCost","useState","useRef","useEffect","effortLevelIcon","effortLevelColor","cn","Icon","HoverCard","effortLevelLabel","UiCheck","UiCopy","Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"ContextMeter.cjs","sources":["../../../src/data/chat/ContextMeter.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { compactTokens, formatCost } from \"../../lib/tokens\";\nimport { UiCheck, UiCopy } from \"../../icons\";\nimport { Icon, type StaticIconComponent } from \"../Icon\";\nimport { HoverCard } from \"../../overlay/HoverCard\";\nimport {\n effortLevelColor,\n effortLevelIcon,\n effortLevelLabel,\n} from \"./effort-icons\";\n\nexport type ContextMeterMode = \"bar\" | \"gauge\";\n\nexport type ContextMeterTokens = {\n input?: number | undefined;\n output?: number | undefined;\n reasoning?: number | undefined;\n cacheRead?: number | undefined;\n cacheWrite?: number | undefined;\n total?: number | undefined;\n};\n\nexport type ContextMeterCost = {\n input?: number | undefined;\n output?: number | undefined;\n reasoning?: number | undefined;\n cacheRead?: number | undefined;\n cacheWrite?: number | undefined;\n total?: number | undefined;\n};\n\nexport type ContextMeterBudget = {\n used?: number | undefined;\n total?: number | undefined;\n remaining?: number | undefined;\n};\n\nexport type ContextMeterProps = {\n /** Trigger shape: a compact `bar` (session header) or a circular `gauge`\n * (chat toolbar). Both open the same hover popover. */\n mode?: ContextMeterMode;\n /** Share of the context window used, 0–100 — drives the fill and tone. */\n usedPercent: number;\n /** Context-window tokens shown in the popover. */\n usedTokens?: number | undefined;\n windowTokens?: number | undefined;\n /** Message count shown in the popover (chat). */\n messageCount?: number | undefined;\n /** Session identifier exposed as a click-to-copy value in the popover. */\n sessionId?: string | undefined;\n /** Terminal chat identities, kept distinct from the generic session id. */\n captainSessionId?: string | undefined;\n providerSessionId?: string | undefined;\n threadId?: string | undefined;\n turnId?: string | undefined;\n /** Resolved backend that produced the terminal chat turn. */\n backend?: string | undefined;\n /** Runtime mechanism used to execute the session, such as api or cmux. */\n executionMode?: string | undefined;\n /** Model id/label and its brand glyph. */\n model?: string | undefined;\n modelIcon?: StaticIconComponent | undefined;\n modelIconClassName?: string | undefined;\n /** Reasoning effort shown with its semantic glyph and color in the hover card. */\n effort?: string | undefined;\n /** Per-bucket token counts for the popover breakdown. */\n tokens?: ContextMeterTokens | undefined;\n /** Per-bucket costs (USD) for the popover breakdown. */\n cost?: ContextMeterCost | undefined;\n budget?: ContextMeterBudget | undefined;\n className?: string | undefined;\n};\n\nconst COPY_STATUS_RESET_MS = 2000;\nconst GAUGE_RADIUS = 15;\nconst GAUGE_CIRCUMFERENCE = 2 * Math.PI * GAUGE_RADIUS;\n\nfunction barTone(pct: number): string {\n return pct > 80\n ? \"bg-red-600 [[data-theme=dark]_&]:bg-red-400\"\n : pct > 50\n ? \"bg-amber-700 [[data-theme=dark]_&]:bg-amber-400\"\n : \"bg-emerald-600 [[data-theme=dark]_&]:bg-emerald-400\";\n}\n\nfunction ringTone(pct: number): string {\n return pct > 80\n ? \"text-red-600 [[data-theme=dark]_&]:text-red-400\"\n : pct > 50\n ? \"text-amber-700 [[data-theme=dark]_&]:text-amber-400\"\n : \"text-emerald-600 [[data-theme=dark]_&]:text-emerald-400\";\n}\n\nfunction textTone(pct: number): string {\n return pct > 80\n ? \"text-red-700 [[data-theme=dark]_&]:text-red-400\"\n : pct > 50\n ? \"text-amber-700 [[data-theme=dark]_&]:text-amber-400\"\n : \"text-emerald-700 [[data-theme=dark]_&]:text-emerald-400\";\n}\n\nfunction Row({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"flex justify-between gap-4\">\n <span className=\"text-muted-foreground\">{label}</span>\n <span className=\"font-medium tabular-nums\">{value}</span>\n </div>\n );\n}\n\nfunction anyPositive(...values: (number | undefined)[]): boolean {\n return values.some((v) => v != null && v > 0);\n}\n\ntype BucketRow = {\n label: string;\n tokens?: number | undefined;\n cost?: number | undefined;\n};\n\ntype CopyableIdentity = {\n key: string;\n label: string;\n value: string;\n};\n\n/** One row per token/cost bucket, kept only when it carries a token or cost\n * value. Cache stays split into read and write on both axes. */\nfunction bucketRows(\n tokens?: ContextMeterTokens,\n cost?: ContextMeterCost,\n): BucketRow[] {\n const rows: BucketRow[] = [\n { label: \"Input\", tokens: tokens?.input, cost: cost?.input },\n { label: \"Output\", tokens: tokens?.output, cost: cost?.output },\n { label: \"Reasoning\", tokens: tokens?.reasoning, cost: cost?.reasoning },\n { label: \"Cache read\", tokens: tokens?.cacheRead, cost: cost?.cacheRead },\n {\n label: \"Cache write\",\n tokens: tokens?.cacheWrite,\n cost: cost?.cacheWrite,\n },\n ];\n return rows.filter((row) => (row.tokens ?? 0) > 0 || (row.cost ?? 0) > 0);\n}\n\nfunction UsageTable({\n rows,\n totalTokens,\n totalCost,\n showTokens,\n showCost,\n}: {\n rows: BucketRow[];\n totalTokens: number;\n totalCost: number;\n showTokens: boolean;\n showCost: boolean;\n}) {\n const numCell = \"px-1 py-0.5 text-right tabular-nums\";\n return (\n <table className=\"w-full border-collapse\">\n <thead>\n <tr className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">\n <th className=\"px-1 py-0.5 text-left font-medium\" />\n {showTokens && (\n <th className=\"px-1 py-0.5 text-right font-medium\">Tokens</th>\n )}\n {showCost && (\n <th className=\"px-1 py-0.5 text-right font-medium\">Cost</th>\n )}\n </tr>\n </thead>\n <tbody>\n {rows.map((row) => (\n <tr key={row.label}>\n <td className=\"px-1 py-0.5 text-left text-muted-foreground\">\n {row.label}\n </td>\n {showTokens && (\n <td className={numCell}>\n {row.tokens ? (\n compactTokens(row.tokens)\n ) : (\n <span className=\"text-muted-foreground/50\">—</span>\n )}\n </td>\n )}\n {showCost && (\n <td className={numCell}>\n {row.cost ? (\n formatCost(row.cost)\n ) : (\n <span className=\"text-muted-foreground/50\">—</span>\n )}\n </td>\n )}\n </tr>\n ))}\n <tr className=\"border-t border-border font-medium\">\n <td className=\"px-1 py-0.5 text-left\">Total</td>\n {showTokens && (\n <td className={numCell}>{compactTokens(totalTokens)}</td>\n )}\n {showCost && <td className={numCell}>{formatCost(totalCost)}</td>}\n </tr>\n </tbody>\n </table>\n );\n}\n\n/** Unified context-window meter. Renders as a compact progress `bar` or a\n * circular `gauge`; hovering or focusing it opens a popover with the model, the\n * runtime and copyable identities, context-window breakdown, per-bucket token\n * usage and the cost + budget detail. Domain-agnostic — callers feed plain\n * values. */\nexport function ContextMeter({\n mode = \"bar\",\n usedPercent,\n usedTokens,\n windowTokens,\n messageCount,\n sessionId,\n captainSessionId,\n providerSessionId,\n threadId,\n turnId,\n backend,\n executionMode,\n model,\n modelIcon: Glyph,\n modelIconClassName,\n effort,\n tokens,\n cost,\n budget,\n className,\n}: ContextMeterProps) {\n const [copyResult, setCopyResult] = useState<\n {\n identity: string;\n value: string;\n status: \"copied\" | \"failed\";\n } | undefined\n >();\n const copyResetTimer = useRef<number | undefined>(undefined);\n useEffect(\n () => () => {\n if (copyResetTimer.current !== undefined) {\n window.clearTimeout(copyResetTimer.current);\n }\n },\n [],\n );\n const pct = Math.min(100, Math.max(0, Math.round(usedPercent)));\n const totalTokens = tokens?.total ?? 0;\n const totalCost = cost?.total ?? 0;\n const EffortGlyph = effort ? effortLevelIcon(effort) : undefined;\n const effortColor = effort ? effortLevelColor(effort) : undefined;\n const identities = [\n sessionId ? { key: \"session\", label: \"Session\", value: sessionId } : undefined,\n captainSessionId\n ? {\n key: \"captain-session\",\n label: \"Captain session\",\n value: captainSessionId,\n }\n : undefined,\n providerSessionId\n ? {\n key: \"provider-session\",\n label: \"Provider session\",\n value: providerSessionId,\n }\n : undefined,\n threadId ? { key: \"thread\", label: \"Thread\", value: threadId } : undefined,\n turnId ? { key: \"turn\", label: \"Turn\", value: turnId } : undefined,\n ].filter((identity): identity is CopyableIdentity => identity !== undefined);\n // The status is transient feedback for the click that produced it — without\n // this it would greet every later hover of the same identity.\n const copyIdentity = async (identity: CopyableIdentity) => {\n if (copyResetTimer.current !== undefined) {\n window.clearTimeout(copyResetTimer.current);\n }\n try {\n await navigator.clipboard.writeText(identity.value);\n setCopyResult({\n identity: identity.key,\n value: identity.value,\n status: \"copied\",\n });\n } catch {\n setCopyResult({\n identity: identity.key,\n value: identity.value,\n status: \"failed\",\n });\n }\n copyResetTimer.current = window.setTimeout(\n () => setCopyResult(undefined),\n COPY_STATUS_RESET_MS,\n );\n };\n\n const trigger =\n mode === \"gauge\" ? (\n <span\n className={cn(\n \"inline-flex items-center rounded-md px-2.5 py-1.5 text-xs text-muted-foreground transition-colors hover:bg-accent hover:text-foreground\",\n className,\n )}\n aria-label={`Context ${pct}% used`}\n >\n <span className=\"relative inline-flex size-9 shrink-0 items-center justify-center\">\n <svg\n data-context-gauge-ring\n aria-hidden=\"true\"\n width=\"36\"\n height=\"36\"\n viewBox=\"0 0 36 36\"\n className={cn(\"absolute inset-0\", ringTone(pct))}\n >\n <circle\n cx=\"18\"\n cy=\"18\"\n r={GAUGE_RADIUS}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n opacity=\"0.15\"\n />\n <circle\n cx=\"18\"\n cy=\"18\"\n r={GAUGE_RADIUS}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeDasharray={GAUGE_CIRCUMFERENCE}\n strokeDashoffset={(1 - pct / 100) * GAUGE_CIRCUMFERENCE}\n strokeLinecap=\"round\"\n transform=\"rotate(-90 18 18)\"\n />\n </svg>\n {Glyph ? (\n <Icon\n icon={Glyph}\n className={cn(\"relative size-5\", modelIconClassName)}\n />\n ) : (\n <span\n className={cn(\n \"relative text-[9px] font-semibold tabular-nums\",\n textTone(pct),\n )}\n >\n {pct}\n </span>\n )}\n </span>\n </span>\n ) : (\n <span\n className={cn(\n \"inline-flex items-center gap-1.5 rounded border border-border px-1.5 py-0.5 text-[11px] text-muted-foreground\",\n className,\n )}\n aria-label={`Context ${pct}% used`}\n >\n <span className=\"shrink-0\">ctx</span>\n <span className=\"h-1.5 w-16 overflow-hidden rounded-full bg-muted\">\n <span\n className={cn(\n \"block h-full rounded-full transition-all\",\n barTone(pct),\n )}\n style={{ width: `${pct}%` }}\n />\n </span>\n <span\n className={cn(\"shrink-0 font-medium tabular-nums\", textTone(pct))}\n >\n {pct}%\n </span>\n </span>\n );\n\n return (\n <HoverCard\n trigger={trigger}\n placement=\"bottom\"\n delay={200}\n cardClassName=\"w-72 p-3\"\n >\n <div className=\"space-y-2.5 text-xs\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"font-semibold\">Context usage</span>\n <span className={cn(\"font-semibold tabular-nums\", textTone(pct))}>\n {pct}%\n </span>\n </div>\n\n {(model || effort) && (\n <div className=\"flex items-center justify-between gap-3 border-b border-border pb-2\">\n {model ? (\n <div className=\"flex min-w-0 items-center gap-2\">\n {Glyph && (\n <Icon\n icon={Glyph}\n className={cn(\"size-4 shrink-0\", modelIconClassName)}\n />\n )}\n <span className=\"truncate font-medium\" title={model}>\n {model}\n </span>\n </div>\n ) : null}\n {effort ? (\n <span\n className={cn(\n \"inline-flex shrink-0 items-center gap-1 font-medium\",\n effortColor,\n )}\n >\n {EffortGlyph ? <EffortGlyph className=\"size-3.5\" /> : null}\n {effortLevelLabel(effort)} effort\n </span>\n ) : null}\n </div>\n )}\n\n {(identities.length > 0 || backend || executionMode) && (\n <div className=\"space-y-1.5 border-b border-border pb-2\">\n {identities.map((identity) => {\n const copyStatus =\n copyResult?.identity === identity.key &&\n copyResult.value === identity.value\n ? copyResult.status\n : undefined;\n return (\n <div\n key={identity.key}\n className=\"flex items-center justify-between gap-4\"\n >\n <span className=\"text-muted-foreground\">\n {identity.label}\n </span>\n <button\n type=\"button\"\n aria-label={\n copyStatus === \"copied\"\n ? `${identity.label} ID copied`\n : copyStatus === \"failed\"\n ? `${identity.label} ID copy failed`\n : `Copy ${identity.label.toLowerCase()} ID`\n }\n title={identity.value}\n className={cn(\n \"flex min-w-0 max-w-48 items-center gap-1.5 font-medium hover:text-foreground\",\n copyStatus === \"failed\" && \"text-destructive\",\n )}\n onClick={() => void copyIdentity(identity)}\n >\n <span className=\"truncate font-mono\">\n {identity.value}\n </span>\n <Icon\n icon={copyStatus === \"copied\" ? UiCheck : UiCopy}\n className=\"size-3.5 shrink-0\"\n />\n </button>\n </div>\n );\n })}\n {backend ? <Row label=\"Backend\" value={backend} /> : null}\n {executionMode ? <Row label=\"Mode\" value={executionMode} /> : null}\n </div>\n )}\n\n <div className=\"space-y-1.5\">\n <div className=\"h-1.5 overflow-hidden rounded-full bg-muted\">\n <div\n className={cn(\"h-full rounded-full\", barTone(pct))}\n style={{ width: `${pct}%` }}\n />\n </div>\n {windowTokens ? (\n <>\n <Row\n label=\"Window\"\n value={`${compactTokens(usedTokens ?? 0)} / ${compactTokens(windowTokens)}`}\n />\n <Row label=\"Free\" value={`${100 - pct}%`} />\n </>\n ) : (\n <Row label=\"Used\" value={`${pct}%`} />\n )}\n {messageCount != null ? (\n <Row label=\"Messages\" value={String(messageCount)} />\n ) : null}\n </div>\n\n {(totalTokens > 0 || totalCost > 0 || budget) && (\n <div className=\"space-y-1.5 border-t border-border pt-2\">\n {(totalTokens > 0 || totalCost > 0) && (\n <UsageTable\n rows={bucketRows(tokens, cost)}\n totalTokens={totalTokens}\n totalCost={totalCost}\n showTokens={totalTokens > 0}\n showCost={totalCost > 0}\n />\n )}\n {budget?.total != null && budget.total > 0 ? (\n <Row\n label=\"Budget\"\n value={`${formatCost(budget.used ?? 0)} / ${formatCost(budget.total)}`}\n />\n ) : budget?.remaining != null ? (\n <Row label=\"Budget left\" value={formatCost(budget.remaining)} />\n ) : anyPositive(budget?.used) ? (\n <Row label=\"Budget\" value={formatCost(budget?.used ?? 0)} />\n ) : null}\n </div>\n )}\n </div>\n </HoverCard>\n );\n}\n"],"names":["jsxs","jsx","tokens","compactTokens","formatCost","useState","useRef","useEffect","effortLevelIcon","effortLevelColor","cn","Icon","HoverCard","effortLevelLabel","UiCheck","UiCopy","Fragment"],"mappings":"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"}
@@ -34,6 +34,13 @@ export type ContextMeterProps = {
34
34
  messageCount?: number | undefined;
35
35
  /** Session identifier exposed as a click-to-copy value in the popover. */
36
36
  sessionId?: string | undefined;
37
+ /** Terminal chat identities, kept distinct from the generic session id. */
38
+ captainSessionId?: string | undefined;
39
+ providerSessionId?: string | undefined;
40
+ threadId?: string | undefined;
41
+ turnId?: string | undefined;
42
+ /** Resolved backend that produced the terminal chat turn. */
43
+ backend?: string | undefined;
37
44
  /** Runtime mechanism used to execute the session, such as api or cmux. */
38
45
  executionMode?: string | undefined;
39
46
  /** Model id/label and its brand glyph. */
@@ -51,8 +58,8 @@ export type ContextMeterProps = {
51
58
  };
52
59
  /** Unified context-window meter. Renders as a compact progress `bar` or a
53
60
  * circular `gauge`; hovering or focusing it opens a popover with the model, the
54
- * copyable session id, execution mode, context-window breakdown, per-bucket
55
- * token usage and the cost + budget detail. Domain-agnostic — callers feed
56
- * plain values. */
57
- export declare function ContextMeter({ mode, usedPercent, usedTokens, windowTokens, messageCount, sessionId, executionMode, model, modelIcon: Glyph, modelIconClassName, effort, tokens, cost, budget, className, }: ContextMeterProps): import("react/jsx-runtime").JSX.Element;
61
+ * runtime and copyable identities, context-window breakdown, per-bucket token
62
+ * usage and the cost + budget detail. Domain-agnostic — callers feed plain
63
+ * values. */
64
+ export declare function ContextMeter({ mode, usedPercent, usedTokens, windowTokens, messageCount, sessionId, captainSessionId, providerSessionId, threadId, turnId, backend, executionMode, model, modelIcon: Glyph, modelIconClassName, effort, tokens, cost, budget, className, }: ContextMeterProps): import("react/jsx-runtime").JSX.Element;
58
65
  //# sourceMappingURL=ContextMeter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMeter.d.ts","sourceRoot":"","sources":["../../../src/data/chat/ContextMeter.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAQ,KAAK,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAQzD,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,OAAO,CAAC;AAE/C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B;4DACwD;IACxD,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC5C,kBAAkB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,yDAAyD;IACzD,MAAM,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACxC,wDAAwD;IACxD,IAAI,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpC,MAAM,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,CAAC;AAsIF;;;;oBAIoB;AACpB,wBAAgB,YAAY,CAAC,EAC3B,IAAY,EACZ,WAAW,EACX,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,aAAa,EACb,KAAK,EACL,SAAS,EAAE,KAAK,EAChB,kBAAkB,EAClB,MAAM,EACN,MAAM,EACN,IAAI,EACJ,MAAM,EACN,SAAS,GACV,EAAE,iBAAiB,2CA0PnB"}
1
+ {"version":3,"file":"ContextMeter.d.ts","sourceRoot":"","sources":["../../../src/data/chat/ContextMeter.tsx"],"names":[],"mappings":"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"}
@@ -77,6 +77,11 @@ function ContextMeter({
77
77
  windowTokens,
78
78
  messageCount,
79
79
  sessionId,
80
+ captainSessionId,
81
+ providerSessionId,
82
+ threadId,
83
+ turnId,
84
+ backend,
80
85
  executionMode,
81
86
  model,
82
87
  modelIcon: Glyph,
@@ -102,17 +107,38 @@ function ContextMeter({
102
107
  const totalCost = (cost == null ? void 0 : cost.total) ?? 0;
103
108
  const EffortGlyph = effort ? effortLevelIcon(effort) : void 0;
104
109
  const effortColor = effort ? effortLevelColor(effort) : void 0;
105
- const copyStatus = copyResult && copyResult.sessionId === sessionId ? copyResult.status : void 0;
106
- const copySessionId = async () => {
107
- if (!sessionId) return;
110
+ const identities = [
111
+ sessionId ? { key: "session", label: "Session", value: sessionId } : void 0,
112
+ captainSessionId ? {
113
+ key: "captain-session",
114
+ label: "Captain session",
115
+ value: captainSessionId
116
+ } : void 0,
117
+ providerSessionId ? {
118
+ key: "provider-session",
119
+ label: "Provider session",
120
+ value: providerSessionId
121
+ } : void 0,
122
+ threadId ? { key: "thread", label: "Thread", value: threadId } : void 0,
123
+ turnId ? { key: "turn", label: "Turn", value: turnId } : void 0
124
+ ].filter((identity) => identity !== void 0);
125
+ const copyIdentity = async (identity) => {
108
126
  if (copyResetTimer.current !== void 0) {
109
127
  window.clearTimeout(copyResetTimer.current);
110
128
  }
111
129
  try {
112
- await navigator.clipboard.writeText(sessionId);
113
- setCopyResult({ sessionId, status: "copied" });
130
+ await navigator.clipboard.writeText(identity.value);
131
+ setCopyResult({
132
+ identity: identity.key,
133
+ value: identity.value,
134
+ status: "copied"
135
+ });
114
136
  } catch {
115
- setCopyResult({ sessionId, status: "failed" });
137
+ setCopyResult({
138
+ identity: identity.key,
139
+ value: identity.value,
140
+ status: "failed"
141
+ });
116
142
  }
117
143
  copyResetTimer.current = window.setTimeout(
118
144
  () => setCopyResult(void 0),
@@ -260,33 +286,44 @@ function ContextMeter({
260
286
  }
261
287
  ) : null
262
288
  ] }),
263
- (sessionId || executionMode) && /* @__PURE__ */ jsxs("div", { className: "space-y-1.5 border-b border-border pb-2", children: [
264
- sessionId ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
265
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Session" }),
266
- /* @__PURE__ */ jsxs(
267
- "button",
289
+ (identities.length > 0 || backend || executionMode) && /* @__PURE__ */ jsxs("div", { className: "space-y-1.5 border-b border-border pb-2", children: [
290
+ identities.map((identity) => {
291
+ const copyStatus = (copyResult == null ? void 0 : copyResult.identity) === identity.key && copyResult.value === identity.value ? copyResult.status : void 0;
292
+ return /* @__PURE__ */ jsxs(
293
+ "div",
268
294
  {
269
- type: "button",
270
- "aria-label": copyStatus === "copied" ? "Session ID copied" : copyStatus === "failed" ? "Session ID copy failed" : "Copy session ID",
271
- title: sessionId,
272
- className: cn(
273
- "flex min-w-0 max-w-48 items-center gap-1.5 font-medium hover:text-foreground",
274
- copyStatus === "failed" && "text-destructive"
275
- ),
276
- onClick: () => void copySessionId(),
295
+ className: "flex items-center justify-between gap-4",
277
296
  children: [
278
- /* @__PURE__ */ jsx("span", { className: "truncate font-mono", children: sessionId }),
279
- /* @__PURE__ */ jsx(
280
- Icon,
297
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: identity.label }),
298
+ /* @__PURE__ */ jsxs(
299
+ "button",
281
300
  {
282
- icon: copyStatus === "copied" ? UiCheck : UiCopy,
283
- className: "size-3.5 shrink-0"
301
+ type: "button",
302
+ "aria-label": copyStatus === "copied" ? `${identity.label} ID copied` : copyStatus === "failed" ? `${identity.label} ID copy failed` : `Copy ${identity.label.toLowerCase()} ID`,
303
+ title: identity.value,
304
+ className: cn(
305
+ "flex min-w-0 max-w-48 items-center gap-1.5 font-medium hover:text-foreground",
306
+ copyStatus === "failed" && "text-destructive"
307
+ ),
308
+ onClick: () => void copyIdentity(identity),
309
+ children: [
310
+ /* @__PURE__ */ jsx("span", { className: "truncate font-mono", children: identity.value }),
311
+ /* @__PURE__ */ jsx(
312
+ Icon,
313
+ {
314
+ icon: copyStatus === "copied" ? UiCheck : UiCopy,
315
+ className: "size-3.5 shrink-0"
316
+ }
317
+ )
318
+ ]
284
319
  }
285
320
  )
286
321
  ]
287
- }
288
- )
289
- ] }) : null,
322
+ },
323
+ identity.key
324
+ );
325
+ }),
326
+ backend ? /* @__PURE__ */ jsx(Row, { label: "Backend", value: backend }) : null,
290
327
  executionMode ? /* @__PURE__ */ jsx(Row, { label: "Mode", value: executionMode }) : null
291
328
  ] }),
292
329
  /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [