@harness-mix/cli 0.1.4 → 0.1.6

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 (146) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +26 -96
  3. package/docs/chatgpt-web-sidebar.md +7 -1
  4. package/docs/cross-platform.md +15 -0
  5. package/docs/harness-handoff-design.md +377 -0
  6. package/docs/harness-management.md +28 -1
  7. package/docs/multi-agent-collaboration.md +9 -9
  8. package/docs/native-codex.md +21 -10
  9. package/output/native-build/harness-mix-shim.exe +0 -0
  10. package/output/native-build/renderer-extension.js +2596 -135
  11. package/package.json +20 -10
  12. package/scripts/chatgpt-context-ui-smoke.cjs +16 -0
  13. package/scripts/codex-accounts-test.cjs +81 -0
  14. package/scripts/codex-accounts-ui-smoke.cjs +70 -0
  15. package/scripts/collaboration-test.cjs +8 -3
  16. package/scripts/collaboration-ui-smoke.cjs +40 -26
  17. package/scripts/e2e-integrations.cjs +52 -0
  18. package/scripts/e2e-native-host.cjs +39 -0
  19. package/scripts/handoff-checkpoint-test.cjs +83 -0
  20. package/scripts/install-native.cjs +4 -1
  21. package/scripts/integrations-test.cjs +123 -0
  22. package/scripts/integrations-ui-smoke.cjs +124 -0
  23. package/scripts/native-protocol-test.cjs +180 -5
  24. package/scripts/native-secret-test.cjs +2 -2
  25. package/scripts/native-shim-test.cjs +20 -4
  26. package/scripts/native-sidebar-test.cjs +7 -0
  27. package/scripts/native-skill-roots-test.cjs +90 -0
  28. package/scripts/native-ui-smoke.cjs +58 -2
  29. package/scripts/publish-native-package.cjs +8 -5
  30. package/scripts/support/integrations-mcp-fixture.cjs +15 -0
  31. package/scripts/switch-harness-test.cjs +27 -1
  32. package/scripts/test-live-mentions.cjs +152 -0
  33. package/src/main/adapters/acp.js +3 -3
  34. package/src/main/adapters/antigravity.js +17 -17
  35. package/src/main/adapters/claude.js +50 -10
  36. package/src/main/adapters/codebuddy.js +1 -0
  37. package/src/main/adapters/codex-app-server.js +20 -13
  38. package/src/main/adapters/codex.js +25 -5
  39. package/src/main/adapters/cursor.js +5 -1
  40. package/src/main/adapters/dsh.js +9 -1
  41. package/src/main/adapters/grok.js +7 -3
  42. package/src/main/adapters/hermes.js +8 -0
  43. package/src/main/adapters/kiro.js +2 -1
  44. package/src/main/adapters/managed-mcp.js +25 -0
  45. package/src/main/adapters/native-acp.js +4 -4
  46. package/src/main/adapters/omp.js +11 -0
  47. package/src/main/adapters/openclaw.js +6 -0
  48. package/src/main/adapters/opencode.js +13 -3
  49. package/src/main/adapters/pi.js +5 -0
  50. package/src/main/adapters/qoder.js +1 -0
  51. package/src/main/adapters/trae.js +4 -0
  52. package/src/main/adapters/zcode.js +3 -0
  53. package/src/main/harness-adapter/manifest.js +17 -2
  54. package/src/main/host/collaboration.js +57 -11
  55. package/src/main/host/handoff-access.js +53 -0
  56. package/src/main/host/handoff-checkpoints.js +206 -0
  57. package/src/main/host/handoff-mcp.cjs +38 -0
  58. package/src/main/host/handoff-tools.js +13 -0
  59. package/src/main/host/handoff.js +28 -6
  60. package/src/main/host/integrations.js +339 -0
  61. package/src/main/host/runtime.js +95 -15
  62. package/src/main/host/store.js +4 -4
  63. package/src/main/native/codex-accounts.js +260 -0
  64. package/src/main/native/host.js +1 -1
  65. package/src/main/native/launcher.js +2 -2
  66. package/src/main/native/protocol.js +176 -14
  67. package/src/main/native/redact.js +1 -1
  68. package/src/main/native/rs/crates/shim/src/main.rs +155 -12
  69. package/src/main/native/thread-list.js +3 -0
  70. package/src/native-ui/desktop-control/dist/tsconfig.tsbuildinfo +1 -1
  71. package/src/native-ui/renderer-extension/dist/types/harness-mix-settings.d.ts.map +1 -1
  72. package/src/native-ui/renderer-extension/dist/types/index.d.ts +4 -0
  73. package/src/native-ui/renderer-extension/dist/types/index.d.ts.map +1 -1
  74. package/src/native-ui/renderer-extension/dist/types/renderer-agent-picker.d.ts +2 -0
  75. package/src/native-ui/renderer-extension/dist/types/renderer-agent-picker.d.ts.map +1 -1
  76. package/src/native-ui/renderer-extension/dist/types/renderer-binding-probe.d.ts.map +1 -1
  77. package/src/native-ui/renderer-extension/dist/types/renderer-chatgpt-context.d.ts +36 -0
  78. package/src/native-ui/renderer-extension/dist/types/renderer-chatgpt-context.d.ts.map +1 -0
  79. package/src/native-ui/renderer-extension/dist/types/renderer-codex-account-state.d.ts +1 -0
  80. package/src/native-ui/renderer-extension/dist/types/renderer-codex-account-state.d.ts.map +1 -1
  81. package/src/native-ui/renderer-extension/dist/types/renderer-composer-dom.d.ts +3 -1
  82. package/src/native-ui/renderer-extension/dist/types/renderer-composer-dom.d.ts.map +1 -1
  83. package/src/native-ui/renderer-extension/dist/types/renderer-harness-handoff.d.ts +53 -0
  84. package/src/native-ui/renderer-extension/dist/types/renderer-harness-handoff.d.ts.map +1 -0
  85. package/src/native-ui/renderer-extension/dist/types/renderer-harness-mentions.d.ts +11 -0
  86. package/src/native-ui/renderer-extension/dist/types/renderer-harness-mentions.d.ts.map +1 -1
  87. package/src/native-ui/renderer-extension/dist/types/renderer-integrations-client.d.ts +105 -0
  88. package/src/native-ui/renderer-extension/dist/types/renderer-integrations-client.d.ts.map +1 -0
  89. package/src/native-ui/renderer-extension/dist/types/renderer-model-client.d.ts +7 -1
  90. package/src/native-ui/renderer-extension/dist/types/renderer-model-client.d.ts.map +1 -1
  91. package/src/native-ui/renderer-extension/dist/types/renderer-settings-lifecycle.d.ts +1 -0
  92. package/src/native-ui/renderer-extension/dist/types/renderer-settings-lifecycle.d.ts.map +1 -1
  93. package/src/native-ui/renderer-extension/dist/types/settings/accounts-list.d.ts +2 -0
  94. package/src/native-ui/renderer-extension/dist/types/settings/accounts-list.d.ts.map +1 -1
  95. package/src/native-ui/renderer-extension/dist/types/settings/accounts-page.d.ts +1 -0
  96. package/src/native-ui/renderer-extension/dist/types/settings/accounts-page.d.ts.map +1 -1
  97. package/src/native-ui/renderer-extension/dist/types/settings/integrations-page.d.ts +6 -0
  98. package/src/native-ui/renderer-extension/dist/types/settings/integrations-page.d.ts.map +1 -0
  99. package/src/native-ui/renderer-extension/dist/types/settings/localization.d.ts +5 -0
  100. package/src/native-ui/renderer-extension/dist/types/settings/localization.d.ts.map +1 -1
  101. package/src/native-ui/renderer-extension/dist/types/settings/pages.d.ts +8 -4
  102. package/src/native-ui/renderer-extension/dist/types/settings/pages.d.ts.map +1 -1
  103. package/src/native-ui/renderer-extension/dist/types/tsconfig.tsbuildinfo +1 -1
  104. package/src/native-ui/renderer-extension/src/harness-mix-settings.ts +4 -1
  105. package/src/native-ui/renderer-extension/src/index.ts +28 -0
  106. package/src/native-ui/renderer-extension/src/renderer-agent-icon.ts +4 -4
  107. package/src/native-ui/renderer-extension/src/renderer-agent-picker.ts +46 -6
  108. package/src/native-ui/renderer-extension/src/renderer-binding-probe.ts +115 -18
  109. package/src/native-ui/renderer-extension/src/renderer-chatgpt-context.ts +87 -0
  110. package/src/native-ui/renderer-extension/src/renderer-codex-account-state.ts +10 -0
  111. package/src/native-ui/renderer-extension/src/renderer-composer-dom.ts +10 -0
  112. package/src/native-ui/renderer-extension/src/renderer-harness-handoff.ts +330 -0
  113. package/src/native-ui/renderer-extension/src/renderer-harness-mentions.ts +556 -123
  114. package/src/native-ui/renderer-extension/src/renderer-integrations-client.ts +59 -0
  115. package/src/native-ui/renderer-extension/src/renderer-model-client.ts +17 -1
  116. package/src/native-ui/renderer-extension/src/renderer-settings-lifecycle.ts +2 -0
  117. package/src/native-ui/renderer-extension/src/settings/accounts-list.ts +16 -1
  118. package/src/native-ui/renderer-extension/src/settings/accounts-page.ts +32 -3
  119. package/src/native-ui/renderer-extension/src/settings/integrations-page.ts +1474 -0
  120. package/src/native-ui/renderer-extension/src/settings/localization.ts +32 -13
  121. package/src/native-ui/renderer-extension/src/settings/pages.ts +49 -18
  122. package/src/native-ui/renderer-extension/src/settings/shell.css +103 -0
  123. package/src/native-ui/renderer-extension/test/renderer-agent-picker.test.ts +44 -13
  124. package/src/native-ui/renderer-extension/test/renderer-chatgpt-context.test.ts +21 -0
  125. package/src/native-ui/renderer-extension/test/renderer-codex-account-state.test.ts +13 -1
  126. package/src/native-ui/renderer-extension/test/renderer-harness-handoff.test.ts +20 -0
  127. package/src/native-ui/renderer-extension/test/renderer-model-client.test.ts +9 -2
  128. package/src/native-ui/renderer-extension/test/settings/localization.test.ts +1 -1
  129. package/src/native-ui/renderer-extension/test/settings/pages.test.ts +77 -8
  130. package/src/native-ui/renderer-extension/test/settings/shell.test.ts +6 -0
  131. package/src/native-ui/shared-contracts/dist/codex-accounts.d.ts +19 -4
  132. package/src/native-ui/shared-contracts/dist/codex-accounts.d.ts.map +1 -1
  133. package/src/native-ui/shared-contracts/dist/codex-accounts.js +2 -0
  134. package/src/native-ui/shared-contracts/dist/codex-accounts.js.map +1 -1
  135. package/src/native-ui/shared-contracts/dist/index.d.ts +2 -2
  136. package/src/native-ui/shared-contracts/dist/index.d.ts.map +1 -1
  137. package/src/native-ui/shared-contracts/dist/index.js +1 -1
  138. package/src/native-ui/shared-contracts/dist/index.js.map +1 -1
  139. package/src/native-ui/shared-contracts/dist/thread-harness-switch.d.ts +29 -0
  140. package/src/native-ui/shared-contracts/dist/thread-harness-switch.d.ts.map +1 -1
  141. package/src/native-ui/shared-contracts/dist/thread-harness-switch.js +13 -0
  142. package/src/native-ui/shared-contracts/dist/thread-harness-switch.js.map +1 -1
  143. package/src/native-ui/shared-contracts/dist/tsconfig.tsbuildinfo +1 -1
  144. package/src/native-ui/shared-contracts/src/codex-accounts.ts +2 -0
  145. package/src/native-ui/shared-contracts/src/index.ts +8 -1
  146. package/src/native-ui/shared-contracts/src/thread-harness-switch.ts +17 -0
@@ -15580,7 +15580,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15580
15580
  planType: codexAccountPlanTypeSchema.optional(),
15581
15581
  codexHome: nonBlankTextSchema3.max(16384),
15582
15582
  active: external_exports.boolean(),
15583
- isDefault: external_exports.boolean()
15583
+ isDefault: external_exports.boolean(),
15584
+ authenticated: external_exports.boolean().optional(),
15585
+ management: external_exports.enum(["native", "isolated"]).optional()
15584
15586
  }).strict();
15585
15587
  var codexAccountListResultSchema = external_exports.object({ accounts: external_exports.array(codexAccountSchema).max(128) }).strict();
15586
15588
  var codexAccountCreateParamsSchema = external_exports.object({ label: nonBlankTextSchema3.max(256).optional() }).strict();
@@ -15698,13 +15700,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15698
15700
  }).strict();
15699
15701
 
15700
15702
  // src/native-ui/shared-contracts/src/thread-harness-switch.ts
15703
+ var harnessHandoffIntentSchema = external_exports.enum(["continue", "execute-plan", "review", "reanalyze"]);
15704
+ var harnessHandoffIncludesSchema = external_exports.object({
15705
+ conversation: external_exports.boolean(),
15706
+ plan: external_exports.boolean(),
15707
+ evidence: external_exports.boolean(),
15708
+ files: external_exports.boolean(),
15709
+ unresolved: external_exports.boolean()
15710
+ }).strict();
15701
15711
  var threadHarnessSwitchParamsSchema = external_exports.object({
15702
15712
  threadId: hostThreadIdSchema,
15703
15713
  harnessId: external_exports.string().min(1),
15704
- note: external_exports.string().max(2e3).optional()
15714
+ note: external_exports.string().max(2e3).optional(),
15715
+ intent: harnessHandoffIntentSchema.optional(),
15716
+ includes: harnessHandoffIncludesSchema.optional()
15705
15717
  }).strict();
15706
15718
  var threadHarnessSwitchResultSchema = external_exports.object({
15707
- threadId: hostThreadIdSchema
15719
+ threadId: hostThreadIdSchema,
15720
+ checkpointId: external_exports.string().min(1)
15708
15721
  }).strict();
15709
15722
 
15710
15723
  // src/native-ui/shared-contracts/src/harness-commands.ts
@@ -16051,7 +16064,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16051
16064
 
16052
16065
  // src/native-ui/renderer-extension/src/renderer-agent-icon.ts
16053
16066
  var RENDERER_AGENT_LABELS = {
16054
- codex: "Codex",
16067
+ codex: "Codex\uFF08\u5B98\u65B9\u539F\u751F\uFF09",
16055
16068
  pi: "Pi",
16056
16069
  "claude-code": "Claude Code",
16057
16070
  "deepseek-harness": "DeepSeek Harness",
@@ -16067,7 +16080,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16067
16080
  zcode: "ZCode",
16068
16081
  trae: "Trae",
16069
16082
  "cursor-cli": "Cursor",
16070
- "codex-harness": "Codex\uFF08\u534F\u4F5C\uFF09"
16083
+ "codex-harness": "Codex\uFF08Harness Mix \u534F\u4F5C\uFF09"
16071
16084
  };
16072
16085
  var PI_PATHS = [
16073
16086
  {
@@ -18023,8 +18036,8 @@ ${error51.stderrTail}`] : []
18023
18036
  sessionImportRetryOpen: "Try opening again",
18024
18037
  sessionImportRetrying: "Opening...",
18025
18038
  connectionsDescription: "View runtime status by Host. Select an item to inspect details or complete its setup.",
18026
- accountsDescription: "Choose the default account for new Codex tasks and check account limits.",
18027
- accountTaskHint: "Existing tasks keep the account they were created with. Multi-account is currently available for Codex.",
18039
+ accountsDescription: "Manage isolated native Codex accounts and compare each account's live limits.",
18040
+ accountTaskHint: "Signing in or switching accounts does not affect tasks already running. New tasks use the selected account.",
18028
18041
  accountConnected: "Connected accounts",
18029
18042
  accountDefaultBadge: "Default",
18030
18043
  accountAdd: "Add Account",
@@ -18051,6 +18064,11 @@ ${error51.stderrTail}`] : []
18051
18064
  accountActive: "Default",
18052
18065
  accountUse: "Set as default",
18053
18066
  accountSignIn: "Sign in",
18067
+ accountSignOut: "Sign out",
18068
+ accountSignOutConfirm: "Sign out of the current official Codex account?",
18069
+ accountSigningOut: "Signing out of official Codex...",
18070
+ accountSignedOut: "Signed out of official Codex.",
18071
+ accountSignOutFailed: "Could not sign out of official Codex.",
18054
18072
  accountSigningIn: "Starting device sign-in...",
18055
18073
  accountDeviceCodePrerequisite: "Before signing in, enable \u201CEnable device code authorization for Codex\u201D in Web Settings \u2192 Account security & sign-in.",
18056
18074
  accountVerificationDescription: "Open the verification page and enter this one-time code:",
@@ -18214,6 +18232,8 @@ ${error51.stderrTail}`] : []
18214
18232
  pageLabels: Object.freeze({
18215
18233
  connections: "Connections",
18216
18234
  accounts: "Accounts",
18235
+ mcp: "MCP",
18236
+ skills: "Skills",
18217
18237
  "session-import": "Session Import",
18218
18238
  updates: "Updates",
18219
18239
  about: "About"
@@ -18263,8 +18283,8 @@ ${error51.stderrTail}`] : []
18263
18283
  sessionImportRetryOpen: "\u91CD\u8BD5\u6253\u5F00",
18264
18284
  sessionImportRetrying: "\u6B63\u5728\u6253\u5F00\u2026\u2026",
18265
18285
  connectionsDescription: "\u6309 Host \u67E5\u770B\u8FD0\u884C\u65F6\u72B6\u6001\u3002\u9009\u62E9\u4E00\u9879\uFF0C\u5728\u53F3\u4FA7\u68C0\u67E5\u8BE6\u60C5\u6216\u5B8C\u6210\u914D\u7F6E\u3002",
18266
- accountsDescription: "\u9009\u62E9\u65B0\u5EFA Codex \u4EFB\u52A1\u7684\u9ED8\u8BA4\u8D26\u53F7\uFF0C\u5E76\u67E5\u770B\u5404\u8D26\u53F7\u989D\u5EA6\u3002",
18267
- accountTaskHint: "\u5207\u6362\u9ED8\u8BA4\u8D26\u53F7\u4E0D\u4F1A\u5F71\u54CD\u5DF2\u5F00\u59CB\u7684\u4EFB\u52A1\u3002\u76EE\u524D\u4EC5\u652F\u6301 Codex \u591A\u8D26\u53F7\u3002",
18286
+ accountsDescription: "\u7BA1\u7406\u76F8\u4E92\u9694\u79BB\u7684\u539F\u751F Codex \u8D26\u53F7\uFF0C\u5E76\u5BF9\u6BD4\u6BCF\u4E2A\u8D26\u53F7\u7684\u5B9E\u65F6\u989D\u5EA6\u3002",
18287
+ accountTaskHint: "\u767B\u5F55\u6216\u5207\u6362\u8D26\u53F7\u4E0D\u4F1A\u5F71\u54CD\u5DF2\u5F00\u59CB\u7684\u4EFB\u52A1\uFF1B\u65B0\u4EFB\u52A1\u4F7F\u7528\u5F53\u524D\u9009\u4E2D\u7684\u8D26\u53F7\u3002",
18268
18288
  accountConnected: "\u5DF2\u8FDE\u63A5\u8D26\u53F7",
18269
18289
  accountDefaultBadge: "\u9ED8\u8BA4",
18270
18290
  accountAdd: "\u6DFB\u52A0\u8D26\u53F7",
@@ -18291,6 +18311,11 @@ ${error51.stderrTail}`] : []
18291
18311
  accountActive: "\u9ED8\u8BA4\u8D26\u53F7",
18292
18312
  accountUse: "\u8BBE\u4E3A\u9ED8\u8BA4",
18293
18313
  accountSignIn: "\u767B\u5F55",
18314
+ accountSignOut: "\u9000\u51FA\u767B\u5F55",
18315
+ accountSignOutConfirm: "\u786E\u5B9A\u9000\u51FA\u5F53\u524D\u5B98\u65B9 Codex \u8D26\u53F7\u5417\uFF1F",
18316
+ accountSigningOut: "\u6B63\u5728\u9000\u51FA\u5B98\u65B9 Codex...",
18317
+ accountSignedOut: "\u5DF2\u9000\u51FA\u5B98\u65B9 Codex\u3002",
18318
+ accountSignOutFailed: "\u9000\u51FA\u5B98\u65B9 Codex \u5931\u8D25\u3002",
18294
18319
  accountSigningIn: "\u6B63\u5728\u542F\u52A8\u8BBE\u5907\u767B\u5F55...",
18295
18320
  accountDeviceCodePrerequisite: "\u767B\u5F55\u524D\uFF0C\u8BF7\u5148\u5728 Web \u7AEF\u7684\u201C\u8BBE\u7F6E \u2192 \u8D26\u53F7\u5B89\u5168\u4E0E\u767B\u5F55\u201D\u4E2D\u5F00\u542F\u201C\u4E3A Codex \u542F\u7528\u8BBE\u5907\u4EE3\u7801\u6388\u6743\u201D\u3002",
18296
18321
  accountVerificationDescription: "\u6253\u5F00\u9A8C\u8BC1\u9875\u9762\u5E76\u8F93\u5165\u4EE5\u4E0B\u4E00\u6B21\u6027\u4EE3\u7801\uFF1A",
@@ -18454,6 +18479,8 @@ ${error51.stderrTail}`] : []
18454
18479
  pageLabels: Object.freeze({
18455
18480
  connections: "\u8FDE\u63A5",
18456
18481
  accounts: "\u8D26\u53F7",
18482
+ mcp: "MCP",
18483
+ skills: "Skills",
18457
18484
  "session-import": "\u4F1A\u8BDD\u5BFC\u5165",
18458
18485
  updates: "\u66F4\u65B0",
18459
18486
  about: "\u5173\u4E8E"
@@ -18536,10 +18563,11 @@ ${error51.stderrTail}`] : []
18536
18563
  return `Agent: ${RENDERER_AGENT_LABELS[state.agent]}${account}${state.phase === "locked" ? " (locked)" : ""}`;
18537
18564
  }
18538
18565
  function rendererAgentPickerView(state, adapterState, switching, agents, availability = {}, codexAccountCount = 0) {
18566
+ const handoffMode = state.phase === "locked" && state.agent !== "codex";
18539
18567
  const optionDisabled = Object.fromEntries(
18540
18568
  agents.map((agent) => [
18541
18569
  agent,
18542
- switching || state.phase === "locked" || agent !== "codex" && (adapterState !== "ready" || availability[agent] !== "ready")
18570
+ switching || state.phase === "locked" && (!handoffMode || agent === "codex" || agent === state.agent) || agent !== "codex" && (adapterState !== "ready" || availability[agent] !== "ready")
18543
18571
  ])
18544
18572
  );
18545
18573
  const downloadVisible = Object.fromEntries(
@@ -18550,7 +18578,7 @@ ${error51.stderrTail}`] : []
18550
18578
  );
18551
18579
  return {
18552
18580
  label: RENDERER_AGENT_LABELS[state.agent],
18553
- triggerDisabled: switching || state.phase === "locked" || agents.length < 2 && codexAccountCount < 2,
18581
+ triggerDisabled: switching || (state.phase === "locked" ? !handoffMode || !agents.some((agent) => optionDisabled[agent] === false) : agents.length < 2 && codexAccountCount < 2),
18554
18582
  nativeModelHidden: switching || state.agent !== "codex",
18555
18583
  optionDisabled,
18556
18584
  downloadVisible,
@@ -18631,7 +18659,21 @@ ${error51.stderrTail}`] : []
18631
18659
  ownershipError.setAttribute("aria-hidden", "true");
18632
18660
  ownershipError.style.display = "none";
18633
18661
  ownershipError.style.font = "bold 16px/1 system-ui, sans-serif";
18634
- trigger.append(iconSlot, spinner, ownershipError);
18662
+ const handoffBadge = document.createElement("span");
18663
+ handoffBadge.textContent = "\u2197";
18664
+ handoffBadge.setAttribute("aria-hidden", "true");
18665
+ handoffBadge.style.display = "none";
18666
+ handoffBadge.style.position = "absolute";
18667
+ handoffBadge.style.right = "1px";
18668
+ handoffBadge.style.bottom = "0";
18669
+ handoffBadge.style.width = "11px";
18670
+ handoffBadge.style.height = "11px";
18671
+ handoffBadge.style.borderRadius = "999px";
18672
+ handoffBadge.style.background = "#4f7ff0";
18673
+ handoffBadge.style.color = "white";
18674
+ handoffBadge.style.font = "700 9px/11px system-ui, sans-serif";
18675
+ handoffBadge.style.textAlign = "center";
18676
+ trigger.append(iconSlot, spinner, ownershipError, handoffBadge);
18635
18677
  const menu = document.createElement("div");
18636
18678
  menu.id = `${composerId}-agent-menu`;
18637
18679
  menu.setAttribute("role", "menu");
@@ -18656,6 +18698,11 @@ ${error51.stderrTail}`] : []
18656
18698
  const options = {};
18657
18699
  const rowsByAgent = /* @__PURE__ */ new Map();
18658
18700
  const groupMessages = pickerGroupMessages();
18701
+ const modeHeading = document.createElement("div");
18702
+ modeHeading.hidden = true;
18703
+ modeHeading.style.padding = "6px 8px 7px";
18704
+ modeHeading.style.font = "600 11px/1 system-ui, sans-serif";
18705
+ modeHeading.style.opacity = "0.58";
18659
18706
  const close = () => {
18660
18707
  if (!popoverOpen(menu)) return;
18661
18708
  if (typeof menu.hidePopover === "function") menu.hidePopover();
@@ -18930,7 +18977,7 @@ ${error51.stderrTail}`] : []
18930
18977
  });
18931
18978
  regroup();
18932
18979
  const unsubscribeGroup = groupPreference.subscribe(regroup);
18933
- menu.append(mainGroup, moreToggle, morePanel, cta);
18980
+ menu.append(modeHeading, mainGroup, moreToggle, morePanel, cta);
18934
18981
  root.append(trigger, menu);
18935
18982
  const onTriggerClick = () => {
18936
18983
  if (popoverOpen(menu)) close();
@@ -18979,6 +19026,8 @@ ${error51.stderrTail}`] : []
18979
19026
  iconSlot,
18980
19027
  spinner,
18981
19028
  ownershipError,
19029
+ handoffBadge,
19030
+ modeHeading,
18982
19031
  menu,
18983
19032
  agents: [...enabledAgents],
18984
19033
  options,
@@ -19022,7 +19071,7 @@ ${error51.stderrTail}`] : []
19022
19071
  control.trigger.setAttribute("aria-busy", String(switching));
19023
19072
  control.trigger.setAttribute(
19024
19073
  "aria-label",
19025
- ownershipError ? pickerGroupMessages().ownershipErrorLabel : state.phase === "locked" ? `Agent: ${view.label}` : `Select Agent, current ${view.label}`
19074
+ ownershipError ? pickerGroupMessages().ownershipErrorLabel : state.phase === "locked" ? state.agent === "codex" ? `Agent: ${view.label}` : `Hand off task from ${view.label}` : `Select Agent, current ${view.label}`
19026
19075
  );
19027
19076
  const activeAccount = codexAccounts.find(({ active }) => active);
19028
19077
  control.codexAccountGroup.render({
@@ -19031,12 +19080,16 @@ ${error51.stderrTail}`] : []
19031
19080
  disabled: switching || state.phase === "locked",
19032
19081
  showBadge: state.agent === "codex" && codexAccounts.length > 1
19033
19082
  });
19034
- control.trigger.title = ownershipError ? pickerGroupMessages().ownershipErrorLabel : rendererAgentPickerTooltip(state, activeAccount);
19083
+ control.trigger.title = ownershipError ? pickerGroupMessages().ownershipErrorLabel : state.phase === "locked" && state.agent !== "codex" ? `Hand off this task from ${view.label} to another Harness` : rendererAgentPickerTooltip(state, activeAccount);
19035
19084
  control.trigger.style.cursor = control.trigger.disabled ? "not-allowed" : "pointer";
19036
19085
  control.trigger.style.opacity = control.trigger.disabled && !switching ? "0.72" : "1";
19037
19086
  control.iconSlot.style.display = switching || ownershipError ? "none" : "inline-flex";
19038
19087
  control.spinner.style.display = switching ? "block" : "none";
19039
19088
  control.ownershipError.style.display = ownershipError && !switching ? "block" : "none";
19089
+ const handoffMode = state.phase === "locked" && state.agent !== "codex";
19090
+ control.handoffBadge.style.display = handoffMode && !switching && !ownershipError ? "block" : "none";
19091
+ control.modeHeading.hidden = !handoffMode;
19092
+ control.modeHeading.textContent = pickerGroupMessages().locale === "zh-CN" ? `\u63A5\u529B\u5230\u5176\u4ED6 Harness` : "Hand off to another Harness";
19040
19093
  if (control.trigger.disabled) control.close();
19041
19094
  for (const agent of control.agents) {
19042
19095
  const option = control.options[agent];
@@ -21277,6 +21330,291 @@ ${error51.stderrTail}`] : []
21277
21330
  return control;
21278
21331
  }
21279
21332
 
21333
+ // src/native-ui/renderer-extension/src/renderer-harness-handoff.ts
21334
+ var HARNESS_HANDOFF_NOTE_MAX_LENGTH = 2e3;
21335
+ function rendererHarnessHandoffMessages(locale) {
21336
+ return locale === "zh-CN" ? {
21337
+ title: "\u63A5\u529B\u5F53\u524D\u4EFB\u52A1",
21338
+ description: "\u4FDD\u7559\u6B64\u4EFB\u52A1\u7A97\u53E3\u3001\u5BF9\u8BDD\u8BB0\u5F55\u548C\u6587\u4EF6\u73B0\u573A\uFF0C\u53EA\u66F4\u6362\u7EE7\u7EED\u6267\u884C\u7684 Harness\u3002",
21339
+ noteLabel: "\u4EA4\u63A5\u8BF4\u660E\uFF08\u53EF\u9009\uFF09",
21340
+ intentLabel: "\u63A5\u529B\u65B9\u5F0F",
21341
+ intentOptions: { continue: "\u7EE7\u7EED\u6267\u884C", "execute-plan": "\u6267\u884C\u4E0A\u4E00\u65B9\u6848", review: "\u72EC\u7ACB\u5BA1\u67E5", reanalyze: "\u91CD\u65B0\u5206\u6790" },
21342
+ includeLabel: "\u5C06\u8981\u4EA4\u63A5",
21343
+ includeOptions: { conversation: "\u8FD1\u671F\u5BF9\u8BDD", plan: "\u5F53\u524D\u8BA1\u5212", evidence: "\u6D4B\u8BD5\u4E0E\u5DE5\u5177\u8BC1\u636E", files: "\u6587\u4EF6\u53D8\u66F4", unresolved: "\u672A\u89E3\u51B3\u95EE\u9898" },
21344
+ notePlaceholder: "\u4F8B\u5982\uFF1A\u6309\u4E0A\u9762\u7684\u65B9\u6848\u7EE7\u7EED\u5B9E\u73B0\uFF0C\u5148\u6838\u5BF9\u5F53\u524D\u6587\u4EF6\u72B6\u6001\u548C\u672A\u5B8C\u6210\u6B65\u9AA4",
21345
+ context: "\u4E0B\u4E00\u6761\u6D88\u606F\u4F1A\u81EA\u52A8\u643A\u5E26\u8FD1\u671F\u5BF9\u8BDD\u3001\u6700\u65B0\u65B9\u6848\u3001\u8BA1\u5212\u548C\u53D8\u66F4\u6587\u4EF6\u3002",
21346
+ running: "\u82E5\u5F53\u524D\u56DE\u5408\u4ECD\u5728\u8FD0\u884C\uFF0C\u8BF7\u5148\u505C\u6B62\u6216\u7B49\u5F85\u5B8C\u6210\u3002",
21347
+ cancel: "\u53D6\u6D88",
21348
+ confirm: "\u786E\u8BA4\u63A5\u529B",
21349
+ submitting: "\u6B63\u5728\u5207\u6362\u2026"
21350
+ } : {
21351
+ title: "Hand off this task",
21352
+ description: "Keep this task, transcript, and working tree; only change the Harness that continues it.",
21353
+ noteLabel: "Handoff note (optional)",
21354
+ intentLabel: "Handoff mode",
21355
+ intentOptions: { continue: "Continue", "execute-plan": "Execute prior plan", review: "Independent review", reanalyze: "Reanalyze" },
21356
+ includeLabel: "Include",
21357
+ includeOptions: { conversation: "Recent conversation", plan: "Current plan", evidence: "Test and tool evidence", files: "File changes", unresolved: "Open issues" },
21358
+ notePlaceholder: "For example: implement the plan above; verify the working tree and remaining steps first",
21359
+ context: "Your next message will include recent context, the latest solution, plan, and changed files.",
21360
+ running: "If a turn is still running, stop it or wait for it to finish first.",
21361
+ cancel: "Cancel",
21362
+ confirm: "Hand off",
21363
+ submitting: "Switching\u2026"
21364
+ };
21365
+ }
21366
+ function setButtonChrome(button, primary = false) {
21367
+ button.style.height = "34px";
21368
+ button.style.padding = "0 14px";
21369
+ button.style.border = primary ? "1px solid color-mix(in srgb, #5b8cff 70%, CanvasText 30%)" : "1px solid color-mix(in srgb, CanvasText 18%, transparent)";
21370
+ button.style.borderRadius = "7px";
21371
+ button.style.background = primary ? "#4f7ff0" : "color-mix(in srgb, Canvas 94%, CanvasText 6%)";
21372
+ button.style.color = primary ? "white" : "CanvasText";
21373
+ button.style.font = "500 13px/1 system-ui, sans-serif";
21374
+ button.style.cursor = "pointer";
21375
+ }
21376
+ function mountRendererHarnessHandoff(composerId, onConfirm) {
21377
+ const dialog = document.createElement("dialog");
21378
+ dialog.id = `${composerId}-harness-handoff`;
21379
+ dialog.setAttribute("aria-modal", "true");
21380
+ dialog.style.width = "min(440px, calc(100vw - 32px))";
21381
+ dialog.style.boxSizing = "border-box";
21382
+ dialog.style.padding = "0";
21383
+ dialog.style.border = "1px solid color-mix(in srgb, CanvasText 18%, transparent)";
21384
+ dialog.style.borderRadius = "14px";
21385
+ dialog.style.background = "Canvas";
21386
+ dialog.style.color = "CanvasText";
21387
+ dialog.style.boxShadow = "0 24px 70px rgba(0, 0, 0, 0.42)";
21388
+ dialog.style.font = "13px/1.45 system-ui, sans-serif";
21389
+ dialog.style.zIndex = "2147483647";
21390
+ const frame = document.createElement("div");
21391
+ frame.style.display = "flex";
21392
+ frame.style.flexDirection = "column";
21393
+ frame.style.gap = "14px";
21394
+ frame.style.padding = "20px";
21395
+ const title = document.createElement("h2");
21396
+ title.style.margin = "0";
21397
+ title.style.font = "600 17px/1.25 system-ui, sans-serif";
21398
+ const description = document.createElement("p");
21399
+ description.style.margin = "-6px 0 0";
21400
+ description.style.opacity = "0.72";
21401
+ const route = document.createElement("div");
21402
+ route.style.display = "grid";
21403
+ route.style.gridTemplateColumns = "1fr auto 1fr";
21404
+ route.style.alignItems = "center";
21405
+ route.style.gap = "10px";
21406
+ route.style.padding = "12px";
21407
+ route.style.borderRadius = "10px";
21408
+ route.style.background = "color-mix(in srgb, CanvasText 6%, transparent)";
21409
+ const fromBox = document.createElement("div");
21410
+ const toBox = document.createElement("div");
21411
+ for (const box of [fromBox, toBox]) {
21412
+ box.style.display = "flex";
21413
+ box.style.alignItems = "center";
21414
+ box.style.gap = "8px";
21415
+ box.style.minWidth = "0";
21416
+ box.style.fontWeight = "600";
21417
+ }
21418
+ const arrow = document.createElement("span");
21419
+ arrow.textContent = "\u2192";
21420
+ arrow.setAttribute("aria-hidden", "true");
21421
+ arrow.style.opacity = "0.55";
21422
+ route.append(fromBox, arrow, toBox);
21423
+ const intentLabel = document.createElement("label");
21424
+ intentLabel.style.display = "flex";
21425
+ intentLabel.style.flexDirection = "column";
21426
+ intentLabel.style.gap = "7px";
21427
+ const intentLabelText = document.createElement("span");
21428
+ intentLabelText.style.fontWeight = "600";
21429
+ const intent = document.createElement("select");
21430
+ intent.style.height = "36px";
21431
+ intent.style.padding = "0 10px";
21432
+ intent.style.border = "1px solid color-mix(in srgb, CanvasText 20%, transparent)";
21433
+ intent.style.borderRadius = "8px";
21434
+ intent.style.background = "Canvas";
21435
+ intent.style.color = "CanvasText";
21436
+ intent.style.font = "13px/1 system-ui, sans-serif";
21437
+ for (const value of ["continue", "execute-plan", "review", "reanalyze"]) {
21438
+ const option = document.createElement("option");
21439
+ option.value = value;
21440
+ intent.append(option);
21441
+ }
21442
+ intentLabel.append(intentLabelText, intent);
21443
+ const includeSection = document.createElement("fieldset");
21444
+ includeSection.style.margin = "0";
21445
+ includeSection.style.padding = "10px 11px";
21446
+ includeSection.style.border = "1px solid color-mix(in srgb, CanvasText 14%, transparent)";
21447
+ includeSection.style.borderRadius = "8px";
21448
+ const includeLegend = document.createElement("legend");
21449
+ includeLegend.style.padding = "0 5px";
21450
+ includeLegend.style.fontWeight = "600";
21451
+ includeSection.append(includeLegend);
21452
+ const includeGrid = document.createElement("div");
21453
+ includeGrid.style.display = "grid";
21454
+ includeGrid.style.gridTemplateColumns = "repeat(2, minmax(0, 1fr))";
21455
+ includeGrid.style.gap = "8px 12px";
21456
+ const includeInputs = {};
21457
+ const includeLabels = {};
21458
+ for (const key of ["conversation", "plan", "evidence", "files", "unresolved"]) {
21459
+ const row = document.createElement("label");
21460
+ row.style.display = "flex";
21461
+ row.style.alignItems = "center";
21462
+ row.style.gap = "7px";
21463
+ const input = document.createElement("input");
21464
+ input.type = "checkbox";
21465
+ input.checked = true;
21466
+ const text = document.createTextNode("");
21467
+ row.append(input, text);
21468
+ includeGrid.append(row);
21469
+ includeInputs[key] = input;
21470
+ includeLabels[key] = text;
21471
+ }
21472
+ includeSection.append(includeGrid);
21473
+ const label = document.createElement("label");
21474
+ label.style.display = "flex";
21475
+ label.style.flexDirection = "column";
21476
+ label.style.gap = "7px";
21477
+ const labelText = document.createElement("span");
21478
+ labelText.style.fontWeight = "600";
21479
+ const note = document.createElement("textarea");
21480
+ note.rows = 3;
21481
+ note.maxLength = HARNESS_HANDOFF_NOTE_MAX_LENGTH;
21482
+ note.style.boxSizing = "border-box";
21483
+ note.style.width = "100%";
21484
+ note.style.minHeight = "76px";
21485
+ note.style.resize = "vertical";
21486
+ note.style.padding = "10px 11px";
21487
+ note.style.border = "1px solid color-mix(in srgb, CanvasText 20%, transparent)";
21488
+ note.style.borderRadius = "8px";
21489
+ note.style.outline = "none";
21490
+ note.style.background = "color-mix(in srgb, Canvas 96%, CanvasText 4%)";
21491
+ note.style.color = "CanvasText";
21492
+ note.style.font = "13px/1.45 system-ui, sans-serif";
21493
+ label.append(labelText, note);
21494
+ const context = document.createElement("p");
21495
+ context.style.margin = "0";
21496
+ context.style.padding = "9px 10px";
21497
+ context.style.borderRadius = "8px";
21498
+ context.style.background = "color-mix(in srgb, #5b8cff 10%, transparent)";
21499
+ const running = document.createElement("p");
21500
+ running.style.margin = "-8px 0 0";
21501
+ running.style.opacity = "0.65";
21502
+ const error51 = document.createElement("p");
21503
+ error51.setAttribute("role", "alert");
21504
+ error51.hidden = true;
21505
+ error51.style.margin = "-8px 0 0";
21506
+ error51.style.color = "#ef6666";
21507
+ const actions = document.createElement("div");
21508
+ actions.style.display = "flex";
21509
+ actions.style.justifyContent = "flex-end";
21510
+ actions.style.gap = "8px";
21511
+ const cancel = document.createElement("button");
21512
+ cancel.type = "button";
21513
+ setButtonChrome(cancel);
21514
+ const confirm = document.createElement("button");
21515
+ confirm.type = "button";
21516
+ setButtonChrome(confirm, true);
21517
+ actions.append(cancel, confirm);
21518
+ frame.append(title, description, route, intentLabel, includeSection, label, context, running, error51, actions);
21519
+ dialog.append(frame);
21520
+ document.body.append(dialog);
21521
+ let from = "pi";
21522
+ let to = "claude-code";
21523
+ let locale = "en";
21524
+ let submitting = false;
21525
+ const render = () => {
21526
+ const messages = rendererHarnessHandoffMessages(locale);
21527
+ title.textContent = messages.title;
21528
+ description.textContent = messages.description;
21529
+ labelText.textContent = messages.noteLabel;
21530
+ intentLabelText.textContent = messages.intentLabel;
21531
+ includeLegend.textContent = messages.includeLabel;
21532
+ for (const [value, text] of Object.entries(messages.intentOptions)) {
21533
+ const option = [...intent.options].find((candidate) => candidate.value === value);
21534
+ if (option) option.textContent = text;
21535
+ }
21536
+ for (const key of Object.keys(includeInputs)) includeLabels[key].data = messages.includeOptions[key];
21537
+ note.placeholder = messages.notePlaceholder;
21538
+ context.textContent = messages.context;
21539
+ running.textContent = messages.running;
21540
+ cancel.textContent = messages.cancel;
21541
+ confirm.textContent = submitting ? messages.submitting : messages.confirm;
21542
+ fromBox.replaceChildren(createRendererAgentIcon(from, 24), document.createTextNode(RENDERER_AGENT_LABELS[from]));
21543
+ toBox.replaceChildren(createRendererAgentIcon(to, 24), document.createTextNode(RENDERER_AGENT_LABELS[to]));
21544
+ note.disabled = submitting;
21545
+ intent.disabled = submitting;
21546
+ includeSection.disabled = submitting;
21547
+ cancel.disabled = submitting;
21548
+ confirm.disabled = submitting;
21549
+ cancel.style.cursor = submitting ? "not-allowed" : "pointer";
21550
+ confirm.style.cursor = submitting ? "wait" : "pointer";
21551
+ confirm.setAttribute("aria-busy", String(submitting));
21552
+ };
21553
+ const close = () => {
21554
+ if (submitting) return;
21555
+ if (dialog.open) dialog.close();
21556
+ };
21557
+ cancel.addEventListener("click", close);
21558
+ confirm.addEventListener("click", () => {
21559
+ if (submitting) return;
21560
+ onConfirm({
21561
+ from,
21562
+ to,
21563
+ note: note.value.trim(),
21564
+ intent: intent.value,
21565
+ includes: Object.fromEntries(Object.entries(includeInputs).map(([key, input]) => [key, input.checked]))
21566
+ });
21567
+ });
21568
+ note.addEventListener("keydown", (event) => {
21569
+ if ((event.ctrlKey || event.metaKey) && event.key === "Enter" && !submitting) {
21570
+ event.preventDefault();
21571
+ confirm.click();
21572
+ }
21573
+ });
21574
+ dialog.addEventListener("cancel", (event) => {
21575
+ if (submitting) event.preventDefault();
21576
+ });
21577
+ const control = {
21578
+ dialog,
21579
+ note,
21580
+ intent,
21581
+ includeInputs,
21582
+ confirm,
21583
+ cancel,
21584
+ error: error51,
21585
+ open(nextFrom, nextTo, nextLocale) {
21586
+ from = nextFrom;
21587
+ to = nextTo;
21588
+ locale = nextLocale;
21589
+ submitting = false;
21590
+ note.value = "";
21591
+ intent.value = "continue";
21592
+ for (const input of Object.values(includeInputs)) input.checked = true;
21593
+ error51.hidden = true;
21594
+ error51.textContent = "";
21595
+ render();
21596
+ if (!dialog.open) dialog.showModal();
21597
+ queueMicrotask(() => note.focus());
21598
+ },
21599
+ close,
21600
+ setSubmitting(nextSubmitting) {
21601
+ submitting = nextSubmitting;
21602
+ render();
21603
+ },
21604
+ showError(message) {
21605
+ error51.textContent = message;
21606
+ error51.hidden = false;
21607
+ },
21608
+ dispose() {
21609
+ submitting = false;
21610
+ if (dialog.open) dialog.close();
21611
+ dialog.remove();
21612
+ }
21613
+ };
21614
+ render();
21615
+ return control;
21616
+ }
21617
+
21280
21618
  // src/native-ui/renderer-extension/src/renderer-composer-dom.ts
21281
21619
  var CODEX_COMPOSER_SELECTOR = "[data-codex-composer-root]";
21282
21620
  var EDITOR_SELECTOR = 'textarea, [contenteditable="true"], [role="textbox"]';
@@ -21564,7 +21902,7 @@ ${error51.stderrTail}`] : []
21564
21902
  setNativeControlHidden(control.nativeContextUsageControl, false);
21565
21903
  setNativeControlHidden(control.nativePermissionModeControl, hidePermissionMode);
21566
21904
  }
21567
- function mountComposerAgentControl(composer, composerId, sendButton, enabledAgents, onSelect, onDownload, onSelectCodexAccount, onOpenProviderPicker, onSelectModel, onSelectThinking, onSelectPermissionMode, onSelectCommand) {
21905
+ function mountComposerAgentControl(composer, composerId, sendButton, enabledAgents, onSelect, onDownload, onSelectCodexAccount, onOpenProviderPicker, onSelectModel, onSelectThinking, onSelectPermissionMode, onSelectCommand, onConfirmHandoff) {
21568
21906
  const nativeModelControl = captureNativeControl(nativeModelControlForComposer(composer));
21569
21907
  const nativeContextUsageControl = captureNativeControl(
21570
21908
  nativeContextUsageControlForComposer(composer)
@@ -21592,6 +21930,7 @@ ${error51.stderrTail}`] : []
21592
21930
  trailingActionAnchor(sendButton),
21593
21931
  onSelectCommand
21594
21932
  );
21933
+ const harnessHandoff = mountRendererHarnessHandoff(composerId, onConfirmHandoff);
21595
21934
  const permissionParent = nativePermissionModeControl?.element.parentElement;
21596
21935
  if (permissionParent && nativePermissionModeControl && nativePermissionModeControlVerified) {
21597
21936
  permissionParent.insertBefore(permissionModePicker.root, nativePermissionModeControl.element);
@@ -21613,6 +21952,7 @@ ${error51.stderrTail}`] : []
21613
21952
  credits,
21614
21953
  usage: null,
21615
21954
  harnessCommands,
21955
+ harnessHandoff,
21616
21956
  sendButton,
21617
21957
  sendDisabledBeforeSwitch: null
21618
21958
  };
@@ -21690,6 +22030,7 @@ ${error51.stderrTail}`] : []
21690
22030
  control.usage?.dispose();
21691
22031
  control.usage = null;
21692
22032
  control.harnessCommands.dispose();
22033
+ control.harnessHandoff.dispose();
21693
22034
  control.permissionModePicker.dispose();
21694
22035
  control.modelPicker.dispose();
21695
22036
  control.picker.dispose();
@@ -21705,6 +22046,10 @@ ${error51.stderrTail}`] : []
21705
22046
  selectedAccountId: validOverrideAccountId ?? activeAccountId
21706
22047
  };
21707
22048
  }
22049
+ function codexAccountRouteOverride(accounts, accountId) {
22050
+ if (!accountId) return null;
22051
+ return accounts.find((account) => account.accountId === accountId)?.management === "isolated" ? accountId : null;
22052
+ }
21708
22053
  var RendererCodexAccountState = class {
21709
22054
  constructor(client) {
21710
22055
  this.client = client;
@@ -22511,6 +22856,39 @@ ${error51.stderrTail}`] : []
22511
22856
  };
22512
22857
  }
22513
22858
 
22859
+ // src/native-ui/renderer-extension/src/renderer-integrations-client.ts
22860
+ var serverSchema = external_exports.object({
22861
+ id: external_exports.string(),
22862
+ name: external_exports.string(),
22863
+ transportType: external_exports.enum(["stdio", "streamable_http"]).optional(),
22864
+ command: external_exports.string().optional().default(""),
22865
+ args: external_exports.array(external_exports.string()).optional().default([]),
22866
+ env: external_exports.record(external_exports.string(), external_exports.string()).optional(),
22867
+ env_vars: external_exports.array(external_exports.string()).optional(),
22868
+ cwd: external_exports.string().nullable().optional(),
22869
+ url: external_exports.string().optional(),
22870
+ bearer_token_env_var: external_exports.string().optional(),
22871
+ http_headers: external_exports.record(external_exports.string(), external_exports.string()).optional(),
22872
+ env_http_headers: external_exports.record(external_exports.string(), external_exports.string()).optional(),
22873
+ enabled: external_exports.boolean(),
22874
+ scope: external_exports.enum(["global", "project"]),
22875
+ editable: external_exports.boolean(),
22876
+ effective: external_exports.boolean(),
22877
+ appliedSessions: external_exports.number()
22878
+ });
22879
+ var skillSchema = external_exports.object({ name: external_exports.string(), path: external_exports.string(), root: external_exports.string(), enabled: external_exports.boolean(), writable: external_exports.boolean(), scope: external_exports.enum(["global", "project"]), status: external_exports.string() });
22880
+ var snapshotSchema = external_exports.object({ harnessId: external_exports.string(), mcpSupported: external_exports.boolean(), skillsSupported: external_exports.boolean(), servers: external_exports.array(serverSchema), native: external_exports.array(external_exports.object({ sessionId: external_exports.string(), name: external_exports.string(), status: external_exports.string(), tools: external_exports.array(external_exports.string()) })), skills: external_exports.array(skillSchema), note: external_exports.string() });
22881
+ var catalogSchema = external_exports.object({ harnesses: external_exports.array(external_exports.object({ id: external_exports.string(), name: external_exports.string(), available: external_exports.boolean(), mcp: external_exports.boolean(), skills: external_exports.boolean() })) });
22882
+ function createRendererIntegrationsClient(send) {
22883
+ return {
22884
+ integrationCatalog: async () => catalogSchema.parse(await send("codexhost/integrations/catalog", {})),
22885
+ listIntegrations: async (input) => snapshotSchema.parse(await send("codexhost/integrations/list", input)),
22886
+ saveMcp: (input) => send("codexhost/integrations/mcp/save", input),
22887
+ removeMcp: (input) => send("codexhost/integrations/mcp/remove", input),
22888
+ changeSkill: (input) => send("codexhost/integrations/skill/change", input)
22889
+ };
22890
+ }
22891
+
22514
22892
  // src/native-ui/renderer-extension/src/renderer-session-import-client.ts
22515
22893
  var RendererSessionImportUnavailableError = class extends Error {
22516
22894
  constructor() {
@@ -22578,6 +22956,7 @@ ${error51.stderrTail}`] : []
22578
22956
  var UPDATE_CHECK_METHOD = "codexhost/update/check";
22579
22957
  var UPDATE_START_METHOD = "codexhost/update/start";
22580
22958
  var UPDATE_STATUS_METHOD = "codexhost/update/status";
22959
+ var RUNTIME_VERSION_METHOD = "harness-mix/runtime/version";
22581
22960
  var CODEX_ACCOUNT_LIST_METHOD = "codexhost/account/list";
22582
22961
  var CODEX_ACCOUNT_REFRESH_METHOD = "codexhost/account/refresh";
22583
22962
  var CODEX_ACCOUNT_CREATE_METHOD = "codexhost/account/create";
@@ -22691,6 +23070,7 @@ ${error51.stderrTail}`] : []
22691
23070
  if (!Array.isArray(result) || !result.every((a) => a && typeof a.id === "string" && typeof a.name === "string" && typeof a.available === "boolean" && typeof a.lead === "boolean")) throw new Error("Invalid collaboration catalog");
22692
23071
  return result;
22693
23072
  },
23073
+ ...createRendererIntegrationsClient((method, params) => manager.sendRequest(method, params)),
22694
23074
  ...createRendererSessionImportClient(
22695
23075
  async (method, params) => manager.sendRequest(method, params)
22696
23076
  ),
@@ -22817,6 +23197,13 @@ ${error51.stderrTail}`] : []
22817
23197
  );
22818
23198
  return updateStatusResultSchema.parse(result);
22819
23199
  },
23200
+ async readCurrentVersion() {
23201
+ const result = await manager.sendRequest(RUNTIME_VERSION_METHOD, {});
23202
+ if (!isRecord6(result) || typeof result.version !== "string" || !result.version.trim()) {
23203
+ throw new Error("Invalid Harness Mix version response");
23204
+ }
23205
+ return { version: result.version.trim() };
23206
+ },
22820
23207
  async inspectCodexAccountUsage(input) {
22821
23208
  const result = await manager.sendRequest(
22822
23209
  "codexhost/account/usage/inspect",
@@ -22879,6 +23266,10 @@ ${error51.stderrTail}`] : []
22879
23266
  );
22880
23267
  return codexAccountLoginCancelResultSchema.parse(result);
22881
23268
  },
23269
+ async logoutCodexAccount() {
23270
+ const result = await manager.sendRequest("codexhost/account/logout", {});
23271
+ return codexAccountMutationResultSchema.parse(result);
23272
+ },
22882
23273
  subscribeCodexAccountLogin(listener) {
22883
23274
  const notifications = notificationTarget(source);
22884
23275
  if (!notifications?.addNotificationCallback) {
@@ -23710,8 +24101,66 @@ ${error51.stderrTail}`] : []
23710
24101
  }
23711
24102
 
23712
24103
  // src/native-ui/renderer-extension/src/renderer-harness-mentions.ts
23713
- var entryKey = (entry) => entry.kind === "agent" ? `agent:${entry.id}` : `session:${entry.id}`;
23714
- var entryLiteral = (entry) => entry.kind === "agent" ? `@${entry.id} ` : `@[${entry.title.replace(/[\[\]()\r\n]/g, "")}](harness-mix://session/${entry.id}) `;
24104
+ var entryKey = (entry) => {
24105
+ if (entry.kind === "agent") return `agent:${entry.id}`;
24106
+ if (entry.kind === "session") return `session:${entry.id}`;
24107
+ return `codex:${entry.id}`;
24108
+ };
24109
+ var entryLiteral = (entry) => {
24110
+ if (entry.kind === "agent") return `#${entry.id} `;
24111
+ if (entry.kind === "session") return `#[${entry.title.replace(/[\[\]()\r\n]/g, "")}](harness-mix://session/${entry.id}) `;
24112
+ return "";
24113
+ };
24114
+ var AGENT_DESCRIPTIONS = {
24115
+ codex: "\u5B98\u65B9 Codex CLI \u539F\u751F\u534F\u540C",
24116
+ "codex-cli": "\u5B98\u65B9 Codex CLI \u539F\u751F\u534F\u540C",
24117
+ pi: "\u8F7B\u91CF\u5FEB\u901F\u539F\u751F\u7F16\u7801 Harness",
24118
+ omp: "Oh My Pi \u589E\u5F3A\u7248\u4EA4\u4E92 Harness",
24119
+ dsh: "DeepSeek Harness \u539F\u751F\u6DF1\u5EA6\u63A8\u7406\u4E0E\u5DE5\u5177\u8C03\u7528",
24120
+ "deepseek-harness": "DeepSeek Harness \u539F\u751F\u6DF1\u5EA6\u63A8\u7406\u4E0E\u5DE5\u5177\u8C03\u7528",
24121
+ claude: "Anthropic Claude Code \u539F\u751F\u534F\u540C",
24122
+ "claude-code": "Anthropic Claude Code \u539F\u751F\u534F\u540C",
24123
+ antigravity: "Google Antigravity 2.0 \u539F\u751F Harness",
24124
+ opencode: "\u5F00\u6E90\u81EA\u4E3B\u7F16\u7801\u667A\u80FD\u4F53",
24125
+ grok: "xAI Grok \u539F\u751F\u534F\u540C\u4E0E\u6DF1\u5EA6\u63A8\u7406",
24126
+ openclaw: "OpenClaw \u4E2A\u4EBA AI \u81EA\u4E3B\u667A\u80FD\u4F53",
24127
+ hermes: "Nous Research Hermes \u81EA\u6211\u8FED\u4EE3\u667A\u80FD\u4F53",
24128
+ qoder: "Qoder \u7F16\u7A0B\u52A9\u624B",
24129
+ codebuddy: "CodeBuddy \u539F\u751F\u667A\u80FD\u4F53",
24130
+ zcode: "ZCode \u81EA\u52A8\u5316\u5DE5\u7A0B\u4EE3\u7406",
24131
+ trae: "Trae \u539F\u751F\u534F\u540C",
24132
+ "kiro-cli": "Kiro CLI \u667A\u80FD\u7F16\u7A0B",
24133
+ "cursor-cli": "Cursor CLI \u539F\u751F\u534F\u540C"
24134
+ };
24135
+ var AGENT_COLORS = {
24136
+ codex: "#3b82f6",
24137
+ "codex-cli": "#3b82f6",
24138
+ "codex-harness": "#3b82f6",
24139
+ grok: "#8b5cf6",
24140
+ opencode: "#a855f7",
24141
+ "claude-code": "#ea580c",
24142
+ claude: "#ea580c",
24143
+ antigravity: "#0284c7",
24144
+ pi: "#d97706",
24145
+ omp: "#d97706",
24146
+ dsh: "#2563eb",
24147
+ "deepseek-harness": "#2563eb",
24148
+ "kiro-cli": "#db2777",
24149
+ openclaw: "#dc2626",
24150
+ hermes: "#059669",
24151
+ qoder: "#7c3aed",
24152
+ codebuddy: "#0891b2",
24153
+ zcode: "#4f46e5",
24154
+ trae: "#0284c7",
24155
+ "cursor-cli": "#475569"
24156
+ };
24157
+ function getAgentColor(agentId) {
24158
+ const normalized = agentId.toLowerCase();
24159
+ for (const [key, color] of Object.entries(AGENT_COLORS)) {
24160
+ if (normalized.includes(key)) return color;
24161
+ }
24162
+ return "#6366f1";
24163
+ }
23715
24164
  function installHarnessMentions(load) {
23716
24165
  const menu = document.createElement("div");
23717
24166
  menu.dataset.harnessMixMentions = "true";
@@ -23721,24 +24170,74 @@ ${error51.stderrTail}`] : []
23721
24170
  menu.hidden = true;
23722
24171
  document.body.append(menu);
23723
24172
  const style = document.createElement("style");
23724
- style.textContent = '[data-harness-mix-mention-active] [data-composer-overlay-floating-ui="true"]{display:none!important}';
24173
+ style.textContent = `
24174
+ [data-harness-mix-has-mentions="true"] {
24175
+ display: flex !important;
24176
+ flex-wrap: wrap !important;
24177
+ align-items: baseline !important;
24178
+ gap: 8px !important;
24179
+ }
24180
+ [data-harness-mix-has-mentions="true"] > [data-harness-mix-selected-mentions] {
24181
+ display: inline-flex !important;
24182
+ align-items: center !important;
24183
+ gap: 8px !important;
24184
+ flex-wrap: wrap !important;
24185
+ vertical-align: baseline !important;
24186
+ line-height: 1.5 !important;
24187
+ }
24188
+ [data-harness-mix-has-mentions="true"] > textarea,
24189
+ [data-harness-mix-has-mentions="true"] > [contenteditable="true"],
24190
+ [data-harness-mix-has-mentions="true"] > .ProseMirror {
24191
+ display: inline-block !important;
24192
+ width: auto !important;
24193
+ min-width: 60px !important;
24194
+ flex: 1 1 auto !important;
24195
+ margin: 0 !important;
24196
+ padding: 0 !important;
24197
+ vertical-align: baseline !important;
24198
+ }
24199
+ [data-harness-mix-mention-badge]:hover {
24200
+ background: rgba(128, 128, 128, 0.14) !important;
24201
+ }
24202
+ `;
23725
24203
  document.head.append(style);
23726
24204
  let activeComposer = null;
23727
24205
  let generation = 0, disposed = false, selected = 0;
23728
24206
  let editor = null;
23729
24207
  let range = null, start = 0, end = 0;
23730
24208
  let entries = [];
23731
- let matches = [], activeKind = "agent", canDelegate = true;
24209
+ let matches = [];
24210
+ let activeKind = "agent";
24211
+ let canDelegate = true;
23732
24212
  const catalogs = /* @__PURE__ */ new Map();
23733
24213
  const badges = /* @__PURE__ */ new Map();
23734
- const selections = /* @__PURE__ */ new Map();
24214
+ const sessionSelections = /* @__PURE__ */ new Map();
24215
+ const conversationKeyFor = (target) => {
24216
+ const composer = target.closest("[data-codex-composer-root]");
24217
+ if (!composer) return target.__harnessMixEditorKey || "default";
24218
+ const portal = composer.querySelector("[data-above-composer-portal]");
24219
+ const portalId = portal?.getAttribute("data-above-composer-conversation-id");
24220
+ if (portalId) return `conversation:${portalId}`;
24221
+ const convEl = composer.closest("[data-conversation-id]") || composer.querySelector("[data-conversation-id]");
24222
+ const convId = convEl?.getAttribute("data-conversation-id");
24223
+ if (convId) return `conversation:${convId}`;
24224
+ const draftId = composer.getAttribute("data-composer-draft-id");
24225
+ if (draftId) return `draft:${draftId}`;
24226
+ const all = composer.querySelectorAll('textarea, [contenteditable="true"]');
24227
+ if (all.length > 1) {
24228
+ const index = Array.from(all).indexOf(target);
24229
+ return `editor:${index >= 0 ? index : "default"}`;
24230
+ }
24231
+ return "default";
24232
+ };
23735
24233
  const selectionsFor = (target) => {
23736
- let perEditor = selections.get(target);
23737
- if (!perEditor) {
23738
- perEditor = /* @__PURE__ */ new Map();
23739
- selections.set(target, perEditor);
24234
+ const key = conversationKeyFor(target);
24235
+ let perSession = sessionSelections.get(key);
24236
+ if (!perSession) {
24237
+ perSession = /* @__PURE__ */ new Map();
24238
+ sessionSelections.set(key, perSession);
23740
24239
  }
23741
- return perEditor;
24240
+ return perSession;
23742
24241
  };
23743
24242
  const replaceSelectionWith = (target, replacement) => {
23744
24243
  if (target instanceof HTMLTextAreaElement) {
@@ -23772,66 +24271,76 @@ ${error51.stderrTail}`] : []
23772
24271
  return true;
23773
24272
  };
23774
24273
  const syncBadges = (target) => {
23775
- for (const [old, strip2] of badges) if (!old.isConnected) {
23776
- strip2.remove();
23777
- badges.delete(old);
23778
- catalogs.delete(old);
24274
+ for (const [old, strip2] of badges) {
24275
+ if (!old.isConnected) {
24276
+ strip2.remove();
24277
+ badges.delete(old);
24278
+ catalogs.delete(old);
24279
+ }
23779
24280
  }
23780
- const perEditor = selections.get(target);
24281
+ const perEditor = selectionsFor(target);
23781
24282
  const hasAny = !!perEditor && perEditor.size > 0;
23782
24283
  let strip = badges.get(target);
24284
+ const container = target.parentElement;
24285
+ if (hasAny) {
24286
+ container?.setAttribute("data-harness-mix-has-mentions", "true");
24287
+ } else {
24288
+ container?.removeAttribute("data-harness-mix-has-mentions");
24289
+ }
23783
24290
  if (!strip && !hasAny) return;
23784
24291
  if (!strip) {
23785
24292
  strip = document.createElement("div");
23786
24293
  strip.dataset.harnessMixSelectedMentions = "true";
23787
24294
  strip.setAttribute("aria-label", "\u5DF2\u63D0\u53CA\u7684\u534F\u4F5C\u8005");
23788
- strip.style.cssText = "display:flex;gap:6px;flex-wrap:wrap;padding:6px 0";
23789
- target.after(strip);
24295
+ strip.style.cssText = "display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap;padding:0;margin:0 4px 0 0;vertical-align:baseline;line-height:normal;";
24296
+ target.before(strip);
23790
24297
  badges.set(target, strip);
23791
24298
  }
24299
+ const newKeys = perEditor ? [...perEditor.values()].map((e) => e.kind === "agent" ? `agent:${e.id}` : e.kind === "session" ? `session:${e.id}` : `codex:${e.id}`).join(",") : "";
24300
+ const currentKeys = [...strip.querySelectorAll("[data-harness-mix-mention-badge]")].map((b) => b.dataset.harnessMixMentionBadge).join(",");
24301
+ if (strip.isConnected && currentKeys === newKeys && strip.style.display === (hasAny ? "inline-flex" : "none")) {
24302
+ return;
24303
+ }
23792
24304
  strip.replaceChildren();
23793
- strip.style.display = hasAny ? "flex" : "none";
24305
+ strip.style.display = hasAny ? "inline-flex" : "none";
23794
24306
  if (!perEditor) return;
23795
24307
  for (const entry of perEditor.values()) {
23796
- const badge = document.createElement("span");
23797
- badge.dataset.harnessMixMentionBadge = entry.kind === "agent" ? `agent:${entry.id}` : `session:${entry.id}`;
23798
- badge.style.cssText = "display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border:1px solid #8883;border-radius:8px;font:12px inherit;background:#8881";
23799
- const iconWrap = document.createElement("span");
23800
- iconWrap.style.cssText = "display:inline-flex;align-items:center;gap:6px";
23801
- iconWrap.append(
23802
- collaborationIcon(entry.kind === "agent" ? entry.id : entry.harnessId, entry.kind === "agent" ? entry.name : entry.title, 16),
23803
- document.createTextNode(entry.kind === "agent" ? entry.name : entry.title)
23804
- );
23805
- const remove = document.createElement("button");
23806
- remove.type = "button";
23807
- remove.dataset.harnessMixMentionRemove = entry.kind === "agent" ? `agent:${entry.id}` : `session:${entry.id}`;
23808
- const removeLabel = entry.kind === "agent" ? `\u79FB\u9664 ${entry.name}` : `\u79FB\u9664\u4F1A\u8BDD ${entry.title}`;
23809
- remove.setAttribute("aria-label", removeLabel);
23810
- remove.title = removeLabel;
23811
- remove.textContent = "\xD7";
23812
- remove.style.cssText = "border:0;background:transparent;color:inherit;cursor:pointer;padding:0 0 0 2px;margin:0;font:600 14px/1 inherit;opacity:.55;line-height:1;display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:50%";
23813
- remove.addEventListener("mouseenter", () => {
23814
- remove.style.opacity = "1";
23815
- remove.style.background = "#8883";
24308
+ const badge = document.createElement("button");
24309
+ badge.type = "button";
24310
+ badge.dataset.harnessMixMentionBadge = entry.kind === "agent" ? `agent:${entry.id}` : entry.kind === "session" ? `session:${entry.id}` : `codex:${entry.id}`;
24311
+ const removeLabel = entry.kind === "agent" ? `\u79FB\u9664\u534F\u4F5C Agent ${entry.name}` : entry.kind === "session" ? `\u79FB\u9664\u5386\u53F2\u4F1A\u8BDD ${entry.title}` : `\u79FB\u9664 Codex \u9009\u9879 ${entry.title}`;
24312
+ badge.setAttribute("aria-label", removeLabel);
24313
+ badge.title = `${removeLabel}\uFF08\u70B9\u51FB\u79FB\u9664\uFF09`;
24314
+ const agentColor = entry.kind === "agent" ? getAgentColor(entry.id) : entry.kind === "codex" ? "#0ea5e9" : "#8b5cf6";
24315
+ badge.style.cssText = `display:inline-flex;align-items:center;gap:4px;padding:1px 5px;border:0;border-radius:4px;background:transparent;color:${agentColor};font:500 15px/1.4 system-ui,-apple-system,BlinkMacSystemFont,sans-serif;user-select:none;cursor:pointer;transition:background 0.15s,opacity 0.15s;`;
24316
+ badge.addEventListener("mouseenter", () => {
24317
+ badge.style.background = "rgba(128,128,128,0.12)";
23816
24318
  });
23817
- remove.addEventListener("mouseleave", () => {
23818
- remove.style.opacity = ".55";
23819
- remove.style.background = "transparent";
24319
+ badge.addEventListener("mouseleave", () => {
24320
+ badge.style.background = "transparent";
23820
24321
  });
23821
- remove.addEventListener("mousedown", (event) => {
24322
+ badge.addEventListener("click", (event) => {
23822
24323
  event.preventDefault();
23823
24324
  event.stopPropagation();
23824
- });
23825
- remove.addEventListener("click", (event) => {
23826
- event.preventDefault();
23827
- event.stopPropagation();
23828
- const live = selections.get(target);
23829
- if (!live) return;
24325
+ const live = selectionsFor(target);
23830
24326
  live.delete(entryKey(entry));
23831
24327
  syncBadges(target);
24328
+ target.focus();
23832
24329
  });
23833
- badge.append(iconWrap, remove);
23834
- badge.title = entry.kind === "agent" ? `@${entry.id}${entry.available ? "" : " \xB7 \u672A\u5C31\u7EEA"}` : `\u5386\u53F2\u4F1A\u8BDD \xB7 ${entry.cwd}`;
24330
+ const iconWrap = document.createElement("span");
24331
+ iconWrap.style.cssText = "display:inline-flex;align-items:center;gap:4px;";
24332
+ if (entry.kind === "agent" || entry.kind === "session") {
24333
+ iconWrap.append(
24334
+ collaborationIcon(entry.kind === "agent" ? entry.id : entry.harnessId, entry.kind === "agent" ? entry.name : entry.title, 16),
24335
+ document.createTextNode(entry.kind === "agent" ? entry.name : entry.title)
24336
+ );
24337
+ } else {
24338
+ const iconSpan = document.createElement("span");
24339
+ iconSpan.textContent = entry.icon || "\u{1F4CC}";
24340
+ iconSpan.style.cssText = "font-size:14px;line-height:1;";
24341
+ iconWrap.append(iconSpan, document.createTextNode(entry.title));
24342
+ }
24343
+ badge.append(iconWrap);
23835
24344
  strip.append(badge);
23836
24345
  }
23837
24346
  };
@@ -23839,14 +24348,33 @@ ${error51.stderrTail}`] : []
23839
24348
  generation++;
23840
24349
  menu.hidden = true;
23841
24350
  activeComposer?.removeAttribute("data-harness-mix-mention-active");
24351
+ activeComposer?.removeAttribute("data-harness-mix-show-native");
23842
24352
  activeComposer = null;
23843
24353
  };
23844
24354
  const choose = (entry) => {
23845
- if (!editor || (entry.kind === "agent" ? !entry.available || !canDelegate : entry.running === true)) return;
24355
+ if (!editor) return;
24356
+ if (entry.kind === "agent" && (!entry.available || !canDelegate)) return;
24357
+ if (entry.kind === "session" && entry.running === true) return;
23846
24358
  const target = editor;
23847
24359
  close();
23848
24360
  target.focus();
23849
24361
  replaceSelectionWith(target, "");
24362
+ if (entry.kind === "codex") {
24363
+ const nativeOverlay = document.querySelector('[data-composer-overlay-floating-ui="true"]');
24364
+ if (nativeOverlay) {
24365
+ const buttons = [...nativeOverlay.querySelectorAll('button, [role="option"]')];
24366
+ const match = buttons.find((b) => (b.innerText || b.textContent || "").includes(entry.title));
24367
+ if (match) {
24368
+ match.click();
24369
+ return;
24370
+ }
24371
+ }
24372
+ if (entry.action === "files") {
24373
+ const fileInput = document.querySelector('input[type="file"]');
24374
+ fileInput?.click();
24375
+ }
24376
+ return;
24377
+ }
23850
24378
  const perEditor = selectionsFor(target);
23851
24379
  const key = entryKey(entry);
23852
24380
  if (perEditor.has(key)) perEditor.delete(key);
@@ -23858,16 +24386,21 @@ ${error51.stderrTail}`] : []
23858
24386
  const tabs = document.createElement("div");
23859
24387
  tabs.setAttribute("role", "tablist");
23860
24388
  tabs.style.cssText = "display:flex;gap:4px;padding:2px 2px 6px;border-bottom:1px solid #8882;margin-bottom:4px";
23861
- for (const kind of ["agent", "session"]) {
24389
+ const tabDefinitions = [
24390
+ { kind: "agent", label: "Agents" },
24391
+ { kind: "session", label: "\u4F1A\u8BDD" }
24392
+ ];
24393
+ for (const tabInfo of tabDefinitions) {
23862
24394
  const tab = document.createElement("button");
23863
24395
  tab.type = "button";
23864
24396
  tab.setAttribute("role", "tab");
23865
- tab.setAttribute("aria-selected", String(activeKind === kind));
23866
- tab.textContent = `${kind === "agent" ? "Agents" : "\u4F1A\u8BDD"} ${matches.filter((entry) => entry.kind === kind).length}`;
23867
- tab.style.cssText = `border:0;border-radius:6px;padding:6px 10px;color:inherit;font:inherit;cursor:pointer;background:${activeKind === kind ? "#8882" : "transparent"}`;
24397
+ tab.setAttribute("aria-selected", String(activeKind === tabInfo.kind));
24398
+ const count = matches.filter((entry) => entry.kind === tabInfo.kind).length;
24399
+ tab.textContent = `${tabInfo.label} ${count}`;
24400
+ tab.style.cssText = `border:0;border-radius:6px;padding:6px 10px;color:inherit;font:inherit;cursor:pointer;background:${activeKind === tabInfo.kind ? "#8882" : "transparent"};transition:background .15s;`;
23868
24401
  tab.addEventListener("mousedown", (event) => event.preventDefault());
23869
24402
  tab.addEventListener("click", () => {
23870
- activeKind = kind;
24403
+ activeKind = tabInfo.kind;
23871
24404
  selected = 0;
23872
24405
  render();
23873
24406
  });
@@ -23890,7 +24423,7 @@ ${error51.stderrTail}`] : []
23890
24423
  row.type = "button";
23891
24424
  row.setAttribute("role", "option");
23892
24425
  row.setAttribute("aria-selected", String(index === selected));
23893
- const available = entry.kind === "agent" ? entry.available && canDelegate : entry.running !== true;
24426
+ const available = entry.kind === "agent" ? entry.available && canDelegate : entry.kind === "session" ? entry.running !== true : true;
23894
24427
  row.disabled = !available;
23895
24428
  row.id = `harness-mention-option-${index}`;
23896
24429
  row.style.cssText = `display:flex;align-items:center;gap:8px;width:100%;text-align:left;border:0;border-radius:7px;padding:7px 8px;color:inherit;font:inherit;cursor:pointer;background:${index === selected ? "#8882" : "transparent"};opacity:${available ? 1 : 0.45}`;
@@ -23898,15 +24431,24 @@ ${error51.stderrTail}`] : []
23898
24431
  copy.style.cssText = "display:flex;flex-direction:column;gap:3px;flex:1;min-width:0";
23899
24432
  const name = document.createElement("span");
23900
24433
  name.textContent = entry.kind === "agent" ? entry.name : entry.title;
23901
- name.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap";
24434
+ name.style.cssText = "overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500;";
23902
24435
  const detail = document.createElement("span");
23903
- detail.textContent = entry.kind === "agent" ? `@${entry.id}` : entry.cwd;
24436
+ detail.textContent = entry.kind === "agent" ? AGENT_DESCRIPTIONS[entry.id] || entry.description || `#${entry.id}` : entry.kind === "session" ? entry.cwd : entry.description || entry.category;
23904
24437
  detail.style.cssText = "font-size:11px;opacity:.55;overflow:hidden;text-overflow:ellipsis;white-space:nowrap";
23905
24438
  copy.append(name, detail);
23906
24439
  const status = document.createElement("span");
23907
- status.textContent = entry.kind === "agent" ? entry.available ? "\u53EF\u534F\u4F5C" : "\u672A\u5C31\u7EEA" : entry.running ? "\u8FD0\u884C\u4E2D" : "\u5F15\u7528";
24440
+ status.textContent = entry.kind === "agent" ? entry.available ? "\u53EF\u534F\u4F5C" : "\u672A\u5C31\u7EEA" : entry.kind === "session" ? entry.running ? "\u8FD0\u884C\u4E2D" : "\u5F15\u7528" : entry.category || "\u539F\u751F";
23908
24441
  status.style.cssText = "font-size:11px;opacity:.6";
23909
- row.append(collaborationIcon(entry.kind === "agent" ? entry.id : entry.harnessId, name.textContent || ""), copy, status);
24442
+ let iconEl;
24443
+ if (entry.kind === "agent" || entry.kind === "session") {
24444
+ iconEl = collaborationIcon(entry.kind === "agent" ? entry.id : entry.harnessId, name.textContent || "", 18);
24445
+ } else {
24446
+ const iconSpan = document.createElement("span");
24447
+ iconSpan.textContent = entry.icon || "\u{1F4CE}";
24448
+ iconSpan.style.cssText = "font-size:16px;line-height:1;width:18px;text-align:center;";
24449
+ iconEl = iconSpan;
24450
+ }
24451
+ row.append(iconEl, copy, status);
23910
24452
  row.addEventListener("mousedown", (event) => event.preventDefault());
23911
24453
  row.addEventListener("click", () => choose(entry));
23912
24454
  list.append(row);
@@ -23946,7 +24488,7 @@ ${error51.stderrTail}`] : []
23946
24488
  end = prefix.length;
23947
24489
  range = caret.cloneRange();
23948
24490
  }
23949
- const match = /(?:^|[\s,。;:])@([\p{L}\p{N}_-]*)$/u.exec(prefix);
24491
+ const match = /(?:^|[\s,。;:])#([\p{L}\p{N}_-]*)$/u.exec(prefix);
23950
24492
  if (!match) {
23951
24493
  close();
23952
24494
  return;
@@ -23961,15 +24503,18 @@ ${error51.stderrTail}`] : []
23961
24503
  syncBadges(editable);
23962
24504
  const query = match[1].toLowerCase();
23963
24505
  canDelegate = catalog.canDelegate !== false;
23964
- matches = [
23965
- ...catalog.agents.filter((a) => a.id.toLowerCase().includes(query) || a.name.toLowerCase().includes(query)).map((a) => ({ kind: "agent", ...a })),
23966
- ...catalog.sessions.filter((session) => `${session.title} ${session.cwd}`.toLowerCase().includes(query)).map((session) => ({ kind: "session", ...session }))
23967
- ];
23968
- activeKind = query && !matches.some((entry) => entry.kind === "agent") && matches.some((entry) => entry.kind === "session") ? "session" : "agent";
24506
+ const matchingAgents = catalog.agents.filter((a) => a.id.toLowerCase().includes(query) || a.name.toLowerCase().includes(query)).map((a) => ({ kind: "agent", title: a.name, ...a }));
24507
+ const matchingSessions = catalog.sessions.filter((s) => `${s.title} ${s.cwd}`.toLowerCase().includes(query)).map((s) => ({ kind: "session", ...s }));
24508
+ matches = [...matchingAgents, ...matchingSessions];
24509
+ if (query && !matchingAgents.length && matchingSessions.length) {
24510
+ activeKind = "session";
24511
+ } else {
24512
+ activeKind = "agent";
24513
+ }
23969
24514
  entries = matches.filter((entry) => entry.kind === activeKind);
23970
- selected = Math.max(0, entries.findIndex((entry) => entry.kind === "agent" ? entry.available && canDelegate : entry.running !== true));
24515
+ selected = Math.max(0, entries.findIndex((entry) => entry.kind === "agent" ? entry.available && canDelegate : entry.kind === "session" ? entry.running !== true : true));
23971
24516
  render();
23972
- menu.hidden = !catalog.agents.length && !catalog.sessions.length && catalog.canDelegate === void 0;
24517
+ menu.hidden = !matches.length && catalog.canDelegate === void 0;
23973
24518
  activeComposer?.removeAttribute("data-harness-mix-mention-active");
23974
24519
  activeComposer = !menu.hidden ? editable.closest("[data-codex-composer-root]") : null;
23975
24520
  activeComposer?.setAttribute("data-harness-mix-mention-active", "true");
@@ -23985,6 +24530,33 @@ ${error51.stderrTail}`] : []
23985
24530
  }
23986
24531
  };
23987
24532
  const keydown = (event) => {
24533
+ const target = event.target;
24534
+ if (target instanceof HTMLElement && target.closest("[data-codex-composer-root]")) {
24535
+ const editable = target.closest('textarea,[contenteditable="true"]');
24536
+ if (editable && event.key === "Backspace") {
24537
+ let isAtStart = false;
24538
+ if (editable instanceof HTMLTextAreaElement) {
24539
+ isAtStart = editable.selectionStart === 0 && editable.selectionEnd === 0;
24540
+ } else {
24541
+ const sel = window.getSelection();
24542
+ if (sel && sel.isCollapsed && sel.rangeCount > 0) {
24543
+ const r = sel.getRangeAt(0);
24544
+ isAtStart = r.startOffset === 0 && (r.startContainer === editable || r.startContainer.textContent === "" || editable.firstChild === r.startContainer);
24545
+ }
24546
+ }
24547
+ if (isAtStart) {
24548
+ const perSession = selectionsFor(editable);
24549
+ if (perSession && perSession.size > 0) {
24550
+ const keys = [...perSession.keys()];
24551
+ const lastKey = keys[keys.length - 1];
24552
+ if (lastKey) perSession.delete(lastKey);
24553
+ syncBadges(editable);
24554
+ event.preventDefault();
24555
+ return;
24556
+ }
24557
+ }
24558
+ }
24559
+ }
23988
24560
  if (menu.hidden || event.isComposing) return;
23989
24561
  if (event.key === "Escape") {
23990
24562
  close();
@@ -23993,9 +24565,12 @@ ${error51.stderrTail}`] : []
23993
24565
  if (!["ArrowDown", "ArrowUp", "ArrowLeft", "ArrowRight", "Enter", "Tab", "Escape"].includes(event.key)) return;
23994
24566
  event.preventDefault();
23995
24567
  event.stopImmediatePropagation();
23996
- if (event.key === "Escape") close();
23997
- else if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
23998
- activeKind = activeKind === "agent" ? "session" : "agent";
24568
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
24569
+ const kinds = ["agent", "session"];
24570
+ const curIdx = kinds.indexOf(activeKind);
24571
+ const nextIdx = (curIdx + (event.key === "ArrowRight" ? 1 : -1) + kinds.length) % kinds.length;
24572
+ const next = kinds[nextIdx];
24573
+ if (next) activeKind = next;
23999
24574
  selected = 0;
24000
24575
  render();
24001
24576
  } else if (event.key === "Enter" || event.key === "Tab") {
@@ -24005,7 +24580,7 @@ ${error51.stderrTail}`] : []
24005
24580
  for (let i = 0; i < entries.length; i++) {
24006
24581
  selected = (selected + (event.key === "ArrowDown" ? 1 : -1) + entries.length) % entries.length;
24007
24582
  const entry = entries[selected];
24008
- if (entry && (entry.kind === "agent" ? entry.available && canDelegate : entry.running !== true)) break;
24583
+ if (entry && (entry.kind === "agent" ? entry.available && canDelegate : entry.kind === "session" ? entry.running !== true : true)) break;
24009
24584
  }
24010
24585
  render();
24011
24586
  menu.querySelector('[role="option"][aria-selected="true"]')?.scrollIntoView({ block: "nearest" });
@@ -24020,7 +24595,7 @@ ${error51.stderrTail}`] : []
24020
24595
  return root.querySelector('textarea,[contenteditable="true"]');
24021
24596
  };
24022
24597
  const injectMentionsInto = (target) => {
24023
- const perEditor = selections.get(target);
24598
+ const perEditor = selectionsFor(target);
24024
24599
  if (!perEditor || perEditor.size === 0) return false;
24025
24600
  const text = [...perEditor.values()].map(entryLiteral).join("");
24026
24601
  if (!text) return false;
@@ -24029,16 +24604,18 @@ ${error51.stderrTail}`] : []
24029
24604
  target.value = `${text}${target.value}`;
24030
24605
  target.dispatchEvent(new Event("input", { bubbles: true }));
24031
24606
  target.dispatchEvent(new Event("change", { bubbles: true }));
24032
- return true;
24033
- }
24034
- const selection = window.getSelection();
24035
- const fresh = document.createRange();
24036
- fresh.selectNodeContents(target);
24037
- fresh.collapse(true);
24038
- selection?.removeAllRanges();
24039
- selection?.addRange(fresh);
24040
- document.dispatchEvent(new Event("selectionchange"));
24041
- document.execCommand("insertText", false, text);
24607
+ } else {
24608
+ const selection = window.getSelection();
24609
+ const fresh = document.createRange();
24610
+ fresh.selectNodeContents(target);
24611
+ fresh.collapse(true);
24612
+ selection?.removeAllRanges();
24613
+ selection?.addRange(fresh);
24614
+ document.dispatchEvent(new Event("selectionchange"));
24615
+ document.execCommand("insertText", false, text);
24616
+ }
24617
+ perEditor.clear();
24618
+ syncBadges(target);
24042
24619
  return true;
24043
24620
  };
24044
24621
  const onSubmitCapture = (event) => {
@@ -24049,26 +24626,70 @@ ${error51.stderrTail}`] : []
24049
24626
  if (!editorEl.closest("[data-codex-composer-root]")) return;
24050
24627
  injectMentionsInto(editorEl);
24051
24628
  };
24629
+ const onFocusIn = (event) => {
24630
+ const target = event.target;
24631
+ if (target instanceof HTMLElement && target.closest("[data-codex-composer-root]")) {
24632
+ const editable = target.closest('textarea,[contenteditable="true"]');
24633
+ if (editable) syncBadges(editable);
24634
+ }
24635
+ };
24636
+ const observer = new MutationObserver((mutations) => {
24637
+ let shouldSync = false;
24638
+ for (const m of mutations) {
24639
+ if (m.target instanceof Element) {
24640
+ if (m.target.closest("[data-harness-mix-selected-mentions]") || m.target.closest("[data-harness-mix-mentions]")) {
24641
+ continue;
24642
+ }
24643
+ }
24644
+ shouldSync = true;
24645
+ break;
24646
+ }
24647
+ if (!shouldSync) return;
24648
+ const composers = document.querySelectorAll("[data-codex-composer-root]");
24649
+ for (const composer of composers) {
24650
+ const el = findEditorIn(composer);
24651
+ if (el) syncBadges(el);
24652
+ }
24653
+ });
24654
+ try {
24655
+ observer.observe(document.body, {
24656
+ childList: true,
24657
+ subtree: true,
24658
+ attributes: true,
24659
+ attributeFilter: ["data-above-composer-conversation-id", "data-conversation-id", "data-composer-draft-id"]
24660
+ });
24661
+ } catch {
24662
+ }
24052
24663
  document.addEventListener("input", input, true);
24053
24664
  document.addEventListener("keydown", keydown, true);
24054
24665
  document.addEventListener("mousedown", outside);
24055
24666
  document.addEventListener("submit", onSubmitCapture, true);
24667
+ document.addEventListener("focusin", onFocusIn, true);
24056
24668
  window.addEventListener("blur", close);
24057
- return { dispose() {
24058
- disposed = true;
24059
- close();
24060
- menu.remove();
24061
- style.remove();
24062
- for (const strip of badges.values()) strip.remove();
24063
- badges.clear();
24064
- catalogs.clear();
24065
- for (const [target, perEditor] of selections) if (!target.isConnected) selections.delete(target);
24066
- document.removeEventListener("input", input, true);
24067
- document.removeEventListener("keydown", keydown, true);
24068
- document.removeEventListener("mousedown", outside);
24069
- document.removeEventListener("submit", onSubmitCapture, true);
24070
- window.removeEventListener("blur", close);
24071
- } };
24669
+ return {
24670
+ sync(target) {
24671
+ syncBadges(target);
24672
+ },
24673
+ dispose() {
24674
+ disposed = true;
24675
+ close();
24676
+ menu.remove();
24677
+ style.remove();
24678
+ observer.disconnect();
24679
+ for (const el of document.querySelectorAll("[data-harness-mix-has-mentions]")) {
24680
+ el.removeAttribute("data-harness-mix-has-mentions");
24681
+ }
24682
+ for (const strip of badges.values()) strip.remove();
24683
+ badges.clear();
24684
+ catalogs.clear();
24685
+ document.removeEventListener("input", input, true);
24686
+ document.removeEventListener("keydown", keydown, true);
24687
+ document.removeEventListener("mousedown", outside);
24688
+ document.removeEventListener("submit", onSubmitCapture, true);
24689
+ document.removeEventListener("focusin", onFocusIn, true);
24690
+ window.removeEventListener("blur", close);
24691
+ }
24692
+ };
24072
24693
  }
24073
24694
 
24074
24695
  // src/native-ui/renderer-extension/src/renderer-collab-cards.ts
@@ -24398,6 +25019,9 @@ ${error51.stderrTail}`] : []
24398
25019
 
24399
25020
  // src/native-ui/renderer-extension/src/settings/accounts-list.ts
24400
25021
  var resetDetailsSequence = 0;
25022
+ function isCodexAccountAuthenticated(account) {
25023
+ return account.authenticated ?? Boolean(account.email);
25024
+ }
24401
25025
  function accountPlanLabel(planType) {
24402
25026
  if (!planType || planType === "unknown") return null;
24403
25027
  if (planType === "free") return "Free";
@@ -24530,7 +25154,7 @@ ${error51.stderrTail}`] : []
24530
25154
  activate.addEventListener("click", input.onActivate);
24531
25155
  actions.append(activate);
24532
25156
  }
24533
- if (!account.email) {
25157
+ if (!isCodexAccountAuthenticated(account)) {
24534
25158
  const signIn = document2.createElement("button");
24535
25159
  signIn.type = "button";
24536
25160
  signIn.className = "settings-account-action";
@@ -24540,6 +25164,16 @@ ${error51.stderrTail}`] : []
24540
25164
  signIn.addEventListener("click", input.onSignIn);
24541
25165
  actions.append(signIn);
24542
25166
  }
25167
+ if (account.management === "native" && isCodexAccountAuthenticated(account) && input.onSignOut) {
25168
+ const signOut = document2.createElement("button");
25169
+ signOut.type = "button";
25170
+ signOut.className = "settings-account-action";
25171
+ signOut.textContent = messages.accountSignOut;
25172
+ signOut.dataset.accountFocus = `${account.accountId}:logout`;
25173
+ signOut.disabled = input.actionsDisabled;
25174
+ signOut.addEventListener("click", input.onSignOut);
25175
+ actions.append(signOut);
25176
+ }
24543
25177
  if (!account.isDefault) {
24544
25178
  const remove = document2.createElement("button");
24545
25179
  remove.type = "button";
@@ -24904,12 +25538,12 @@ ${error51.stderrTail}`] : []
24904
25538
  const restoreFocus = accountListFocusRestorer(list, search);
24905
25539
  body.replaceChildren();
24906
25540
  status.textContent = loginMessage ?? "";
24907
- connectedCount.textContent = String(accounts.filter((account) => account.email).length);
25541
+ connectedCount.textContent = String(accounts.filter(isCodexAccountAuthenticated).length);
24908
25542
  search.disabled = login !== null || loginStartingAccountId !== null;
24909
25543
  for (const [display, button] of displayButtons) {
24910
25544
  button.setAttribute("aria-pressed", String(display === usageDisplay));
24911
25545
  }
24912
- refreshUsage.disabled = (!getClient()?.inspectCodexAccountUsage || !accounts.some((account) => account.email)) && !getClient()?.listHarnessAccounts || harnessAccounts?.refreshing === true || [...usageByAccountId.values()].some((usage) => usage.status === "loading") || accountBusy();
25546
+ refreshUsage.disabled = (!getClient()?.inspectCodexAccountUsage || !accounts.some(isCodexAccountAuthenticated)) && !getClient()?.listHarnessAccounts || harnessAccounts?.refreshing === true || [...usageByAccountId.values()].some((usage) => usage.status === "loading") || accountBusy();
24913
25547
  const query = search.value.trim().toLocaleLowerCase();
24914
25548
  harnessAccounts?.update(query, usageDisplay);
24915
25549
  const visibleAccounts = accounts.filter(
@@ -24924,6 +25558,7 @@ ${error51.stderrTail}`] : []
24924
25558
  emptyRow.append(emptyCell);
24925
25559
  body.append(emptyRow);
24926
25560
  }
25561
+ add.hidden = false;
24927
25562
  add.disabled = accountBusy();
24928
25563
  for (const account of visibleAccounts) {
24929
25564
  body.append(
@@ -24936,6 +25571,7 @@ ${error51.stderrTail}`] : []
24936
25571
  resetExpanded: expandedResetAccounts.has(account.accountId),
24937
25572
  onActivate: () => mutate(() => client().activateCodexAccount({ accountId: account.accountId })),
24938
25573
  onSignIn: () => startLogin(account.accountId),
25574
+ ...account.management === "native" && getClient()?.logoutCodexAccount ? { onSignOut: () => signOut() } : {},
24939
25575
  onDelete: () => deleteAccount(account.accountId),
24940
25576
  onRetry: () => {
24941
25577
  usageByAccountId.delete(account.accountId);
@@ -25009,7 +25645,7 @@ ${error51.stderrTail}`] : []
25009
25645
  };
25010
25646
  const loadUsage = (nextAccounts) => {
25011
25647
  const inspect = getClient()?.inspectCodexAccountUsage;
25012
- const signedIn = nextAccounts.filter((account) => account.email);
25648
+ const signedIn = nextAccounts.filter(isCodexAccountAuthenticated);
25013
25649
  const keep = new Set(signedIn.map((account) => account.accountId));
25014
25650
  for (const accountId of [...usageByAccountId.keys()]) {
25015
25651
  if (!keep.has(accountId)) usageByAccountId.delete(accountId);
@@ -25120,6 +25756,27 @@ ${error51.stderrTail}`] : []
25120
25756
  }
25121
25757
  });
25122
25758
  };
25759
+ const signOut = () => {
25760
+ const logout = getClient()?.logoutCodexAccount;
25761
+ if (!logout || accountBusy()) return;
25762
+ if (document2.defaultView?.confirm?.(messages.accountSignOutConfirm) === false) return;
25763
+ accountActivating = true;
25764
+ loginMessage = messages.accountSigningOut;
25765
+ render();
25766
+ void context.runLatest(() => logout(), {
25767
+ success(result) {
25768
+ accountActivating = false;
25769
+ loginMessage = messages.accountSignedOut;
25770
+ usageByAccountId.clear();
25771
+ setAccounts([result.account]);
25772
+ },
25773
+ failure(error51) {
25774
+ accountActivating = false;
25775
+ loginMessage = errorMessage(error51, messages.accountSignOutFailed);
25776
+ render();
25777
+ }
25778
+ });
25779
+ };
25123
25780
  const createAndLogin = () => {
25124
25781
  if (accountBusy()) return;
25125
25782
  accountCreating = true;
@@ -26030,6 +26687,1717 @@ ${error51.stderrTail}`] : []
26030
26687
  }
26031
26688
  }
26032
26689
 
26690
+ // src/native-ui/renderer-extension/src/settings/integrations-page.ts
26691
+ function createIntegrationSettingsPage(kind, messages, getClient) {
26692
+ const zh = messages.locale === "zh-CN";
26693
+ const tr = (cn, en) => zh ? cn : en;
26694
+ return Object.freeze({
26695
+ id: kind,
26696
+ label: kind === "mcp" ? "MCP" : "Skills",
26697
+ icon: kind === "mcp" ? "connections" : "session-import",
26698
+ mount(context) {
26699
+ const { content } = context;
26700
+ const lifecycle = { signal: context.signal, runLatest: context.runLatest, get disposed() {
26701
+ return context.signal.aborted;
26702
+ } };
26703
+ const doc = content.ownerDocument;
26704
+ const el = (tag, text = "") => {
26705
+ const node = doc.createElement(tag);
26706
+ node.textContent = text;
26707
+ return node;
26708
+ };
26709
+ const title = el("h2", kind === "mcp" ? "MCP" : "Skills");
26710
+ const note = el("p", kind === "mcp" ? tr("\u6309 Harness \u7BA1\u7406 MCP \u670D\u52A1\u5668\u3002\u914D\u7F6E\u4F1A\u5728\u4E0B\u6B21\u6253\u5F00\u539F\u751F\u4F1A\u8BDD\u65F6\u4F20\u5165\u3002", "Manage MCP servers per Harness. Configuration is passed to the next native session.") : tr("\u628A\u6280\u80FD\u6587\u4EF6\u6216\u5B8C\u6574\u6280\u80FD\u6587\u4EF6\u5939\u62D6\u5230\u8FD9\u91CC\uFF0C\u76F4\u63A5\u5B89\u88C5\u5230\u539F\u751F\u6280\u80FD\u76EE\u5F55\u3002", "Drop a skill file or a complete skill folder here to install it in the native skill directory."));
26711
+ note.className = "settings-page-description";
26712
+ const controls = el("div");
26713
+ controls.className = "settings-integrations-controls";
26714
+ const harness = el("select");
26715
+ harness.setAttribute("aria-label", "Harness");
26716
+ const level = el("select");
26717
+ level.setAttribute("aria-label", tr("\u4F5C\u7528\u8303\u56F4", "Scope"));
26718
+ for (const [value, label] of [["global", tr("\u5168\u5C40", "Global")], ["project", tr("\u9879\u76EE", "Project")]]) {
26719
+ const option = el("option", label);
26720
+ option.value = value;
26721
+ level.append(option);
26722
+ }
26723
+ const cwd = el("input");
26724
+ cwd.placeholder = tr("\u9879\u76EE\u7EDD\u5BF9\u8DEF\u5F84", "Absolute project path");
26725
+ cwd.setAttribute("aria-label", cwd.placeholder);
26726
+ cwd.hidden = true;
26727
+ const refreshButton = el("button", tr("\u5237\u65B0", "Refresh"));
26728
+ refreshButton.type = "button";
26729
+ refreshButton.className = "settings-command-button settings-command-button--secondary";
26730
+ const status = el("p");
26731
+ status.className = "settings-integrations-status";
26732
+ status.setAttribute("role", "status");
26733
+ status.setAttribute("aria-live", "polite");
26734
+ const body = el("div");
26735
+ body.className = "settings-integrations-body";
26736
+ let busy = false;
26737
+ const selectedScope = () => ({ harnessId: harness.value, scope: level.value === "project" ? "project" : "global", ...level.value === "project" ? { cwd: cwd.value.trim() } : {} });
26738
+ const client = () => {
26739
+ const value = getClient();
26740
+ if (!value) throw new Error(tr("Host \u5C1A\u672A\u8FDE\u63A5\uFF0C\u8BF7\u8FDE\u63A5\u540E\u5237\u65B0\u3002", "Host is not connected. Connect and refresh."));
26741
+ return value;
26742
+ };
26743
+ const fail = (error51) => {
26744
+ status.textContent = error51 instanceof Error ? error51.message : String(error51);
26745
+ status.setAttribute("role", "alert");
26746
+ };
26747
+ const setBusy = (value) => {
26748
+ busy = value;
26749
+ content.dataset.integrationBusy = String(value);
26750
+ for (const node of content.querySelectorAll("button, input, select, textarea")) node.disabled = value || node.dataset.readonly === "true";
26751
+ };
26752
+ const button = (label, action, primary = false) => {
26753
+ const node = el("button", label);
26754
+ node.type = "button";
26755
+ node.className = `settings-command-button ${primary ? "settings-command-button--primary" : "settings-command-button--secondary"}`;
26756
+ node.addEventListener("click", action, { signal: lifecycle.signal });
26757
+ return node;
26758
+ };
26759
+ const mutate = async (operation) => {
26760
+ if (busy) return;
26761
+ const selected = selectedScope();
26762
+ setBusy(true);
26763
+ status.textContent = tr("\u6B63\u5728\u4FDD\u5B58\u2026", "Saving\u2026");
26764
+ status.setAttribute("role", "status");
26765
+ try {
26766
+ await operation(client(), selected);
26767
+ if (!lifecycle.disposed) {
26768
+ setBusy(false);
26769
+ await refresh();
26770
+ status.textContent = tr("\u5DF2\u4FDD\u5B58\uFF0C\u4E0B\u6B21\u6253\u5F00\u539F\u751F\u4F1A\u8BDD\u65F6\u751F\u6548\u3002", "Saved. Applies on the next native session open.");
26771
+ }
26772
+ } catch (error51) {
26773
+ if (!lifecycle.disposed) {
26774
+ setBusy(false);
26775
+ fail(error51);
26776
+ }
26777
+ }
26778
+ };
26779
+ const mutateCustom = async (operation) => {
26780
+ if (busy) return;
26781
+ setBusy(true);
26782
+ status.textContent = tr("\u6B63\u5728\u4FDD\u5B58\u2026", "Saving\u2026");
26783
+ status.setAttribute("role", "status");
26784
+ try {
26785
+ const message = await operation(client());
26786
+ if (!lifecycle.disposed) {
26787
+ setBusy(false);
26788
+ await refresh();
26789
+ status.textContent = message || tr("\u5DF2\u4FDD\u5B58\uFF0C\u4E0B\u6B21\u6253\u5F00\u539F\u751F\u4F1A\u8BDD\u65F6\u751F\u6548\u3002", "Saved. Applies on the next native session open.");
26790
+ }
26791
+ } catch (error51) {
26792
+ if (!lifecycle.disposed) {
26793
+ setBusy(false);
26794
+ fail(error51);
26795
+ }
26796
+ }
26797
+ };
26798
+ const bytesToBase64 = (buffer) => {
26799
+ const bytes = new Uint8Array(buffer);
26800
+ let binary = "";
26801
+ for (let offset = 0; offset < bytes.length; offset += 32768) binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
26802
+ return btoa(binary);
26803
+ };
26804
+ const fileFromEntry = (entry) => new Promise((resolve, reject) => entry.file?.(resolve, reject));
26805
+ const entriesFromReader = async (entry) => {
26806
+ const reader = entry.createReader?.();
26807
+ if (!reader) return [];
26808
+ const all = [];
26809
+ while (true) {
26810
+ const batch = await new Promise((resolve, reject) => reader.readEntries(resolve, reject));
26811
+ if (!batch.length) break;
26812
+ all.push(...batch);
26813
+ }
26814
+ return all;
26815
+ };
26816
+ const walkEntry = async (entry, prefix, output) => {
26817
+ if (entry.isFile) {
26818
+ output.push({ path: `${prefix}${entry.name}`, file: await fileFromEntry(entry) });
26819
+ return;
26820
+ }
26821
+ if (entry.isDirectory) for (const child of await entriesFromReader(entry)) await walkEntry(child, `${prefix}${entry.name}/`, output);
26822
+ };
26823
+ const parseDroppedSkills = async (incoming) => {
26824
+ if (!incoming.length) throw new Error(tr("\u6CA1\u6709\u8BFB\u53D6\u5230\u6587\u4EF6\u3002", "No files were read."));
26825
+ if (incoming.length > 500 || incoming.reduce((sum, item) => sum + item.file.size, 0) > 10 * 1024 * 1024) throw new Error(tr("\u6280\u80FD\u8D85\u8FC7 10 MB \u6216 500 \u4E2A\u6587\u4EF6\u3002", "Skill exceeds 10 MB or 500 files."));
26826
+ let normalized = incoming;
26827
+ if (incoming.length === 1) {
26828
+ if (!/\.md$/i.test(incoming[0].file.name)) throw new Error(tr("\u5355\u6587\u4EF6\u6280\u80FD\u5FC5\u987B\u662F Markdown \u6587\u4EF6\u3002", "A single-file skill must be a Markdown file."));
26829
+ normalized = [{ path: "SKILL.md", file: incoming[0].file }];
26830
+ } else {
26831
+ const paths = incoming.map((item) => item.path.replaceAll("\\", "/"));
26832
+ const first = paths[0].split("/")[0];
26833
+ if (first && paths.every((value) => value.startsWith(`${first}/`))) normalized = incoming.map((item, index) => ({ ...item, path: paths[index].slice(first.length + 1) }));
26834
+ if (!normalized.some((item) => item.path === "SKILL.md")) throw new Error(tr("\u6280\u80FD\u6587\u4EF6\u5939\u6839\u76EE\u5F55\u5FC5\u987B\u5305\u542B SKILL.md\u3002", "The skill folder root must contain SKILL.md."));
26835
+ }
26836
+ const skillFile = normalized.find((item) => item.path === "SKILL.md");
26837
+ const markdown = await skillFile.file.text();
26838
+ const declared = markdown.match(/^---[\s\S]*?^name:\s*["']?([^\r\n"']+)/m)?.[1]?.trim();
26839
+ const fallback = incoming.length === 1 ? incoming[0].file.name.replace(/\.md$/i, "") : incoming[0].path.split(/[\\/]/)[0];
26840
+ const name = (declared || fallback || "skill").toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
26841
+ if (!name) throw new Error(tr("\u65E0\u6CD5\u4ECE\u6587\u4EF6\u4E2D\u786E\u5B9A\u6709\u6548\u7684\u6280\u80FD\u540D\u79F0\u3002", "Could not determine a valid skill name from the files."));
26842
+ const files = [];
26843
+ for (const item of normalized) files.push({ path: item.path.replaceAll("\\", "/"), contentBase64: bytesToBase64(await item.file.arrayBuffer()) });
26844
+ return { name, files };
26845
+ };
26846
+ const field = (form, label, node) => {
26847
+ const wrap = el("label", label);
26848
+ wrap.className = "settings-integrations-field";
26849
+ wrap.append(node);
26850
+ form.append(wrap);
26851
+ };
26852
+ let targetEditServerName = void 0;
26853
+ const editInHarness = (harnessId, serverName) => {
26854
+ harness.value = harnessId;
26855
+ targetEditServerName = serverName;
26856
+ void refresh();
26857
+ };
26858
+ const toManagedForCopy = (s, newEnabled) => {
26859
+ const isHttp = s.transportType === "streamable_http" || typeof s.url === "string" && s.url.trim().length > 0;
26860
+ if (isHttp) {
26861
+ return {
26862
+ name: s.name,
26863
+ transportType: "streamable_http",
26864
+ enabled: newEnabled !== void 0 ? newEnabled : s.enabled ?? true,
26865
+ url: s.url || "",
26866
+ ...s.bearer_token_env_var?.trim() ? { bearer_token_env_var: s.bearer_token_env_var.trim() } : {},
26867
+ ...s.http_headers && Object.keys(s.http_headers).length ? { http_headers: s.http_headers } : {},
26868
+ ...s.env_http_headers && Object.keys(s.env_http_headers).length ? { env_http_headers: s.env_http_headers } : {}
26869
+ };
26870
+ }
26871
+ return {
26872
+ name: s.name,
26873
+ transportType: "stdio",
26874
+ enabled: newEnabled !== void 0 ? newEnabled : s.enabled ?? true,
26875
+ command: s.command || "",
26876
+ ...s.args?.length ? { args: s.args } : {},
26877
+ ...s.env && Object.keys(s.env).length ? { env: s.env } : {},
26878
+ ...s.env_vars?.length ? { env_vars: s.env_vars } : {},
26879
+ ...s.cwd?.trim() ? { cwd: s.cwd.trim() } : {}
26880
+ };
26881
+ };
26882
+ const renderMcp = (snapshot) => {
26883
+ const toolbar = el("div");
26884
+ toolbar.className = "settings-integrations-toolbar";
26885
+ const search = el("input");
26886
+ search.type = "search";
26887
+ search.placeholder = tr("\u641C\u7D22 MCP \u670D\u52A1\u5668", "Search MCP servers");
26888
+ search.setAttribute("aria-label", search.placeholder);
26889
+ const list = el("div");
26890
+ list.className = "settings-integrations-list";
26891
+ const editor = el("div");
26892
+ editor.className = "settings-mcp-editor";
26893
+ editor.hidden = true;
26894
+ const showList = () => {
26895
+ editor.hidden = true;
26896
+ list.hidden = false;
26897
+ toolbar.hidden = false;
26898
+ };
26899
+ const showEditor = (server) => {
26900
+ editor.replaceChildren();
26901
+ editor.hidden = false;
26902
+ list.hidden = true;
26903
+ toolbar.hidden = true;
26904
+ const heading = el("div");
26905
+ heading.className = "settings-integrations-editor-head";
26906
+ const backBtn = button(tr("\u2039 \u8FD4\u56DE", "\u2039 Back"), showList);
26907
+ const title2 = el("h3", server ? tr(`\u66F4\u65B0 ${server.name} MCP`, `Update ${server.name} MCP`) : tr("\u8FDE\u63A5\u81F3\u81EA\u5B9A\u4E49 MCP", "Connect to a custom MCP"));
26908
+ const docsLink = el("a", tr("\u6587\u6863 \u2197", "Docs \u2197"));
26909
+ docsLink.href = "https://modelcontextprotocol.io/introduction";
26910
+ docsLink.target = "_blank";
26911
+ docsLink.rel = "noreferrer noopener";
26912
+ docsLink.className = "settings-mcp-docs-link";
26913
+ heading.append(backBtn, title2, docsLink);
26914
+ if (server?.editable) {
26915
+ const uninstallBtn = button(tr("\u5378\u8F7D", "Uninstall"), () => {
26916
+ void mutate(async (value, selected) => {
26917
+ await value.removeMcp({ ...selected, id: server.id });
26918
+ if (!lifecycle.disposed) showList();
26919
+ });
26920
+ });
26921
+ uninstallBtn.classList.add("settings-command-button--danger");
26922
+ heading.append(uninstallBtn);
26923
+ }
26924
+ const createTrashBtn = (onRemove) => {
26925
+ const btn = el("button");
26926
+ btn.type = "button";
26927
+ btn.className = "settings-mcp-icon-btn";
26928
+ btn.setAttribute("aria-label", tr("\u79FB\u9664", "Remove"));
26929
+ btn.title = tr("\u79FB\u9664", "Remove");
26930
+ btn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg>';
26931
+ btn.addEventListener("click", onRemove);
26932
+ return btn;
26933
+ };
26934
+ let transportType = server?.transportType === "streamable_http" || !!server?.url ? "streamable_http" : "stdio";
26935
+ const form = el("form");
26936
+ form.className = "settings-integrations-form";
26937
+ const basicCard = el("div");
26938
+ basicCard.className = "settings-integrations-form--card";
26939
+ const name = el("input");
26940
+ name.required = true;
26941
+ name.pattern = "[a-zA-Z0-9](?:[a-zA-Z0-9_]|-){0,63}";
26942
+ name.placeholder = "MCP server name";
26943
+ name.value = server?.name ?? "";
26944
+ field(basicCard, tr("\u540D\u79F0", "Name"), name);
26945
+ const typeField = el("div");
26946
+ typeField.className = "settings-integrations-field";
26947
+ typeField.append(el("span", tr("\u7C7B\u578B", "Type")));
26948
+ const toggle = el("div");
26949
+ toggle.className = "settings-mcp-type-toggle";
26950
+ const stdioBtn = el("button", "STDIO");
26951
+ stdioBtn.type = "button";
26952
+ stdioBtn.className = "settings-mcp-type-btn";
26953
+ const httpBtn = el("button", tr("\u6D41\u5F0F HTTP", "Streamable HTTP"));
26954
+ httpBtn.type = "button";
26955
+ httpBtn.className = "settings-mcp-type-btn";
26956
+ toggle.append(stdioBtn, httpBtn);
26957
+ typeField.append(toggle);
26958
+ basicCard.append(typeField);
26959
+ if (server) {
26960
+ const switchNotice = el("p", tr("\u5982\u9700\u5207\u6362 MCP \u670D\u52A1\u5668\u7C7B\u578B\uFF0C\u8BF7\u5148\u5378\u8F7D\u5F53\u524D\u914D\u7F6E\u3002", "If you would like to switch MCP server type, please uninstall first."));
26961
+ switchNotice.className = "settings-mcp-notice";
26962
+ basicCard.append(switchNotice);
26963
+ }
26964
+ const transportCard = el("div");
26965
+ transportCard.className = "settings-integrations-form--card settings-mcp-transport-card";
26966
+ const stdioSection = el("div");
26967
+ stdioSection.className = "settings-mcp-section";
26968
+ const command = el("input");
26969
+ command.placeholder = "openai-dev-mcp serve-sqlite";
26970
+ command.value = server?.command ?? "";
26971
+ field(stdioSection, tr("\u542F\u52A8\u547D\u4EE4", "Command to launch"), command);
26972
+ const argsField = el("div");
26973
+ argsField.className = "settings-integrations-field";
26974
+ argsField.append(el("span", tr("\u53C2\u6570", "Arguments")));
26975
+ const argsList = el("div");
26976
+ argsList.className = "settings-mcp-args";
26977
+ const addArg = (value = "") => {
26978
+ const row = el("div");
26979
+ row.className = "settings-mcp-arg";
26980
+ const input = el("input");
26981
+ input.value = value;
26982
+ input.placeholder = tr("\u547D\u4EE4\u53C2\u6570", "Command argument");
26983
+ row.append(input, createTrashBtn(() => row.remove()));
26984
+ argsList.append(row);
26985
+ };
26986
+ for (const value of server?.args?.length ? server.args : transportType === "stdio" ? [""] : []) addArg(value);
26987
+ const addArgBtn = button(tr("\uFF0B \u6DFB\u52A0\u53C2\u6570", "+ Add argument"), () => addArg());
26988
+ addArgBtn.classList.add("settings-mcp-add-arg");
26989
+ argsField.append(argsList, addArgBtn);
26990
+ stdioSection.append(argsField);
26991
+ const envField = el("div");
26992
+ envField.className = "settings-integrations-field";
26993
+ envField.append(el("span", tr("\u73AF\u5883\u53D8\u91CF", "Environment variables")));
26994
+ const envList = el("div");
26995
+ envList.className = "settings-mcp-args";
26996
+ const addEnv = (key = "", val = "") => {
26997
+ const row = el("div");
26998
+ row.className = "settings-mcp-kv-row";
26999
+ const keyInput = el("input");
27000
+ keyInput.value = key;
27001
+ keyInput.placeholder = tr("\u952E", "Key");
27002
+ const valInput = el("input");
27003
+ valInput.value = val;
27004
+ valInput.placeholder = tr("\u503C", "Value");
27005
+ row.append(keyInput, valInput, createTrashBtn(() => row.remove()));
27006
+ envList.append(row);
27007
+ };
27008
+ if (server?.env) {
27009
+ for (const [k, v] of Object.entries(server.env)) addEnv(k, String(v ?? ""));
27010
+ }
27011
+ const addEnvBtn = button(tr("\uFF0B \u6DFB\u52A0\u73AF\u5883\u53D8\u91CF", "+ Add environment variable"), () => addEnv());
27012
+ addEnvBtn.classList.add("settings-mcp-add-arg");
27013
+ envField.append(envList, addEnvBtn);
27014
+ stdioSection.append(envField);
27015
+ const envPassField = el("div");
27016
+ envPassField.className = "settings-integrations-field";
27017
+ envPassField.append(el("span", tr("\u73AF\u5883\u53D8\u91CF\u4F20\u9012", "Environment variable passthrough")));
27018
+ const envPassList = el("div");
27019
+ envPassList.className = "settings-mcp-args";
27020
+ const addEnvPass = (value = "") => {
27021
+ const row = el("div");
27022
+ row.className = "settings-mcp-arg";
27023
+ const input = el("input");
27024
+ input.value = value;
27025
+ input.placeholder = tr("\u53D8\u91CF\u540D\uFF0C\u4F8B\u5982\uFF1AGITHUB_TOKEN", "Variable name, e.g. GITHUB_TOKEN");
27026
+ row.append(input, createTrashBtn(() => row.remove()));
27027
+ envPassList.append(row);
27028
+ };
27029
+ if (server?.env_vars) {
27030
+ for (const v of server.env_vars) addEnvPass(v);
27031
+ }
27032
+ const addEnvPassBtn = button(tr("\uFF0B \u6DFB\u52A0\u53D8\u91CF", "+ Add variable"), () => addEnvPass());
27033
+ addEnvPassBtn.classList.add("settings-mcp-add-arg");
27034
+ envPassField.append(envPassList, addEnvPassBtn);
27035
+ stdioSection.append(envPassField);
27036
+ const cwd2 = el("input");
27037
+ cwd2.placeholder = "~/code";
27038
+ cwd2.value = server?.cwd ?? "";
27039
+ field(stdioSection, tr("\u5DE5\u4F5C\u76EE\u5F55", "Working directory"), cwd2);
27040
+ const httpSection = el("div");
27041
+ httpSection.className = "settings-mcp-section";
27042
+ const url2 = el("input");
27043
+ url2.placeholder = "https://mcp.example.com/mcp";
27044
+ url2.value = server?.url ?? "";
27045
+ field(httpSection, "URL", url2);
27046
+ const bearerToken = el("input");
27047
+ bearerToken.placeholder = "MCP_BEARER_TOKEN";
27048
+ bearerToken.value = server?.bearer_token_env_var ?? "";
27049
+ field(httpSection, tr("Bearer \u4EE4\u724C\u73AF\u5883\u53D8\u91CF", "Bearer token env var"), bearerToken);
27050
+ const headersField = el("div");
27051
+ headersField.className = "settings-integrations-field";
27052
+ headersField.append(el("span", tr("\u6807\u5934", "Headers")));
27053
+ const headersList = el("div");
27054
+ headersList.className = "settings-mcp-args";
27055
+ const addHeader = (key = "", val = "") => {
27056
+ const row = el("div");
27057
+ row.className = "settings-mcp-kv-row";
27058
+ const keyInput = el("input");
27059
+ keyInput.value = key;
27060
+ keyInput.placeholder = tr("\u952E", "Key");
27061
+ const valInput = el("input");
27062
+ valInput.value = val;
27063
+ valInput.placeholder = tr("\u503C", "Value");
27064
+ row.append(keyInput, valInput, createTrashBtn(() => row.remove()));
27065
+ headersList.append(row);
27066
+ };
27067
+ if (server?.http_headers) {
27068
+ for (const [k, v] of Object.entries(server.http_headers)) addHeader(k, String(v ?? ""));
27069
+ }
27070
+ const addHeaderBtn = button(tr("\uFF0B \u6DFB\u52A0\u6807\u5934", "+ Add header"), () => addHeader());
27071
+ addHeaderBtn.classList.add("settings-mcp-add-arg");
27072
+ headersField.append(headersList, addHeaderBtn);
27073
+ httpSection.append(headersField);
27074
+ const envHeadersField = el("div");
27075
+ envHeadersField.className = "settings-integrations-field";
27076
+ envHeadersField.append(el("span", tr("\u6765\u81EA\u73AF\u5883\u53D8\u91CF\u7684\u6807\u5934", "Headers from environment variables")));
27077
+ const envHeadersList = el("div");
27078
+ envHeadersList.className = "settings-mcp-args";
27079
+ const addEnvHeader = (key = "", val = "") => {
27080
+ const row = el("div");
27081
+ row.className = "settings-mcp-kv-row";
27082
+ const keyInput = el("input");
27083
+ keyInput.value = key;
27084
+ keyInput.placeholder = tr("\u6807\u5934\u540D\u79F0", "Header name");
27085
+ const valInput = el("input");
27086
+ valInput.value = val;
27087
+ valInput.placeholder = tr("\u73AF\u5883\u53D8\u91CF\u540D\u79F0", "Environment variable name");
27088
+ row.append(keyInput, valInput, createTrashBtn(() => row.remove()));
27089
+ envHeadersList.append(row);
27090
+ };
27091
+ if (server?.env_http_headers) {
27092
+ for (const [k, v] of Object.entries(server.env_http_headers)) addEnvHeader(k, String(v ?? ""));
27093
+ }
27094
+ const addEnvHeaderBtn = button(tr("\uFF0B \u6DFB\u52A0\u53D8\u91CF", "+ Add variable"), () => addEnvHeader());
27095
+ addEnvHeaderBtn.classList.add("settings-mcp-add-arg");
27096
+ envHeadersField.append(envHeadersList, addEnvHeaderBtn);
27097
+ httpSection.append(envHeadersField);
27098
+ const updateTypeView = () => {
27099
+ stdioBtn.dataset.active = String(transportType === "stdio");
27100
+ httpBtn.dataset.active = String(transportType === "streamable_http");
27101
+ stdioSection.hidden = transportType !== "stdio";
27102
+ httpSection.hidden = transportType !== "streamable_http";
27103
+ command.required = transportType === "stdio";
27104
+ url2.required = transportType === "streamable_http";
27105
+ };
27106
+ stdioBtn.addEventListener("click", () => {
27107
+ transportType = "stdio";
27108
+ updateTypeView();
27109
+ });
27110
+ httpBtn.addEventListener("click", () => {
27111
+ transportType = "streamable_http";
27112
+ updateTypeView();
27113
+ });
27114
+ updateTypeView();
27115
+ transportCard.append(stdioSection, httpSection);
27116
+ const security = el("p", tr("\u51ED\u636E\u548C\u73AF\u5883\u53D8\u91CF\u5C06\u5728\u539F\u751F Harness \u8FD0\u884C\u73AF\u5883\u4E2D\u89E3\u6790\u4E0E\u6CE8\u5165\uFF0C\u4E0D\u4F1A\u6CC4\u9732\u5728\u5BBF\u4E3B\u8FDB\u7A0B\u4E2D\u3002", "Credentials and environment variables are resolved and injected within the native Harness environment."));
27117
+ security.className = "settings-integrations-callout";
27118
+ const save = button(tr("\u4FDD\u5B58 MCP", "Save MCP"), () => {
27119
+ }, true);
27120
+ save.type = "submit";
27121
+ form.append(basicCard, transportCard, security, save);
27122
+ form.addEventListener("submit", (event) => {
27123
+ event.preventDefault();
27124
+ if (transportType === "stdio") {
27125
+ const args = [...argsList.querySelectorAll("input")].map((input) => input.value.trim()).filter((value) => value.length > 0);
27126
+ const env = {};
27127
+ for (const row of envList.querySelectorAll(".settings-mcp-kv-row")) {
27128
+ const [k, v] = row.querySelectorAll("input");
27129
+ if (k?.value.trim() && v?.value) env[k.value.trim()] = v.value;
27130
+ }
27131
+ const env_vars = [...envPassList.querySelectorAll("input")].map((input) => input.value.trim()).filter((v) => v.length > 0);
27132
+ const cwdVal = cwd2.value.trim();
27133
+ void mutate((value, selected) => value.saveMcp({
27134
+ ...selected,
27135
+ server: {
27136
+ ...server?.id ? { id: server.id } : {},
27137
+ name: name.value.trim(),
27138
+ transportType: "stdio",
27139
+ command: command.value.trim(),
27140
+ args,
27141
+ ...Object.keys(env).length ? { env } : {},
27142
+ ...env_vars.length ? { env_vars } : {},
27143
+ ...cwdVal ? { cwd: cwdVal } : {},
27144
+ enabled: server?.enabled ?? true
27145
+ }
27146
+ }));
27147
+ } else {
27148
+ const http_headers = {};
27149
+ for (const row of headersList.querySelectorAll(".settings-mcp-kv-row")) {
27150
+ const [k, v] = row.querySelectorAll("input");
27151
+ if (k?.value.trim() && v?.value) http_headers[k.value.trim()] = v.value;
27152
+ }
27153
+ const env_http_headers = {};
27154
+ for (const row of envHeadersList.querySelectorAll(".settings-mcp-kv-row")) {
27155
+ const [k, v] = row.querySelectorAll("input");
27156
+ if (k?.value.trim() && v?.value.trim()) env_http_headers[k.value.trim()] = v.value.trim();
27157
+ }
27158
+ const token = bearerToken.value.trim();
27159
+ void mutate((value, selected) => value.saveMcp({
27160
+ ...selected,
27161
+ server: {
27162
+ ...server?.id ? { id: server.id } : {},
27163
+ name: name.value.trim(),
27164
+ transportType: "streamable_http",
27165
+ url: url2.value.trim(),
27166
+ ...token ? { bearer_token_env_var: token } : {},
27167
+ ...Object.keys(http_headers).length ? { http_headers } : {},
27168
+ ...Object.keys(env_http_headers).length ? { env_http_headers } : {},
27169
+ enabled: server?.enabled ?? true
27170
+ }
27171
+ }));
27172
+ }
27173
+ }, { signal: lifecycle.signal });
27174
+ editor.append(heading, form);
27175
+ name.focus();
27176
+ };
27177
+ if (targetEditServerName) {
27178
+ const target = targetEditServerName === "__new__" ? void 0 : snapshot.servers.find((s) => s.name === targetEditServerName);
27179
+ targetEditServerName = void 0;
27180
+ showEditor(target);
27181
+ body.append(toolbar, list, editor);
27182
+ return;
27183
+ }
27184
+ const addButton = button(tr("\uFF0B \u6DFB\u52A0 MCP", "+ Add MCP"), () => showEditor(), true);
27185
+ toolbar.append(search, addButton);
27186
+ for (const native of snapshot.native) {
27187
+ const row = el("section");
27188
+ row.className = "settings-integrations-row settings-integrations-row--native";
27189
+ row.append(el("strong", `${tr("\u539F\u751F\u72B6\u6001", "Native status")} \xB7 ${native.name || native.sessionId}`), el("span", native.status), el("code", native.tools.join(", ")));
27190
+ list.append(row);
27191
+ }
27192
+ const toManaged = (s, newEnabled) => ({
27193
+ id: s.id,
27194
+ name: s.name,
27195
+ enabled: newEnabled,
27196
+ ...s.transportType ? { transportType: s.transportType } : {},
27197
+ ...s.command ? { command: s.command } : {},
27198
+ ...s.args?.length ? { args: s.args } : {},
27199
+ ...s.env ? { env: s.env } : {},
27200
+ ...s.env_vars?.length ? { env_vars: s.env_vars } : {},
27201
+ ...s.cwd ? { cwd: s.cwd } : {},
27202
+ ...s.url ? { url: s.url } : {},
27203
+ ...s.bearer_token_env_var ? { bearer_token_env_var: s.bearer_token_env_var } : {},
27204
+ ...s.http_headers ? { http_headers: s.http_headers } : {},
27205
+ ...s.env_http_headers ? { env_http_headers: s.env_http_headers } : {}
27206
+ });
27207
+ const serverRows = [];
27208
+ for (const server of snapshot.servers) {
27209
+ const row = el("section");
27210
+ row.className = "settings-integrations-row";
27211
+ const isHttp = server.transportType === "streamable_http" || !!server.url;
27212
+ row.dataset.search = `${server.name} ${server.command || ""} ${server.url || ""}`.toLowerCase();
27213
+ const detail = el("div");
27214
+ const state = !server.effective ? tr("\u88AB\u9879\u76EE\u914D\u7F6E\u8986\u76D6", "Overridden by project") : !server.enabled ? tr("\u5DF2\u505C\u7528", "Disabled") : server.appliedSessions ? tr(`\u5DF2\u4F20\u5165 ${server.appliedSessions} \u4E2A\u4F1A\u8BDD`, `Passed to ${server.appliedSessions} sessions`) : tr("\u5DF2\u914D\u7F6E", "Configured");
27215
+ const typeTag = isHttp ? " [HTTP]" : "";
27216
+ const summary = isHttp ? server.url || "" : [server.command, ...server.args || []].filter(Boolean).join(" ");
27217
+ detail.append(el("strong", `${server.name}${typeTag}`), el("p", `${server.scope === "global" ? tr("\u5168\u5C40", "Global") : tr("\u9879\u76EE", "Project")} \xB7 ${state}`), el("code", summary));
27218
+ row.append(detail);
27219
+ if (server.editable) {
27220
+ const editBtn = button(tr("\u7F16\u8F91", "Edit"), () => showEditor(server));
27221
+ const toggleBtn = button(server.enabled ? tr("\u505C\u7528", "Disable") : tr("\u542F\u7528", "Enable"), () => {
27222
+ void mutate((value, selected) => value.saveMcp({ ...selected, server: toManaged(server, !server.enabled) }));
27223
+ });
27224
+ const syncBtn = button(tr("\u540C\u6B65\u2026", "Sync\u2026"), () => {
27225
+ void client().integrationCatalog().then((catalog) => {
27226
+ const targets = catalog.harnesses.filter((h) => h.mcp && h.id !== harness.value);
27227
+ showMcpSyncDialog(server, { id: harness.value, name: harness.selectedOptions[0]?.text || harness.value }, targets);
27228
+ });
27229
+ });
27230
+ const delBtn = button(tr("\u5220\u9664", "Delete"), () => {
27231
+ void mutate((value, selected) => value.removeMcp({ ...selected, id: server.id }));
27232
+ });
27233
+ row.append(editBtn, toggleBtn, syncBtn, delBtn);
27234
+ }
27235
+ list.append(row);
27236
+ serverRows.push(row);
27237
+ }
27238
+ if (!snapshot.servers.length) {
27239
+ const empty = el("div", tr("\u8FD8\u6CA1\u6709 MCP \u670D\u52A1\u5668\uFF0C\u70B9\u51FB\u201C\u6DFB\u52A0 MCP\u201D\u5F00\u59CB\u914D\u7F6E\u3002", "No MCP servers yet. Select \u201CAdd MCP\u201D to configure one."));
27240
+ empty.className = "settings-integrations-empty";
27241
+ list.append(empty);
27242
+ }
27243
+ search.addEventListener("input", () => {
27244
+ const query = search.value.trim().toLowerCase();
27245
+ for (const row of serverRows) row.hidden = !!query && !row.dataset.search.includes(query);
27246
+ }, { signal: lifecycle.signal });
27247
+ if (!snapshot.mcpSupported) {
27248
+ addButton.disabled = true;
27249
+ const unavailable = el("div", tr("\u6B64 Harness \u5C1A\u65E0\u5DF2\u786E\u8BA4\u7684 MCP \u914D\u7F6E\u63A5\u53E3\u3002", "This Harness has no verified MCP configuration interface."));
27250
+ unavailable.className = "settings-integrations-callout";
27251
+ list.prepend(unavailable);
27252
+ }
27253
+ body.append(toolbar, list, editor);
27254
+ };
27255
+ const showMcpSyncDialog = (server, sourceHarness, targetHarnesses) => {
27256
+ if (!targetHarnesses.length) {
27257
+ fail(new Error(tr("\u6CA1\u6709\u5176\u4ED6\u652F\u6301 MCP \u7684\u539F\u751F Harness \u53EF\u4F9B\u540C\u6B65\u3002", "No other native Harnesses support MCP for sync.")));
27258
+ return;
27259
+ }
27260
+ const modal = el("dialog");
27261
+ modal.className = "settings-skills-sync-modal settings-mcp-sync-modal";
27262
+ const mTitle = el("h3", tr(`\u540C\u6B65 MCP\u3010${server.name}\u3011`, `Sync MCP [${server.name}]`));
27263
+ const isHttp = server.transportType === "streamable_http" || !!server.url;
27264
+ const summary = isHttp ? server.url || "" : [server.command, ...server.args || []].filter(Boolean).join(" ");
27265
+ const mDesc = el("p", tr(
27266
+ `\u4ECE ${sourceHarness.name} \u590D\u5236\u8BE5 MCP \u914D\u7F6E\uFF08${isHttp ? "HTTP" : "stdio"}\uFF1A${summary}\uFF09\u5230\u9009\u4E2D\u7684 Harness\uFF1A`,
27267
+ `Copy MCP configuration (${isHttp ? "HTTP" : "stdio"}: ${summary}) from ${sourceHarness.name} to selected Harnesses:`
27268
+ ));
27269
+ const form = el("form");
27270
+ const checkList = el("div");
27271
+ checkList.style.display = "grid";
27272
+ checkList.style.gap = "8px";
27273
+ checkList.style.margin = "12px 0";
27274
+ checkList.style.maxHeight = "240px";
27275
+ checkList.style.overflowY = "auto";
27276
+ const checkboxes = [];
27277
+ for (const h of targetHarnesses) {
27278
+ const label = el("label");
27279
+ label.style.display = "flex";
27280
+ label.style.gap = "8px";
27281
+ label.style.alignItems = "center";
27282
+ label.style.cursor = "pointer";
27283
+ const cb = el("input");
27284
+ cb.type = "checkbox";
27285
+ cb.value = h.id;
27286
+ cb.checked = true;
27287
+ checkboxes.push(cb);
27288
+ label.append(cb, el("span", h.name));
27289
+ checkList.append(label);
27290
+ }
27291
+ const btnRow = el("div");
27292
+ btnRow.style.display = "flex";
27293
+ btnRow.style.gap = "8px";
27294
+ btnRow.style.justifyContent = "flex-end";
27295
+ btnRow.style.marginTop = "14px";
27296
+ const cancelBtn = button(tr("\u53D6\u6D88", "Cancel"), () => {
27297
+ modal.close();
27298
+ modal.remove();
27299
+ });
27300
+ const confirmBtn = button(tr("\u786E\u8BA4\u540C\u6B65", "Confirm Sync"), () => {
27301
+ const selectedHarnesses = checkboxes.filter((cb) => cb.checked).map((cb) => cb.value);
27302
+ modal.close();
27303
+ modal.remove();
27304
+ if (!selectedHarnesses.length) return;
27305
+ void mutateCustom(async (c) => {
27306
+ const scopeType = level.value === "project" ? "project" : "global";
27307
+ const currentCwd = level.value === "project" ? cwd.value.trim() : void 0;
27308
+ const successes = [];
27309
+ const errors = [];
27310
+ const cleanConfig = toManagedForCopy(server);
27311
+ for (const targetId of selectedHarnesses) {
27312
+ const targetH = targetHarnesses.find((h) => h.id === targetId);
27313
+ try {
27314
+ await c.saveMcp({
27315
+ harnessId: targetId,
27316
+ scope: scopeType,
27317
+ ...currentCwd ? { cwd: currentCwd } : {},
27318
+ server: cleanConfig
27319
+ });
27320
+ if (targetH) successes.push(targetH.name);
27321
+ } catch (err) {
27322
+ errors.push(`${targetH?.name || targetId}: ${err instanceof Error ? err.message : String(err)}`);
27323
+ }
27324
+ }
27325
+ if (!successes.length && errors.length) throw new Error(errors.join("; "));
27326
+ return tr(
27327
+ `\u540C\u6B65\u5B8C\u6210\uFF01\u5DF2\u914D\u7F6E\u5230\uFF1A${successes.join("\u3001")}${errors.length ? `\uFF08\u8DF3\u8FC7: ${errors.join("; ")}\uFF09` : ""}`,
27328
+ `Sync complete! Configured on: ${successes.join(", ")}${errors.length ? ` (Skipped: ${errors.join("; ")})` : ""}`
27329
+ );
27330
+ });
27331
+ }, true);
27332
+ btnRow.append(cancelBtn, confirmBtn);
27333
+ form.append(checkList, btnRow);
27334
+ modal.append(mTitle, mDesc, form);
27335
+ content.append(modal);
27336
+ modal.showModal();
27337
+ };
27338
+ const showMcpDistributeDialog = (targetHarnesses) => {
27339
+ if (!targetHarnesses.length) {
27340
+ fail(new Error(tr("\u6CA1\u6709\u652F\u6301 MCP \u6CE8\u5165\u7684\u539F\u751F Harness\u3002", "No native Harnesses support MCP injection.")));
27341
+ return;
27342
+ }
27343
+ const modal = el("dialog");
27344
+ modal.className = "settings-mcp-distribute-modal";
27345
+ const mTitle = el("h3", tr("\u65B0\u5EFA\u5E76\u6279\u91CF\u5206\u53D1 MCP", "Create & Distribute MCP"));
27346
+ const mDesc = el("p", tr("\u914D\u7F6E MCP \u670D\u52A1\u5668\uFF0C\u5E76\u4E00\u6B21\u6027\u4FDD\u5B58\u5206\u53D1\u81F3\u9009\u4E2D\u7684\u6240\u6709 Harness\u3002", "Configure MCP server once and distribute to all selected Harnesses."));
27347
+ const form = el("form");
27348
+ form.className = "settings-integrations-form";
27349
+ let transportType = "stdio";
27350
+ const typeToggle = el("div");
27351
+ typeToggle.className = "settings-mcp-type-toggle";
27352
+ const stdioBtn = el("button", tr("\u6807\u51C6\u8F93\u5165\u8F93\u51FA (stdio)", "Standard I/O (stdio)"));
27353
+ stdioBtn.type = "button";
27354
+ stdioBtn.className = "settings-mcp-type-btn";
27355
+ stdioBtn.dataset.active = "true";
27356
+ const httpBtn = el("button", tr("\u6D41\u5F0F HTTP (SSE)", "Streamable HTTP (SSE)"));
27357
+ httpBtn.type = "button";
27358
+ httpBtn.className = "settings-mcp-type-btn";
27359
+ typeToggle.append(stdioBtn, httpBtn);
27360
+ const nameInput = el("input");
27361
+ nameInput.required = true;
27362
+ nameInput.placeholder = "my-mcp-server";
27363
+ nameInput.pattern = "[a-zA-Z0-9](?:[a-zA-Z0-9_]|-){0,63}";
27364
+ field(form, tr("MCP \u670D\u52A1\u5668\u540D\u79F0\uFF08\u5FC5\u586B\uFF09", "MCP server name (required)"), nameInput);
27365
+ const typeField = el("div");
27366
+ typeField.className = "settings-integrations-field";
27367
+ typeField.append(el("span", tr("\u4F20\u8F93\u534F\u8BAE", "Transport Protocol")), typeToggle);
27368
+ form.append(typeField);
27369
+ const stdioCard = el("div");
27370
+ stdioCard.className = "settings-integrations-form--card";
27371
+ const cmdInput = el("input");
27372
+ cmdInput.placeholder = "npx / uvx / node / ...";
27373
+ field(stdioCard, tr("\u53EF\u6267\u884C\u547D\u4EE4 (Command)", "Executable Command"), cmdInput);
27374
+ const argsInput = el("input");
27375
+ argsInput.placeholder = "-y @modelcontextprotocol/server-filesystem D:/data";
27376
+ field(stdioCard, tr("\u53C2\u6570\uFF08\u7A7A\u683C\u5206\u9694\uFF0C\u652F\u6301\u5F15\u53F7\uFF09", "Arguments (space separated, quotes supported)"), argsInput);
27377
+ const envInput = el("input");
27378
+ envInput.placeholder = "KEY1=val1, KEY2=val2";
27379
+ field(stdioCard, tr("\u73AF\u5883\u53D8\u91CF\uFF08\u53EF\u9009\uFF0CKEY=VAL \u9017\u53F7\u6216\u6362\u884C\u5206\u9694\uFF09", "Environment variables (optional, KEY=VAL separated)"), envInput);
27380
+ const httpCard = el("div");
27381
+ httpCard.className = "settings-integrations-form--card";
27382
+ httpCard.hidden = true;
27383
+ const urlInput = el("input");
27384
+ urlInput.type = "url";
27385
+ urlInput.placeholder = "https://mcp.example.com/sse";
27386
+ field(httpCard, tr("MCP \u670D\u52A1\u5668 URL", "MCP Server URL"), urlInput);
27387
+ const tokenInput = el("input");
27388
+ tokenInput.placeholder = "API_KEY_ENV_NAME";
27389
+ field(httpCard, tr("Bearer Token \u73AF\u5883\u53D8\u91CF\u540D\uFF08\u53EF\u9009\uFF09", "Bearer token env var name (optional)"), tokenInput);
27390
+ stdioBtn.addEventListener("click", () => {
27391
+ transportType = "stdio";
27392
+ stdioBtn.dataset.active = "true";
27393
+ delete httpBtn.dataset.active;
27394
+ stdioCard.hidden = false;
27395
+ httpCard.hidden = true;
27396
+ });
27397
+ httpBtn.addEventListener("click", () => {
27398
+ transportType = "streamable_http";
27399
+ httpBtn.dataset.active = "true";
27400
+ delete stdioBtn.dataset.active;
27401
+ stdioCard.hidden = true;
27402
+ httpCard.hidden = false;
27403
+ });
27404
+ form.append(stdioCard, httpCard);
27405
+ const targetSection = el("div");
27406
+ targetSection.className = "settings-integrations-form--card";
27407
+ const targetHead = el("div");
27408
+ targetHead.style.display = "flex";
27409
+ targetHead.style.justifyContent = "space-between";
27410
+ targetHead.style.alignItems = "center";
27411
+ targetHead.style.marginBottom = "8px";
27412
+ const targetTitle = el("strong", tr("\u5206\u53D1\u76EE\u6807 Harness\uFF1A", "Target Harnesses:"));
27413
+ targetTitle.style.fontSize = "12px";
27414
+ const toggleAllBtn = el("button", tr("\u5168\u9009 / \u53D6\u6D88\u5168\u9009", "Select / Deselect All"));
27415
+ toggleAllBtn.type = "button";
27416
+ toggleAllBtn.className = "settings-command-button settings-command-button--secondary";
27417
+ toggleAllBtn.style.fontSize = "11px";
27418
+ toggleAllBtn.style.padding = "3px 8px";
27419
+ targetHead.append(targetTitle, toggleAllBtn);
27420
+ targetSection.append(targetHead);
27421
+ const checkList = el("div");
27422
+ checkList.style.display = "grid";
27423
+ checkList.style.gridTemplateColumns = "repeat(auto-fill, minmax(130px, 1fr))";
27424
+ checkList.style.gap = "8px";
27425
+ const checkboxes = [];
27426
+ for (const h of targetHarnesses) {
27427
+ const label = el("label");
27428
+ label.style.display = "flex";
27429
+ label.style.gap = "6px";
27430
+ label.style.alignItems = "center";
27431
+ label.style.cursor = "pointer";
27432
+ label.style.fontSize = "12px";
27433
+ const cb = el("input");
27434
+ cb.type = "checkbox";
27435
+ cb.value = h.id;
27436
+ cb.checked = true;
27437
+ checkboxes.push(cb);
27438
+ label.append(cb, el("span", h.name));
27439
+ checkList.append(label);
27440
+ }
27441
+ targetSection.append(checkList);
27442
+ form.append(targetSection);
27443
+ toggleAllBtn.addEventListener("click", () => {
27444
+ const anyChecked = checkboxes.some((cb) => cb.checked);
27445
+ for (const cb of checkboxes) cb.checked = !anyChecked;
27446
+ });
27447
+ const btnRow = el("div");
27448
+ btnRow.style.display = "flex";
27449
+ btnRow.style.gap = "8px";
27450
+ btnRow.style.justifyContent = "flex-end";
27451
+ btnRow.style.marginTop = "14px";
27452
+ const cancelBtn = button(tr("\u53D6\u6D88", "Cancel"), () => {
27453
+ modal.close();
27454
+ modal.remove();
27455
+ });
27456
+ const submitBtn = el("button", tr("\u786E\u8BA4\u5E76\u5206\u53D1", "Confirm & Distribute"));
27457
+ submitBtn.type = "submit";
27458
+ submitBtn.className = "settings-command-button settings-command-button--primary";
27459
+ btnRow.append(cancelBtn, submitBtn);
27460
+ form.append(btnRow);
27461
+ form.addEventListener("submit", (event) => {
27462
+ event.preventDefault();
27463
+ const serverName = nameInput.value.trim();
27464
+ if (!serverName) return;
27465
+ const selectedHarnesses = checkboxes.filter((cb) => cb.checked).map((cb) => cb.value);
27466
+ if (!selectedHarnesses.length) {
27467
+ fail(new Error(tr("\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u4E2A\u76EE\u6807 Harness\u3002", "Please select at least one target Harness.")));
27468
+ return;
27469
+ }
27470
+ let serverConfig;
27471
+ if (transportType === "streamable_http") {
27472
+ const url2 = urlInput.value.trim();
27473
+ if (!url2) {
27474
+ fail(new Error(tr("\u6D41\u5F0F HTTP \u6A21\u5F0F\u5FC5\u987B\u586B\u5199 URL\u3002", "URL is required for streamable HTTP.")));
27475
+ return;
27476
+ }
27477
+ serverConfig = {
27478
+ name: serverName,
27479
+ transportType: "streamable_http",
27480
+ enabled: true,
27481
+ url: url2,
27482
+ ...tokenInput.value.trim() ? { bearer_token_env_var: tokenInput.value.trim() } : {}
27483
+ };
27484
+ } else {
27485
+ const cmd = cmdInput.value.trim();
27486
+ if (!cmd) {
27487
+ fail(new Error(tr("stdio \u6A21\u5F0F\u5FC5\u987B\u586B\u5199\u547D\u4EE4\u3002", "Command is required for stdio mode.")));
27488
+ return;
27489
+ }
27490
+ const rawArgs = argsInput.value.trim().match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g)?.map((s) => s.replace(/^['"]|['"]$/g, "")) || [];
27491
+ const envMap = {};
27492
+ for (const part of envInput.value.split(/[,;\n]/)) {
27493
+ const eq = part.indexOf("=");
27494
+ if (eq > 0) {
27495
+ const k = part.slice(0, eq).trim();
27496
+ const v = part.slice(eq + 1).trim();
27497
+ if (k) envMap[k] = v;
27498
+ }
27499
+ }
27500
+ serverConfig = {
27501
+ name: serverName,
27502
+ transportType: "stdio",
27503
+ enabled: true,
27504
+ command: cmd,
27505
+ ...rawArgs.length ? { args: rawArgs } : {},
27506
+ ...Object.keys(envMap).length ? { env: envMap } : {}
27507
+ };
27508
+ }
27509
+ modal.close();
27510
+ modal.remove();
27511
+ void mutateCustom(async (c) => {
27512
+ const scopeType = level.value === "project" ? "project" : "global";
27513
+ const currentCwd = level.value === "project" ? cwd.value.trim() : void 0;
27514
+ const successes = [];
27515
+ const errors = [];
27516
+ for (const targetId of selectedHarnesses) {
27517
+ const targetH = targetHarnesses.find((h) => h.id === targetId);
27518
+ try {
27519
+ await c.saveMcp({
27520
+ harnessId: targetId,
27521
+ scope: scopeType,
27522
+ ...currentCwd ? { cwd: currentCwd } : {},
27523
+ server: serverConfig
27524
+ });
27525
+ if (targetH) successes.push(targetH.name);
27526
+ } catch (err) {
27527
+ errors.push(`${targetH?.name || targetId}: ${err instanceof Error ? err.message : String(err)}`);
27528
+ }
27529
+ }
27530
+ if (!successes.length && errors.length) throw new Error(errors.join("; "));
27531
+ return tr(
27532
+ `\u5DF2\u6210\u529F\u5206\u53D1\u3010${serverName}\u3011\u81F3\uFF1A${successes.join("\u3001")}${errors.length ? `\uFF08\u8DF3\u8FC7: ${errors.join("; ")}\uFF09` : ""}`,
27533
+ `Distributed [${serverName}] to: ${successes.join(", ")}${errors.length ? ` (Skipped: ${errors.join("; ")})` : ""}`
27534
+ );
27535
+ });
27536
+ });
27537
+ modal.append(mTitle, mDesc, form);
27538
+ content.append(modal);
27539
+ modal.showModal();
27540
+ };
27541
+ const renderMcpOverview = (_catalog, items) => {
27542
+ const supported = items.filter((i) => i.harness.mcp);
27543
+ const uniqueServers = /* @__PURE__ */ new Map();
27544
+ let totalServersCount = 0;
27545
+ let totalNativeCount = 0;
27546
+ for (const item of items) {
27547
+ if (item.snapshot?.servers) {
27548
+ totalServersCount += item.snapshot.servers.length;
27549
+ for (const s of item.snapshot.servers) {
27550
+ const list = uniqueServers.get(s.name) || [];
27551
+ list.push({ harness: item.harness, server: s });
27552
+ uniqueServers.set(s.name, list);
27553
+ }
27554
+ }
27555
+ if (item.snapshot?.native) {
27556
+ totalNativeCount += item.snapshot.native.length;
27557
+ }
27558
+ }
27559
+ const statsBar = el("div");
27560
+ statsBar.className = "settings-skills-overview-stats settings-mcp-overview-stats";
27561
+ const statsSummary = el("span", tr(
27562
+ `\u{1F4CA} \u5171 ${items.length} \u4E2A Harness \xB7 ${supported.length} \u4E2A\u652F\u6301\u539F\u751F MCP \u6CE8\u5165 \xB7 \u5DF2\u914D\u7F6E ${uniqueServers.size} \u79CD\u72EC\u7ACB MCP\uFF08\u5171 ${totalServersCount} \u4E2A\u5B9E\u4F8B\uFF09${totalNativeCount ? ` \xB7 ${totalNativeCount} \u4E2A\u6D3B\u8DC3\u539F\u751F\u8FDE\u63A5` : ""}`,
27563
+ `\u{1F4CA} ${items.length} Harnesses \xB7 ${supported.length} with native MCP injection \xB7 ${uniqueServers.size} unique MCPs (${totalServersCount} instances)${totalNativeCount ? ` \xB7 ${totalNativeCount} active native connections` : ""}`
27564
+ ));
27565
+ statsBar.append(statsSummary);
27566
+ const toolbar = el("div");
27567
+ toolbar.className = "settings-integrations-toolbar";
27568
+ const searchInput = el("input");
27569
+ searchInput.type = "search";
27570
+ searchInput.placeholder = tr("\u6309\u540D\u79F0\u3001\u547D\u4EE4\u6216 URL \u8FC7\u6EE4 MCP \u670D\u52A1\u5668\u2026", "Filter MCP servers by name, command, or URL\u2026");
27571
+ searchInput.setAttribute("aria-label", searchInput.placeholder);
27572
+ const tabsWrap = el("div");
27573
+ tabsWrap.className = "settings-skills-tabs settings-mcp-tabs";
27574
+ const btnByHarness = el("button", tr("\u6309 Harness \u67E5\u770B", "By Harness"));
27575
+ btnByHarness.type = "button";
27576
+ btnByHarness.className = "settings-skills-tab-btn";
27577
+ btnByHarness.dataset.active = "true";
27578
+ const btnByServer = el("button", tr("\u6309 Server \u6C47\u603B", "By Server"));
27579
+ btnByServer.type = "button";
27580
+ btnByServer.className = "settings-skills-tab-btn";
27581
+ tabsWrap.append(btnByHarness, btnByServer);
27582
+ const distributeBtn = button(tr("\uFF0B \u65B0\u5EFA\u5E76\u5206\u53D1 MCP", "\uFF0B New & Distribute MCP"), () => {
27583
+ showMcpDistributeDialog(supported.map((i) => i.harness));
27584
+ }, true);
27585
+ toolbar.append(searchInput, tabsWrap, distributeBtn);
27586
+ const viewsContainer = el("div");
27587
+ viewsContainer.className = "settings-skills-views settings-mcp-views";
27588
+ let activeTab = "harness";
27589
+ const updateView = () => {
27590
+ viewsContainer.replaceChildren();
27591
+ const query = searchInput.value.trim().toLowerCase();
27592
+ if (activeTab === "harness") {
27593
+ const grid = el("div");
27594
+ grid.className = "settings-skills-overview-grid settings-mcp-overview-grid";
27595
+ for (const item of items) {
27596
+ const allServers = item.snapshot?.servers || [];
27597
+ const allNative = item.snapshot?.native || [];
27598
+ const matchingServers = query ? allServers.filter(
27599
+ (s) => s.name.toLowerCase().includes(query) || s.command && s.command.toLowerCase().includes(query) || s.url && s.url.toLowerCase().includes(query) || s.args && s.args.some((a) => a.toLowerCase().includes(query))
27600
+ ) : allServers;
27601
+ const matchingNative = query ? allNative.filter(
27602
+ (n) => n.name && n.name.toLowerCase().includes(query) || n.sessionId && n.sessionId.toLowerCase().includes(query) || n.tools && n.tools.some((t) => t.toLowerCase().includes(query))
27603
+ ) : allNative;
27604
+ if (query && !item.harness.name.toLowerCase().includes(query) && matchingServers.length === 0 && matchingNative.length === 0) {
27605
+ continue;
27606
+ }
27607
+ const card = el("section");
27608
+ card.className = "settings-skills-harness-card settings-mcp-harness-card";
27609
+ const head = el("div");
27610
+ head.className = "settings-skills-harness-head settings-mcp-harness-head";
27611
+ const hTitle = el("strong", item.harness.name);
27612
+ const badge = el("span");
27613
+ badge.className = `settings-skills-badge ${item.harness.mcp ? "settings-skills-badge--active" : ""}`;
27614
+ badge.textContent = item.harness.mcp ? tr(`${allServers.length} \u4E2A MCP`, `${allServers.length} MCPs`) : tr("\u672A\u63D0\u4F9B MCP \u63A5\u53E3", "No native MCP interface");
27615
+ head.append(hTitle, badge);
27616
+ card.append(head);
27617
+ if (!item.harness.mcp) {
27618
+ const note2 = el("p", tr("\u6B64 Harness \u5C1A\u65E0\u5DF2\u786E\u8BA4\u7684 MCP \u914D\u7F6E\u63A5\u53E3\u3002", "This Harness has no verified MCP configuration interface."));
27619
+ note2.className = "settings-mcp-notice";
27620
+ card.append(note2);
27621
+ } else if (item.error) {
27622
+ const errNote = el("p", item.error);
27623
+ errNote.className = "settings-mcp-notice";
27624
+ errNote.style.color = "#ef4444";
27625
+ card.append(errNote);
27626
+ } else {
27627
+ if (matchingNative.length > 0) {
27628
+ const nativeBox = el("div");
27629
+ nativeBox.className = "settings-mcp-native-box";
27630
+ const nativeTitle = el("div");
27631
+ nativeTitle.className = "settings-mcp-native-title";
27632
+ nativeTitle.textContent = tr(`\u{1F7E2} \u539F\u751F\u8FD0\u884C\u65F6\u6D3B\u8DC3 (${matchingNative.length})`, `\u{1F7E2} Active Native Sessions (${matchingNative.length})`);
27633
+ nativeBox.append(nativeTitle);
27634
+ for (const n of matchingNative) {
27635
+ const nRow = el("div");
27636
+ nRow.className = "settings-mcp-native-item";
27637
+ const nHeader = el("div");
27638
+ nHeader.append(
27639
+ el("strong", n.name || n.sessionId),
27640
+ el("span", ` \xB7 ${n.status}${n.tools?.length ? ` \xB7 ${n.tools.length} ${tr("\u5DE5\u5177", "tools")}` : ""}`)
27641
+ );
27642
+ nRow.append(nHeader);
27643
+ if (n.tools?.length) {
27644
+ const toolPreview = n.tools.slice(0, 4).join(", ") + (n.tools.length > 4 ? ` +${n.tools.length - 4}` : "");
27645
+ nRow.append(el("code", toolPreview));
27646
+ }
27647
+ nativeBox.append(nRow);
27648
+ }
27649
+ card.append(nativeBox);
27650
+ }
27651
+ if (matchingServers.length === 0) {
27652
+ const empty = el("p", query ? tr("\u65E0\u5339\u914D MCP \u670D\u52A1\u5668", "No matching MCP servers") : tr("\u6682\u672A\u914D\u7F6E MCP \u670D\u52A1\u5668", "No MCP servers configured"));
27653
+ empty.className = "settings-mcp-notice";
27654
+ card.append(empty);
27655
+ } else {
27656
+ const list = el("div");
27657
+ list.className = "settings-skills-list-compact settings-mcp-list-compact";
27658
+ for (const s of matchingServers) {
27659
+ const row = el("div");
27660
+ row.className = "settings-skills-item-row settings-mcp-item-row";
27661
+ const isHttp = s.transportType === "streamable_http" || !!s.url;
27662
+ const summary = isHttp ? s.url || "" : [s.command, ...s.args || []].filter(Boolean).join(" ");
27663
+ const stateText = !s.effective ? tr(" \xB7 \u88AB\u9879\u76EE\u8986\u76D6", " \xB7 Overridden") : !s.enabled ? tr(" \xB7 \u5DF2\u505C\u7528", " \xB7 Disabled") : s.appliedSessions ? tr(` \xB7 \u4F20\u5165 ${s.appliedSessions} \u4F1A\u8BDD`, ` \xB7 ${s.appliedSessions} sessions`) : tr(" \xB7 \u5DF2\u914D\u7F6E", " \xB7 Configured");
27664
+ const info = el("div");
27665
+ info.append(
27666
+ el("strong", `${s.name}${isHttp ? " [HTTP]" : " [stdio]"}`),
27667
+ el("span", stateText),
27668
+ el("code", summary)
27669
+ );
27670
+ const actions = el("div");
27671
+ actions.className = "settings-skills-item-actions settings-mcp-item-actions";
27672
+ actions.append(button(s.enabled ? tr("\u505C\u7528", "Disable") : tr("\u542F\u7528", "Enable"), () => {
27673
+ void mutateCustom(async (c) => {
27674
+ const scopeType = level.value === "project" ? "project" : "global";
27675
+ const currentCwd = level.value === "project" ? cwd.value.trim() : void 0;
27676
+ await c.saveMcp({
27677
+ harnessId: item.harness.id,
27678
+ scope: scopeType,
27679
+ ...currentCwd ? { cwd: currentCwd } : {},
27680
+ server: toManagedForCopy(s, !s.enabled)
27681
+ });
27682
+ return tr(
27683
+ `\u5DF2${s.enabled ? "\u505C\u7528" : "\u542F\u7528"}\u3010${s.name}\u3011\uFF08${item.harness.name}\uFF09\u3002`,
27684
+ `${s.enabled ? "Disabled" : "Enabled"} [${s.name}] (${item.harness.name}).`
27685
+ );
27686
+ });
27687
+ }));
27688
+ const otherSupported = supported.filter((h) => h.harness.id !== item.harness.id);
27689
+ if (otherSupported.length > 0) {
27690
+ actions.append(button(tr("\u540C\u6B65\u2026", "Sync\u2026"), () => {
27691
+ showMcpSyncDialog(s, item.harness, otherSupported.map((h) => h.harness));
27692
+ }));
27693
+ }
27694
+ actions.append(button(tr("\u7F16\u8F91", "Edit"), () => {
27695
+ editInHarness(item.harness.id, s.name);
27696
+ }));
27697
+ row.append(info, actions);
27698
+ list.append(row);
27699
+ }
27700
+ card.append(list);
27701
+ }
27702
+ const cardFooter = el("div");
27703
+ cardFooter.className = "settings-mcp-card-footer";
27704
+ const addBtn = button(tr("\uFF0B \u6DFB\u52A0 MCP", "\uFF0B Add MCP"), () => {
27705
+ editInHarness(item.harness.id, "__new__");
27706
+ });
27707
+ cardFooter.append(addBtn);
27708
+ card.append(cardFooter);
27709
+ }
27710
+ grid.append(card);
27711
+ }
27712
+ viewsContainer.append(grid);
27713
+ } else {
27714
+ const matrixList = el("div");
27715
+ matrixList.className = "settings-skills-matrix-list settings-mcp-matrix-list";
27716
+ let matchedCount = 0;
27717
+ for (const [serverName, installations] of uniqueServers.entries()) {
27718
+ const firstServer = installations[0].server;
27719
+ const isHttp = firstServer.transportType === "streamable_http" || !!firstServer.url;
27720
+ const summary = isHttp ? firstServer.url || "" : [firstServer.command, ...firstServer.args || []].filter(Boolean).join(" ");
27721
+ if (query && !serverName.toLowerCase().includes(query) && !summary.toLowerCase().includes(query) && !installations.some((i) => i.harness.name.toLowerCase().includes(query))) {
27722
+ continue;
27723
+ }
27724
+ matchedCount++;
27725
+ const card = el("section");
27726
+ card.className = "settings-skills-matrix-card settings-mcp-matrix-card";
27727
+ const head = el("div");
27728
+ head.className = "settings-skills-matrix-head settings-mcp-matrix-head";
27729
+ const titleWrap = el("div");
27730
+ titleWrap.style.display = "flex";
27731
+ titleWrap.style.alignItems = "center";
27732
+ titleWrap.style.gap = "8px";
27733
+ titleWrap.append(el("strong", serverName), el("span", `[${isHttp ? "HTTP" : "stdio"}]`));
27734
+ head.append(
27735
+ titleWrap,
27736
+ el("span", tr(`\u5DF2\u5728 ${installations.length} \u4E2A Harness \u914D\u7F6E`, `Configured in ${installations.length} harnesses`))
27737
+ );
27738
+ const codeSummary = el("code");
27739
+ codeSummary.style.fontSize = "11px";
27740
+ codeSummary.style.color = "var(--settings-muted)";
27741
+ codeSummary.style.overflowWrap = "anywhere";
27742
+ codeSummary.textContent = summary;
27743
+ const tags = el("div");
27744
+ tags.className = "settings-skills-tags settings-mcp-tags";
27745
+ for (const inst of installations) {
27746
+ const tag = el("span");
27747
+ tag.className = `settings-skills-tag settings-mcp-tag ${inst.server.enabled ? "" : "settings-mcp-tag--disabled"}`;
27748
+ tag.textContent = `\u2713 ${inst.harness.name}${inst.server.enabled ? "" : tr(" (\u5DF2\u505C\u7528)", " (disabled)")}`;
27749
+ tags.append(tag);
27750
+ }
27751
+ const installedIds = new Set(installations.map((i) => i.harness.id));
27752
+ const missingHarnesses = supported.filter((h) => !installedIds.has(h.harness.id));
27753
+ const syncRow = el("div");
27754
+ syncRow.className = "settings-skills-sync-actions settings-mcp-sync-actions";
27755
+ if (missingHarnesses.length > 0) {
27756
+ const label = el("span", tr("\u672A\u914D\u7F6E\u4E8E\uFF1A", "Not configured in: "));
27757
+ label.style.fontSize = "11px";
27758
+ label.style.color = "var(--settings-muted)";
27759
+ syncRow.append(label);
27760
+ for (const missing of missingHarnesses) {
27761
+ const installBtn = button(`+ ${missing.harness.name}`, () => {
27762
+ void mutateCustom(async (c) => {
27763
+ const scopeType = level.value === "project" ? "project" : "global";
27764
+ const currentCwd = level.value === "project" ? cwd.value.trim() : void 0;
27765
+ await c.saveMcp({
27766
+ harnessId: missing.harness.id,
27767
+ scope: scopeType,
27768
+ ...currentCwd ? { cwd: currentCwd } : {},
27769
+ server: toManagedForCopy(firstServer)
27770
+ });
27771
+ return tr(`\u5DF2\u5C06 MCP\u3010${serverName}\u3011\u540C\u6B65\u5230 ${missing.harness.name}\u3002`, `Configured [${serverName}] to ${missing.harness.name}.`);
27772
+ });
27773
+ });
27774
+ syncRow.append(installBtn);
27775
+ }
27776
+ if (missingHarnesses.length > 1) {
27777
+ const installAllBtn = button(tr("\u4E00\u952E\u540C\u6B65\u5230\u5168\u90E8\u652F\u6301\u7684 Harness", "Sync to all supported"), () => {
27778
+ void mutateCustom(async (c) => {
27779
+ const scopeType = level.value === "project" ? "project" : "global";
27780
+ const currentCwd = level.value === "project" ? cwd.value.trim() : void 0;
27781
+ const successes = [];
27782
+ for (const missing of missingHarnesses) {
27783
+ try {
27784
+ await c.saveMcp({
27785
+ harnessId: missing.harness.id,
27786
+ scope: scopeType,
27787
+ ...currentCwd ? { cwd: currentCwd } : {},
27788
+ server: toManagedForCopy(firstServer)
27789
+ });
27790
+ successes.push(missing.harness.name);
27791
+ } catch {
27792
+ }
27793
+ }
27794
+ return tr(`\u5DF2\u5C06 MCP\u3010${serverName}\u3011\u540C\u6B65\u5230\uFF1A${successes.join("\u3001")}\u3002`, `Synced [${serverName}] to: ${successes.join(", ")}.`);
27795
+ });
27796
+ }, true);
27797
+ syncRow.append(installAllBtn);
27798
+ }
27799
+ } else {
27800
+ const complete = el("span", tr("\u2713 \u5DF2\u5728\u6240\u6709\u652F\u6301\u7684 Harness \u4E2D\u914D\u7F6E\u5C31\u7EEA", "\u2713 Ready across all supported Harnesses"));
27801
+ complete.style.fontSize = "11px";
27802
+ complete.style.color = "#10a37f";
27803
+ syncRow.append(complete);
27804
+ }
27805
+ card.append(head, codeSummary, tags, syncRow);
27806
+ matrixList.append(card);
27807
+ }
27808
+ if (matchedCount === 0) {
27809
+ const empty = el("div", tr("\u672A\u5339\u914D\u5230\u4EFB\u4F55 MCP \u670D\u52A1\u5668\u3002", "No MCP servers matched the search."));
27810
+ empty.className = "settings-integrations-empty";
27811
+ matrixList.append(empty);
27812
+ }
27813
+ viewsContainer.append(matrixList);
27814
+ }
27815
+ };
27816
+ btnByHarness.addEventListener("click", () => {
27817
+ activeTab = "harness";
27818
+ btnByHarness.dataset.active = "true";
27819
+ delete btnByServer.dataset.active;
27820
+ updateView();
27821
+ }, { signal: lifecycle.signal });
27822
+ btnByServer.addEventListener("click", () => {
27823
+ activeTab = "server";
27824
+ btnByServer.dataset.active = "true";
27825
+ delete btnByHarness.dataset.active;
27826
+ updateView();
27827
+ }, { signal: lifecycle.signal });
27828
+ searchInput.addEventListener("input", () => {
27829
+ updateView();
27830
+ }, { signal: lifecycle.signal });
27831
+ updateView();
27832
+ body.append(statsBar, toolbar, viewsContainer);
27833
+ };
27834
+ const showSyncDialog = (skill, sourceHarness, targetHarnesses) => {
27835
+ const sourceDir = skill.path.replace(/[/\\][^/\\]+$/, "");
27836
+ if (!targetHarnesses.length) {
27837
+ fail(new Error(tr("\u6CA1\u6709\u5176\u4ED6\u652F\u6301\u6280\u80FD\u7684\u539F\u751F Harness \u53EF\u4F9B\u540C\u6B65\u3002", "No other native Harnesses support skills for sync.")));
27838
+ return;
27839
+ }
27840
+ const modal = el("dialog");
27841
+ modal.className = "settings-skills-sync-modal";
27842
+ const mTitle = el("h3", tr(`\u540C\u6B65\u6280\u80FD\u3010${skill.name}\u3011`, `Sync skill [${skill.name}]`));
27843
+ const mDesc = el("p", tr(`\u4ECE ${sourceHarness.name} \u590D\u5236\u8BE5\u6280\u80FD\u5230\u4EE5\u4E0B\u9009\u4E2D\u7684 Harness\uFF1A`, `Copy skill from ${sourceHarness.name} to selected Harnesses:`));
27844
+ const form = el("form");
27845
+ const checkList = el("div");
27846
+ checkList.style.display = "grid";
27847
+ checkList.style.gap = "8px";
27848
+ checkList.style.margin = "12px 0";
27849
+ const checkboxes = [];
27850
+ for (const h of targetHarnesses) {
27851
+ const label = el("label");
27852
+ label.style.display = "flex";
27853
+ label.style.gap = "8px";
27854
+ label.style.alignItems = "center";
27855
+ label.style.cursor = "pointer";
27856
+ const cb = el("input");
27857
+ cb.type = "checkbox";
27858
+ cb.value = h.id;
27859
+ cb.checked = true;
27860
+ checkboxes.push(cb);
27861
+ label.append(cb, el("span", h.name));
27862
+ checkList.append(label);
27863
+ }
27864
+ const btnRow = el("div");
27865
+ btnRow.style.display = "flex";
27866
+ btnRow.style.gap = "8px";
27867
+ btnRow.style.justifyContent = "flex-end";
27868
+ btnRow.style.marginTop = "14px";
27869
+ const cancelBtn = button(tr("\u53D6\u6D88", "Cancel"), () => {
27870
+ modal.close();
27871
+ modal.remove();
27872
+ });
27873
+ const confirmBtn = button(tr("\u786E\u8BA4\u540C\u6B65", "Confirm Sync"), () => {
27874
+ const selectedHarnesses = checkboxes.filter((cb) => cb.checked).map((cb) => cb.value);
27875
+ modal.close();
27876
+ modal.remove();
27877
+ if (!selectedHarnesses.length) return;
27878
+ void mutateCustom(async (c) => {
27879
+ const scopeType = level.value === "project" ? "project" : "global";
27880
+ const currentCwd = level.value === "project" ? cwd.value.trim() : void 0;
27881
+ const successes = [];
27882
+ const errors = [];
27883
+ for (const targetId of selectedHarnesses) {
27884
+ const targetH = targetHarnesses.find((h) => h.id === targetId);
27885
+ try {
27886
+ await c.changeSkill({
27887
+ harnessId: targetId,
27888
+ scope: scopeType,
27889
+ ...currentCwd ? { cwd: currentCwd } : {},
27890
+ name: skill.name,
27891
+ source: sourceDir,
27892
+ action: "install"
27893
+ });
27894
+ if (targetH) successes.push(targetH.name);
27895
+ } catch (err) {
27896
+ errors.push(`${targetH?.name || targetId}: ${err instanceof Error ? err.message : String(err)}`);
27897
+ }
27898
+ }
27899
+ return tr(
27900
+ `\u540C\u6B65\u5B8C\u6210\uFF01\u5DF2\u5B89\u88C5\u5230\uFF1A${successes.join("\u3001")}${errors.length ? `\uFF08\u8DF3\u8FC7: ${errors.join("; ")}\uFF09` : ""}`,
27901
+ `Sync complete! Installed to: ${successes.join(", ")}${errors.length ? ` (Skipped: ${errors.join("; ")})` : ""}`
27902
+ );
27903
+ });
27904
+ }, true);
27905
+ btnRow.append(cancelBtn, confirmBtn);
27906
+ form.append(checkList, btnRow);
27907
+ modal.append(mTitle, mDesc, form);
27908
+ content.append(modal);
27909
+ modal.showModal();
27910
+ };
27911
+ const renderSkills = (snapshot) => {
27912
+ const drop = el("div");
27913
+ drop.className = "settings-skill-dropzone";
27914
+ drop.tabIndex = 0;
27915
+ drop.setAttribute("role", "button");
27916
+ const dropTitle = el("strong", tr("\u62D6\u62FD\u6280\u80FD\u5230\u8FD9\u91CC", "Drop a skill here"));
27917
+ const dropHint = el("span", tr("\u652F\u6301\u5355\u4E2A Markdown \u6587\u4EF6\u6216\u5305\u542B SKILL.md \u7684\u6587\u4EF6\u5939 \xB7 \u6700\u5927 10 MB / 500 \u4E2A\u6587\u4EF6", "Supports one Markdown file or a folder containing SKILL.md \xB7 up to 10 MB / 500 files"));
27918
+ const picker = el("input");
27919
+ picker.type = "file";
27920
+ picker.multiple = true;
27921
+ picker.hidden = true;
27922
+ picker.setAttribute("webkitdirectory", "");
27923
+ const choose = button(tr("\u9009\u62E9\u6280\u80FD\u6587\u4EF6\u5939", "Choose skill folder"), () => picker.click());
27924
+ drop.append(dropTitle, dropHint, choose, picker);
27925
+ const list = el("div");
27926
+ list.className = "settings-integrations-list";
27927
+ const installFiles = async (incoming) => {
27928
+ const parsed = await parseDroppedSkills(incoming);
27929
+ await mutate((value, selected) => value.changeSkill({ ...selected, name: parsed.name, files: parsed.files, action: "install" }));
27930
+ };
27931
+ const receiveFiles = async (transfer) => {
27932
+ try {
27933
+ let incoming = [];
27934
+ if ("items" in transfer && transfer.items.length) {
27935
+ const entries = [...transfer.items].map((item) => item.webkitGetAsEntry?.() ?? null).filter((entry) => entry !== null);
27936
+ if (entries.length) for (const entry of entries) await walkEntry(entry, "", incoming);
27937
+ }
27938
+ const fileList = "files" in transfer ? transfer.files : transfer;
27939
+ if (!incoming.length) incoming = [...fileList].map((file2) => ({ path: file2.webkitRelativePath || file2.name, file: file2 }));
27940
+ await installFiles(incoming);
27941
+ } catch (error51) {
27942
+ fail(error51);
27943
+ }
27944
+ };
27945
+ for (const eventName of ["dragenter", "dragover"]) drop.addEventListener(eventName, (event) => {
27946
+ event.preventDefault();
27947
+ if (!busy) drop.dataset.dragOver = "true";
27948
+ }, { signal: lifecycle.signal });
27949
+ drop.addEventListener("dragleave", () => {
27950
+ delete drop.dataset.dragOver;
27951
+ }, { signal: lifecycle.signal });
27952
+ drop.addEventListener("drop", (event) => {
27953
+ event.preventDefault();
27954
+ delete drop.dataset.dragOver;
27955
+ if (!busy && event.dataTransfer) void receiveFiles(event.dataTransfer);
27956
+ }, { signal: lifecycle.signal });
27957
+ picker.addEventListener("change", () => {
27958
+ if (picker.files?.length) void receiveFiles(picker.files);
27959
+ picker.value = "";
27960
+ }, { signal: lifecycle.signal });
27961
+ if (!snapshot.skillsSupported) {
27962
+ drop.dataset.disabled = "true";
27963
+ choose.disabled = true;
27964
+ dropHint.textContent = tr("\u6B64 Harness \u7684\u539F\u751F\u6280\u80FD\u76EE\u5F55\u5C1A\u672A\u786E\u8BA4\u3002", "This Harness has no verified native skill directory.");
27965
+ }
27966
+ for (const skill of snapshot.skills) {
27967
+ const row = el("section");
27968
+ row.className = "settings-integrations-row";
27969
+ const detail = el("div");
27970
+ detail.append(el("strong", skill.name), el("p", skill.enabled ? tr("\u5DF2\u5B89\u88C5 \xB7 \u52A0\u8F7D\u72B6\u6001\u672A\u62A5\u544A", "Installed \xB7 load status unreported") : tr("\u5DF2\u505C\u7528 \xB7 \u6587\u4EF6\u5DF2\u4FDD\u7559", "Disabled \xB7 files retained")), el("code", skill.path));
27971
+ row.append(detail);
27972
+ if (skill.writable) {
27973
+ row.append(button(skill.enabled ? tr("\u505C\u7528", "Disable") : tr("\u6062\u590D", "Restore"), () => {
27974
+ void mutate((value, selected) => value.changeSkill({ ...selected, name: skill.name, root: skill.root, action: skill.enabled ? "disable" : "enable" }));
27975
+ }));
27976
+ } else {
27977
+ row.append(el("span", tr("\u94FE\u63A5\u76EE\u5F55\uFF0C\u53EA\u8BFB", "Linked directory, read-only")));
27978
+ }
27979
+ const syncBtn = button(tr("\u540C\u6B65\u5230\u2026", "Sync to\u2026"), () => {
27980
+ void lifecycle.runLatest(() => client().integrationCatalog(), {
27981
+ success: (cat) => {
27982
+ const targetHarnesses = cat.harnesses.filter((h) => h.skills && h.id !== snapshot.harnessId);
27983
+ showSyncDialog(skill, { id: snapshot.harnessId, name: snapshot.harnessId }, targetHarnesses);
27984
+ },
27985
+ failure: fail
27986
+ });
27987
+ });
27988
+ row.append(syncBtn);
27989
+ list.append(row);
27990
+ }
27991
+ if (!snapshot.skills.length) {
27992
+ const empty = el("div", tr("\u8FD8\u6CA1\u6709\u53D1\u73B0\u6280\u80FD\u3002\u62D6\u5165\u6587\u4EF6\u5373\u53EF\u5B89\u88C5\u3002", "No skills found. Drop files above to install one."));
27993
+ empty.className = "settings-integrations-empty";
27994
+ list.append(empty);
27995
+ }
27996
+ body.append(drop, list);
27997
+ };
27998
+ const renderSkillsOverview = (catalog, items) => {
27999
+ const drop = el("div");
28000
+ drop.className = "settings-skill-dropzone";
28001
+ drop.tabIndex = 0;
28002
+ drop.setAttribute("role", "button");
28003
+ const dropTitle = el("strong", tr("\u62D6\u62FD\u6280\u80FD\u5230\u8FD9\u91CC\uFF0C\u4E00\u952E\u5206\u53D1\u5B89\u88C5", "Drop a skill here to distribute and install"));
28004
+ const dropHint = el("span", tr("\u652F\u6301\u5355\u4E2A Markdown \u6587\u4EF6\u6216\u5305\u542B SKILL.md \u7684\u6587\u4EF6\u5939 \xB7 \u81EA\u52A8\u5B89\u88C5\u81F3\u6240\u9009 Harness", "Supports one Markdown file or folder with SKILL.md \xB7 Installs to target Harnesses"));
28005
+ const targetRow = el("div");
28006
+ targetRow.className = "settings-skills-target-row";
28007
+ const targetLabel = el("span", tr("\u5B89\u88C5\u76EE\u6807\uFF1A", "Target: "));
28008
+ const targetSelect = el("select");
28009
+ targetSelect.setAttribute("aria-label", tr("\u9009\u62E9\u76EE\u6807 Harness", "Select target Harness"));
28010
+ const allOption = el("option", tr("\u5168\u90E8\u652F\u6301\u7684 Harness", "All supported Harnesses"));
28011
+ allOption.value = "__all__";
28012
+ targetSelect.append(allOption);
28013
+ for (const item of items) {
28014
+ if (item.harness.skills) {
28015
+ const opt = el("option", item.harness.name);
28016
+ opt.value = item.harness.id;
28017
+ targetSelect.append(opt);
28018
+ }
28019
+ }
28020
+ const picker = el("input");
28021
+ picker.type = "file";
28022
+ picker.multiple = true;
28023
+ picker.hidden = true;
28024
+ picker.setAttribute("webkitdirectory", "");
28025
+ const choose = button(tr("\u9009\u62E9\u6280\u80FD\u6587\u4EF6\u5939", "Choose skill folder"), () => picker.click());
28026
+ targetRow.append(targetLabel, targetSelect, choose, picker);
28027
+ drop.append(dropTitle, dropHint, targetRow);
28028
+ const receiveOverviewFiles = async (transfer) => {
28029
+ try {
28030
+ let incoming = [];
28031
+ if ("items" in transfer && transfer.items.length) {
28032
+ const entries = [...transfer.items].map((item) => item.webkitGetAsEntry?.() ?? null).filter((entry) => entry !== null);
28033
+ if (entries.length) for (const entry of entries) await walkEntry(entry, "", incoming);
28034
+ }
28035
+ const fileList = "files" in transfer ? transfer.files : transfer;
28036
+ if (!incoming.length) incoming = [...fileList].map((file2) => ({ path: file2.webkitRelativePath || file2.name, file: file2 }));
28037
+ const parsed = await parseDroppedSkills(incoming);
28038
+ await mutateCustom(async (c) => {
28039
+ const scopeType = level.value === "project" ? "project" : "global";
28040
+ const currentCwd = level.value === "project" ? cwd.value.trim() : void 0;
28041
+ const targets = targetSelect.value === "__all__" ? items.filter((i) => i.harness.skills).map((i) => i.harness) : items.filter((i) => i.harness.id === targetSelect.value).map((i) => i.harness);
28042
+ if (!targets.length) throw new Error(tr("\u6CA1\u6709\u53EF\u5B89\u88C5\u7684\u76EE\u6807 Harness\u3002", "No available target Harnesses."));
28043
+ const successNames = [];
28044
+ const errors = [];
28045
+ for (const target of targets) {
28046
+ try {
28047
+ await c.changeSkill({
28048
+ harnessId: target.id,
28049
+ scope: scopeType,
28050
+ ...currentCwd ? { cwd: currentCwd } : {},
28051
+ name: parsed.name,
28052
+ files: parsed.files,
28053
+ action: "install"
28054
+ });
28055
+ successNames.push(target.name);
28056
+ } catch (err) {
28057
+ errors.push(`${target.name}: ${err instanceof Error ? err.message : String(err)}`);
28058
+ }
28059
+ }
28060
+ if (!successNames.length && errors.length) throw new Error(errors.join("; "));
28061
+ return tr(
28062
+ `\u5DF2\u6210\u529F\u5C06\u6280\u80FD\u3010${parsed.name}\u3011\u5B89\u88C5\u5230\uFF1A${successNames.join("\u3001")}${errors.length ? `\uFF08\u8DF3\u8FC7: ${errors.join("; ")}\uFF09` : ""}`,
28063
+ `Successfully installed skill [${parsed.name}] to: ${successNames.join(", ")}${errors.length ? ` (Skipped: ${errors.join("; ")})` : ""}`
28064
+ );
28065
+ });
28066
+ } catch (error51) {
28067
+ fail(error51);
28068
+ }
28069
+ };
28070
+ for (const eventName of ["dragenter", "dragover"]) drop.addEventListener(eventName, (event) => {
28071
+ event.preventDefault();
28072
+ if (!busy) drop.dataset.dragOver = "true";
28073
+ }, { signal: lifecycle.signal });
28074
+ drop.addEventListener("dragleave", () => {
28075
+ delete drop.dataset.dragOver;
28076
+ }, { signal: lifecycle.signal });
28077
+ drop.addEventListener("drop", (event) => {
28078
+ event.preventDefault();
28079
+ delete drop.dataset.dragOver;
28080
+ if (!busy && event.dataTransfer) void receiveOverviewFiles(event.dataTransfer);
28081
+ }, { signal: lifecycle.signal });
28082
+ picker.addEventListener("change", () => {
28083
+ if (picker.files?.length) void receiveOverviewFiles(picker.files);
28084
+ picker.value = "";
28085
+ }, { signal: lifecycle.signal });
28086
+ const supported = items.filter((i) => i.harness.skills);
28087
+ const uniqueSkills = /* @__PURE__ */ new Map();
28088
+ for (const item of items) {
28089
+ if (!item.snapshot?.skills) continue;
28090
+ for (const s of item.snapshot.skills) {
28091
+ const list = uniqueSkills.get(s.name) || [];
28092
+ list.push({ harness: item.harness, skill: s });
28093
+ uniqueSkills.set(s.name, list);
28094
+ }
28095
+ }
28096
+ const statsBar = el("div");
28097
+ statsBar.className = "settings-skills-overview-stats";
28098
+ const statsSummary = el("span", tr(
28099
+ `\u{1F4CA} \u5171 ${items.length} \u4E2A Harness \xB7 ${supported.length} \u4E2A\u5DF2\u914D\u7F6E\u539F\u751F\u6280\u80FD\u76EE\u5F55 \xB7 \u53D1\u73B0 ${uniqueSkills.size} \u4E2A\u53BB\u91CD\u6280\u80FD`,
28100
+ `\u{1F4CA} ${items.length} Harnesses \xB7 ${supported.length} with native skills \xB7 ${uniqueSkills.size} unique skills found`
28101
+ ));
28102
+ statsBar.append(statsSummary);
28103
+ const toolbar = el("div");
28104
+ toolbar.className = "settings-integrations-toolbar";
28105
+ const searchInput = el("input");
28106
+ searchInput.type = "search";
28107
+ searchInput.placeholder = tr("\u6309\u540D\u79F0\u8FC7\u6EE4\u6280\u80FD\u2026", "Filter skills by name\u2026");
28108
+ searchInput.setAttribute("aria-label", searchInput.placeholder);
28109
+ const tabsWrap = el("div");
28110
+ tabsWrap.className = "settings-skills-tabs";
28111
+ const btnByHarness = el("button", tr("\u6309 Harness \u67E5\u770B", "By Harness"));
28112
+ btnByHarness.type = "button";
28113
+ btnByHarness.className = "settings-skills-tab-btn";
28114
+ btnByHarness.dataset.active = "true";
28115
+ const btnBySkill = el("button", tr("\u6309 Skill \u6C47\u603B", "By Skill"));
28116
+ btnBySkill.type = "button";
28117
+ btnBySkill.className = "settings-skills-tab-btn";
28118
+ tabsWrap.append(btnByHarness, btnBySkill);
28119
+ toolbar.append(searchInput, tabsWrap);
28120
+ const viewsContainer = el("div");
28121
+ viewsContainer.className = "settings-skills-views";
28122
+ let activeTab = "harness";
28123
+ const updateView = () => {
28124
+ viewsContainer.replaceChildren();
28125
+ const query = searchInput.value.trim().toLowerCase();
28126
+ if (activeTab === "harness") {
28127
+ const grid = el("div");
28128
+ grid.className = "settings-skills-overview-grid";
28129
+ for (const item of items) {
28130
+ const allSkills = item.snapshot?.skills || [];
28131
+ const matchingSkills = query ? allSkills.filter((s) => s.name.toLowerCase().includes(query) || s.path.toLowerCase().includes(query)) : allSkills;
28132
+ if (query && !item.harness.name.toLowerCase().includes(query) && matchingSkills.length === 0) {
28133
+ continue;
28134
+ }
28135
+ const card = el("section");
28136
+ card.className = "settings-skills-harness-card";
28137
+ const head = el("div");
28138
+ head.className = "settings-skills-harness-head";
28139
+ const hTitle = el("strong", item.harness.name);
28140
+ const badge = el("span");
28141
+ badge.className = `settings-skills-badge ${item.harness.skills ? "settings-skills-badge--active" : ""}`;
28142
+ badge.textContent = item.harness.skills ? tr(`${allSkills.length} \u4E2A\u6280\u80FD`, `${allSkills.length} skills`) : tr("\u672A\u914D\u7F6E\u76EE\u5F55", "No native directory");
28143
+ head.append(hTitle, badge);
28144
+ card.append(head);
28145
+ if (!item.harness.skills) {
28146
+ const note2 = el("p", tr("\u6B64 Harness \u6682\u672A\u914D\u7F6E\u539F\u751F\u6280\u80FD\u76EE\u5F55\u3002", "This Harness has no verified native skill directory."));
28147
+ note2.className = "settings-mcp-notice";
28148
+ card.append(note2);
28149
+ } else if (matchingSkills.length === 0) {
28150
+ const empty = el("p", query ? tr("\u65E0\u5339\u914D\u6280\u80FD", "No matching skills") : tr("\u6682\u672A\u5B89\u88C5\u6280\u80FD", "No skills installed"));
28151
+ empty.className = "settings-mcp-notice";
28152
+ card.append(empty);
28153
+ } else {
28154
+ const list = el("div");
28155
+ list.className = "settings-skills-list-compact";
28156
+ for (const s of matchingSkills) {
28157
+ const row = el("div");
28158
+ row.className = "settings-skills-item-row";
28159
+ const info = el("div");
28160
+ info.append(
28161
+ el("strong", s.name),
28162
+ el("span", s.enabled ? tr(" \xB7 \u5DF2\u5B89\u88C5", " \xB7 Installed") : tr(" \xB7 \u5DF2\u505C\u7528", " \xB7 Disabled")),
28163
+ el("code", s.path)
28164
+ );
28165
+ const actions = el("div");
28166
+ actions.className = "settings-skills-item-actions";
28167
+ if (s.writable) {
28168
+ actions.append(button(s.enabled ? tr("\u505C\u7528", "Disable") : tr("\u6062\u590D", "Restore"), () => {
28169
+ void mutateCustom(async (c) => {
28170
+ const scopeType = level.value === "project" ? "project" : "global";
28171
+ const currentCwd = level.value === "project" ? cwd.value.trim() : void 0;
28172
+ await c.changeSkill({
28173
+ harnessId: item.harness.id,
28174
+ scope: scopeType,
28175
+ ...currentCwd ? { cwd: currentCwd } : {},
28176
+ name: s.name,
28177
+ root: s.root,
28178
+ action: s.enabled ? "disable" : "enable"
28179
+ });
28180
+ });
28181
+ }));
28182
+ }
28183
+ const otherSupported = supported.filter((h) => h.harness.id !== item.harness.id);
28184
+ if (otherSupported.length > 0) {
28185
+ const syncBtn = button(tr("\u540C\u6B65\u2026", "Sync\u2026"), () => {
28186
+ showSyncDialog(s, item.harness, otherSupported.map((h) => h.harness));
28187
+ });
28188
+ actions.append(syncBtn);
28189
+ }
28190
+ row.append(info, actions);
28191
+ list.append(row);
28192
+ }
28193
+ card.append(list);
28194
+ }
28195
+ grid.append(card);
28196
+ }
28197
+ viewsContainer.append(grid);
28198
+ } else {
28199
+ const matrixList = el("div");
28200
+ matrixList.className = "settings-skills-matrix-list";
28201
+ let matchedCount = 0;
28202
+ for (const [skillName, installations] of uniqueSkills.entries()) {
28203
+ if (query && !skillName.toLowerCase().includes(query) && !installations.some((i) => i.skill.path.toLowerCase().includes(query))) {
28204
+ continue;
28205
+ }
28206
+ matchedCount++;
28207
+ const card = el("section");
28208
+ card.className = "settings-skills-matrix-card";
28209
+ const head = el("div");
28210
+ head.className = "settings-skills-matrix-head";
28211
+ head.append(
28212
+ el("strong", skillName),
28213
+ el("span", tr(`\u5DF2\u5728 ${installations.length} \u4E2A Harness \u5B89\u88C5`, `Installed in ${installations.length} harnesses`))
28214
+ );
28215
+ const tags = el("div");
28216
+ tags.className = "settings-skills-tags";
28217
+ for (const inst of installations) {
28218
+ const tag = el("span");
28219
+ tag.className = "settings-skills-tag";
28220
+ tag.textContent = `\u2713 ${inst.harness.name}${inst.skill.enabled ? "" : tr(" (\u5DF2\u505C\u7528)", " (disabled)")}`;
28221
+ tags.append(tag);
28222
+ }
28223
+ const installedIds = new Set(installations.map((i) => i.harness.id));
28224
+ const missingHarnesses = supported.filter((h) => !installedIds.has(h.harness.id));
28225
+ const syncRow = el("div");
28226
+ syncRow.className = "settings-skills-sync-actions";
28227
+ if (missingHarnesses.length > 0) {
28228
+ const label = el("span", tr("\u672A\u5B89\u88C5\u4E8E\uFF1A", "Not installed in: "));
28229
+ label.style.fontSize = "11px";
28230
+ label.style.color = "var(--settings-muted)";
28231
+ syncRow.append(label);
28232
+ const sourceSkill = installations[0].skill;
28233
+ const sourceDir = sourceSkill.path.replace(/[/\\][^/\\]+$/, "");
28234
+ for (const missing of missingHarnesses) {
28235
+ const installBtn = button(`+ ${missing.harness.name}`, () => {
28236
+ void mutateCustom(async (c) => {
28237
+ const scopeType = level.value === "project" ? "project" : "global";
28238
+ const currentCwd = level.value === "project" ? cwd.value.trim() : void 0;
28239
+ await c.changeSkill({
28240
+ harnessId: missing.harness.id,
28241
+ scope: scopeType,
28242
+ ...currentCwd ? { cwd: currentCwd } : {},
28243
+ name: skillName,
28244
+ source: sourceDir,
28245
+ action: "install"
28246
+ });
28247
+ return tr(`\u5DF2\u5C06\u3010${skillName}\u3011\u540C\u6B65\u5B89\u88C5\u5230 ${missing.harness.name}\u3002`, `Installed [${skillName}] to ${missing.harness.name}.`);
28248
+ });
28249
+ });
28250
+ syncRow.append(installBtn);
28251
+ }
28252
+ if (missingHarnesses.length > 1) {
28253
+ const installAllBtn = button(tr("\u4E00\u952E\u540C\u6B65\u5230\u5168\u90E8", "Sync to all"), () => {
28254
+ void mutateCustom(async (c) => {
28255
+ const scopeType = level.value === "project" ? "project" : "global";
28256
+ const currentCwd = level.value === "project" ? cwd.value.trim() : void 0;
28257
+ const successes = [];
28258
+ for (const missing of missingHarnesses) {
28259
+ try {
28260
+ await c.changeSkill({
28261
+ harnessId: missing.harness.id,
28262
+ scope: scopeType,
28263
+ ...currentCwd ? { cwd: currentCwd } : {},
28264
+ name: skillName,
28265
+ source: sourceDir,
28266
+ action: "install"
28267
+ });
28268
+ successes.push(missing.harness.name);
28269
+ } catch {
28270
+ }
28271
+ }
28272
+ return tr(`\u5DF2\u5C06\u3010${skillName}\u3011\u540C\u6B65\u5B89\u88C5\u5230\uFF1A${successes.join("\u3001")}\u3002`, `Synced [${skillName}] to: ${successes.join(", ")}.`);
28273
+ });
28274
+ }, true);
28275
+ syncRow.append(installAllBtn);
28276
+ }
28277
+ } else {
28278
+ const complete = el("span", tr("\u5DF2\u5728\u6240\u6709\u652F\u6301\u7684 Harness \u4E2D\u5C31\u7EEA", "Ready across all supported Harnesses"));
28279
+ complete.style.fontSize = "11px";
28280
+ complete.style.color = "#10a37f";
28281
+ syncRow.append(complete);
28282
+ }
28283
+ card.append(head, tags, syncRow);
28284
+ matrixList.append(card);
28285
+ }
28286
+ if (matchedCount === 0) {
28287
+ const empty = el("div", tr("\u672A\u5339\u914D\u5230\u4EFB\u4F55\u6280\u80FD\u3002", "No skills matched the search."));
28288
+ empty.className = "settings-integrations-empty";
28289
+ matrixList.append(empty);
28290
+ }
28291
+ viewsContainer.append(matrixList);
28292
+ }
28293
+ };
28294
+ btnByHarness.addEventListener("click", () => {
28295
+ activeTab = "harness";
28296
+ btnByHarness.dataset.active = "true";
28297
+ delete btnBySkill.dataset.active;
28298
+ updateView();
28299
+ }, { signal: lifecycle.signal });
28300
+ btnBySkill.addEventListener("click", () => {
28301
+ activeTab = "skill";
28302
+ btnBySkill.dataset.active = "true";
28303
+ delete btnByHarness.dataset.active;
28304
+ updateView();
28305
+ }, { signal: lifecycle.signal });
28306
+ searchInput.addEventListener("input", () => {
28307
+ updateView();
28308
+ }, { signal: lifecycle.signal });
28309
+ updateView();
28310
+ body.append(drop, statsBar, toolbar, viewsContainer);
28311
+ };
28312
+ const render = (snapshot) => {
28313
+ body.replaceChildren();
28314
+ if (kind === "mcp") renderMcp(snapshot);
28315
+ else renderSkills(snapshot);
28316
+ };
28317
+ const refresh = async () => {
28318
+ if (busy || lifecycle.disposed) return;
28319
+ if (level.value === "project" && !cwd.value.trim()) {
28320
+ body.replaceChildren();
28321
+ status.textContent = tr("\u586B\u5199\u9879\u76EE\u8DEF\u5F84\u540E\u5373\u53EF\u8BFB\u53D6\u3002", "Enter the project path to continue.");
28322
+ cwd.focus();
28323
+ return;
28324
+ }
28325
+ setBusy(true);
28326
+ status.textContent = tr("\u6B63\u5728\u8BFB\u53D6\u2026", "Loading\u2026");
28327
+ status.setAttribute("role", "status");
28328
+ if (harness.value === "__all__") {
28329
+ await lifecycle.runLatest(async () => {
28330
+ const catalog = await client().integrationCatalog();
28331
+ const scopeType = level.value === "project" ? "project" : "global";
28332
+ const currentCwd = level.value === "project" ? cwd.value.trim() : void 0;
28333
+ const items = await Promise.all(
28334
+ catalog.harnesses.map(async (h) => {
28335
+ try {
28336
+ const snap = await client().listIntegrations({
28337
+ harnessId: h.id,
28338
+ scope: scopeType,
28339
+ ...currentCwd ? { cwd: currentCwd } : {}
28340
+ });
28341
+ return { harness: h, snapshot: snap, error: null };
28342
+ } catch (err) {
28343
+ return { harness: h, snapshot: null, error: err instanceof Error ? err.message : String(err) };
28344
+ }
28345
+ })
28346
+ );
28347
+ return { catalog, items };
28348
+ }, {
28349
+ success: (data) => {
28350
+ body.replaceChildren();
28351
+ if (kind === "mcp") {
28352
+ renderMcpOverview(data.catalog, data.items);
28353
+ } else {
28354
+ renderSkillsOverview(data.catalog, data.items);
28355
+ }
28356
+ status.textContent = "";
28357
+ },
28358
+ failure: fail
28359
+ });
28360
+ } else {
28361
+ await lifecycle.runLatest(() => client().listIntegrations(selectedScope()), { success: (data) => {
28362
+ render(data);
28363
+ status.textContent = "";
28364
+ }, failure: fail });
28365
+ }
28366
+ if (!lifecycle.disposed) setBusy(false);
28367
+ };
28368
+ refreshButton.addEventListener("click", () => {
28369
+ void refresh();
28370
+ }, { signal: lifecycle.signal });
28371
+ controls.append(harness, level, cwd, refreshButton);
28372
+ content.append(title, note, controls, status, body);
28373
+ harness.addEventListener("change", () => {
28374
+ void refresh();
28375
+ }, { signal: lifecycle.signal });
28376
+ level.addEventListener("change", () => {
28377
+ cwd.hidden = level.value !== "project";
28378
+ void refresh();
28379
+ }, { signal: lifecycle.signal });
28380
+ cwd.addEventListener("change", () => {
28381
+ void refresh();
28382
+ }, { signal: lifecycle.signal });
28383
+ void lifecycle.runLatest(() => client().integrationCatalog(), { success: (data) => {
28384
+ const allOption = el("option", tr("\u5168\u90E8 Harness\uFF08\u603B\u89C8\uFF09", "All Harnesses (Overview)"));
28385
+ allOption.value = "__all__";
28386
+ harness.append(allOption);
28387
+ for (const item of data.harnesses) {
28388
+ const option = el("option", `${item.name}${item.available ? "" : tr(" \xB7 \u672A\u5C31\u7EEA", " \xB7 not ready")}`);
28389
+ option.value = item.id;
28390
+ harness.append(option);
28391
+ }
28392
+ void refresh();
28393
+ }, failure: fail });
28394
+ return void 0;
28395
+ }
28396
+ });
28397
+ }
28398
+ var createMcpSettingsPage = (messages, getClient) => createIntegrationSettingsPage("mcp", messages, getClient);
28399
+ var createSkillsSettingsPage = (messages, getClient) => createIntegrationSettingsPage("skills", messages, getClient);
28400
+
26033
28401
  // src/native-ui/renderer-extension/src/settings/update-request.ts
26034
28402
  var RENDERER_UPDATE_REQUEST_TIMEOUT_MS = 15e3;
26035
28403
  var RendererUpdateRequestTimeoutError = class extends Error {
@@ -26149,7 +28517,7 @@ ${error51.stderrTail}`] : []
26149
28517
  }
26150
28518
  return `${scaled.toFixed(scaled >= 10 ? 0 : 1)} ${unit}`;
26151
28519
  }
26152
- function aboutPage(messages) {
28520
+ function aboutPage(messages, getClient = () => null) {
26153
28521
  return Object.freeze({
26154
28522
  id: "about",
26155
28523
  label: messages.pageLabels.about,
@@ -26171,7 +28539,7 @@ ${error51.stderrTail}`] : []
26171
28539
  versionRow.className = "settings-about-version-row";
26172
28540
  const versionBadge = document2.createElement("span");
26173
28541
  versionBadge.className = "settings-about-version-badge";
26174
- versionBadge.textContent = "v0.1.2";
28542
+ versionBadge.textContent = "v\u2026";
26175
28543
  const checkUpdateBtn = document2.createElement("button");
26176
28544
  checkUpdateBtn.type = "button";
26177
28545
  checkUpdateBtn.className = "settings-command-button settings-command-button--secondary";
@@ -26213,6 +28581,20 @@ ${error51.stderrTail}`] : []
26213
28581
  repositorySection.append(openSource, repository);
26214
28582
  panel.append(product, tagline, versionRow, introduction, starCallout, repositorySection);
26215
28583
  context.content.append(heading, panel);
28584
+ const client = getClient();
28585
+ const readVersion = client?.readCurrentVersion ? () => client.readCurrentVersion() : client ? () => client.checkUpdate().then(({ currentVersion }) => ({ version: currentVersion })) : null;
28586
+ if (readVersion) {
28587
+ void context.runLatest(readVersion, {
28588
+ success(result) {
28589
+ versionBadge.textContent = `v${result.version}`;
28590
+ },
28591
+ failure() {
28592
+ versionBadge.textContent = "v\u2014";
28593
+ }
28594
+ });
28595
+ } else {
28596
+ versionBadge.textContent = "v\u2014";
28597
+ }
26216
28598
  return void 0;
26217
28599
  }
26218
28600
  });
@@ -26526,16 +28908,18 @@ ${error51.stderrTail}`] : []
26526
28908
  }
26527
28909
  });
26528
28910
  }
26529
- function createDefaultRendererSettingsPages(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null, getAccountClient = () => null, getSessionImportClient = () => null, openImportedThread = () => Promise.reject(new Error("Imported Thread navigation is unavailable"))) {
28911
+ function createDefaultRendererSettingsPages(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null, getAccountClient = () => null, getSessionImportClient = () => null, openImportedThread = () => Promise.reject(new Error("Imported Thread navigation is unavailable")), getIntegrationsClient = () => null) {
26530
28912
  return Object.freeze([
26531
28913
  createConnectionsSettingsPage(messages, getDiagnostics),
26532
28914
  createAccountsSettingsPage(messages, getAccountClient),
28915
+ createMcpSettingsPage(messages, getIntegrationsClient),
28916
+ createSkillsSettingsPage(messages, getIntegrationsClient),
26533
28917
  createSessionImportSettingsPage(messages, getSessionImportClient, openImportedThread),
26534
28918
  updatesPage(messages, getUpdateClient),
26535
- aboutPage(messages)
28919
+ aboutPage(messages, getUpdateClient)
26536
28920
  ]);
26537
28921
  }
26538
- function createDefaultRendererSettingsRegistry(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null, getAccountClient = () => null, getSessionImportClient = () => null, openImportedThread) {
28922
+ function createDefaultRendererSettingsRegistry(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null, getAccountClient = () => null, getSessionImportClient = () => null, openImportedThread, getIntegrationsClient) {
26539
28923
  return createRendererSettingsPageRegistry(
26540
28924
  createDefaultRendererSettingsPages(
26541
28925
  messages,
@@ -26543,13 +28927,14 @@ ${error51.stderrTail}`] : []
26543
28927
  getDiagnostics,
26544
28928
  getAccountClient,
26545
28929
  getSessionImportClient,
26546
- openImportedThread
28930
+ openImportedThread,
28931
+ getIntegrationsClient
26547
28932
  )
26548
28933
  );
26549
28934
  }
26550
28935
 
26551
28936
  // src/native-ui/renderer-extension/src/settings/shell.css
26552
- var shell_default = ':host {\r\n --settings-bg: light-dark(#ffffff, #202020);\r\n --settings-sidebar: light-dark(#f7f7f8, #191919);\r\n --settings-panel: light-dark(#ffffff, #232323);\r\n --settings-surface: light-dark(#f6f6f6, #292929);\r\n --settings-surface-hover: light-dark(#eeeeee, #303030);\r\n --settings-inset: light-dark(#f3f3f3, #161616);\r\n --settings-text: light-dark(#0d0d0d, #ececec);\r\n --settings-muted: light-dark(#676767, #a3a3a3);\r\n --settings-subtle: light-dark(#8a8a8a, #777777);\r\n --settings-border: light-dark(rgb(13 13 13 / 9%), rgb(255 255 255 / 9%));\r\n --settings-divider: light-dark(rgb(13 13 13 / 7%), rgb(255 255 255 / 7%));\r\n --settings-hover: light-dark(rgb(13 13 13 / 5%), rgb(255 255 255 / 7%));\r\n --settings-active: light-dark(rgb(13 13 13 / 7%), rgb(255 255 255 / 9%));\r\n --settings-focus: light-dark(#0b75d1, #66aaf9);\r\n --settings-primary: light-dark(#171717, #f4f4f4);\r\n --settings-primary-hover: light-dark(#2f2f2f, #ffffff);\r\n --settings-primary-text: light-dark(#ffffff, #171717);\r\n --settings-warning: light-dark(#8a5500, #f5c96a);\r\n --settings-warning-bg: light-dark(#fff8e6, rgb(245 201 106 / 8%));\r\n --settings-warning-border: light-dark(#ead8a8, rgb(245 201 106 / 24%));\r\n --settings-danger: light-dark(#b42318, #f87171);\r\n --settings-danger-bg: light-dark(#fff1f0, rgb(239 68 68 / 8%));\r\n --settings-danger-border: light-dark(#f3c7c3, rgb(239 68 68 / 22%));\r\n --settings-success: light-dark(#16784a, #4ade80);\r\n color: var(--settings-text);\r\n color-scheme: inherit;\r\n font:\r\n 13px/1.5 system-ui,\r\n -apple-system,\r\n BlinkMacSystemFont,\r\n "Segoe UI",\r\n sans-serif;\r\n letter-spacing: 0;\r\n}\r\n\r\n*,\r\n*::before,\r\n*::after {\r\n box-sizing: border-box;\r\n letter-spacing: 0;\r\n}\r\n\r\nbutton,\r\ninput,\r\nselect {\r\n font: inherit;\r\n}\r\n\r\nbutton {\r\n color: inherit;\r\n}\r\n\r\n[hidden] {\r\n display: none !important;\r\n}\r\n\r\n.settings-visually-hidden {\r\n position: absolute;\r\n width: 1px;\r\n height: 1px;\r\n padding: 0;\r\n margin: -1px;\r\n overflow: hidden;\r\n clip-path: inset(50%);\r\n white-space: nowrap;\r\n border: 0;\r\n}\r\n\r\n.codexhost-settings-dialog {\r\n width: min(1120px, calc(100vw - 32px));\r\n height: min(780px, calc(100vh - 32px));\r\n max-width: none;\r\n max-height: none;\r\n margin: auto;\r\n padding: 0;\r\n overflow: hidden;\r\n color: var(--settings-text);\r\n background: var(--settings-bg);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 14px;\r\n box-shadow: light-dark(0 16px 42px rgb(0 0 0 / 16%), 0 20px 54px rgb(0 0 0 / 42%));\r\n}\r\n\r\n.codexhost-settings-dialog::backdrop {\r\n background: light-dark(rgb(0 0 0 / 24%), rgb(0 0 0 / 56%));\r\n backdrop-filter: blur(1px);\r\n}\r\n\r\n.settings-frame,\r\n.settings-layout {\r\n width: 100%;\r\n height: 100%;\r\n min-width: 0;\r\n min-height: 0;\r\n}\r\n\r\n.settings-frame {\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.settings-layout {\r\n flex: 1;\r\n display: grid;\r\n grid-template-columns: 184px minmax(0, 1fr);\r\n background: var(--settings-bg);\r\n}\r\n\r\n.settings-sidebar {\r\n display: flex;\r\n min-width: 0;\r\n min-height: 0;\r\n flex-direction: column;\r\n overflow: hidden;\r\n background: var(--settings-sidebar);\r\n border-right: 1px solid var(--settings-border);\r\n padding-top: 14px;\r\n}\r\n\r\n.settings-header {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n height: 48px;\r\n flex: none;\r\n padding: 0 12px;\r\n border-bottom: 1px solid var(--settings-border);\r\n}\r\n\r\n.settings-header-actions {\r\n display: flex;\r\n align-items: center;\r\n flex: none;\r\n gap: 12px;\r\n margin-left: auto;\r\n}\r\n\r\n.settings-brand {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 7px;\r\n}\r\n\r\n.settings-brand__mark {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 26px;\r\n height: 26px;\r\n flex: none;\r\n color: var(--settings-text);\r\n}\r\n\r\n.settings-brand__mark .codexhost-settings-icon {\r\n width: 24px;\r\n height: 24px;\r\n object-fit: contain;\r\n}\r\n\r\n.settings-brand__copy {\r\n display: flex;\r\n min-width: 0;\r\n align-items: baseline;\r\n gap: 0;\r\n line-height: 20px;\r\n}\r\n\r\n.settings-brand__name {\r\n overflow: hidden;\r\n color: var(--settings-text);\r\n font-size: 13px;\r\n font-weight: 600;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-brand__title {\r\n margin-left: 8px;\r\n padding-left: 8px;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n font-weight: 400;\r\n border-left: 1px solid var(--settings-border);\r\n}\r\n\r\n.settings-nav {\r\n display: flex;\r\n min-width: 0;\r\n min-height: 0;\r\n flex: 1;\r\n flex-direction: column;\r\n gap: 2px;\r\n padding: 0 7px 10px;\r\n overflow-y: auto;\r\n}\r\n\r\n.settings-nav-section-label {\r\n min-height: 24px;\r\n padding: 4px 9px 2px;\r\n color: var(--settings-subtle);\r\n font-size: 11px;\r\n font-weight: 600;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-nav-section-label:not(:first-child) {\r\n margin-top: 8px;\r\n}\r\n\r\n.settings-nav-button {\r\n display: grid;\r\n grid-template-columns: 16px minmax(0, 1fr);\r\n align-items: center;\r\n width: 100%;\r\n position: relative;\r\n min-height: 34px;\r\n flex: none;\r\n gap: 9px;\r\n padding: 6px 9px;\r\n color: var(--settings-text);\r\n font-size: 13px;\r\n line-height: 20px;\r\n text-align: left;\r\n background: transparent;\r\n border: 0;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-nav-button .codexhost-settings-icon {\r\n width: 16px;\r\n height: 16px;\r\n opacity: 0.9;\r\n}\r\n\r\n.settings-nav-button:hover {\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-nav-button[aria-current="page"] {\r\n background: var(--settings-active);\r\n color: var(--settings-text);\r\n font-weight: 500;\r\n}\r\n\r\n.settings-nav-button span {\r\n min-width: 0;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-nav-star-link {\r\n margin-top: 0;\r\n color: var(--settings-text);\r\n text-decoration: none;\r\n}\r\n\r\n.settings-nav-star-link .codexhost-settings-icon {\r\n color: var(--settings-warning);\r\n}\r\n\r\n.settings-nav-star-link:hover {\r\n color: var(--settings-warning);\r\n background: var(--settings-warning-bg);\r\n}\r\n\r\n.settings-icon-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 28px;\r\n height: 28px;\r\n flex: none;\r\n padding: 0;\r\n color: var(--settings-muted);\r\n background: transparent;\r\n border: 0;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-icon-button:hover {\r\n color: var(--settings-text);\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-icon-button:focus-visible,\r\n.settings-nav-button:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 1px;\r\n}\r\n\r\n.settings-page {\r\n display: block;\r\n position: relative;\r\n min-width: 0;\r\n min-height: 0;\r\n overflow-y: auto;\r\n background: var(--settings-bg);\r\n scrollbar-gutter: stable;\r\n}\r\n\r\n.settings-page__content {\r\n width: min(930px, calc(100% - 80px));\r\n margin-inline: auto;\r\n}\r\n\r\n.settings-page__content {\r\n min-width: 0;\r\n padding: 28px 0 36px;\r\n}\r\n\r\n.settings-section-label {\r\n min-height: auto;\r\n margin: 0;\r\n padding: 0 0 18px;\r\n color: var(--settings-text);\r\n font-size: 18px;\r\n font-weight: 600;\r\n line-height: 26px;\r\n}\r\n\r\n.settings-status-list,\r\n.settings-empty {\r\n overflow: hidden;\r\n background: var(--settings-panel);\r\n}\r\n\r\n.settings-status-row {\r\n display: grid;\r\n grid-template-columns: minmax(170px, 1fr) auto minmax(280px, 1.45fr);\r\n position: relative;\r\n align-items: center;\r\n min-height: 72px;\r\n gap: 20px;\r\n padding: 12px 0;\r\n}\r\n\r\n.settings-status-row:not(:last-child)::after {\r\n content: "";\r\n position: absolute;\r\n right: 0;\r\n bottom: 0;\r\n left: 0;\r\n height: 1px;\r\n background: var(--settings-divider);\r\n}\r\n\r\n.settings-status-row__identity {\r\n display: inline-flex;\r\n align-items: center;\r\n min-width: 0;\r\n color: var(--settings-text);\r\n gap: 10px;\r\n font-size: 14px;\r\n font-weight: 500;\r\n line-height: 22px;\r\n}\r\n\r\n.settings-status-row__icon {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 36px;\r\n height: 36px;\r\n flex: none;\r\n color: var(--settings-muted);\r\n background: var(--settings-surface);\r\n border-radius: 50%;\r\n}\r\n\r\n.settings-status-badge {\r\n flex: none;\r\n padding: 3px 8px;\r\n color: var(--settings-muted);\r\n font-size: 11px;\r\n font-weight: 500;\r\n line-height: 18px;\r\n background: var(--settings-surface);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-status-row__detail {\r\n min-width: 0;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n line-height: 20px;\r\n}\r\n\r\n.settings-page-description {\r\n max-width: 760px;\r\n margin: -10px 0 20px;\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-session-import-header {\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: space-between;\r\n gap: 24px;\r\n}\r\n\r\n.settings-session-import-header .settings-section-label {\r\n min-width: 0;\r\n}\r\n\r\n.settings-session-import-harness {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 12px;\r\n margin: -12px 0 16px;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n}\r\n\r\n.settings-session-import-harness > span {\r\n flex: none;\r\n}\r\n\r\n.settings-session-import-harness__options {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n flex: 1;\r\n gap: 6px;\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n scrollbar-width: none;\r\n}\r\n\r\n.settings-session-import-harness__options::-webkit-scrollbar {\r\n display: none;\r\n}\r\n\r\n.settings-session-import-harness__option {\r\n min-height: 32px;\r\n flex: none;\r\n padding: 6px 10px;\r\n color: var(--settings-muted);\r\n font: inherit;\r\n font-size: 12px;\r\n white-space: nowrap;\r\n background: rgb(255 255 255 / 4%);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 6px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-session-import-harness__option[aria-pressed="true"] {\r\n color: var(--settings-text);\r\n background: var(--settings-active);\r\n border-color: rgb(51 156 255 / 50%);\r\n}\r\n\r\n.settings-session-import-harness__option:disabled {\r\n opacity: 0.38;\r\n cursor: not-allowed;\r\n}\r\n\r\n.settings-session-import-harness__option:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 2px;\r\n}\r\n\r\n.settings-session-import-harness + .settings-page-description {\r\n margin-top: 0;\r\n margin-bottom: 4px;\r\n}\r\n\r\n.settings-session-import-availability-note {\r\n margin-top: 0;\r\n}\r\n\r\n.settings-session-import-search,\r\n.settings-session-import-pagination {\r\n display: flex;\r\n flex-wrap: wrap;\r\n align-items: center;\r\n gap: 10px;\r\n margin: 16px 0;\r\n}\r\n\r\n.settings-session-import-search input {\r\n flex: 1;\r\n min-width: 160px;\r\n}\r\n\r\n.settings-session-import-search input,\r\n.settings-session-import-pagination select {\r\n min-height: 36px;\r\n padding: 6px 10px;\r\n color: var(--settings-text);\r\n background: var(--settings-bg);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-session-import-search input:focus-visible,\r\n.settings-session-import-pagination select:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 2px;\r\n}\r\n\r\n.settings-session-import-pagination {\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n}\r\n\r\n.settings-session-import-pagination label {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n}\r\n\r\n.settings-session-import-pagination > span {\r\n flex: 1;\r\n min-width: 130px;\r\n}\r\n\r\n.settings-session-import-pagination__navigation {\r\n display: flex;\r\n gap: 8px;\r\n margin-left: auto;\r\n}\r\n\r\n.settings-session-import-content,\r\n.settings-session-import-list {\r\n display: grid;\r\n gap: 10px;\r\n}\r\n\r\n.settings-session-import-status {\r\n display: flex;\r\n align-items: center;\r\n min-height: 64px;\r\n gap: 12px;\r\n padding: 16px;\r\n color: var(--settings-muted);\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 8px;\r\n}\r\n\r\n.settings-session-import-status.is-error {\r\n color: #ef4444;\r\n}\r\n\r\n.settings-session-import-recovery {\r\n display: grid;\r\n justify-items: start;\r\n gap: 14px;\r\n padding: 16px;\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 8px;\r\n}\r\n\r\n.settings-session-import-recovery:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 2px;\r\n}\r\n\r\n.settings-session-import-recovery__copy {\r\n display: grid;\r\n gap: 4px;\r\n}\r\n\r\n.settings-session-import-recovery__copy strong {\r\n color: var(--settings-text);\r\n font-size: 14px;\r\n}\r\n\r\n.settings-session-import-recovery__copy p {\r\n margin: 0;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n line-height: 20px;\r\n}\r\n\r\n.settings-session-import-recovery__path {\r\n display: flex;\r\n align-items: stretch;\r\n width: 100%;\r\n min-width: 0;\r\n overflow: hidden;\r\n border: 1px solid var(--settings-border);\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-session-import-recovery__path code {\r\n min-width: 0;\r\n flex: 1;\r\n padding: 8px 10px;\r\n overflow-x: auto;\r\n color: var(--settings-text);\r\n font-size: 12px;\r\n line-height: 20px;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-session-import-recovery__path .settings-command-button {\r\n min-height: 0;\r\n flex: none;\r\n border-width: 0 0 0 1px;\r\n border-radius: 0;\r\n}\r\n\r\n.settings-session-import-row {\r\n display: grid;\r\n grid-template-columns: minmax(0, 1fr) auto;\r\n align-items: center;\r\n gap: 20px;\r\n min-width: 0;\r\n padding: 16px;\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 8px;\r\n}\r\n\r\n.settings-session-import-row__copy {\r\n display: grid;\r\n min-width: 0;\r\n gap: 4px;\r\n}\r\n\r\n.settings-session-import-row__copy strong {\r\n overflow: hidden;\r\n color: var(--settings-text);\r\n font-size: 14px;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-session-import-row__copy span,\r\n.settings-session-import-row__cwd {\r\n overflow: hidden;\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 18px;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-session-import-row__cwd {\r\n display: block;\r\n min-width: 0;\r\n background: transparent;\r\n}\r\n\r\n.settings-session-import-row__action {\r\n display: flex;\r\n align-items: flex-end;\r\n flex-direction: column;\r\n gap: 8px;\r\n}\r\n\r\n.settings-session-import-running {\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n}\r\n\r\n.settings-preference-row {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 32px;\r\n min-height: 88px;\r\n padding: 18px 0;\r\n border-top: 1px solid var(--settings-divider);\r\n border-bottom: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-preference-row__copy {\r\n display: flex;\r\n flex: 1 1 auto;\r\n flex-direction: column;\r\n min-width: 0;\r\n gap: 5px;\r\n}\r\n\r\n.settings-preference-row__copy strong {\r\n color: var(--settings-text);\r\n font-size: 15px;\r\n font-weight: 600;\r\n line-height: 22px;\r\n}\r\n\r\n.settings-preference-row__copy span {\r\n max-width: 680px;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n line-height: 20px;\r\n}\r\n\r\n.settings-preference-switch {\r\n display: inline-flex;\r\n align-items: center;\r\n width: 42px;\r\n height: 24px;\r\n flex: none;\r\n padding: 2px;\r\n border: 0;\r\n border-radius: 999px;\r\n background: var(--settings-surface-hover);\r\n cursor: pointer;\r\n transition: background 120ms ease;\r\n}\r\n\r\n.settings-preference-switch[aria-checked="true"] {\r\n justify-content: flex-end;\r\n background: var(--settings-focus);\r\n}\r\n\r\n.settings-preference-switch:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 2px;\r\n}\r\n\r\n.settings-preference-switch__thumb {\r\n width: 20px;\r\n height: 20px;\r\n border-radius: 50%;\r\n background: var(--settings-primary-text);\r\n box-shadow: 0 1px 3px rgb(0 0 0 / 24%);\r\n}\r\n\r\n.settings-connection-page-header {\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: space-between;\r\n gap: 18px;\r\n margin-bottom: 18px;\r\n}\r\n\r\n.settings-connection-page-header .settings-section-label {\r\n padding-bottom: 0;\r\n}\r\n\r\n.settings-connection-page-header .settings-page-description {\r\n margin: 5px 0 0;\r\n}\r\n\r\n.settings-connections-content,\r\n.settings-connections-layout,\r\n.settings-connection-list,\r\n.settings-connection-rows {\r\n min-width: 0;\r\n}\r\n\r\n.settings-connections-layout {\r\n display: grid;\r\n grid-template-columns: minmax(0, 1.55fr) minmax(280px, 0.85fr);\r\n align-items: start;\r\n gap: 18px;\r\n}\r\n\r\n.settings-connection-list,\r\n.settings-connection-inspector {\r\n overflow: hidden;\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 10px;\r\n}\r\n\r\n.settings-connection-host-strip {\r\n display: grid;\r\n grid-template-columns: 30px minmax(0, 1fr) 30px;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 5px;\r\n padding: 9px 10px;\r\n border-bottom: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-connection-host-scroll {\r\n display: none;\r\n align-items: center;\r\n justify-content: center;\r\n width: 30px;\r\n height: 34px;\r\n padding: 0;\r\n color: var(--settings-muted);\r\n background: var(--settings-inset);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-connection-host-strip[data-connection-host-overflow="true"]\r\n .settings-connection-host-scroll {\r\n display: inline-flex;\r\n}\r\n\r\n.settings-connection-host-strip:not([data-connection-host-overflow="true"]) {\r\n grid-template-columns: minmax(0, 1fr);\r\n}\r\n\r\n.settings-connection-host-scroll:hover:not(:disabled) {\r\n color: var(--settings-text);\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-connection-host-scroll:disabled {\r\n cursor: default;\r\n opacity: 0.35;\r\n}\r\n\r\n.settings-connection-host-scroll:focus-visible,\r\n.settings-connection-host-tab:focus-visible,\r\n.settings-connection-row:focus-visible,\r\n.settings-connection-install-link:focus-visible,\r\n.settings-connection-view-error:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 1px;\r\n}\r\n\r\n.settings-connection-host-tabs {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 6px;\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n overscroll-behavior-x: contain;\r\n scrollbar-width: none;\r\n scroll-behavior: smooth;\r\n scroll-snap-type: x proximity;\r\n touch-action: pan-x;\r\n}\r\n\r\n.settings-connection-host-tabs::-webkit-scrollbar {\r\n display: none;\r\n}\r\n\r\n.settings-connection-host-tab {\r\n display: inline-flex;\r\n align-items: center;\r\n height: 30px;\r\n min-width: max-content;\r\n flex: none;\r\n padding: 0 9px;\r\n color: var(--settings-muted);\r\n font: inherit;\r\n font-size: 12px;\r\n line-height: 18px;\r\n white-space: nowrap;\r\n background: var(--settings-inset);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 7px;\r\n cursor: pointer;\r\n scroll-snap-align: start;\r\n}\r\n\r\n.settings-connection-host-tab:hover {\r\n color: var(--settings-text);\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-connection-host-tab[aria-selected="true"] {\r\n color: var(--settings-text);\r\n font-weight: 600;\r\n background: var(--settings-active);\r\n border-color: var(--settings-border);\r\n}\r\n\r\n.settings-connection-table-header,\r\n.settings-connection-row {\r\n display: grid;\r\n grid-template-columns: minmax(160px, 1fr) minmax(92px, auto) 108px;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 10px;\r\n}\r\n\r\n.settings-connection-table-header {\r\n min-height: 30px;\r\n padding: 0 10px;\r\n color: var(--settings-muted);\r\n font-size: 10px;\r\n font-weight: 600;\r\n line-height: 16px;\r\n text-transform: uppercase;\r\n letter-spacing: 0.06em;\r\n background: transparent;\r\n border-bottom: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-connection-row {\r\n min-height: 52px;\r\n padding: 8px 10px;\r\n cursor: pointer;\r\n border-bottom: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-connection-row:last-child {\r\n border-bottom: 0;\r\n}\r\n\r\n.settings-connection-row:hover {\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-connection-row[data-connection-selected="true"] {\r\n background: var(--settings-surface);\r\n}\r\n\r\n.settings-connection-row__identity,\r\n.settings-connection-inspector__identity {\r\n display: inline-flex;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 8px;\r\n color: var(--settings-text);\r\n}\r\n\r\n.settings-connection-row__identity strong,\r\n.settings-connection-inspector__identity strong {\r\n min-width: 0;\r\n overflow-wrap: anywhere;\r\n font-size: 12px;\r\n font-weight: 500;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-connection-row__mark {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 24px;\r\n height: 24px;\r\n flex: none;\r\n color: var(--settings-muted);\r\n font-size: 10px;\r\n font-weight: 700;\r\n background: var(--settings-surface);\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-connection-row__mark--logo {\r\n color: var(--settings-text);\r\n background: transparent;\r\n}\r\n\r\n.settings-connection-row__mark--logo > img,\r\n.settings-connection-row__mark--logo > svg {\r\n display: block;\r\n max-width: 18px;\r\n max-height: 18px;\r\n}\r\n\r\n.settings-connection-row__status {\r\n display: inline-flex;\r\n align-items: center;\r\n width: fit-content;\r\n gap: 5px;\r\n color: var(--settings-muted);\r\n font-size: 11px;\r\n font-weight: 500;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-connection-row__status::before {\r\n width: 6px;\r\n height: 6px;\r\n flex: none;\r\n content: "";\r\n background: currentColor;\r\n border-radius: 50%;\r\n}\r\n\r\n.settings-connection-row__status[data-connection-tone="ready"] {\r\n color: var(--settings-success);\r\n}\r\n\r\n.settings-connection-row__status[data-connection-tone="checking"] {\r\n color: var(--settings-warning);\r\n}\r\n\r\n.settings-connection-row__status[data-connection-tone="setup"] {\r\n color: var(--settings-muted);\r\n}\r\n\r\n.settings-connection-row__status[data-connection-tone="setup"]::before {\r\n background: transparent;\r\n border: 1.5px solid currentColor;\r\n}\r\n\r\n.settings-connection-row__status[data-connection-tone="failed"] {\r\n color: var(--settings-danger);\r\n}\r\n\r\n.settings-connection-row__action {\r\n display: flex;\r\n align-items: center;\r\n justify-content: flex-end;\r\n min-width: 0;\r\n gap: 4px;\r\n}\r\n\r\n.settings-connection-row__handle {\r\n display: inline-flex;\r\n flex: none;\r\n align-items: center;\r\n justify-content: center;\r\n width: 16px;\r\n color: var(--settings-muted);\r\n cursor: grab;\r\n opacity: 0.6;\r\n}\r\n\r\n.settings-connection-row__handle:hover {\r\n opacity: 1;\r\n}\r\n\r\n.settings-connection-row[draggable="true"] {\r\n cursor: grab;\r\n}\r\n\r\n.settings-connection-row[data-connection-dragging="true"] {\r\n opacity: 0.4;\r\n}\r\n\r\n.settings-connection-row[data-connection-drop-indicator="before"] {\r\n box-shadow: inset 0 2px 0 0 var(--settings-focus);\r\n}\r\n\r\n.settings-connection-row[data-connection-drop-indicator="after"] {\r\n box-shadow: inset 0 -2px 0 0 var(--settings-focus);\r\n}\r\n\r\n.settings-connection-row__group-toggle {\r\n display: inline-flex;\r\n flex: none;\r\n align-items: center;\r\n justify-content: center;\r\n width: 26px;\r\n height: 26px;\r\n color: var(--settings-muted);\r\n background: transparent;\r\n border: 0;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-connection-row__group-toggle:hover {\r\n color: var(--settings-text);\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-connection-group-divider {\r\n padding: 10px 12px 6px;\r\n color: var(--settings-muted);\r\n font-size: 10px;\r\n font-weight: 600;\r\n line-height: 16px;\r\n text-transform: uppercase;\r\n letter-spacing: 0.06em;\r\n /* No border-top here: the row immediately above already carries its own\r\n border-bottom (it is no longer :last-child once this divider follows\r\n it), so adding one here would double the separator line. */\r\n}\r\n\r\n.settings-connection-group-more[data-connection-drag-over="true"] {\r\n background: rgb(51 156 255 / 8%);\r\n}\r\n\r\n.settings-connection-group-hint {\r\n display: grid;\r\n gap: 3px;\r\n margin: 0 12px 12px;\r\n padding: 14px 16px;\r\n text-align: center;\r\n border: 1.5px dashed var(--settings-border);\r\n border-radius: 10px;\r\n}\r\n\r\n.settings-connection-group-more[data-connection-drag-over="true"] .settings-connection-group-hint {\r\n border-color: var(--settings-focus);\r\n}\r\n\r\n.settings-connection-group-hint strong {\r\n color: var(--settings-text);\r\n font-size: 12.5px;\r\n font-weight: 500;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-connection-group-hint span {\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 17px;\r\n}\r\n\r\n.settings-connection-group-reset {\r\n display: flex;\r\n width: 100%;\r\n align-items: center;\r\n gap: 6px;\r\n padding: 10px 12px;\r\n color: var(--settings-muted);\r\n font: inherit;\r\n font-size: 12px;\r\n text-align: left;\r\n background: transparent;\r\n border: 0;\r\n border-top: 1px solid var(--settings-divider);\r\n cursor: pointer;\r\n}\r\n\r\n.settings-connection-group-reset:hover {\r\n color: var(--settings-text);\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-connection-install-link {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 26px;\r\n height: 26px;\r\n color: var(--settings-focus);\r\n text-decoration: none;\r\n background: transparent;\r\n border: 1px solid transparent;\r\n border-radius: 7px;\r\n opacity: 0;\r\n transition: opacity 120ms ease;\r\n}\r\n\r\n.settings-connection-row:hover .settings-connection-install-link,\r\n.settings-connection-install-link:focus-visible {\r\n opacity: 1;\r\n}\r\n\r\n.settings-connection-install-link:hover {\r\n color: var(--settings-focus);\r\n background: var(--settings-active);\r\n border-color: var(--settings-border);\r\n}\r\n\r\n.settings-connection-view-error {\r\n padding: 4px 7px;\r\n color: var(--settings-danger);\r\n font: inherit;\r\n font-size: 11px;\r\n line-height: 18px;\r\n background: transparent;\r\n border: 0;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-connection-view-error:hover {\r\n color: var(--settings-danger);\r\n background: var(--settings-danger-bg);\r\n}\r\n\r\n.settings-connection-inspector {\r\n position: sticky;\r\n top: 18px;\r\n}\r\n\r\n.settings-connection-inspector__header {\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: space-between;\r\n min-width: 0;\r\n gap: 10px;\r\n padding: 12px;\r\n border-bottom: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-connection-inspector__body {\r\n display: grid;\r\n min-width: 0;\r\n gap: 12px;\r\n padding: 12px;\r\n}\r\n\r\n.settings-connection-install-callout {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 14px;\r\n padding: 14px;\r\n background: var(--settings-surface);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 10px;\r\n}\r\n\r\n.settings-connection-install-head {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 12px;\r\n min-width: 0;\r\n}\r\n\r\n.settings-connection-install-head > div {\r\n min-width: 0;\r\n flex: 1;\r\n}\r\n\r\n.settings-connection-install-callout__icon {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n flex: none;\r\n color: var(--settings-focus);\r\n background: var(--settings-active);\r\n border-radius: 8px;\r\n}\r\n\r\n.settings-connection-install-callout strong,\r\n.settings-connection-install-head strong,\r\n.settings-connection-error-summary strong,\r\n.settings-connection-state-summary strong {\r\n display: block;\r\n margin: 0 0 4px;\r\n color: var(--settings-text);\r\n font-size: 13px;\r\n font-weight: 600;\r\n line-height: 19px;\r\n}\r\n\r\n.settings-connection-install-callout p,\r\n.settings-connection-install-head p,\r\n.settings-connection-error-summary p,\r\n.settings-connection-state-summary p,\r\n.settings-connection-issue-note {\r\n margin: 0;\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-connection-install-button {\r\n width: 100%;\r\n}\r\n\r\n.settings-connection-error-summary {\r\n padding: 13px 14px;\r\n color: var(--settings-danger);\r\n background: var(--settings-danger-bg);\r\n border: 1px solid var(--settings-danger-border);\r\n border-radius: 10px;\r\n}\r\n\r\n.settings-connection-error-metadata {\r\n display: grid;\r\n gap: 7px;\r\n padding: 12px;\r\n background: var(--settings-inset);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 9px;\r\n}\r\n\r\n.settings-connection-detail-line {\r\n display: grid;\r\n grid-template-columns: 92px minmax(0, 1fr);\r\n gap: 10px;\r\n min-width: 0;\r\n color: var(--settings-muted);\r\n font-size: 10px;\r\n line-height: 16px;\r\n}\r\n\r\n.settings-connection-detail-line code {\r\n min-width: 0;\r\n overflow-wrap: anywhere;\r\n color: var(--settings-text);\r\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\r\n white-space: pre-wrap;\r\n}\r\n\r\n.settings-connection-error-log-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 10px;\r\n}\r\n\r\n.settings-connection-error-log-header strong {\r\n color: var(--settings-text);\r\n font-size: 11px;\r\n font-weight: 600;\r\n}\r\n\r\n.settings-connection-error-log-header .settings-command-button {\r\n min-height: 30px;\r\n padding: 5px 9px;\r\n font-size: 11px;\r\n}\r\n\r\n.settings-connection-stderr {\r\n max-height: 220px;\r\n min-width: 0;\r\n margin: 0;\r\n padding: 11px;\r\n overflow: auto;\r\n color: var(--settings-text);\r\n font:\r\n 10px/16px ui-monospace,\r\n "SFMono-Regular",\r\n Consolas,\r\n "Liberation Mono",\r\n monospace;\r\n white-space: pre-wrap;\r\n overflow-wrap: anywhere;\r\n background: var(--settings-inset);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 9px;\r\n}\r\n\r\n.settings-connection-error-actions {\r\n display: grid;\r\n grid-template-columns: minmax(0, 1fr);\r\n gap: 8px;\r\n}\r\n\r\n.settings-connection-error-actions .settings-command-button {\r\n width: 100%;\r\n}\r\n\r\n.settings-connection-issue-note {\r\n margin-top: -4px;\r\n}\r\n\r\n.settings-connection-state-summary {\r\n padding: 14px;\r\n background: var(--settings-surface);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 10px;\r\n}\r\n\r\n.settings-empty {\r\n display: flex;\r\n align-items: center;\r\n min-height: 72px;\r\n padding: 12px 16px;\r\n}\r\n\r\n.settings-empty > div {\r\n display: grid;\r\n min-width: 0;\r\n gap: 2px;\r\n}\r\n\r\n.settings-empty strong {\r\n color: var(--settings-text);\r\n font-size: 13px;\r\n font-weight: 500;\r\n line-height: 19px;\r\n}\r\n\r\n.settings-empty span {\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n line-height: 19px;\r\n}\r\n\r\n.settings-about-panel {\r\n display: grid;\r\n max-width: 720px;\r\n gap: 18px;\r\n padding: 24px;\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 12px;\r\n}\r\n\r\n.settings-about-product {\r\n color: var(--settings-text);\r\n font-size: 24px;\r\n font-weight: 700;\r\n line-height: 32px;\r\n}\r\n\r\n.settings-about-tagline {\r\n color: var(--settings-text);\r\n font-size: 16px;\r\n font-weight: 600;\r\n line-height: 24px;\r\n}\r\n\r\n.settings-about-version-row {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n margin: 4px 0 8px;\r\n}\r\n\r\n.settings-about-version-badge {\r\n display: inline-flex;\r\n align-items: center;\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: var(--settings-text);\r\n background: var(--settings-surface);\r\n border: 1px solid var(--settings-border);\r\n padding: 4px 10px;\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-about-copy {\r\n display: grid;\r\n max-width: 660px;\r\n gap: 12px;\r\n}\r\n\r\n.settings-about-copy p,\r\n.settings-about-repository p {\r\n margin: 0;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n line-height: 21px;\r\n}\r\n\r\n.settings-about-star-callout {\r\n margin: 2px 0;\r\n color: var(--settings-warning);\r\n font-size: 14px;\r\n font-weight: 600;\r\n line-height: 22px;\r\n}\r\n\r\n.settings-about-repository {\r\n display: grid;\r\n gap: 10px;\r\n padding-top: 18px;\r\n border-top: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-about-repository-link {\r\n display: flex;\r\n align-items: center;\r\n width: fit-content;\r\n min-width: 0;\r\n max-width: 100%;\r\n gap: 8px;\r\n color: var(--settings-focus);\r\n font-size: 13px;\r\n font-weight: 600;\r\n text-decoration: none;\r\n}\r\n\r\n.settings-about-repository-link:hover {\r\n text-decoration: underline;\r\n}\r\n\r\n.settings-about-repository-link code {\r\n min-width: 0;\r\n overflow: hidden;\r\n color: var(--settings-muted);\r\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\r\n font-size: 11px;\r\n font-weight: 400;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-page-error {\r\n padding: 16px;\r\n color: var(--settings-text);\r\n font-size: 13px;\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 20px;\r\n}\r\n\r\n.settings-update-metadata {\r\n display: grid;\r\n grid-template-columns: repeat(3, minmax(0, 1fr));\r\n gap: 24px;\r\n margin-bottom: 24px;\r\n padding: 0 4px 20px;\r\n border-bottom: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-update-metadata__item {\r\n display: grid;\r\n min-width: 0;\r\n gap: 4px;\r\n}\r\n\r\n.settings-update-metadata__item span {\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-update-metadata__item strong {\r\n min-width: 0;\r\n overflow-wrap: anywhere;\r\n color: var(--settings-text);\r\n font-size: 15px;\r\n font-weight: 500;\r\n line-height: 22px;\r\n}\r\n\r\n/* The only emphasis on this screen: a latest version newer than the installed one. */\r\n.settings-update-metadata__value--newer {\r\n color: var(--settings-focus);\r\n}\r\n\r\n.settings-update-panel {\r\n display: grid;\r\n gap: 12px;\r\n padding: 20px;\r\n color: var(--settings-text);\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 8px;\r\n}\r\n\r\n.settings-update-panel__head {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 8px;\r\n}\r\n\r\n.settings-update-panel__head .codexhost-settings-icon {\r\n color: var(--settings-muted);\r\n}\r\n\r\n.settings-update-panel[data-update-state="available"] .codexhost-settings-icon,\r\n.settings-update-panel[data-update-state="downloading"] .codexhost-settings-icon,\r\n.settings-update-panel[data-update-state="installing"] .codexhost-settings-icon,\r\n.settings-update-panel[data-update-state="restarting"] .codexhost-settings-icon {\r\n color: var(--settings-focus);\r\n}\r\n\r\n.settings-update-panel[data-update-state="current"] .codexhost-settings-icon {\r\n color: var(--settings-success);\r\n}\r\n\r\n.settings-update-panel[data-update-state="failed"] .codexhost-settings-icon,\r\n.settings-update-panel[data-update-state="error"] .codexhost-settings-icon {\r\n color: var(--settings-danger);\r\n}\r\n\r\n.settings-update-panel__title {\r\n min-width: 0;\r\n overflow-wrap: anywhere;\r\n color: var(--settings-text);\r\n font-size: 14px;\r\n font-weight: 600;\r\n line-height: 22px;\r\n}\r\n\r\n.settings-update-summary,\r\n.settings-update-error {\r\n margin: 0;\r\n overflow-wrap: anywhere;\r\n font-size: 13px;\r\n line-height: 20px;\r\n}\r\n\r\n.settings-update-summary {\r\n color: var(--settings-muted);\r\n}\r\n\r\n.settings-update-error {\r\n color: var(--settings-danger);\r\n}\r\n\r\n.settings-update-progress {\r\n width: 100%;\r\n height: 8px;\r\n accent-color: var(--settings-focus);\r\n}\r\n\r\n.settings-update-progress-detail {\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 18px;\r\n}\r\n\r\n/* Release notes scroll with the page; a scroller inside a scroller traps the wheel. */\r\n.settings-update-notes-section {\r\n min-width: 0;\r\n margin-top: 24px;\r\n padding-top: 24px;\r\n border-top: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-update-notes-section:empty {\r\n display: none;\r\n}\r\n\r\n.settings-update-notes {\r\n display: grid;\r\n min-width: 0;\r\n gap: 12px;\r\n color: var(--settings-muted);\r\n font-size: 14px;\r\n line-height: 22px;\r\n overflow-wrap: anywhere;\r\n}\r\n\r\n.settings-update-notes > :first-child {\r\n margin-top: 0;\r\n}\r\n\r\n.settings-update-notes > :last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-update-notes h1,\r\n.settings-update-notes h2,\r\n.settings-update-notes h3,\r\n.settings-update-notes h4,\r\n.settings-update-notes h5,\r\n.settings-update-notes h6 {\r\n margin: 6px 0 0;\r\n color: var(--settings-text);\r\n font-weight: 600;\r\n}\r\n\r\n.settings-update-notes h1 {\r\n font-size: 18px;\r\n line-height: 26px;\r\n}\r\n\r\n.settings-update-notes h2 {\r\n font-size: 17px;\r\n line-height: 24px;\r\n}\r\n\r\n.settings-update-notes h3,\r\n.settings-update-notes h4,\r\n.settings-update-notes h5,\r\n.settings-update-notes h6 {\r\n font-size: 14px;\r\n line-height: 22px;\r\n}\r\n\r\n.settings-update-notes p,\r\n.settings-update-notes ul,\r\n.settings-update-notes ol,\r\n.settings-update-notes pre,\r\n.settings-update-notes blockquote {\r\n margin: 0;\r\n}\r\n\r\n.settings-update-notes ul,\r\n.settings-update-notes ol {\r\n padding-left: 24px;\r\n}\r\n\r\n.settings-update-notes li {\r\n padding-left: 4px;\r\n}\r\n\r\n.settings-update-notes li::marker {\r\n color: var(--settings-muted);\r\n font-size: 0.85em;\r\n}\r\n\r\n.settings-update-notes li + li {\r\n margin-top: 14px;\r\n}\r\n\r\n.settings-update-notes .release-note-translation {\r\n display: block;\r\n margin-top: 3px;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n line-height: 20px;\r\n}\r\n\r\n.settings-update-notes blockquote {\r\n padding: 8px 12px;\r\n color: var(--settings-muted);\r\n border-left: 3px solid var(--settings-focus);\r\n background: var(--settings-surface);\r\n}\r\n\r\n.settings-update-notes hr {\r\n width: 100%;\r\n margin: 2px 0;\r\n border: 0;\r\n border-top: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-update-notes strong {\r\n color: var(--settings-text);\r\n font-weight: 600;\r\n}\r\n\r\n.settings-update-notes a {\r\n color: var(--settings-focus);\r\n text-decoration: none;\r\n}\r\n\r\n.settings-update-notes a:hover {\r\n text-decoration: underline;\r\n}\r\n\r\n.settings-update-notes code {\r\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\r\n font-size: 12px;\r\n}\r\n\r\n.settings-update-notes :not(pre) > code {\r\n padding: 1px 5px;\r\n background: var(--settings-surface);\r\n border-radius: 4px;\r\n}\r\n\r\n.settings-update-notes pre {\r\n min-width: 0;\r\n max-width: 100%;\r\n padding: 10px 12px;\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n background: var(--settings-inset);\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-update-notes pre code {\r\n line-height: 18px;\r\n white-space: pre-wrap;\r\n}\r\n\r\n/* Manual update sits directly under the status panel, not behind a disclosure:\r\n automatic updates can fail for machine-local reasons and this is the way out. */\r\n.settings-update-controls {\r\n display: grid;\r\n min-width: 0;\r\n gap: 10px;\r\n margin-top: 24px;\r\n}\r\n\r\n.settings-update-manual-title {\r\n color: var(--settings-text);\r\n font-size: 15px;\r\n font-weight: 600;\r\n line-height: 22px;\r\n}\r\n\r\n.settings-update-manual {\r\n display: grid;\r\n min-width: 0;\r\n gap: 8px;\r\n}\r\n\r\n.settings-update-manual[hidden] {\r\n display: none;\r\n}\r\n\r\n.settings-update-manual-description {\r\n margin: 0;\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-update-manual-description.is-fallback {\r\n color: var(--settings-danger);\r\n}\r\n\r\n.settings-update-command {\r\n display: flex;\r\n align-items: stretch;\r\n min-width: 0;\r\n overflow: hidden;\r\n border: 1px solid var(--settings-border);\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-update-command code {\r\n min-width: 0;\r\n flex: 1;\r\n padding: 9px 12px;\r\n overflow-x: auto;\r\n color: var(--settings-text);\r\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\r\n font-size: 12px;\r\n line-height: 20px;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-update-command__copy {\r\n display: inline-flex;\r\n align-items: center;\r\n flex: none;\r\n gap: 6px;\r\n padding: 0 12px;\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n background: transparent;\r\n border: 0;\r\n border-left: 1px solid var(--settings-border);\r\n cursor: pointer;\r\n}\r\n\r\n.settings-update-command__copy:hover {\r\n color: var(--settings-text);\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-update-command__copy:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: -2px;\r\n}\r\n\r\n.settings-update-actions {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 12px;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.settings-command-button,\r\n.settings-update-link {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex: none;\r\n width: max-content;\r\n max-width: 100%;\r\n min-height: 30px;\r\n gap: 6px;\r\n padding: 5px 10px;\r\n white-space: nowrap;\r\n color: var(--settings-primary-text);\r\n font: inherit;\r\n font-size: 12px;\r\n text-decoration: none;\r\n background: var(--settings-primary);\r\n border: 1px solid var(--settings-primary);\r\n border-radius: 7px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-command-button--secondary,\r\n.settings-update-link {\r\n color: var(--settings-text);\r\n background: var(--settings-panel);\r\n border-color: var(--settings-border);\r\n}\r\n\r\n.settings-command-button:hover:not(:disabled) {\r\n background: var(--settings-primary-hover);\r\n border-color: var(--settings-primary-hover);\r\n}\r\n\r\n.settings-command-button--secondary:hover:not(:disabled),\r\n.settings-update-link:hover {\r\n background: var(--settings-hover);\r\n border-color: var(--settings-border);\r\n}\r\n\r\n.settings-command-button--danger {\r\n color: #f87171;\r\n}\r\n\r\n.settings-command-button--danger:hover:not(:disabled) {\r\n color: #fecaca;\r\n background: rgb(127 29 29 / 24%);\r\n border-color: rgb(248 113 113 / 45%);\r\n}\r\n\r\n.settings-command-button:disabled {\r\n cursor: default;\r\n opacity: 0.45;\r\n}\r\n\r\n.settings-command-button:disabled,\r\n.settings-command-button[aria-disabled="true"] {\r\n opacity: 0.55;\r\n cursor: not-allowed;\r\n filter: none;\r\n}\r\n\r\n.settings-command-button:focus-visible,\r\n.settings-update-link:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 2px;\r\n}\r\n\r\n.codexhost-settings-icon {\r\n display: block;\r\n flex: none;\r\n stroke: currentColor;\r\n}\r\n\r\n@media (max-width: 720px) {\r\n .codexhost-settings-dialog {\r\n width: calc(100vw - 16px);\r\n height: calc(100vh - 16px);\r\n border-radius: 10px;\r\n }\r\n\r\n .settings-layout {\r\n grid-template-columns: minmax(0, 1fr);\r\n grid-template-rows: auto minmax(0, 1fr);\r\n }\r\n\r\n .settings-session-import-row {\r\n grid-template-columns: minmax(0, 1fr);\r\n }\r\n\r\n .settings-session-import-row__action {\r\n align-items: flex-start;\r\n }\r\n\r\n .settings-sidebar {\r\n border-right: 0;\r\n border-bottom: 1px solid var(--settings-border);\r\n }\r\n\r\n .settings-header {\r\n height: 56px;\r\n padding-inline: 14px;\r\n }\r\n\r\n .settings-sidebar {\r\n padding-top: 20px;\r\n }\r\n\r\n .settings-nav {\r\n flex: none;\r\n flex-direction: row;\r\n gap: 4px;\r\n padding: 7px 8px 8px;\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n }\r\n\r\n .settings-nav-section-label {\r\n display: none;\r\n }\r\n\r\n .settings-nav-button {\r\n width: auto;\r\n min-width: max-content;\r\n min-height: 34px;\r\n grid-template-columns: 16px auto;\r\n border-radius: 10px;\r\n }\r\n\r\n .settings-nav-star-link {\r\n margin-top: 0;\r\n }\r\n\r\n .settings-page__content {\r\n width: calc(100% - 40px);\r\n }\r\n\r\n .settings-page__content {\r\n padding-top: 32px;\r\n padding-bottom: 32px;\r\n }\r\n\r\n .settings-section-label {\r\n padding-bottom: 20px;\r\n font-size: 20px;\r\n line-height: 26px;\r\n }\r\n\r\n .settings-update-metadata {\r\n grid-template-columns: minmax(0, 1fr);\r\n gap: 16px;\r\n }\r\n\r\n .settings-status-row {\r\n grid-template-columns: minmax(0, 1fr) auto;\r\n gap: 16px;\r\n }\r\n\r\n .settings-account-header,\r\n .settings-connection-page-header {\r\n flex-direction: column;\r\n }\r\n\r\n .settings-account-header > .settings-command-button,\r\n .settings-connection-page-header > .settings-command-button {\r\n width: 100%;\r\n }\r\n\r\n .settings-connections-layout {\r\n grid-template-columns: minmax(0, 1fr);\r\n }\r\n\r\n .settings-connection-inspector {\r\n position: static;\r\n }\r\n\r\n .settings-status-row__detail {\r\n grid-column: 1 / -1;\r\n margin: -8px 0 0 58px;\r\n }\r\n}\r\n\r\n@media (forced-colors: active) {\r\n :host {\r\n --settings-bg: Canvas;\r\n --settings-sidebar: Canvas;\r\n --settings-panel: Canvas;\r\n --settings-surface: Canvas;\r\n --settings-surface-hover: Highlight;\r\n --settings-inset: Canvas;\r\n --settings-text: CanvasText;\r\n --settings-muted: GrayText;\r\n --settings-subtle: GrayText;\r\n --settings-border: ButtonBorder;\r\n --settings-divider: ButtonBorder;\r\n --settings-hover: Highlight;\r\n --settings-active: Highlight;\r\n --settings-focus: Highlight;\r\n --settings-primary: ButtonFace;\r\n --settings-primary-hover: Highlight;\r\n --settings-primary-text: ButtonText;\r\n --settings-warning: CanvasText;\r\n --settings-warning-bg: Canvas;\r\n --settings-warning-border: ButtonBorder;\r\n --settings-danger: CanvasText;\r\n --settings-danger-bg: Canvas;\r\n --settings-danger-border: ButtonBorder;\r\n --settings-success: CanvasText;\r\n }\r\n}\r\n\r\n@media (prefers-reduced-motion: reduce) {\r\n *,\r\n *::before,\r\n *::after {\r\n scroll-behavior: auto !important;\r\n transition-duration: 0s !important;\r\n }\r\n}\r\n\r\n/* Harness Mix: Model Configuration & One-click Install */\r\n.settings-model-config-panel {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n padding: 14px;\r\n margin-top: 14px;\r\n border-radius: 8px;\r\n background: var(--settings-surface);\r\n border: 1px solid var(--settings-border);\r\n}\r\n\r\n.settings-model-config-head {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n}\r\n\r\n.settings-model-config-title {\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: var(--settings-text);\r\n}\r\n\r\n.settings-model-config-description {\r\n font-size: 11px;\r\n color: var(--settings-muted);\r\n margin: 0;\r\n}\r\n\r\n.settings-model-config-loading,\r\n.settings-model-config-empty {\r\n font-size: 12px;\r\n color: var(--settings-muted);\r\n padding: 8px 0;\r\n}\r\n\r\n.settings-model-config-form {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n margin-top: 4px;\r\n}\r\n\r\n.settings-model-config-field {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 6px;\r\n}\r\n\r\n.settings-model-config-label {\r\n font-size: 11px;\r\n font-weight: 600;\r\n color: var(--settings-muted);\r\n text-transform: uppercase;\r\n letter-spacing: 0.5px;\r\n}\r\n\r\n.settings-model-config-select {\r\n height: 32px;\r\n padding: 0 10px;\r\n border-radius: 6px;\r\n border: 1px solid var(--settings-border);\r\n background: var(--settings-panel);\r\n color: var(--settings-text);\r\n font-size: 12px;\r\n outline: none;\r\n}\r\n\r\n.settings-model-config-select:focus {\r\n border-color: var(--settings-primary);\r\n}\r\n\r\n.settings-model-config-actions {\r\n display: flex;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n margin-top: 6px;\r\n}\r\n\r\n.settings-model-config-feedback {\r\n font-size: 12px;\r\n font-weight: 500;\r\n}\r\n\r\n.settings-feedback-success {\r\n color: var(--settings-success);\r\n}\r\n\r\n.settings-feedback-error {\r\n color: var(--settings-danger);\r\n}\r\n\r\n.settings-feedback-info {\r\n color: var(--settings-primary);\r\n}\r\n\r\n.settings-install-command-box {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 6px;\r\n min-width: 0;\r\n margin: 0;\r\n}\r\n\r\n.settings-install-command-label {\r\n font-size: 11px;\r\n font-weight: 600;\r\n color: var(--settings-muted);\r\n}\r\n\r\n.settings-install-command-row {\r\n display: flex;\r\n align-items: center;\r\n background: var(--settings-inset);\r\n padding: 8px 12px;\r\n border-radius: 6px;\r\n border: 1px solid var(--settings-border);\r\n min-width: 0;\r\n overflow-x: auto;\r\n}\r\n\r\n.settings-install-command-row code {\r\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\r\n font-size: 12px;\r\n line-height: 18px;\r\n color: var(--settings-text);\r\n user-select: all;\r\n white-space: pre-wrap;\r\n word-break: break-all;\r\n}\r\n\r\n.settings-install-actions {\r\n display: grid;\r\n grid-template-columns: minmax(0, 1fr);\r\n gap: 8px;\r\n margin-top: 4px;\r\n}\r\n\r\n.settings-install-actions .settings-command-button {\r\n width: 100%;\r\n justify-content: center;\r\n}\r\n\r\n.settings-install-feedback {\r\n font-size: 12px;\r\n font-weight: 500;\r\n line-height: 18px;\r\n margin-top: 2px;\r\n overflow-wrap: anywhere;\r\n}\r\n\r\n.settings-install-manual-card {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n background: var(--settings-inset);\r\n padding: 12px 14px;\r\n border-radius: 8px;\r\n border: 1px solid var(--settings-border);\r\n margin-top: 6px;\r\n margin-bottom: 4px;\r\n}\r\n\r\n.settings-install-manual-badge {\r\n display: inline-flex;\r\n align-items: center;\r\n font-size: 11px;\r\n font-weight: 600;\r\n color: var(--settings-accent, #10a37f);\r\n background: var(--settings-accent-subtle, rgba(16, 163, 127, 0.1));\r\n padding: 2px 8px;\r\n border-radius: 4px;\r\n width: fit-content;\r\n}\r\n\r\n.settings-install-manual-notice {\r\n font-size: 12px;\r\n line-height: 18px;\r\n color: var(--settings-text);\r\n margin: 0;\r\n}\r\n\r\n.settings-install-steps {\r\n margin: 0;\r\n padding-left: 18px;\r\n font-size: 12px;\r\n line-height: 20px;\r\n color: var(--settings-muted);\r\n}\r\n\r\n.settings-install-steps li {\r\n margin-bottom: 2px;\r\n}\r\n';
28937
+ var shell_default = ':host {\r\n --settings-bg: light-dark(#ffffff, #202020);\r\n --settings-sidebar: light-dark(#f7f7f8, #191919);\r\n --settings-panel: light-dark(#ffffff, #232323);\r\n --settings-surface: light-dark(#f6f6f6, #292929);\r\n --settings-surface-hover: light-dark(#eeeeee, #303030);\r\n --settings-inset: light-dark(#f3f3f3, #161616);\r\n --settings-text: light-dark(#0d0d0d, #ececec);\r\n --settings-muted: light-dark(#676767, #a3a3a3);\r\n --settings-subtle: light-dark(#8a8a8a, #777777);\r\n --settings-border: light-dark(rgb(13 13 13 / 9%), rgb(255 255 255 / 9%));\r\n --settings-divider: light-dark(rgb(13 13 13 / 7%), rgb(255 255 255 / 7%));\r\n --settings-hover: light-dark(rgb(13 13 13 / 5%), rgb(255 255 255 / 7%));\r\n --settings-active: light-dark(rgb(13 13 13 / 7%), rgb(255 255 255 / 9%));\r\n --settings-focus: light-dark(#0b75d1, #66aaf9);\r\n --settings-primary: light-dark(#171717, #f4f4f4);\r\n --settings-primary-hover: light-dark(#2f2f2f, #ffffff);\r\n --settings-primary-text: light-dark(#ffffff, #171717);\r\n --settings-warning: light-dark(#8a5500, #f5c96a);\r\n --settings-warning-bg: light-dark(#fff8e6, rgb(245 201 106 / 8%));\r\n --settings-warning-border: light-dark(#ead8a8, rgb(245 201 106 / 24%));\r\n --settings-danger: light-dark(#b42318, #f87171);\r\n --settings-danger-bg: light-dark(#fff1f0, rgb(239 68 68 / 8%));\r\n --settings-danger-border: light-dark(#f3c7c3, rgb(239 68 68 / 22%));\r\n --settings-success: light-dark(#16784a, #4ade80);\r\n color: var(--settings-text);\r\n color-scheme: inherit;\r\n font:\r\n 13px/1.5 system-ui,\r\n -apple-system,\r\n BlinkMacSystemFont,\r\n "Segoe UI",\r\n sans-serif;\r\n letter-spacing: 0;\r\n}\r\n\r\n*,\r\n*::before,\r\n*::after {\r\n box-sizing: border-box;\r\n letter-spacing: 0;\r\n}\r\n\r\nbutton,\r\ninput,\r\nselect {\r\n font: inherit;\r\n}\r\n\r\nbutton {\r\n color: inherit;\r\n}\r\n\r\n[hidden] {\r\n display: none !important;\r\n}\r\n\r\n.settings-visually-hidden {\r\n position: absolute;\r\n width: 1px;\r\n height: 1px;\r\n padding: 0;\r\n margin: -1px;\r\n overflow: hidden;\r\n clip-path: inset(50%);\r\n white-space: nowrap;\r\n border: 0;\r\n}\r\n\r\n.codexhost-settings-dialog {\r\n width: min(1120px, calc(100vw - 32px));\r\n height: min(780px, calc(100vh - 32px));\r\n max-width: none;\r\n max-height: none;\r\n margin: auto;\r\n padding: 0;\r\n overflow: hidden;\r\n color: var(--settings-text);\r\n background: var(--settings-bg);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 14px;\r\n box-shadow: light-dark(0 16px 42px rgb(0 0 0 / 16%), 0 20px 54px rgb(0 0 0 / 42%));\r\n}\r\n\r\n.codexhost-settings-dialog::backdrop {\r\n background: light-dark(rgb(0 0 0 / 24%), rgb(0 0 0 / 56%));\r\n backdrop-filter: blur(1px);\r\n}\r\n\r\n.settings-frame,\r\n.settings-layout {\r\n width: 100%;\r\n height: 100%;\r\n min-width: 0;\r\n min-height: 0;\r\n}\r\n\r\n.settings-frame {\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.settings-layout {\r\n flex: 1;\r\n display: grid;\r\n grid-template-columns: 184px minmax(0, 1fr);\r\n background: var(--settings-bg);\r\n}\r\n\r\n.settings-sidebar {\r\n display: flex;\r\n min-width: 0;\r\n min-height: 0;\r\n flex-direction: column;\r\n overflow: hidden;\r\n background: var(--settings-sidebar);\r\n border-right: 1px solid var(--settings-border);\r\n padding-top: 14px;\r\n}\r\n\r\n.settings-header {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n height: 48px;\r\n flex: none;\r\n padding: 0 12px;\r\n border-bottom: 1px solid var(--settings-border);\r\n}\r\n\r\n.settings-header-actions {\r\n display: flex;\r\n align-items: center;\r\n flex: none;\r\n gap: 12px;\r\n margin-left: auto;\r\n}\r\n\r\n.settings-brand {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 7px;\r\n}\r\n\r\n.settings-brand__mark {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 26px;\r\n height: 26px;\r\n flex: none;\r\n color: var(--settings-text);\r\n}\r\n\r\n.settings-brand__mark .codexhost-settings-icon {\r\n width: 24px;\r\n height: 24px;\r\n object-fit: contain;\r\n}\r\n\r\n.settings-brand__copy {\r\n display: flex;\r\n min-width: 0;\r\n align-items: baseline;\r\n gap: 0;\r\n line-height: 20px;\r\n}\r\n\r\n.settings-brand__name {\r\n overflow: hidden;\r\n color: var(--settings-text);\r\n font-size: 13px;\r\n font-weight: 600;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-brand__title {\r\n margin-left: 8px;\r\n padding-left: 8px;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n font-weight: 400;\r\n border-left: 1px solid var(--settings-border);\r\n}\r\n\r\n.settings-nav {\r\n display: flex;\r\n min-width: 0;\r\n min-height: 0;\r\n flex: 1;\r\n flex-direction: column;\r\n gap: 2px;\r\n padding: 0 7px 10px;\r\n overflow-y: auto;\r\n}\r\n\r\n.settings-nav-section-label {\r\n min-height: 24px;\r\n padding: 4px 9px 2px;\r\n color: var(--settings-subtle);\r\n font-size: 11px;\r\n font-weight: 600;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-nav-section-label:not(:first-child) {\r\n margin-top: 8px;\r\n}\r\n\r\n.settings-nav-button {\r\n display: grid;\r\n grid-template-columns: 16px minmax(0, 1fr);\r\n align-items: center;\r\n width: 100%;\r\n position: relative;\r\n min-height: 34px;\r\n flex: none;\r\n gap: 9px;\r\n padding: 6px 9px;\r\n color: var(--settings-text);\r\n font-size: 13px;\r\n line-height: 20px;\r\n text-align: left;\r\n background: transparent;\r\n border: 0;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-nav-button .codexhost-settings-icon {\r\n width: 16px;\r\n height: 16px;\r\n opacity: 0.9;\r\n}\r\n\r\n.settings-nav-button:hover {\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-nav-button[aria-current="page"] {\r\n background: var(--settings-active);\r\n color: var(--settings-text);\r\n font-weight: 500;\r\n}\r\n\r\n.settings-nav-button span {\r\n min-width: 0;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-nav-star-link {\r\n margin-top: 0;\r\n color: var(--settings-text);\r\n text-decoration: none;\r\n}\r\n\r\n.settings-nav-star-link .codexhost-settings-icon {\r\n color: var(--settings-warning);\r\n}\r\n\r\n.settings-nav-star-link:hover {\r\n color: var(--settings-warning);\r\n background: var(--settings-warning-bg);\r\n}\r\n\r\n.settings-icon-button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 28px;\r\n height: 28px;\r\n flex: none;\r\n padding: 0;\r\n color: var(--settings-muted);\r\n background: transparent;\r\n border: 0;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-icon-button:hover {\r\n color: var(--settings-text);\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-icon-button:focus-visible,\r\n.settings-nav-button:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 1px;\r\n}\r\n\r\n.settings-page {\r\n display: block;\r\n position: relative;\r\n min-width: 0;\r\n min-height: 0;\r\n overflow-y: auto;\r\n background: var(--settings-bg);\r\n scrollbar-gutter: stable;\r\n}\r\n\r\n.settings-page__content {\r\n width: min(930px, calc(100% - 80px));\r\n margin-inline: auto;\r\n}\r\n\r\n.settings-page__content {\r\n min-width: 0;\r\n padding: 28px 0 36px;\r\n}\r\n\r\n.settings-section-label {\r\n min-height: auto;\r\n margin: 0;\r\n padding: 0 0 18px;\r\n color: var(--settings-text);\r\n font-size: 18px;\r\n font-weight: 600;\r\n line-height: 26px;\r\n}\r\n\r\n.settings-status-list,\r\n.settings-empty {\r\n overflow: hidden;\r\n background: var(--settings-panel);\r\n}\r\n\r\n.settings-status-row {\r\n display: grid;\r\n grid-template-columns: minmax(170px, 1fr) auto minmax(280px, 1.45fr);\r\n position: relative;\r\n align-items: center;\r\n min-height: 72px;\r\n gap: 20px;\r\n padding: 12px 0;\r\n}\r\n\r\n.settings-status-row:not(:last-child)::after {\r\n content: "";\r\n position: absolute;\r\n right: 0;\r\n bottom: 0;\r\n left: 0;\r\n height: 1px;\r\n background: var(--settings-divider);\r\n}\r\n\r\n.settings-status-row__identity {\r\n display: inline-flex;\r\n align-items: center;\r\n min-width: 0;\r\n color: var(--settings-text);\r\n gap: 10px;\r\n font-size: 14px;\r\n font-weight: 500;\r\n line-height: 22px;\r\n}\r\n\r\n.settings-status-row__icon {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 36px;\r\n height: 36px;\r\n flex: none;\r\n color: var(--settings-muted);\r\n background: var(--settings-surface);\r\n border-radius: 50%;\r\n}\r\n\r\n.settings-status-badge {\r\n flex: none;\r\n padding: 3px 8px;\r\n color: var(--settings-muted);\r\n font-size: 11px;\r\n font-weight: 500;\r\n line-height: 18px;\r\n background: var(--settings-surface);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-status-row__detail {\r\n min-width: 0;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n line-height: 20px;\r\n}\r\n\r\n.settings-page-description {\r\n max-width: 760px;\r\n margin: -10px 0 20px;\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-session-import-header {\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: space-between;\r\n gap: 24px;\r\n}\r\n\r\n.settings-session-import-header .settings-section-label {\r\n min-width: 0;\r\n}\r\n\r\n.settings-session-import-harness {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 12px;\r\n margin: -12px 0 16px;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n}\r\n\r\n.settings-session-import-harness > span {\r\n flex: none;\r\n}\r\n\r\n.settings-session-import-harness__options {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n flex: 1;\r\n gap: 6px;\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n scrollbar-width: none;\r\n}\r\n\r\n.settings-session-import-harness__options::-webkit-scrollbar {\r\n display: none;\r\n}\r\n\r\n.settings-session-import-harness__option {\r\n min-height: 32px;\r\n flex: none;\r\n padding: 6px 10px;\r\n color: var(--settings-muted);\r\n font: inherit;\r\n font-size: 12px;\r\n white-space: nowrap;\r\n background: rgb(255 255 255 / 4%);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 6px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-session-import-harness__option[aria-pressed="true"] {\r\n color: var(--settings-text);\r\n background: var(--settings-active);\r\n border-color: rgb(51 156 255 / 50%);\r\n}\r\n\r\n.settings-session-import-harness__option:disabled {\r\n opacity: 0.38;\r\n cursor: not-allowed;\r\n}\r\n\r\n.settings-session-import-harness__option:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 2px;\r\n}\r\n\r\n.settings-session-import-harness + .settings-page-description {\r\n margin-top: 0;\r\n margin-bottom: 4px;\r\n}\r\n\r\n.settings-session-import-availability-note {\r\n margin-top: 0;\r\n}\r\n\r\n.settings-session-import-search,\r\n.settings-session-import-pagination {\r\n display: flex;\r\n flex-wrap: wrap;\r\n align-items: center;\r\n gap: 10px;\r\n margin: 16px 0;\r\n}\r\n\r\n.settings-session-import-search input {\r\n flex: 1;\r\n min-width: 160px;\r\n}\r\n\r\n.settings-session-import-search input,\r\n.settings-session-import-pagination select {\r\n min-height: 36px;\r\n padding: 6px 10px;\r\n color: var(--settings-text);\r\n background: var(--settings-bg);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-session-import-search input:focus-visible,\r\n.settings-session-import-pagination select:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 2px;\r\n}\r\n\r\n.settings-session-import-pagination {\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n}\r\n\r\n.settings-session-import-pagination label {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n}\r\n\r\n.settings-session-import-pagination > span {\r\n flex: 1;\r\n min-width: 130px;\r\n}\r\n\r\n.settings-session-import-pagination__navigation {\r\n display: flex;\r\n gap: 8px;\r\n margin-left: auto;\r\n}\r\n\r\n.settings-session-import-content,\r\n.settings-session-import-list {\r\n display: grid;\r\n gap: 10px;\r\n}\r\n\r\n.settings-session-import-status {\r\n display: flex;\r\n align-items: center;\r\n min-height: 64px;\r\n gap: 12px;\r\n padding: 16px;\r\n color: var(--settings-muted);\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 8px;\r\n}\r\n\r\n.settings-session-import-status.is-error {\r\n color: #ef4444;\r\n}\r\n\r\n.settings-session-import-recovery {\r\n display: grid;\r\n justify-items: start;\r\n gap: 14px;\r\n padding: 16px;\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 8px;\r\n}\r\n\r\n.settings-session-import-recovery:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 2px;\r\n}\r\n\r\n.settings-session-import-recovery__copy {\r\n display: grid;\r\n gap: 4px;\r\n}\r\n\r\n.settings-session-import-recovery__copy strong {\r\n color: var(--settings-text);\r\n font-size: 14px;\r\n}\r\n\r\n.settings-session-import-recovery__copy p {\r\n margin: 0;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n line-height: 20px;\r\n}\r\n\r\n.settings-session-import-recovery__path {\r\n display: flex;\r\n align-items: stretch;\r\n width: 100%;\r\n min-width: 0;\r\n overflow: hidden;\r\n border: 1px solid var(--settings-border);\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-session-import-recovery__path code {\r\n min-width: 0;\r\n flex: 1;\r\n padding: 8px 10px;\r\n overflow-x: auto;\r\n color: var(--settings-text);\r\n font-size: 12px;\r\n line-height: 20px;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-session-import-recovery__path .settings-command-button {\r\n min-height: 0;\r\n flex: none;\r\n border-width: 0 0 0 1px;\r\n border-radius: 0;\r\n}\r\n\r\n.settings-session-import-row {\r\n display: grid;\r\n grid-template-columns: minmax(0, 1fr) auto;\r\n align-items: center;\r\n gap: 20px;\r\n min-width: 0;\r\n padding: 16px;\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 8px;\r\n}\r\n\r\n.settings-session-import-row__copy {\r\n display: grid;\r\n min-width: 0;\r\n gap: 4px;\r\n}\r\n\r\n.settings-session-import-row__copy strong {\r\n overflow: hidden;\r\n color: var(--settings-text);\r\n font-size: 14px;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-session-import-row__copy span,\r\n.settings-session-import-row__cwd {\r\n overflow: hidden;\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 18px;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-session-import-row__cwd {\r\n display: block;\r\n min-width: 0;\r\n background: transparent;\r\n}\r\n\r\n.settings-session-import-row__action {\r\n display: flex;\r\n align-items: flex-end;\r\n flex-direction: column;\r\n gap: 8px;\r\n}\r\n\r\n.settings-session-import-running {\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n}\r\n\r\n.settings-preference-row {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 32px;\r\n min-height: 88px;\r\n padding: 18px 0;\r\n border-top: 1px solid var(--settings-divider);\r\n border-bottom: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-preference-row__copy {\r\n display: flex;\r\n flex: 1 1 auto;\r\n flex-direction: column;\r\n min-width: 0;\r\n gap: 5px;\r\n}\r\n\r\n.settings-preference-row__copy strong {\r\n color: var(--settings-text);\r\n font-size: 15px;\r\n font-weight: 600;\r\n line-height: 22px;\r\n}\r\n\r\n.settings-preference-row__copy span {\r\n max-width: 680px;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n line-height: 20px;\r\n}\r\n\r\n.settings-preference-switch {\r\n display: inline-flex;\r\n align-items: center;\r\n width: 42px;\r\n height: 24px;\r\n flex: none;\r\n padding: 2px;\r\n border: 0;\r\n border-radius: 999px;\r\n background: var(--settings-surface-hover);\r\n cursor: pointer;\r\n transition: background 120ms ease;\r\n}\r\n\r\n.settings-preference-switch[aria-checked="true"] {\r\n justify-content: flex-end;\r\n background: var(--settings-focus);\r\n}\r\n\r\n.settings-preference-switch:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 2px;\r\n}\r\n\r\n.settings-preference-switch__thumb {\r\n width: 20px;\r\n height: 20px;\r\n border-radius: 50%;\r\n background: var(--settings-primary-text);\r\n box-shadow: 0 1px 3px rgb(0 0 0 / 24%);\r\n}\r\n\r\n.settings-connection-page-header {\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: space-between;\r\n gap: 18px;\r\n margin-bottom: 18px;\r\n}\r\n\r\n.settings-connection-page-header .settings-section-label {\r\n padding-bottom: 0;\r\n}\r\n\r\n.settings-connection-page-header .settings-page-description {\r\n margin: 5px 0 0;\r\n}\r\n\r\n.settings-connections-content,\r\n.settings-connections-layout,\r\n.settings-connection-list,\r\n.settings-connection-rows {\r\n min-width: 0;\r\n}\r\n\r\n.settings-connections-layout {\r\n display: grid;\r\n grid-template-columns: minmax(0, 1.55fr) minmax(280px, 0.85fr);\r\n align-items: start;\r\n gap: 18px;\r\n}\r\n\r\n.settings-connection-list,\r\n.settings-connection-inspector {\r\n overflow: hidden;\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 10px;\r\n}\r\n\r\n.settings-connection-host-strip {\r\n display: grid;\r\n grid-template-columns: 30px minmax(0, 1fr) 30px;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 5px;\r\n padding: 9px 10px;\r\n border-bottom: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-connection-host-scroll {\r\n display: none;\r\n align-items: center;\r\n justify-content: center;\r\n width: 30px;\r\n height: 34px;\r\n padding: 0;\r\n color: var(--settings-muted);\r\n background: var(--settings-inset);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 8px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-connection-host-strip[data-connection-host-overflow="true"]\r\n .settings-connection-host-scroll {\r\n display: inline-flex;\r\n}\r\n\r\n.settings-connection-host-strip:not([data-connection-host-overflow="true"]) {\r\n grid-template-columns: minmax(0, 1fr);\r\n}\r\n\r\n.settings-connection-host-scroll:hover:not(:disabled) {\r\n color: var(--settings-text);\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-connection-host-scroll:disabled {\r\n cursor: default;\r\n opacity: 0.35;\r\n}\r\n\r\n.settings-connection-host-scroll:focus-visible,\r\n.settings-connection-host-tab:focus-visible,\r\n.settings-connection-row:focus-visible,\r\n.settings-connection-install-link:focus-visible,\r\n.settings-connection-view-error:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 1px;\r\n}\r\n\r\n.settings-connection-host-tabs {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 6px;\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n overscroll-behavior-x: contain;\r\n scrollbar-width: none;\r\n scroll-behavior: smooth;\r\n scroll-snap-type: x proximity;\r\n touch-action: pan-x;\r\n}\r\n\r\n.settings-connection-host-tabs::-webkit-scrollbar {\r\n display: none;\r\n}\r\n\r\n.settings-connection-host-tab {\r\n display: inline-flex;\r\n align-items: center;\r\n height: 30px;\r\n min-width: max-content;\r\n flex: none;\r\n padding: 0 9px;\r\n color: var(--settings-muted);\r\n font: inherit;\r\n font-size: 12px;\r\n line-height: 18px;\r\n white-space: nowrap;\r\n background: var(--settings-inset);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 7px;\r\n cursor: pointer;\r\n scroll-snap-align: start;\r\n}\r\n\r\n.settings-connection-host-tab:hover {\r\n color: var(--settings-text);\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-connection-host-tab[aria-selected="true"] {\r\n color: var(--settings-text);\r\n font-weight: 600;\r\n background: var(--settings-active);\r\n border-color: var(--settings-border);\r\n}\r\n\r\n.settings-connection-table-header,\r\n.settings-connection-row {\r\n display: grid;\r\n grid-template-columns: minmax(160px, 1fr) minmax(92px, auto) 108px;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 10px;\r\n}\r\n\r\n.settings-connection-table-header {\r\n min-height: 30px;\r\n padding: 0 10px;\r\n color: var(--settings-muted);\r\n font-size: 10px;\r\n font-weight: 600;\r\n line-height: 16px;\r\n text-transform: uppercase;\r\n letter-spacing: 0.06em;\r\n background: transparent;\r\n border-bottom: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-connection-row {\r\n min-height: 52px;\r\n padding: 8px 10px;\r\n cursor: pointer;\r\n border-bottom: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-connection-row:last-child {\r\n border-bottom: 0;\r\n}\r\n\r\n.settings-connection-row:hover {\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-connection-row[data-connection-selected="true"] {\r\n background: var(--settings-surface);\r\n}\r\n\r\n.settings-connection-row__identity,\r\n.settings-connection-inspector__identity {\r\n display: inline-flex;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 8px;\r\n color: var(--settings-text);\r\n}\r\n\r\n.settings-connection-row__identity strong,\r\n.settings-connection-inspector__identity strong {\r\n min-width: 0;\r\n overflow-wrap: anywhere;\r\n font-size: 12px;\r\n font-weight: 500;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-connection-row__mark {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 24px;\r\n height: 24px;\r\n flex: none;\r\n color: var(--settings-muted);\r\n font-size: 10px;\r\n font-weight: 700;\r\n background: var(--settings-surface);\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-connection-row__mark--logo {\r\n color: var(--settings-text);\r\n background: transparent;\r\n}\r\n\r\n.settings-connection-row__mark--logo > img,\r\n.settings-connection-row__mark--logo > svg {\r\n display: block;\r\n max-width: 18px;\r\n max-height: 18px;\r\n}\r\n\r\n.settings-connection-row__status {\r\n display: inline-flex;\r\n align-items: center;\r\n width: fit-content;\r\n gap: 5px;\r\n color: var(--settings-muted);\r\n font-size: 11px;\r\n font-weight: 500;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-connection-row__status::before {\r\n width: 6px;\r\n height: 6px;\r\n flex: none;\r\n content: "";\r\n background: currentColor;\r\n border-radius: 50%;\r\n}\r\n\r\n.settings-connection-row__status[data-connection-tone="ready"] {\r\n color: var(--settings-success);\r\n}\r\n\r\n.settings-connection-row__status[data-connection-tone="checking"] {\r\n color: var(--settings-warning);\r\n}\r\n\r\n.settings-connection-row__status[data-connection-tone="setup"] {\r\n color: var(--settings-muted);\r\n}\r\n\r\n.settings-connection-row__status[data-connection-tone="setup"]::before {\r\n background: transparent;\r\n border: 1.5px solid currentColor;\r\n}\r\n\r\n.settings-connection-row__status[data-connection-tone="failed"] {\r\n color: var(--settings-danger);\r\n}\r\n\r\n.settings-connection-row__action {\r\n display: flex;\r\n align-items: center;\r\n justify-content: flex-end;\r\n min-width: 0;\r\n gap: 4px;\r\n}\r\n\r\n.settings-connection-row__handle {\r\n display: inline-flex;\r\n flex: none;\r\n align-items: center;\r\n justify-content: center;\r\n width: 16px;\r\n color: var(--settings-muted);\r\n cursor: grab;\r\n opacity: 0.6;\r\n}\r\n\r\n.settings-connection-row__handle:hover {\r\n opacity: 1;\r\n}\r\n\r\n.settings-connection-row[draggable="true"] {\r\n cursor: grab;\r\n}\r\n\r\n.settings-connection-row[data-connection-dragging="true"] {\r\n opacity: 0.4;\r\n}\r\n\r\n.settings-connection-row[data-connection-drop-indicator="before"] {\r\n box-shadow: inset 0 2px 0 0 var(--settings-focus);\r\n}\r\n\r\n.settings-connection-row[data-connection-drop-indicator="after"] {\r\n box-shadow: inset 0 -2px 0 0 var(--settings-focus);\r\n}\r\n\r\n.settings-connection-row__group-toggle {\r\n display: inline-flex;\r\n flex: none;\r\n align-items: center;\r\n justify-content: center;\r\n width: 26px;\r\n height: 26px;\r\n color: var(--settings-muted);\r\n background: transparent;\r\n border: 0;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-connection-row__group-toggle:hover {\r\n color: var(--settings-text);\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-connection-group-divider {\r\n padding: 10px 12px 6px;\r\n color: var(--settings-muted);\r\n font-size: 10px;\r\n font-weight: 600;\r\n line-height: 16px;\r\n text-transform: uppercase;\r\n letter-spacing: 0.06em;\r\n /* No border-top here: the row immediately above already carries its own\r\n border-bottom (it is no longer :last-child once this divider follows\r\n it), so adding one here would double the separator line. */\r\n}\r\n\r\n.settings-connection-group-more[data-connection-drag-over="true"] {\r\n background: rgb(51 156 255 / 8%);\r\n}\r\n\r\n.settings-connection-group-hint {\r\n display: grid;\r\n gap: 3px;\r\n margin: 0 12px 12px;\r\n padding: 14px 16px;\r\n text-align: center;\r\n border: 1.5px dashed var(--settings-border);\r\n border-radius: 10px;\r\n}\r\n\r\n.settings-connection-group-more[data-connection-drag-over="true"] .settings-connection-group-hint {\r\n border-color: var(--settings-focus);\r\n}\r\n\r\n.settings-connection-group-hint strong {\r\n color: var(--settings-text);\r\n font-size: 12.5px;\r\n font-weight: 500;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-connection-group-hint span {\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 17px;\r\n}\r\n\r\n.settings-connection-group-reset {\r\n display: flex;\r\n width: 100%;\r\n align-items: center;\r\n gap: 6px;\r\n padding: 10px 12px;\r\n color: var(--settings-muted);\r\n font: inherit;\r\n font-size: 12px;\r\n text-align: left;\r\n background: transparent;\r\n border: 0;\r\n border-top: 1px solid var(--settings-divider);\r\n cursor: pointer;\r\n}\r\n\r\n.settings-connection-group-reset:hover {\r\n color: var(--settings-text);\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-connection-install-link {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 26px;\r\n height: 26px;\r\n color: var(--settings-focus);\r\n text-decoration: none;\r\n background: transparent;\r\n border: 1px solid transparent;\r\n border-radius: 7px;\r\n opacity: 0;\r\n transition: opacity 120ms ease;\r\n}\r\n\r\n.settings-connection-row:hover .settings-connection-install-link,\r\n.settings-connection-install-link:focus-visible {\r\n opacity: 1;\r\n}\r\n\r\n.settings-connection-install-link:hover {\r\n color: var(--settings-focus);\r\n background: var(--settings-active);\r\n border-color: var(--settings-border);\r\n}\r\n\r\n.settings-connection-view-error {\r\n padding: 4px 7px;\r\n color: var(--settings-danger);\r\n font: inherit;\r\n font-size: 11px;\r\n line-height: 18px;\r\n background: transparent;\r\n border: 0;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-connection-view-error:hover {\r\n color: var(--settings-danger);\r\n background: var(--settings-danger-bg);\r\n}\r\n\r\n.settings-connection-inspector {\r\n position: sticky;\r\n top: 18px;\r\n}\r\n\r\n.settings-connection-inspector__header {\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: space-between;\r\n min-width: 0;\r\n gap: 10px;\r\n padding: 12px;\r\n border-bottom: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-connection-inspector__body {\r\n display: grid;\r\n min-width: 0;\r\n gap: 12px;\r\n padding: 12px;\r\n}\r\n\r\n.settings-connection-install-callout {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 14px;\r\n padding: 14px;\r\n background: var(--settings-surface);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 10px;\r\n}\r\n\r\n.settings-connection-install-head {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: 12px;\r\n min-width: 0;\r\n}\r\n\r\n.settings-connection-install-head > div {\r\n min-width: 0;\r\n flex: 1;\r\n}\r\n\r\n.settings-connection-install-callout__icon {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n flex: none;\r\n color: var(--settings-focus);\r\n background: var(--settings-active);\r\n border-radius: 8px;\r\n}\r\n\r\n.settings-connection-install-callout strong,\r\n.settings-connection-install-head strong,\r\n.settings-connection-error-summary strong,\r\n.settings-connection-state-summary strong {\r\n display: block;\r\n margin: 0 0 4px;\r\n color: var(--settings-text);\r\n font-size: 13px;\r\n font-weight: 600;\r\n line-height: 19px;\r\n}\r\n\r\n.settings-connection-install-callout p,\r\n.settings-connection-install-head p,\r\n.settings-connection-error-summary p,\r\n.settings-connection-state-summary p,\r\n.settings-connection-issue-note {\r\n margin: 0;\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-connection-install-button {\r\n width: 100%;\r\n}\r\n\r\n.settings-connection-error-summary {\r\n padding: 13px 14px;\r\n color: var(--settings-danger);\r\n background: var(--settings-danger-bg);\r\n border: 1px solid var(--settings-danger-border);\r\n border-radius: 10px;\r\n}\r\n\r\n.settings-connection-error-metadata {\r\n display: grid;\r\n gap: 7px;\r\n padding: 12px;\r\n background: var(--settings-inset);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 9px;\r\n}\r\n\r\n.settings-connection-detail-line {\r\n display: grid;\r\n grid-template-columns: 92px minmax(0, 1fr);\r\n gap: 10px;\r\n min-width: 0;\r\n color: var(--settings-muted);\r\n font-size: 10px;\r\n line-height: 16px;\r\n}\r\n\r\n.settings-connection-detail-line code {\r\n min-width: 0;\r\n overflow-wrap: anywhere;\r\n color: var(--settings-text);\r\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\r\n white-space: pre-wrap;\r\n}\r\n\r\n.settings-connection-error-log-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 10px;\r\n}\r\n\r\n.settings-connection-error-log-header strong {\r\n color: var(--settings-text);\r\n font-size: 11px;\r\n font-weight: 600;\r\n}\r\n\r\n.settings-connection-error-log-header .settings-command-button {\r\n min-height: 30px;\r\n padding: 5px 9px;\r\n font-size: 11px;\r\n}\r\n\r\n.settings-connection-stderr {\r\n max-height: 220px;\r\n min-width: 0;\r\n margin: 0;\r\n padding: 11px;\r\n overflow: auto;\r\n color: var(--settings-text);\r\n font:\r\n 10px/16px ui-monospace,\r\n "SFMono-Regular",\r\n Consolas,\r\n "Liberation Mono",\r\n monospace;\r\n white-space: pre-wrap;\r\n overflow-wrap: anywhere;\r\n background: var(--settings-inset);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 9px;\r\n}\r\n\r\n.settings-connection-error-actions {\r\n display: grid;\r\n grid-template-columns: minmax(0, 1fr);\r\n gap: 8px;\r\n}\r\n\r\n.settings-connection-error-actions .settings-command-button {\r\n width: 100%;\r\n}\r\n\r\n.settings-connection-issue-note {\r\n margin-top: -4px;\r\n}\r\n\r\n.settings-connection-state-summary {\r\n padding: 14px;\r\n background: var(--settings-surface);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 10px;\r\n}\r\n\r\n.settings-empty {\r\n display: flex;\r\n align-items: center;\r\n min-height: 72px;\r\n padding: 12px 16px;\r\n}\r\n\r\n.settings-empty > div {\r\n display: grid;\r\n min-width: 0;\r\n gap: 2px;\r\n}\r\n\r\n.settings-empty strong {\r\n color: var(--settings-text);\r\n font-size: 13px;\r\n font-weight: 500;\r\n line-height: 19px;\r\n}\r\n\r\n.settings-empty span {\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n line-height: 19px;\r\n}\r\n\r\n.settings-about-panel {\r\n display: grid;\r\n max-width: 720px;\r\n gap: 18px;\r\n padding: 24px;\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 12px;\r\n}\r\n\r\n.settings-about-product {\r\n color: var(--settings-text);\r\n font-size: 24px;\r\n font-weight: 700;\r\n line-height: 32px;\r\n}\r\n\r\n.settings-about-tagline {\r\n color: var(--settings-text);\r\n font-size: 16px;\r\n font-weight: 600;\r\n line-height: 24px;\r\n}\r\n\r\n.settings-about-version-row {\r\n display: flex;\r\n align-items: center;\r\n gap: 12px;\r\n margin: 4px 0 8px;\r\n}\r\n\r\n.settings-about-version-badge {\r\n display: inline-flex;\r\n align-items: center;\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: var(--settings-text);\r\n background: var(--settings-surface);\r\n border: 1px solid var(--settings-border);\r\n padding: 4px 10px;\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-about-copy {\r\n display: grid;\r\n max-width: 660px;\r\n gap: 12px;\r\n}\r\n\r\n.settings-about-copy p,\r\n.settings-about-repository p {\r\n margin: 0;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n line-height: 21px;\r\n}\r\n\r\n.settings-about-star-callout {\r\n margin: 2px 0;\r\n color: var(--settings-warning);\r\n font-size: 14px;\r\n font-weight: 600;\r\n line-height: 22px;\r\n}\r\n\r\n.settings-about-repository {\r\n display: grid;\r\n gap: 10px;\r\n padding-top: 18px;\r\n border-top: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-about-repository-link {\r\n display: flex;\r\n align-items: center;\r\n width: fit-content;\r\n min-width: 0;\r\n max-width: 100%;\r\n gap: 8px;\r\n color: var(--settings-focus);\r\n font-size: 13px;\r\n font-weight: 600;\r\n text-decoration: none;\r\n}\r\n\r\n.settings-about-repository-link:hover {\r\n text-decoration: underline;\r\n}\r\n\r\n.settings-about-repository-link code {\r\n min-width: 0;\r\n overflow: hidden;\r\n color: var(--settings-muted);\r\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\r\n font-size: 11px;\r\n font-weight: 400;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-page-error {\r\n padding: 16px;\r\n color: var(--settings-text);\r\n font-size: 13px;\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 20px;\r\n}\r\n\r\n.settings-update-metadata {\r\n display: grid;\r\n grid-template-columns: repeat(3, minmax(0, 1fr));\r\n gap: 24px;\r\n margin-bottom: 24px;\r\n padding: 0 4px 20px;\r\n border-bottom: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-update-metadata__item {\r\n display: grid;\r\n min-width: 0;\r\n gap: 4px;\r\n}\r\n\r\n.settings-update-metadata__item span {\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-update-metadata__item strong {\r\n min-width: 0;\r\n overflow-wrap: anywhere;\r\n color: var(--settings-text);\r\n font-size: 15px;\r\n font-weight: 500;\r\n line-height: 22px;\r\n}\r\n\r\n/* The only emphasis on this screen: a latest version newer than the installed one. */\r\n.settings-update-metadata__value--newer {\r\n color: var(--settings-focus);\r\n}\r\n\r\n.settings-update-panel {\r\n display: grid;\r\n gap: 12px;\r\n padding: 20px;\r\n color: var(--settings-text);\r\n background: var(--settings-panel);\r\n border: 1px solid var(--settings-border);\r\n border-radius: 8px;\r\n}\r\n\r\n.settings-update-panel__head {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 8px;\r\n}\r\n\r\n.settings-update-panel__head .codexhost-settings-icon {\r\n color: var(--settings-muted);\r\n}\r\n\r\n.settings-update-panel[data-update-state="available"] .codexhost-settings-icon,\r\n.settings-update-panel[data-update-state="downloading"] .codexhost-settings-icon,\r\n.settings-update-panel[data-update-state="installing"] .codexhost-settings-icon,\r\n.settings-update-panel[data-update-state="restarting"] .codexhost-settings-icon {\r\n color: var(--settings-focus);\r\n}\r\n\r\n.settings-update-panel[data-update-state="current"] .codexhost-settings-icon {\r\n color: var(--settings-success);\r\n}\r\n\r\n.settings-update-panel[data-update-state="failed"] .codexhost-settings-icon,\r\n.settings-update-panel[data-update-state="error"] .codexhost-settings-icon {\r\n color: var(--settings-danger);\r\n}\r\n\r\n.settings-update-panel__title {\r\n min-width: 0;\r\n overflow-wrap: anywhere;\r\n color: var(--settings-text);\r\n font-size: 14px;\r\n font-weight: 600;\r\n line-height: 22px;\r\n}\r\n\r\n.settings-update-summary,\r\n.settings-update-error {\r\n margin: 0;\r\n overflow-wrap: anywhere;\r\n font-size: 13px;\r\n line-height: 20px;\r\n}\r\n\r\n.settings-update-summary {\r\n color: var(--settings-muted);\r\n}\r\n\r\n.settings-update-error {\r\n color: var(--settings-danger);\r\n}\r\n\r\n.settings-update-progress {\r\n width: 100%;\r\n height: 8px;\r\n accent-color: var(--settings-focus);\r\n}\r\n\r\n.settings-update-progress-detail {\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 18px;\r\n}\r\n\r\n/* Release notes scroll with the page; a scroller inside a scroller traps the wheel. */\r\n.settings-update-notes-section {\r\n min-width: 0;\r\n margin-top: 24px;\r\n padding-top: 24px;\r\n border-top: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-update-notes-section:empty {\r\n display: none;\r\n}\r\n\r\n.settings-update-notes {\r\n display: grid;\r\n min-width: 0;\r\n gap: 12px;\r\n color: var(--settings-muted);\r\n font-size: 14px;\r\n line-height: 22px;\r\n overflow-wrap: anywhere;\r\n}\r\n\r\n.settings-update-notes > :first-child {\r\n margin-top: 0;\r\n}\r\n\r\n.settings-update-notes > :last-child {\r\n margin-bottom: 0;\r\n}\r\n\r\n.settings-update-notes h1,\r\n.settings-update-notes h2,\r\n.settings-update-notes h3,\r\n.settings-update-notes h4,\r\n.settings-update-notes h5,\r\n.settings-update-notes h6 {\r\n margin: 6px 0 0;\r\n color: var(--settings-text);\r\n font-weight: 600;\r\n}\r\n\r\n.settings-update-notes h1 {\r\n font-size: 18px;\r\n line-height: 26px;\r\n}\r\n\r\n.settings-update-notes h2 {\r\n font-size: 17px;\r\n line-height: 24px;\r\n}\r\n\r\n.settings-update-notes h3,\r\n.settings-update-notes h4,\r\n.settings-update-notes h5,\r\n.settings-update-notes h6 {\r\n font-size: 14px;\r\n line-height: 22px;\r\n}\r\n\r\n.settings-update-notes p,\r\n.settings-update-notes ul,\r\n.settings-update-notes ol,\r\n.settings-update-notes pre,\r\n.settings-update-notes blockquote {\r\n margin: 0;\r\n}\r\n\r\n.settings-update-notes ul,\r\n.settings-update-notes ol {\r\n padding-left: 24px;\r\n}\r\n\r\n.settings-update-notes li {\r\n padding-left: 4px;\r\n}\r\n\r\n.settings-update-notes li::marker {\r\n color: var(--settings-muted);\r\n font-size: 0.85em;\r\n}\r\n\r\n.settings-update-notes li + li {\r\n margin-top: 14px;\r\n}\r\n\r\n.settings-update-notes .release-note-translation {\r\n display: block;\r\n margin-top: 3px;\r\n color: var(--settings-muted);\r\n font-size: 13px;\r\n line-height: 20px;\r\n}\r\n\r\n.settings-update-notes blockquote {\r\n padding: 8px 12px;\r\n color: var(--settings-muted);\r\n border-left: 3px solid var(--settings-focus);\r\n background: var(--settings-surface);\r\n}\r\n\r\n.settings-update-notes hr {\r\n width: 100%;\r\n margin: 2px 0;\r\n border: 0;\r\n border-top: 1px solid var(--settings-divider);\r\n}\r\n\r\n.settings-update-notes strong {\r\n color: var(--settings-text);\r\n font-weight: 600;\r\n}\r\n\r\n.settings-update-notes a {\r\n color: var(--settings-focus);\r\n text-decoration: none;\r\n}\r\n\r\n.settings-update-notes a:hover {\r\n text-decoration: underline;\r\n}\r\n\r\n.settings-update-notes code {\r\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\r\n font-size: 12px;\r\n}\r\n\r\n.settings-update-notes :not(pre) > code {\r\n padding: 1px 5px;\r\n background: var(--settings-surface);\r\n border-radius: 4px;\r\n}\r\n\r\n.settings-update-notes pre {\r\n min-width: 0;\r\n max-width: 100%;\r\n padding: 10px 12px;\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n background: var(--settings-inset);\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-update-notes pre code {\r\n line-height: 18px;\r\n white-space: pre-wrap;\r\n}\r\n\r\n/* Manual update sits directly under the status panel, not behind a disclosure:\r\n automatic updates can fail for machine-local reasons and this is the way out. */\r\n.settings-update-controls {\r\n display: grid;\r\n min-width: 0;\r\n gap: 10px;\r\n margin-top: 24px;\r\n}\r\n\r\n.settings-update-manual-title {\r\n color: var(--settings-text);\r\n font-size: 15px;\r\n font-weight: 600;\r\n line-height: 22px;\r\n}\r\n\r\n.settings-update-manual {\r\n display: grid;\r\n min-width: 0;\r\n gap: 8px;\r\n}\r\n\r\n.settings-update-manual[hidden] {\r\n display: none;\r\n}\r\n\r\n.settings-update-manual-description {\r\n margin: 0;\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n line-height: 18px;\r\n}\r\n\r\n.settings-update-manual-description.is-fallback {\r\n color: var(--settings-danger);\r\n}\r\n\r\n.settings-update-command {\r\n display: flex;\r\n align-items: stretch;\r\n min-width: 0;\r\n overflow: hidden;\r\n border: 1px solid var(--settings-border);\r\n border-radius: 6px;\r\n}\r\n\r\n.settings-update-command code {\r\n min-width: 0;\r\n flex: 1;\r\n padding: 9px 12px;\r\n overflow-x: auto;\r\n color: var(--settings-text);\r\n font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;\r\n font-size: 12px;\r\n line-height: 20px;\r\n white-space: nowrap;\r\n}\r\n\r\n.settings-update-command__copy {\r\n display: inline-flex;\r\n align-items: center;\r\n flex: none;\r\n gap: 6px;\r\n padding: 0 12px;\r\n color: var(--settings-muted);\r\n font-size: 12px;\r\n background: transparent;\r\n border: 0;\r\n border-left: 1px solid var(--settings-border);\r\n cursor: pointer;\r\n}\r\n\r\n.settings-update-command__copy:hover {\r\n color: var(--settings-text);\r\n background: var(--settings-hover);\r\n}\r\n\r\n.settings-update-command__copy:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: -2px;\r\n}\r\n\r\n.settings-update-actions {\r\n display: flex;\r\n align-items: center;\r\n min-width: 0;\r\n gap: 12px;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.settings-command-button,\r\n.settings-update-link {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex: none;\r\n width: max-content;\r\n max-width: 100%;\r\n min-height: 30px;\r\n gap: 6px;\r\n padding: 5px 10px;\r\n white-space: nowrap;\r\n color: var(--settings-primary-text);\r\n font: inherit;\r\n font-size: 12px;\r\n text-decoration: none;\r\n background: var(--settings-primary);\r\n border: 1px solid var(--settings-primary);\r\n border-radius: 7px;\r\n cursor: pointer;\r\n}\r\n\r\n.settings-command-button--secondary,\r\n.settings-update-link {\r\n color: var(--settings-text);\r\n background: var(--settings-panel);\r\n border-color: var(--settings-border);\r\n}\r\n\r\n.settings-command-button:hover:not(:disabled) {\r\n background: var(--settings-primary-hover);\r\n border-color: var(--settings-primary-hover);\r\n}\r\n\r\n.settings-command-button--secondary:hover:not(:disabled),\r\n.settings-update-link:hover {\r\n background: var(--settings-hover);\r\n border-color: var(--settings-border);\r\n}\r\n\r\n.settings-command-button--danger {\r\n color: #f87171;\r\n}\r\n\r\n.settings-command-button--danger:hover:not(:disabled) {\r\n color: #fecaca;\r\n background: rgb(127 29 29 / 24%);\r\n border-color: rgb(248 113 113 / 45%);\r\n}\r\n\r\n.settings-command-button:disabled {\r\n cursor: default;\r\n opacity: 0.45;\r\n}\r\n\r\n.settings-command-button:disabled,\r\n.settings-command-button[aria-disabled="true"] {\r\n opacity: 0.55;\r\n cursor: not-allowed;\r\n filter: none;\r\n}\r\n\r\n.settings-command-button:focus-visible,\r\n.settings-update-link:focus-visible {\r\n outline: 2px solid var(--settings-focus);\r\n outline-offset: 2px;\r\n}\r\n\r\n.codexhost-settings-icon {\r\n display: block;\r\n flex: none;\r\n stroke: currentColor;\r\n}\r\n\r\n@media (max-width: 720px) {\r\n .codexhost-settings-dialog {\r\n width: calc(100vw - 16px);\r\n height: calc(100vh - 16px);\r\n border-radius: 10px;\r\n }\r\n\r\n .settings-layout {\r\n grid-template-columns: minmax(0, 1fr);\r\n grid-template-rows: auto minmax(0, 1fr);\r\n }\r\n\r\n .settings-session-import-row {\r\n grid-template-columns: minmax(0, 1fr);\r\n }\r\n\r\n .settings-session-import-row__action {\r\n align-items: flex-start;\r\n }\r\n\r\n .settings-sidebar {\r\n border-right: 0;\r\n border-bottom: 1px solid var(--settings-border);\r\n }\r\n\r\n .settings-header {\r\n height: 56px;\r\n padding-inline: 14px;\r\n }\r\n\r\n .settings-sidebar {\r\n padding-top: 20px;\r\n }\r\n\r\n .settings-nav {\r\n flex: none;\r\n flex-direction: row;\r\n gap: 4px;\r\n padding: 7px 8px 8px;\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n }\r\n\r\n .settings-nav-section-label {\r\n display: none;\r\n }\r\n\r\n .settings-nav-button {\r\n width: auto;\r\n min-width: max-content;\r\n min-height: 34px;\r\n grid-template-columns: 16px auto;\r\n border-radius: 10px;\r\n }\r\n\r\n .settings-nav-star-link {\r\n margin-top: 0;\r\n }\r\n\r\n .settings-page__content {\r\n width: calc(100% - 40px);\r\n }\r\n\r\n .settings-page__content {\r\n padding-top: 32px;\r\n padding-bottom: 32px;\r\n }\r\n\r\n .settings-section-label {\r\n padding-bottom: 20px;\r\n font-size: 20px;\r\n line-height: 26px;\r\n }\r\n\r\n .settings-update-metadata {\r\n grid-template-columns: minmax(0, 1fr);\r\n gap: 16px;\r\n }\r\n\r\n .settings-status-row {\r\n grid-template-columns: minmax(0, 1fr) auto;\r\n gap: 16px;\r\n }\r\n\r\n .settings-account-header,\r\n .settings-connection-page-header {\r\n flex-direction: column;\r\n }\r\n\r\n .settings-account-header > .settings-command-button,\r\n .settings-connection-page-header > .settings-command-button {\r\n width: 100%;\r\n }\r\n\r\n .settings-connections-layout {\r\n grid-template-columns: minmax(0, 1fr);\r\n }\r\n\r\n .settings-connection-inspector {\r\n position: static;\r\n }\r\n\r\n .settings-status-row__detail {\r\n grid-column: 1 / -1;\r\n margin: -8px 0 0 58px;\r\n }\r\n}\r\n\r\n@media (forced-colors: active) {\r\n :host {\r\n --settings-bg: Canvas;\r\n --settings-sidebar: Canvas;\r\n --settings-panel: Canvas;\r\n --settings-surface: Canvas;\r\n --settings-surface-hover: Highlight;\r\n --settings-inset: Canvas;\r\n --settings-text: CanvasText;\r\n --settings-muted: GrayText;\r\n --settings-subtle: GrayText;\r\n --settings-border: ButtonBorder;\r\n --settings-divider: ButtonBorder;\r\n --settings-hover: Highlight;\r\n --settings-active: Highlight;\r\n --settings-focus: Highlight;\r\n --settings-primary: ButtonFace;\r\n --settings-primary-hover: Highlight;\r\n --settings-primary-text: ButtonText;\r\n --settings-warning: CanvasText;\r\n --settings-warning-bg: Canvas;\r\n --settings-warning-border: ButtonBorder;\r\n --settings-danger: CanvasText;\r\n --settings-danger-bg: Canvas;\r\n --settings-danger-border: ButtonBorder;\r\n --settings-success: CanvasText;\r\n }\r\n}\r\n\r\n@media (prefers-reduced-motion: reduce) {\r\n *,\r\n *::before,\r\n *::after {\r\n scroll-behavior: auto !important;\r\n transition-duration: 0s !important;\r\n }\r\n}\r\n\r\n/* Harness Mix: Model Configuration & One-click Install */\r\n.settings-model-config-panel {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n padding: 14px;\r\n margin-top: 14px;\r\n border-radius: 8px;\r\n background: var(--settings-surface);\r\n border: 1px solid var(--settings-border);\r\n}\r\n\r\n.settings-model-config-head {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n}\r\n\r\n.settings-model-config-title {\r\n font-size: 13px;\r\n font-weight: 600;\r\n color: var(--settings-text);\r\n}\r\n\r\n.settings-model-config-description {\r\n font-size: 11px;\r\n color: var(--settings-muted);\r\n margin: 0;\r\n}\r\n\r\n.settings-model-config-loading,\r\n.settings-model-config-empty {\r\n font-size: 12px;\r\n color: var(--settings-muted);\r\n padding: 8px 0;\r\n}\r\n\r\n.settings-model-config-form {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 12px;\r\n margin-top: 4px;\r\n}\r\n\r\n.settings-model-config-field {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 6px;\r\n}\r\n\r\n.settings-model-config-label {\r\n font-size: 11px;\r\n font-weight: 600;\r\n color: var(--settings-muted);\r\n text-transform: uppercase;\r\n letter-spacing: 0.5px;\r\n}\r\n\r\n.settings-model-config-select {\r\n height: 32px;\r\n padding: 0 10px;\r\n border-radius: 6px;\r\n border: 1px solid var(--settings-border);\r\n background: var(--settings-panel);\r\n color: var(--settings-text);\r\n font-size: 12px;\r\n outline: none;\r\n}\r\n\r\n.settings-model-config-select:focus {\r\n border-color: var(--settings-primary);\r\n}\r\n\r\n.settings-model-config-actions {\r\n display: flex;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n margin-top: 6px;\r\n}\r\n\r\n.settings-model-config-feedback {\r\n font-size: 12px;\r\n font-weight: 500;\r\n}\r\n\r\n.settings-feedback-success {\r\n color: var(--settings-success);\r\n}\r\n\r\n.settings-feedback-error {\r\n color: var(--settings-danger);\r\n}\r\n\r\n.settings-feedback-info {\r\n color: var(--settings-primary);\r\n}\r\n\r\n.settings-install-command-box {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 6px;\r\n min-width: 0;\r\n margin: 0;\r\n}\r\n\r\n.settings-install-command-label {\r\n font-size: 11px;\r\n font-weight: 600;\r\n color: var(--settings-muted);\r\n}\r\n\r\n.settings-install-command-row {\r\n display: flex;\r\n align-items: center;\r\n background: var(--settings-inset);\r\n padding: 8px 12px;\r\n border-radius: 6px;\r\n border: 1px solid var(--settings-border);\r\n min-width: 0;\r\n overflow-x: auto;\r\n}\r\n\r\n.settings-install-command-row code {\r\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\r\n font-size: 12px;\r\n line-height: 18px;\r\n color: var(--settings-text);\r\n user-select: all;\r\n white-space: pre-wrap;\r\n word-break: break-all;\r\n}\r\n\r\n.settings-install-actions {\r\n display: grid;\r\n grid-template-columns: minmax(0, 1fr);\r\n gap: 8px;\r\n margin-top: 4px;\r\n}\r\n\r\n.settings-install-actions .settings-command-button {\r\n width: 100%;\r\n justify-content: center;\r\n}\r\n\r\n.settings-install-feedback {\r\n font-size: 12px;\r\n font-weight: 500;\r\n line-height: 18px;\r\n margin-top: 2px;\r\n overflow-wrap: anywhere;\r\n}\r\n\r\n.settings-install-manual-card {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n background: var(--settings-inset);\r\n padding: 12px 14px;\r\n border-radius: 8px;\r\n border: 1px solid var(--settings-border);\r\n margin-top: 6px;\r\n margin-bottom: 4px;\r\n}\r\n\r\n.settings-install-manual-badge {\r\n display: inline-flex;\r\n align-items: center;\r\n font-size: 11px;\r\n font-weight: 600;\r\n color: var(--settings-accent, #10a37f);\r\n background: var(--settings-accent-subtle, rgba(16, 163, 127, 0.1));\r\n padding: 2px 8px;\r\n border-radius: 4px;\r\n width: fit-content;\r\n}\r\n\r\n.settings-install-manual-notice {\r\n font-size: 12px;\r\n line-height: 18px;\r\n color: var(--settings-text);\r\n margin: 0;\r\n}\r\n\r\n.settings-install-steps {\r\n margin: 0;\r\n padding-left: 18px;\r\n font-size: 12px;\r\n line-height: 20px;\r\n color: var(--settings-muted);\r\n}\r\n\r\n.settings-install-steps li {\r\n margin-bottom: 2px;\r\n}\r\n/* MCP and Skills share native settings controls while keeping separate flows. */\n.settings-integrations-controls { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 18px 0 12px; }\n.settings-integrations-controls input { flex: 1; min-width: 180px; }\n.settings-integrations-controls input[hidden] { display: none; }\n.settings-integrations-controls select, .settings-integrations-controls input,\n.settings-integrations-field input, .settings-integrations-toolbar input { box-sizing: border-box; padding: 9px 11px; border: 1px solid var(--settings-border, #8885); border-radius: 8px; color: inherit; background: var(--settings-input, transparent); font: inherit; }\n.settings-integrations-status { min-height: 18px; margin: 0 0 6px; color: var(--settings-muted); font-size: 12px; }\n.settings-integrations-body p { font-size: 12px; line-height: 1.6; opacity: .8; }\n.settings-integrations-toolbar { display: flex; gap: 10px; align-items: center; margin: 8px 0 16px; }\n.settings-integrations-toolbar input { flex: 1; }\n.settings-integrations-list { display: grid; gap: 8px; }\n.settings-integrations-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; border: 1px solid var(--settings-border, #8885); padding: 14px; border-radius: 10px; background: var(--settings-surface, transparent); }\n.settings-integrations-row > div { flex: 1; min-width: 180px; }\n.settings-integrations-row p { margin: 3px 0; }\n.settings-integrations-row code { display: block; overflow-wrap: anywhere; font-size: 11px; color: var(--settings-muted); }\n.settings-integrations-row--native { border-style: dashed; }\n.settings-integrations-empty { padding: 36px 18px; border: 1px dashed var(--settings-border, #8885); border-radius: 10px; text-align: center; color: var(--settings-muted); font-size: 12px; }\n.settings-integrations-editor-head { display: flex; align-items: center; gap: 12px; }\n.settings-integrations-editor-head h3 { margin: 0; }\n.settings-integrations-form { display: grid; gap: 14px; margin: 16px 0 28px; }\n.settings-integrations-form--card { padding: 16px; border: 1px solid var(--settings-border, #8885); border-radius: 12px; }\n.settings-integrations-field { display: grid; gap: 6px; font-size: 12px; }\n.settings-integrations-form > button { justify-self: start; }\n.settings-mcp-args { display: grid; gap: 7px; }\n.settings-mcp-arg { display: flex; gap: 8px; align-items: center; }\n.settings-mcp-arg input { flex: 1; }\n.settings-mcp-kv-row { display: flex; gap: 8px; align-items: center; }\n.settings-mcp-kv-row input { flex: 1; }\n.settings-mcp-add-arg { margin-top: 7px; }\n.settings-mcp-docs-link { display: inline-flex; align-items: center; gap: 4px; color: var(--settings-muted, #888); font-size: 13px; text-decoration: none; transition: color 150ms ease; }\n.settings-mcp-docs-link:hover { color: var(--settings-text, #fff); text-decoration: underline; }\n.settings-integrations-editor-head .settings-command-button--danger { margin-left: auto; }\n.settings-mcp-type-toggle { display: inline-flex; padding: 3px; border-radius: 8px; background: var(--settings-inset, rgba(255, 255, 255, 0.06)); border: 1px solid var(--settings-border, #8885); gap: 2px; width: fit-content; }\n.settings-mcp-type-btn { padding: 5px 14px; border-radius: 6px; border: none; background: transparent; color: var(--settings-muted, #888); font: inherit; font-size: 12px; font-weight: 500; cursor: pointer; transition: all 120ms ease; }\n.settings-mcp-type-btn:hover { color: var(--settings-text, #fff); }\n.settings-mcp-type-btn[data-active="true"] { background: var(--settings-active, rgba(255, 255, 255, 0.15)); color: var(--settings-text, #fff); font-weight: 600; }\n.settings-mcp-notice { margin: 4px 0 0; color: var(--settings-muted, #888); font-size: 12px; line-height: 1.5; }\n.settings-mcp-section { display: grid; gap: 14px; }\n.settings-mcp-icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; padding: 0; border: 1px solid var(--settings-border, #8885); border-radius: 8px; background: var(--settings-input, transparent); color: var(--settings-muted, #888); cursor: pointer; flex: none; transition: all 120ms ease; }\n.settings-mcp-icon-btn:hover:not(:disabled) { background: rgba(239, 68, 68, 0.15); border-color: rgba(239, 68, 68, 0.4); color: #f87171; }\n.settings-mcp-icon-btn svg { width: 14px; height: 14px; display: block; }\n.settings-integrations-callout { margin: 0; padding: 10px 12px; border-radius: 8px; background: var(--settings-inset); }\n.settings-skill-dropzone { display: grid; justify-items: center; gap: 8px; padding: 34px 22px; margin: 8px 0 18px; border: 1.5px dashed var(--settings-border, #8887); border-radius: 14px; background: var(--settings-inset); text-align: center; transition: border-color 120ms ease, background 120ms ease, transform 120ms ease; }\n.settings-skill-dropzone > span { max-width: 520px; color: var(--settings-muted); font-size: 12px; line-height: 18px; }\n.settings-skill-dropzone[data-drag-over="true"] { border-color: var(--settings-accent, #10a37f); background: var(--settings-accent-subtle, rgba(16, 163, 127, .1)); transform: scale(.995); }\n.settings-skill-dropzone[data-disabled="true"] { opacity: .55; }\n.settings-skills-target-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: center; margin-top: 6px; }\n.settings-skills-target-row select { padding: 6px 10px; border: 1px solid var(--settings-border, #8885); border-radius: 8px; background: var(--settings-input, transparent); color: inherit; font: inherit; font-size: 12px; }\n.settings-skills-overview-stats { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 6px 0 10px; font-size: 12px; color: var(--settings-muted); }\n.settings-skills-tabs { display: inline-flex; padding: 3px; border-radius: 8px; background: var(--settings-inset, rgba(255, 255, 255, 0.06)); border: 1px solid var(--settings-border, #8885); gap: 2px; }\n.settings-skills-tab-btn { padding: 5px 14px; border-radius: 6px; border: none; background: transparent; color: var(--settings-muted, #888); font: inherit; font-size: 12px; font-weight: 500; cursor: pointer; transition: all 120ms ease; }\n.settings-skills-tab-btn:hover { color: var(--settings-text, #fff); }\n.settings-skills-tab-btn[data-active="true"] { background: var(--settings-active, rgba(255, 255, 255, 0.15)); color: var(--settings-text, #fff); font-weight: 600; }\n.settings-skills-overview-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 14px; margin-top: 10px; }\n.settings-skills-harness-card { border: 1px solid var(--settings-border, #8885); border-radius: 12px; padding: 14px; background: var(--settings-surface, transparent); display: flex; flex-direction: column; gap: 10px; }\n.settings-skills-harness-head { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--settings-border, #8883); padding-bottom: 8px; }\n.settings-skills-harness-head strong { font-size: 14px; }\n.settings-skills-badge { font-size: 11px; padding: 2px 8px; border-radius: 10px; background: var(--settings-inset, rgba(255, 255, 255, 0.08)); color: var(--settings-muted); }\n.settings-skills-badge--active { background: rgba(16, 163, 127, 0.15); color: #10a37f; }\n.settings-skills-list-compact { display: flex; flex-direction: column; gap: 8px; max-height: 280px; overflow-y: auto; }\n.settings-skills-item-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 6px; background: var(--settings-inset, rgba(255, 255, 255, 0.03)); font-size: 12px; }\n.settings-skills-item-row strong { font-size: 13px; }\n.settings-skills-item-row code { font-size: 10px; color: var(--settings-muted); overflow-wrap: anywhere; display: block; }\n.settings-skills-item-actions { display: flex; gap: 6px; align-items: center; flex: none; }\n.settings-skills-matrix-list { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }\n.settings-skills-matrix-card { border: 1px solid var(--settings-border, #8885); border-radius: 10px; padding: 12px 14px; background: var(--settings-surface, transparent); display: flex; flex-direction: column; gap: 8px; }\n.settings-skills-matrix-head { display: flex; justify-content: space-between; align-items: center; }\n.settings-skills-matrix-head span { font-size: 11px; color: var(--settings-muted); }\n.settings-skills-tags { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }\n.settings-skills-tag { font-size: 11px; padding: 3px 8px; border-radius: 6px; background: rgba(16, 163, 127, 0.15); color: #10a37f; border: 1px solid rgba(16, 163, 127, 0.3); }\n.settings-skills-sync-actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 4px; }\n.settings-skills-sync-modal { border: 1px solid var(--settings-border, #8885); border-radius: 12px; background: var(--settings-bg, #1e1e1e); color: inherit; padding: 20px 24px; max-width: 420px; box-shadow: 0 16px 32px rgba(0, 0, 0, 0.5); }\n.settings-skills-sync-modal::backdrop { background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(2px); }\n.settings-skills-sync-modal h3 { margin: 0 0 8px; font-size: 16px; }\n.settings-skills-sync-modal p { margin: 0 0 12px; font-size: 12px; color: var(--settings-muted); }\n.settings-mcp-overview-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 14px; margin-top: 10px; }\n.settings-mcp-harness-card { border: 1px solid var(--settings-border, #8885); border-radius: 12px; padding: 14px; background: var(--settings-surface, transparent); display: flex; flex-direction: column; gap: 10px; }\n.settings-mcp-harness-head { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--settings-border, #8883); padding-bottom: 8px; }\n.settings-mcp-harness-head strong { font-size: 14px; }\n.settings-mcp-native-box { padding: 8px 10px; border-radius: 8px; background: rgba(16, 163, 127, 0.08); border: 1px dashed rgba(16, 163, 127, 0.3); font-size: 11px; display: flex; flex-direction: column; gap: 4px; }\n.settings-mcp-native-title { font-weight: 600; color: #10a37f; display: flex; align-items: center; gap: 6px; }\n.settings-mcp-native-item { display: flex; flex-direction: column; gap: 2px; color: var(--settings-muted); }\n.settings-mcp-native-item code { font-size: 10px; overflow-wrap: anywhere; }\n.settings-mcp-list-compact { display: flex; flex-direction: column; gap: 8px; max-height: 280px; overflow-y: auto; }\n.settings-mcp-item-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 6px; background: var(--settings-inset, rgba(255, 255, 255, 0.03)); font-size: 12px; }\n.settings-mcp-item-row strong { font-size: 13px; }\n.settings-mcp-item-row code { font-size: 10px; color: var(--settings-muted); overflow-wrap: anywhere; display: block; }\n.settings-mcp-item-actions { display: flex; gap: 6px; align-items: center; flex: none; }\n.settings-mcp-card-footer { display: flex; justify-content: flex-end; margin-top: auto; padding-top: 6px; border-top: 1px solid var(--settings-border, #8882); }\n.settings-mcp-matrix-list { display: flex; flex-direction: column; gap: 10px; margin-top: 10px; }\n.settings-mcp-matrix-card { border: 1px solid var(--settings-border, #8885); border-radius: 10px; padding: 12px 14px; background: var(--settings-surface, transparent); display: flex; flex-direction: column; gap: 8px; }\n.settings-mcp-matrix-head { display: flex; justify-content: space-between; align-items: center; }\n.settings-mcp-matrix-head span { font-size: 11px; color: var(--settings-muted); }\n.settings-mcp-tags { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }\n.settings-mcp-tag { font-size: 11px; padding: 3px 8px; border-radius: 6px; background: rgba(16, 163, 127, 0.15); color: #10a37f; border: 1px solid rgba(16, 163, 127, 0.3); }\n.settings-mcp-tag--disabled { background: rgba(255, 255, 255, 0.05); color: var(--settings-muted); border-color: var(--settings-border, #8885); }\n.settings-mcp-sync-actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 4px; }\n.settings-mcp-distribute-modal { border: 1px solid var(--settings-border, #8885); border-radius: 12px; background: var(--settings-bg, #1e1e1e); color: inherit; padding: 20px 24px; max-width: 540px; width: 92%; max-height: 85vh; overflow-y: auto; box-shadow: 0 16px 32px rgba(0, 0, 0, 0.5); }\n.settings-mcp-distribute-modal::backdrop { background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(2px); }\n.settings-mcp-distribute-modal h3 { margin: 0 0 8px; font-size: 16px; }\n.settings-mcp-distribute-modal p { margin: 0 0 12px; font-size: 12px; color: var(--settings-muted); }\n\n\n';
26553
28938
 
26554
28939
  // src/native-ui/renderer-extension/src/settings/accounts.css
26555
28940
  var accounts_default = '.settings-harness-accounts {\n margin-top: 32px;\n}\n\n.settings-harness-accounts__title {\n margin: 0 0 16px;\n font-size: 14px;\n font-weight: 500;\n}\n\n.settings-harness-account__identity {\n min-width: 0;\n}\n\n.settings-harness-account__identity > .settings-account-email {\n display: block;\n max-width: 24ch;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-harness-account__logo {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n flex: none;\n}\n\n.settings-harness-account {\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-wrap: wrap;\n gap: 20px;\n padding: 20px 24px;\n}\n\n.settings-harness-account > .settings-account-row__person {\n flex: 1 1 280px;\n min-width: 0;\n}\n\n.settings-harness-account > .settings-account-usage {\n flex: 1 1 220px;\n min-width: 0;\n}\n\n.settings-harness-account > .settings-harness-account__actions {\n flex: 0 0 auto;\n}\n\n.settings-harness-account__badge {\n display: inline-flex;\n align-items: center;\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n font-weight: 500;\n line-height: 16px;\n}\n\n.settings-harness-account__badge--ready {\n background: rgba(16, 185, 129, 0.12);\n color: #10b981;\n border: 1px solid rgba(16, 185, 129, 0.28);\n}\n\n.settings-harness-account__badge--unconfigured {\n background: rgba(245, 158, 11, 0.12);\n color: #f59e0b;\n border: 1px solid rgba(245, 158, 11, 0.28);\n}\n\n.settings-harness-account__badge--not_installed {\n background: rgba(156, 163, 175, 0.12);\n color: var(--settings-muted);\n border: 1px solid rgba(156, 163, 175, 0.25);\n}\n\n.settings-harness-account__config-hint {\n margin-top: 6px;\n font-size: 11px;\n color: var(--settings-muted);\n display: flex;\n align-items: center;\n gap: 4px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-harness-account__config-hint code {\n font-family: ui-monospace, Consolas, monospace;\n font-size: 11px;\n background: var(--settings-surface);\n border: 1px solid var(--settings-border);\n padding: 1px 5px;\n border-radius: 4px;\n}\n\n.settings-harness-account__actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.settings-harness-account__login-btn {\n font-size: 12px;\n padding: 6px 12px;\n white-space: nowrap;\n}\n\n.settings-harness-account + .settings-harness-account {\n border-top: 1px solid var(--settings-border);\n}\n\n.settings-harness-account > div {\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n@media (max-width: 700px) {\n .settings-harness-account {\n grid-template-columns: minmax(0, 1fr);\n padding: 16px;\n }\n}\n\n.settings-account-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 20px;\n}\n\n.settings-account-eyebrow {\n margin: 0 0 8px;\n color: var(--settings-muted);\n font-size: 11px;\n letter-spacing: 0.13em;\n}\n\n.settings-account-header > :first-child {\n min-width: 0;\n flex: 1 1 auto;\n}\n\n.settings-account-header > .settings-command-button {\n flex: none;\n white-space: nowrap;\n margin-top: 20px;\n min-height: 36px;\n padding: 8px 12px;\n border-radius: 7px;\n}\n\n.settings-account-header .settings-section-label {\n margin: 0;\n padding: 0;\n font-size: 27px;\n line-height: 1.4;\n font-weight: 650;\n letter-spacing: -0.035em;\n}\n.settings-account-header .settings-page-description {\n margin: 8px 0 0;\n font-size: 13px;\n}\n\n.settings-account-status {\n margin: 0;\n color: var(--settings-muted);\n font-size: 12px;\n}\n.settings-account-status:empty {\n display: none;\n}\n\n.settings-account-help-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n margin-top: 20px;\n flex-wrap: wrap;\n}\n.settings-account-task-hint {\n display: flex;\n align-items: flex-start;\n gap: 9px;\n margin: 0;\n color: var(--settings-muted);\n font-size: 12px;\n flex: 1 1 280px;\n}\n.settings-account-task-hint svg {\n flex: none;\n margin-top: 1px;\n}\n.settings-account-help-button {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n padding: 8px 12px;\n color: var(--settings-muted);\n font-size: 12px;\n background: transparent;\n border: 0;\n border-radius: 7px;\n cursor: pointer;\n}\n.settings-account-help-button:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n.settings-account-device-code-note {\n margin: 12px 0 0;\n font-size: 12px;\n padding: 10px 12px;\n color: var(--settings-warning);\n background: var(--settings-warning-bg);\n border: 1px solid var(--settings-warning-border);\n border-radius: 8px;\n}\n\n.settings-account-toolbar {\n margin-top: 27px;\n padding: 18px 0;\n border-top: 1px solid var(--settings-border);\n display: flex;\n align-items: center;\n gap: 14px;\n flex-wrap: wrap;\n}\n.settings-account-count {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n white-space: nowrap;\n}\n.settings-account-count > :last-child {\n color: var(--settings-muted);\n font-variant-numeric: tabular-nums;\n}\n.settings-account-search {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--settings-muted);\n margin-right: auto;\n min-width: 0;\n max-width: 100%;\n}\n.settings-account-search svg {\n flex: none;\n}\n.settings-account-toolbar input {\n min-width: 80px;\n width: 150px;\n max-width: 100%;\n padding: 5px 0;\n color: var(--settings-text);\n background: transparent;\n border: 0;\n font-size: 13px;\n}\n.settings-account-toolbar input::placeholder {\n color: var(--settings-muted);\n}\n.settings-account-display-controls {\n display: flex;\n padding: 3px;\n border: 1px solid var(--settings-border);\n border-radius: 7px;\n background: var(--settings-inset);\n}\n.settings-account-display-controls button {\n padding: 4px 10px;\n color: var(--settings-muted);\n background: transparent;\n border: 0;\n border-radius: 4px;\n font-size: 12px;\n cursor: pointer;\n}\n.settings-account-display-controls button:hover {\n color: var(--settings-text);\n}\n.settings-account-display-controls button[aria-pressed="true"] {\n color: var(--settings-text);\n background: var(--settings-active);\n}\n\n.settings-account-list {\n --account-border: light-dark(#e2e2e8, #36363b);\n --account-muted: light-dark(#676773, #a5a5af);\n border: 1px solid var(--account-border);\n border-radius: 11px;\n overflow: hidden;\n container-type: inline-size;\n}\n.settings-account-table {\n width: 100%;\n table-layout: fixed;\n border-collapse: collapse;\n font-size: 12px;\n}\n.settings-account-table th {\n padding: 13px 20px;\n color: var(--account-muted);\n background: light-dark(#f8f8fa, #202024);\n font-size: 11px;\n font-weight: 500;\n text-align: left;\n}\n.settings-account-table th:nth-child(1) {\n width: 32%;\n}\n.settings-account-table th:nth-child(2) {\n width: 38%;\n}\n.settings-account-table th:nth-child(3) {\n width: 12%;\n}\n.settings-account-table th:nth-child(4) {\n width: 18%;\n text-align: right;\n}\n.settings-account-table td {\n padding: 19px 20px;\n vertical-align: middle;\n border-top: 1px solid var(--settings-divider);\n}\n.settings-account-row {\n background: light-dark(#ffffff, #232326);\n}\n.settings-account-row:hover {\n background: light-dark(#f7f7fa, #26262a);\n}\n.settings-account-row__person {\n display: grid;\n grid-template-columns: 34px minmax(0, 1fr);\n align-items: center;\n gap: 11px;\n min-width: 0;\n}\n.settings-account-row__mark {\n display: grid;\n place-items: center;\n width: 34px;\n height: 34px;\n color: light-dark(#67558d, #c3baff);\n background: light-dark(#f0ecf7, #353044);\n border: 1px solid light-dark(#d9d0e6, #4d435f);\n border-radius: 10px;\n}\n.settings-account-row__identity {\n min-width: 0;\n}\n.settings-account-title {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n}\n.settings-account-email {\n min-width: 0;\n overflow: hidden;\n font-size: 13px;\n font-weight: 550;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.settings-account-metadata {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 7px;\n margin-top: 4px;\n color: var(--settings-muted);\n}\n.settings-account-domain {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.settings-account-plan-separator {\n flex: none;\n}\n.settings-account-plan {\n flex: none;\n padding: 1px 6px;\n color: var(--settings-muted);\n border: 1px solid var(--settings-border);\n border-radius: 5px;\n font-size: 11px;\n white-space: nowrap;\n}\n.settings-account-plan--highlighted {\n color: light-dark(#654f91, #c8bfff);\n background: light-dark(#f2edf9, #a99bff18);\n border-color: light-dark(#d9ccea, #a99bff52);\n font-weight: 600;\n}\n.settings-account-active {\n flex: none;\n padding: 2px 7px;\n color: light-dark(#66548e, #bdb4ff);\n background: light-dark(#f4f0fb, #aca0ff12);\n border: 1px solid light-dark(#dfd5f1, #aca0ff24);\n border-radius: 5px;\n font-size: 11px;\n white-space: nowrap;\n}\n\n.settings-account-usage {\n display: grid;\n gap: 14px;\n max-width: 380px;\n}\n.settings-account-usage__meter {\n display: grid;\n grid-template-columns: 48px minmax(36px, 1fr) 96px;\n align-items: center;\n gap: 3px 10px;\n}\n:host([lang="zh-CN"]) .settings-account-usage__meter {\n grid-template-columns: 48px minmax(36px, 1fr) 72px;\n}\n\n.settings-account-usage__title {\n color: light-dark(#5d5d68, #c3c3cd);\n font-size: 12px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.settings-account-usage__percent {\n display: flex;\n align-items: baseline;\n justify-content: flex-end;\n gap: 4px;\n font-size: 14px;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n.settings-account-usage__value-label {\n color: var(--settings-muted);\n font-size: 11px;\n font-weight: 400;\n}\n.settings-account-usage__percent--warn {\n color: var(--settings-warning);\n}\n.settings-account-usage__percent--hot {\n color: var(--settings-danger);\n}\n.settings-account-usage__bar {\n height: 4px;\n overflow: hidden;\n background: light-dark(#e3e1e8, #3c3c43);\n border-radius: 4px;\n}\n.settings-account-usage__bar > span {\n display: block;\n height: 100%;\n background: light-dark(#81769e, #9993b8);\n border-radius: inherit;\n}\n.settings-account-usage__bar--warn > span {\n background: var(--settings-warning);\n}\n.settings-account-usage__bar--hot > span {\n background: var(--settings-danger);\n}\n.settings-account-usage__sub {\n grid-column: 2 / -1;\n color: var(--account-muted);\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n overflow-wrap: anywhere;\n}\n.settings-account-usage__message,\n.settings-account-unknown {\n color: var(--settings-muted);\n}\n.settings-account-usage > button {\n justify-self: start;\n}\n.settings-account-actions {\n display: flex;\n justify-content: flex-end;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n.settings-account-action {\n padding: 8px 10px;\n min-height: 36px;\n font-size: 12px;\n color: var(--settings-text);\n background: transparent;\n border: 1px solid transparent;\n border-radius: 7px;\n white-space: nowrap;\n cursor: pointer;\n}\n.settings-account-action:hover {\n background: var(--settings-hover);\n}\n.settings-account-action:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.settings-account-actions .settings-account-delete {\n color: var(--settings-muted);\n}\n.settings-account-actions .settings-account-delete:hover,\n.settings-account-actions .settings-account-delete:focus-visible {\n color: var(--settings-danger);\n background: var(--settings-danger-bg);\n}\n.settings-account-mobile-label {\n display: none;\n}\n.settings-account-reset-summary {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n min-height: 32px;\n padding: 3px 0;\n font-size: 12px;\n white-space: nowrap;\n color: var(--settings-text);\n background: transparent;\n border: 0;\n border-radius: 5px;\n cursor: pointer;\n}\n.settings-account-reset-summary:hover {\n background: var(--settings-hover);\n}\n.settings-account-reset-summary[aria-expanded="true"] > svg:last-child {\n transform: rotate(90deg);\n}\n.settings-account-details-row > td {\n background: var(--settings-inset);\n}\n.settings-account-reset-details {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n flex-wrap: wrap;\n}\n.settings-account-reset-details strong {\n font-size: 12px;\n}\n.settings-account-reset-expiry {\n margin: 6px 0;\n color: var(--settings-muted);\n font-size: 11px;\n}\n.settings-account-reset-expiry.is-warn {\n color: var(--settings-warning);\n}\n.settings-account-reset-expiry.is-hot {\n color: var(--settings-danger);\n}\n.settings-account-reset-list {\n margin: 8px 0 0;\n padding: 0;\n list-style: none;\n color: var(--settings-muted);\n font-size: 11px;\n}\n.settings-account-reset-list li + li {\n margin-top: 4px;\n}\n.settings-account-empty {\n text-align: center;\n color: var(--settings-muted);\n}\n.settings-account-verification {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n color: var(--settings-muted);\n}\n.settings-account-verification a {\n color: var(--settings-focus);\n overflow-wrap: anywhere;\n}\n.settings-account-verification code {\n padding: 5px 8px;\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 600;\n letter-spacing: 0.08em;\n background: var(--settings-inset);\n border-radius: 6px;\n}\n.settings-account-list :focus-visible,\n.settings-account-toolbar :focus-visible,\n.settings-account-help-button:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: -2px;\n}\n\n@container (min-width: 611px) and (max-width: 800px) {\n .settings-account-table th,\n .settings-account-table td {\n padding-left: 12px;\n padding-right: 12px;\n }\n .settings-account-table th:nth-child(1) {\n width: 30%;\n }\n .settings-account-table th:nth-child(2) {\n width: 37%;\n }\n .settings-account-table th:nth-child(4) {\n width: 21%;\n }\n}\n\n@container (max-width: 610px) {\n .settings-account-table,\n .settings-account-table tbody {\n display: block;\n }\n .settings-account-table thead {\n display: none;\n }\n .settings-account-row {\n display: grid;\n grid-template-columns: 1fr 1fr;\n padding: 16px;\n gap: 12px;\n border-bottom: 1px solid var(--settings-divider);\n }\n .settings-account-table .settings-account-row > td {\n padding: 0;\n border: 0;\n }\n .settings-account-row > td:nth-child(1),\n .settings-account-row > td:nth-child(2) {\n grid-column: 1 / -1;\n }\n .settings-account-row > td:nth-child(3) {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .settings-account-mobile-label {\n display: inline;\n color: var(--settings-muted);\n font-size: 11px;\n }\n .settings-account-usage {\n max-width: none;\n }\n .settings-account-table tr:not(.settings-account-row),\n .settings-account-table tr:not(.settings-account-row) > td {\n display: block;\n }\n}\n\n@media (forced-colors: active) {\n .settings-account-usage__bar {\n border: 1px solid CanvasText;\n }\n .settings-account-usage__bar > span {\n background: Highlight;\n }\n}\n';
@@ -27014,8 +29399,10 @@ ${accounts_default}`;
27014
29399
  const pages = [
27015
29400
  createConnectionsSettingsPage(messages, options.getConnectionDiagnostics ?? (() => null)),
27016
29401
  createAccountsSettingsPage(messages, options.getAccountClient ?? (() => null)),
29402
+ createMcpSettingsPage(messages, options.getIntegrationsClient ?? (() => null)),
29403
+ createSkillsSettingsPage(messages, options.getIntegrationsClient ?? (() => null)),
27017
29404
  updatesPage(messages, options.getUpdateClient ?? (() => null)),
27018
- aboutPage(messages)
29405
+ aboutPage(messages, options.getUpdateClient ?? (() => null))
27019
29406
  ];
27020
29407
  const nextShell = installRendererSettingsShell(pages, messages, ownerWindow.document);
27021
29408
  const nextTrigger = installRendererSettingsHeaderTrigger({
@@ -27401,13 +29788,19 @@ ${accounts_default}`;
27401
29788
  const composer = editor.closest("[data-codex-composer-root]");
27402
29789
  if (!composer) return { agents: [], sessions: [] };
27403
29790
  const state = controller.get(composer);
27404
- if (state.agent === "codex") return { agents: [], sessions: [] };
27405
29791
  const client = modelClientForHost(modelControl?.currentHostId?.() ?? "local");
27406
29792
  const [agentResult, sessionResult] = await Promise.allSettled([
27407
29793
  client?.listCollaborationAgents?.() ?? Promise.resolve([]),
27408
29794
  client?.listHarnessSessions?.({ harnessId: harnessIdSchema.parse("all-harnesses"), query, offset: 0, limit: 12 }) ?? Promise.resolve({ candidates: [], total: 0 })
27409
29795
  ]);
27410
29796
  const agents = agentResult.status === "fulfilled" ? agentResult.value : [];
29797
+ window.__lastMentionDebug = {
29798
+ hasClient: !!client,
29799
+ agentStatus: agentResult.status,
29800
+ agentValue: agentResult.status === "fulfilled" ? agentResult.value : agentResult.reason?.message,
29801
+ sessionStatus: sessionResult.status,
29802
+ sessionValue: sessionResult.status === "fulfilled" ? sessionResult.value : sessionResult.reason?.message
29803
+ };
27411
29804
  const sessions = sessionResult.status === "fulfilled" ? sessionResult.value.candidates.map((candidate) => {
27412
29805
  const match = /^\[([^\]]+)\]\s*/.exec(candidate.title ?? "");
27413
29806
  return { id: candidate.nativeSessionId, title: (candidate.title ?? "\u672A\u547D\u540D\u4F1A\u8BDD").replace(/^\[[^\]]+\]\s*/, ""), harnessId: match?.[1] ?? "codex", cwd: candidate.cwd, running: candidate.running };
@@ -27430,6 +29823,11 @@ ${accounts_default}`;
27430
29823
  getUpdateClient: () => modelControl,
27431
29824
  getAccountClient: () => modelControl,
27432
29825
  getConnectionDiagnostics: () => connectionDiagnostics,
29826
+ getIntegrationsClient: () => {
29827
+ const client = modelClientForHost("local");
29828
+ if (!client?.integrationCatalog || !client.listIntegrations || !client.saveMcp || !client.removeMcp || !client.changeSkill) return null;
29829
+ return { integrationCatalog: () => client.integrationCatalog(), listIntegrations: (input) => client.listIntegrations(input), saveMcp: (input) => client.saveMcp(input), removeMcp: (input) => client.removeMcp(input), changeSkill: (input) => client.changeSkill(input) };
29830
+ },
27433
29831
  getSessionImportClient: () => {
27434
29832
  const client = modelClientForHost("local");
27435
29833
  const sources = client?.listSessionImportSources;
@@ -27553,7 +29951,7 @@ ${accounts_default}`;
27553
29951
  mounted.control,
27554
29952
  controller.get(mounted.composer),
27555
29953
  adapterStatus.state,
27556
- accounts?.switching === true || controller.isSwitching(mounted.composer) || mounted.ownershipStatus === "loading",
29954
+ accounts?.switching === true || controller.isSwitching(mounted.composer) || mounted.harnessSwitching || mounted.ownershipStatus === "loading",
27557
29955
  activeHarnessAvailabilityState().availability,
27558
29956
  mounted.modelView,
27559
29957
  mounted.permissionModeView,
@@ -27825,6 +30223,54 @@ ${accounts_default}`;
27825
30223
  }
27826
30224
  }
27827
30225
  };
30226
+ const handoffComposerThread = async (mounted, request) => {
30227
+ const threadId = threadIdFromComposerModelTarget(mounted.modelTarget);
30228
+ const current = controller.get(mounted.composer);
30229
+ if (!threadId || current.phase !== "locked" || current.agent === "codex" || current.agent !== request.from || request.to === current.agent || mounted.harnessSwitching) {
30230
+ return;
30231
+ }
30232
+ const client = modelClientForHostFrom(modelControl, mounted.hostId);
30233
+ if (!client?.switchHarness) {
30234
+ mounted.control.harnessHandoff.showError(
30235
+ settingsLifecycle.locale === "zh-CN" ? "\u5F53\u524D\u4EFB\u52A1\u65E0\u6CD5\u4F7F\u7528 Harness \u63A5\u529B\u3002" : "Harness handoff is unavailable for this task."
30236
+ );
30237
+ return;
30238
+ }
30239
+ mounted.harnessSwitching = true;
30240
+ mounted.control.harnessHandoff.setSubmitting(true);
30241
+ renderMounted(mounted);
30242
+ try {
30243
+ await client.switchHarness({
30244
+ threadId,
30245
+ harnessId: externalHarnessIds[request.to],
30246
+ ...request.note ? { note: request.note } : {},
30247
+ intent: request.intent,
30248
+ includes: request.includes
30249
+ });
30250
+ if (disposed || mountedByComposer.get(mounted.composer) !== mounted || threadIdFromComposerModelTarget(mounted.modelTarget) !== threadId) {
30251
+ return;
30252
+ }
30253
+ mounted.harnessSwitching = false;
30254
+ mounted.control.harnessHandoff.setSubmitting(false);
30255
+ mounted.control.harnessHandoff.close();
30256
+ mounted.modelView = { status: "loading" };
30257
+ mounted.permissionModeView = { status: "loading" };
30258
+ mounted.threadConfiguration = void 0;
30259
+ mounted.usage = null;
30260
+ mounted.accountCredits = null;
30261
+ await loadThreadOwnership(mounted);
30262
+ } catch (error51) {
30263
+ mounted.control.harnessHandoff.showError(
30264
+ error51 instanceof Error ? error51.message : String(error51)
30265
+ );
30266
+ } finally {
30267
+ if (mountedByComposer.get(mounted.composer) === mounted) {
30268
+ mounted.harnessSwitching = false;
30269
+ mounted.control.harnessHandoff.setSubmitting(false);
30270
+ renderMounted(mounted);
30271
+ }
30272
+ }
30273
+ };
27828
30274
  const refreshMountedConversationTarget = (mounted) => {
27829
30275
  const currentTarget = findComposerModelTarget(mounted.composer);
27830
30276
  const resolution = lateConversationTargetResolution(
@@ -28517,9 +30963,8 @@ ${accounts_default}`;
28517
30963
  await policy.clear();
28518
30964
  if (!isCurrent() || window.__codexhostDraftPrewarmPolicyV1 !== policy) return;
28519
30965
  if (!policy.selectAccount) throw new Error("Codex Account selection is unavailable");
28520
- const override = accountId === accounts.selection.activeAccountId ? null : accountId;
28521
- policy.selectAccount(override);
28522
- accounts.overrideAccountId = override;
30966
+ policy.selectAccount(codexAccountRouteOverride(accounts.accounts, accountId));
30967
+ accounts.overrideAccountId = accountId === accounts.selection.activeAccountId ? null : accountId;
28523
30968
  } catch {
28524
30969
  if (isCurrent()) void loadCodexAccounts();
28525
30970
  } finally {
@@ -28809,6 +31254,13 @@ ${accounts_default}`;
28809
31254
  (agent) => {
28810
31255
  const mounted2 = mountedByComposer.get(composer);
28811
31256
  if (!composer.isConnected || !mounted2) return;
31257
+ const current = controller.get(composer);
31258
+ if (current.phase === "locked") {
31259
+ if (current.agent !== "codex" && agent !== "codex") {
31260
+ mounted2.control.harnessHandoff.open(current.agent, agent, settingsLifecycle.locale);
31261
+ }
31262
+ return;
31263
+ }
28812
31264
  void switchComposerAgent(mounted2, agent);
28813
31265
  },
28814
31266
  openInstallPage,
@@ -28838,6 +31290,11 @@ ${accounts_default}`;
28838
31290
  (command) => {
28839
31291
  const mounted2 = mountedByComposer.get(composer);
28840
31292
  if (mounted2) selectCommand(mounted2, command);
31293
+ },
31294
+ (request) => {
31295
+ const mounted2 = mountedByComposer.get(composer);
31296
+ if (!composer.isConnected || !mounted2) return;
31297
+ void handoffComposerThread(mounted2, request);
28841
31298
  }
28842
31299
  );
28843
31300
  const mounted = {
@@ -28853,7 +31310,8 @@ ${accounts_default}`;
28853
31310
  accountCredits: inherited?.accountCredits ?? null,
28854
31311
  hostId: inherited?.hostId ?? hostId,
28855
31312
  usageRequestGeneration: 0,
28856
- commandRequestGeneration: 0
31313
+ commandRequestGeneration: 0,
31314
+ harnessSwitching: false
28857
31315
  };
28858
31316
  mountedByComposer.set(composer, mounted);
28859
31317
  if (isComposerModelWriteAllowed(modelTarget)) {
@@ -29020,7 +31478,10 @@ ${accounts_default}`;
29020
31478
  if (current.agent === "codex") {
29021
31479
  const selection = composerCodexAccounts(composer)?.selection;
29022
31480
  const accountId = controller.isSubmissionPending(composer) && current.codexAccountId ? current.codexAccountId : selection?.selectedAccountId;
29023
- const override = accountId === selection?.activeAccountId ? null : accountId ?? null;
31481
+ const override = codexAccountRouteOverride(
31482
+ composerCodexAccounts(composer)?.accounts ?? [],
31483
+ accountId
31484
+ );
29024
31485
  const policy = window.__codexhostDraftPrewarmPolicyV1;
29025
31486
  if (override !== null && (policy?.hostId !== mounted.hostId || !policy.selectAccount)) {
29026
31487
  return false;
@@ -29065,7 +31526,7 @@ ${accounts_default}`;
29065
31526
  const onKeyDown = (event) => {
29066
31527
  const composer = isComposerInputIntent(event) ? composerForTarget(event.target) : null;
29067
31528
  const mounted = composer ? mountedByComposer.get(composer) : void 0;
29068
- if (composer && (composerCodexAccounts(composer)?.switching || controller.isSwitching(composer))) {
31529
+ if (composer && (composerCodexAccounts(composer)?.switching || controller.isSwitching(composer) || mounted?.harnessSwitching)) {
29069
31530
  if (isComposerSubmissionKey(event)) blockEvent(event);
29070
31531
  return;
29071
31532
  }