@xopcai/xopc 0.0.274 → 0.0.275

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 (128) hide show
  1. package/dist/browser-ext/_locales/en/messages.json +215 -0
  2. package/dist/browser-ext/_locales/zh_CN/messages.json +215 -0
  3. package/dist/browser-ext/dist/assets/{auth-O8RiOF3l.js → auth-ClQTK565.js} +97 -38
  4. package/dist/browser-ext/dist/assets/{sidepanel-C86O7q5Y.css → sidepanel-CeGqObOa.css} +41 -20
  5. package/dist/browser-ext/dist/background.js +36 -4
  6. package/dist/browser-ext/dist/sidepanel.html +2 -2
  7. package/dist/browser-ext/dist/sidepanel.js +416 -299
  8. package/dist/browser-ext/manifest.json +6 -4
  9. package/dist/extensions/telegram/xopc.extension.json +1 -1
  10. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BckaANxj.js → agent-avatar-dicebear-Dx6x7MXq.js} +1 -1
  11. package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-B8eyC6K1.js → agent-defaults-settings-panel-BuxTpjkf.js} +1 -1
  12. package/dist/gateway/static/root/assets/{agents-CSWj_yo1.js → agents-_f9HEOol.js} +1 -1
  13. package/dist/gateway/static/root/assets/{app-management-settings-panel-DY-Zbgmt.js → app-management-settings-panel-BYKWXcVl.js} +1 -1
  14. package/dist/gateway/static/root/assets/{appearance-settings-CoJR7ZRl.js → appearance-settings-BmhSJc4X.js} +1 -1
  15. package/dist/gateway/static/root/assets/apps-page-DYTnK9lL.js +1 -0
  16. package/dist/gateway/static/root/assets/{archive-plugin-BwAlRT53.js → archive-plugin-BY6ncIeE.js} +1 -1
  17. package/dist/gateway/static/root/assets/{attachment-load-R835uxgL.js → attachment-load-B6cw8KtO.js} +1 -1
  18. package/dist/gateway/static/root/assets/{automations-page-BEZy0P_u.js → automations-page-D1WwsSf3.js} +1 -1
  19. package/dist/gateway/static/root/assets/automations-workspace-CjF56MI_.js +6 -0
  20. package/dist/gateway/static/root/assets/{binary-plugins-CESFx3yb.js → binary-plugins-CC-wYm0K.js} +1 -1
  21. package/dist/gateway/static/root/assets/{block-editor-DDJcf2wR.js → block-editor-D8rh9KNe.js} +3 -3
  22. package/dist/gateway/static/root/assets/{browser-automations-page-BH4lSfr5.js → browser-automations-page-CMrffyct.js} +2 -2
  23. package/dist/gateway/static/root/assets/browser-settings-page-1onvP1Se.js +8 -0
  24. package/dist/gateway/static/root/assets/capabilities-settings-panel-C9ZSJxjr.js +8 -0
  25. package/dist/gateway/static/root/assets/channels-settings-CvLTnI99.js +1 -0
  26. package/dist/gateway/static/root/assets/{chat-terminal-dock-D8U97O95.js → chat-terminal-dock-F_dUdZ8l.js} +2 -2
  27. package/dist/gateway/static/root/assets/connectors-page-D7NHV8B2.js +2 -0
  28. package/dist/gateway/static/root/assets/{date-picker-7sDSMswL.js → date-picker-MHuajwQ-.js} +1 -1
  29. package/dist/gateway/static/root/assets/{dependency-picker-DMIC86ZW.js → dependency-picker-BcMJJI9X.js} +1 -1
  30. package/dist/gateway/static/root/assets/{desktop-pet-BtdiY5jK.js → desktop-pet-DlNm_7H0.js} +1 -1
  31. package/dist/gateway/static/root/assets/{desktop-pet-settings-D_B8azDH.js → desktop-pet-settings-BI1JQMnE.js} +1 -1
  32. package/dist/gateway/static/root/assets/device-pairing-wizard-Cp5jO5B_.js +1 -0
  33. package/dist/gateway/static/root/assets/{extension-debug-page-CoFKb01d.js → extension-debug-page-DZr0GkkA.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-page-CEkNsCAY.js → extension-page-QsHoQ6VX.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-settings-page-Bi2R8P5j.js → extension-settings-page-I2YX4Tzb.js} +1 -1
  36. package/dist/gateway/static/root/assets/gateway-settings-GwfQu8rN.js +1 -0
  37. package/dist/gateway/static/root/assets/{heartbeat-settings-DQtelFiU.js → heartbeat-settings-D-hVYXzL.js} +1 -1
  38. package/dist/gateway/static/root/assets/home-page-SEW_0k8Q.js +1 -0
  39. package/dist/gateway/static/root/assets/{index-SxqsTD4i.js → index-DfZZLrWp.js} +34 -34
  40. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BuYmZS1K.js → keyboard-shortcuts-settings-D_I-hiG2.js} +1 -1
  41. package/dist/gateway/static/root/assets/local-app-workbench-page-BcY7wIHs.js +2 -0
  42. package/dist/gateway/static/root/assets/{local-apps-page-CExnZyGZ.js → local-apps-page-DniZuXJJ.js} +1 -1
  43. package/dist/gateway/static/root/assets/{logs-page-CA5ArMoN.js → logs-page-DIiOMrJ_.js} +2 -2
  44. package/dist/gateway/static/root/assets/{management-settings-1UiJPrkX.js → management-settings-BPw41YX6.js} +1 -1
  45. package/dist/gateway/static/root/assets/{media-plugins-nNFOk9HL.js → media-plugins-BoP3LSQz.js} +1 -1
  46. package/dist/gateway/static/root/assets/note-detail-panel-BI2xr54R.js +5 -0
  47. package/dist/gateway/static/root/assets/notes-page-CM7Ns8i1.js +8 -0
  48. package/dist/gateway/static/root/assets/{page-tabs-CRombigq.js → page-tabs-B21WfV92.js} +1 -1
  49. package/dist/gateway/static/root/assets/{preview-open-alternatives-Bcuj43lk.js → preview-open-alternatives-BZoDpPqV.js} +1 -1
  50. package/dist/gateway/static/root/assets/{proactive-card-Cb3Xeoyx.js → proactive-card-Bw9CbzUX.js} +1 -1
  51. package/dist/gateway/static/root/assets/{proactive-page-TbF9KVpm.js → proactive-page-Czw_CEDB.js} +1 -1
  52. package/dist/gateway/static/root/assets/project-detail-page-jOECabbf.js +1 -0
  53. package/dist/gateway/static/root/assets/projects-page-Ck9j5q0x.js +1 -0
  54. package/dist/gateway/static/root/assets/remote-access-hub-2xcpaLTC.js +1 -0
  55. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-BudlvBu-.js → runtime-tools-settings-panel-Bz5gIRjy.js} +2 -2
  56. package/dist/gateway/static/root/assets/{schema-form-Ch3MEX4h.js → schema-form-CqM0ntNm.js} +1 -1
  57. package/dist/gateway/static/root/assets/sessions-page-CE9MK60k.js +1 -0
  58. package/dist/gateway/static/root/assets/settings-advanced-gate-D0grhQan.js +1 -0
  59. package/dist/gateway/static/root/assets/{settings-form-section-CIA1AA-A.js → settings-form-section-LqcDYJ2m.js} +1 -1
  60. package/dist/gateway/static/root/assets/{settings-page-B0Khoduh.js → settings-page-BpvBmheO.js} +1 -1
  61. package/dist/gateway/static/root/assets/setup-status-panel-CYuqNzWH.js +1 -0
  62. package/dist/gateway/static/root/assets/{share-preview-page-Cj9XWg-X.js → share-preview-page-F3qhAryJ.js} +1 -1
  63. package/dist/gateway/static/root/assets/shares-settings-B4wSoQM3.js +1 -0
  64. package/dist/gateway/static/root/assets/{skill-reload-api-BM4Ezjbx.js → skill-reload-api-C3LD7fkR.js} +1 -1
  65. package/dist/gateway/static/root/assets/{skills-page-Dyh1kf9t.js → skills-page-D9fI548d.js} +1 -1
  66. package/dist/gateway/static/root/assets/{skills-page.utils-DsQZkMti.js → skills-page.utils-DZNmyYqU.js} +1 -1
  67. package/dist/gateway/static/root/assets/{system-settings-panel-BSho_Tpk.js → system-settings-panel-CMsmFOhV.js} +1 -1
  68. package/dist/gateway/static/root/assets/task-detail-page-DRwTJ8E0.js +1 -0
  69. package/dist/gateway/static/root/assets/{tunnel-api-4DUHxSQG.js → tunnel-api-DGaqXwql.js} +1 -1
  70. package/dist/gateway/static/root/assets/{use-autosave-BG8Yx7hj.js → use-autosave-bXCl0Y0j.js} +1 -1
  71. package/dist/gateway/static/root/assets/user-model-page-B3RjDSri.js +2 -0
  72. package/dist/gateway/static/root/assets/{voice-api-key-field-DYXwDhHq.js → voice-api-key-field-Cx9rl7mP.js} +1 -1
  73. package/dist/gateway/static/root/assets/{work-discovery-overlay-CQqjzaRo.js → work-discovery-overlay-ywJpaqKp.js} +1 -1
  74. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-C5H-Fd-U.js → workflow-run-setup-panel-DyGukxOL.js} +2 -2
  75. package/dist/gateway/static/root/assets/workflows-page-CifIqO2B.js +6 -0
  76. package/dist/gateway/static/root/index.html +1 -1
  77. package/dist/package.js +1 -1
  78. package/dist/src/agent/child-agent-factory.d.ts +3 -0
  79. package/dist/src/agent/child-agent-factory.js +2 -1
  80. package/dist/src/agent/external-tools/endpoint-provider.js +1 -1
  81. package/dist/src/agent/tools/factory.d.ts +1 -0
  82. package/dist/src/agent/tools/factory.js +21 -4
  83. package/dist/src/agent/workflow/workflow-child-tools.js +2 -0
  84. package/dist/src/browser/providers/browser-ext-install.d.ts +1 -1
  85. package/dist/src/browser/providers/browser-ext-install.js +8 -3
  86. package/dist/src/browser/providers/realtime-extension.d.ts +4 -1
  87. package/dist/src/browser/providers/realtime-extension.js +26 -10
  88. package/dist/src/browser/readiness.d.ts +4 -1
  89. package/dist/src/browser/readiness.js +11 -5
  90. package/dist/src/cli/commands/onboard.js +1 -1
  91. package/dist/src/gateway/gateway-workflow-host.types.d.ts +2 -0
  92. package/dist/src/gateway/heartbeat/service.js +1 -1
  93. package/dist/src/gateway/hono/routes/browser.js +24 -11
  94. package/dist/src/gateway/hono/routes/endpoint-tools.js +9 -0
  95. package/dist/src/gateway/hono/routes/models.js +6 -0
  96. package/dist/src/gateway/hono/routes/voice.js +1 -1
  97. package/dist/src/heartbeat/index.js +1 -1
  98. package/dist/src/providers/model-catalog-persistence.js +4 -0
  99. package/dist/src/providers/model-catalog-types.d.ts +1 -0
  100. package/dist/src/providers/xopc-cloud-model-source.js +12 -1
  101. package/dist/src/storage/sqlite/endpoint-session-binding-repository.d.ts +1 -0
  102. package/dist/src/storage/sqlite/endpoint-session-binding-repository.js +9 -1
  103. package/dist/src/storage/sqlite/index.d.ts +1 -1
  104. package/dist/src/storage/sqlite/index.js +2 -2
  105. package/dist/src/workflows/service/workflow-run-service.js +4 -1
  106. package/package.json +3 -3
  107. package/dist/gateway/static/root/assets/apps-page-CSMvkuot.js +0 -1
  108. package/dist/gateway/static/root/assets/automations-workspace-CpaI13J7.js +0 -6
  109. package/dist/gateway/static/root/assets/browser-settings-page-CbTooPd2.js +0 -8
  110. package/dist/gateway/static/root/assets/capabilities-settings-panel-C4LZWHhv.js +0 -8
  111. package/dist/gateway/static/root/assets/channels-settings-BAljmSa7.js +0 -1
  112. package/dist/gateway/static/root/assets/connectors-page-CVRMjNNr.js +0 -2
  113. package/dist/gateway/static/root/assets/device-pairing-wizard-Dmh3Nh4d.js +0 -1
  114. package/dist/gateway/static/root/assets/gateway-settings-q9p3sduo.js +0 -1
  115. package/dist/gateway/static/root/assets/home-page-COpGnTFZ.js +0 -1
  116. package/dist/gateway/static/root/assets/local-app-workbench-page-DV_17Zxc.js +0 -2
  117. package/dist/gateway/static/root/assets/note-detail-panel-B5OQ0fBY.js +0 -5
  118. package/dist/gateway/static/root/assets/notes-page-CVPPMVDl.js +0 -8
  119. package/dist/gateway/static/root/assets/project-detail-page-B9OQ2l9x.js +0 -1
  120. package/dist/gateway/static/root/assets/projects-page-DCqSTNkY.js +0 -1
  121. package/dist/gateway/static/root/assets/remote-access-hub-d9Fg70gX.js +0 -1
  122. package/dist/gateway/static/root/assets/sessions-page-D8RiQ-ag.js +0 -1
  123. package/dist/gateway/static/root/assets/settings-advanced-gate-DVH_l6Hr.js +0 -1
  124. package/dist/gateway/static/root/assets/setup-status-panel-COJFl4N_.js +0 -1
  125. package/dist/gateway/static/root/assets/shares-settings-_OuE6A0G.js +0 -1
  126. package/dist/gateway/static/root/assets/task-detail-page-B5HWM12k.js +0 -1
  127. package/dist/gateway/static/root/assets/user-model-page-IjVyv5jj.js +0 -2
  128. package/dist/gateway/static/root/assets/workflows-page-D1hMyPsY.js +0 -6
@@ -30,12 +30,15 @@ const STAGING_MAX_AGE_MS = 3600 * 1e3;
30
30
  const INSTALLED_ARTIFACT_NAMES = [
31
31
  "manifest.json",
32
32
  "dist",
33
- "icons"
33
+ "icons",
34
+ "_locales"
34
35
  ];
35
36
  const BROWSER_EXT_REQUIRED_FILES = [
36
37
  "manifest.json",
37
38
  "dist/background.js",
38
- "dist/sidepanel.html"
39
+ "dist/sidepanel.html",
40
+ "_locales/en/messages.json",
41
+ "_locales/zh_CN/messages.json"
39
42
  ];
40
43
  function moduleDir() {
41
44
  return dirname(fileURLToPath(import.meta.url));
@@ -53,7 +56,8 @@ function browserExtContentHash(dir) {
53
56
  const relativePaths = [
54
57
  "manifest.json",
55
58
  ...collectFiles("dist"),
56
- ...collectFiles("icons")
59
+ ...collectFiles("icons"),
60
+ ...collectFiles("_locales")
57
61
  ].sort();
58
62
  for (const relativePath of relativePaths) {
59
63
  hash.update(relativePath);
@@ -220,6 +224,7 @@ function copyBundledTree(src, dest) {
220
224
  mkdirSync(dest, { recursive: true });
221
225
  copyBundledFile(join(src, "manifest.json"), join(dest, "manifest.json"));
222
226
  copyBundledDirectory(join(src, "dist"), join(dest, "dist"));
227
+ copyBundledDirectory(join(src, "_locales"), join(dest, "_locales"));
223
228
  for (const icon of BROWSER_EXT_ICON_FILES) {
224
229
  const iconSrc = join(src, "icons", icon);
225
230
  if (existsSync(iconSrc)) copyBundledFile(iconSrc, join(dest, "icons", icon));
@@ -21,9 +21,12 @@ export declare class RealtimeExtensionBrowserProvider {
21
21
  expectedProtocolVersion: number;
22
22
  extensionVersion: string;
23
23
  principalId: string;
24
+ endpointCount: number;
25
+ selectionRequired: boolean;
24
26
  transport: "gateway-realtime";
25
27
  };
26
28
  shutdown(): Promise<void>;
27
29
  private endpointForInput;
28
- private currentEndpoint;
30
+ private defaultEndpoint;
31
+ private browserEndpoints;
29
32
  }
@@ -14,14 +14,18 @@ var RealtimeExtensionBrowserProvider = class {
14
14
  async start() {}
15
15
  async waitForConnection(timeoutMs = this.connectionTimeout) {
16
16
  const deadline = Date.now() + timeoutMs;
17
- while (!this.currentEndpoint()) {
17
+ while (this.browserEndpoints().length === 0) {
18
18
  if (Date.now() >= deadline) throw new Error(`Extension connection timeout after ${timeoutMs}ms. Open the xopc Chrome extension and connect it to this Gateway.`);
19
19
  await new Promise((resolve) => setTimeout(resolve, 200));
20
20
  }
21
21
  }
22
22
  async send(input, timeoutMs = this.commandTimeout, visualFallback = true) {
23
23
  const endpoint = this.endpointForInput(input);
24
- if (!endpoint) throw new Error("Extension not connected to this Gateway. Open the xopc Chrome extension and connect it first.");
24
+ if (!endpoint) {
25
+ if (input.target?.kind === "endpoint") throw new Error(`The Chrome endpoint bound to this Session is offline (${input.target.endpointId}). Reconnect that browser or bind another one.`);
26
+ if (this.browserEndpoints().length > 1) throw new Error("Multiple Chrome extensions are connected. Attach this Session to a tab or choose a browser device first.");
27
+ throw new Error("Extension not connected to this Gateway. Open the xopc Chrome extension and connect it first.");
28
+ }
25
29
  const tool = this.runtime.registry.getTool(endpoint.endpointId, BROWSER_CONTROL_ENDPOINT_TOOL_NAME);
26
30
  if (!tool) throw new Error("Connected browser extension does not support authenticated Realtime browser control. Reload or update the extension.");
27
31
  const id = crypto.randomUUID();
@@ -51,17 +55,20 @@ var RealtimeExtensionBrowserProvider = class {
51
55
  }
52
56
  }
53
57
  isConnected() {
54
- return Boolean(this.currentEndpoint());
58
+ return this.browserEndpoints().length > 0;
55
59
  }
56
60
  getConnectionStatus() {
57
- const endpoint = this.currentEndpoint();
61
+ const endpoints = this.browserEndpoints();
62
+ const endpoint = endpoints.length === 1 ? endpoints[0] : void 0;
58
63
  return {
59
- socketConnected: Boolean(endpoint),
60
- connected: Boolean(endpoint),
61
- protocolVersion: endpoint ? 4 : null,
64
+ socketConnected: endpoints.length > 0,
65
+ connected: endpoints.length > 0,
66
+ protocolVersion: endpoints.length > 0 ? 4 : null,
62
67
  expectedProtocolVersion: 4,
63
68
  extensionVersion: endpoint?.appVersion ?? null,
64
69
  principalId: endpoint?.principalId ?? null,
70
+ endpointCount: endpoints.length,
71
+ selectionRequired: endpoints.length > 1,
65
72
  transport: "gateway-realtime"
66
73
  };
67
74
  }
@@ -73,10 +80,19 @@ var RealtimeExtensionBrowserProvider = class {
73
80
  if (!binding || !endpoint || endpoint.principalId !== binding.principalId) return void 0;
74
81
  return endpoint;
75
82
  }
76
- return this.currentEndpoint();
83
+ if (input.target?.kind === "endpoint") {
84
+ const endpoint = this.runtime.registry.get(input.target.endpointId);
85
+ if (!endpoint || endpoint.kind !== "browser" || !endpoint.tools.some((tool) => tool.descriptor.name === "browser.control")) return;
86
+ return endpoint;
87
+ }
88
+ return this.defaultEndpoint();
89
+ }
90
+ defaultEndpoint() {
91
+ const endpoints = this.browserEndpoints();
92
+ return endpoints.length === 1 ? endpoints[0] : void 0;
77
93
  }
78
- currentEndpoint() {
79
- return this.runtime.registry.list().filter((endpoint) => endpoint.kind === "browser" && endpoint.tools.some((tool) => tool.descriptor.name === "browser.control")).sort((left, right) => right.lastHeartbeatAt - left.lastHeartbeatAt)[0];
94
+ browserEndpoints() {
95
+ return this.runtime.registry.list().filter((endpoint) => endpoint.kind === "browser" && endpoint.tools.some((tool) => tool.descriptor.name === "browser.control")).sort((left, right) => right.lastHeartbeatAt - left.lastHeartbeatAt);
80
96
  }
81
97
  };
82
98
  //#endregion
@@ -12,4 +12,7 @@ export declare class BrowserNotReadyError extends Error {
12
12
  constructor(hint: BrowserSetupHint);
13
13
  }
14
14
  export declare function buildBrowserSetupDeepLink(driver: BrowserDriverKind): string;
15
- export declare function checkBrowserReadiness(cfg: Config | undefined): Promise<BrowserNotReadyError | null>;
15
+ export declare function checkBrowserReadiness(cfg: Config | undefined, options?: {
16
+ extensionConnected?: boolean;
17
+ checkExtensionInstall?: boolean;
18
+ }): Promise<BrowserNotReadyError | null>;
@@ -14,17 +14,23 @@ var BrowserNotReadyError = class extends Error {
14
14
  function buildBrowserSetupDeepLink(driver) {
15
15
  return `/settings/agent-browser?driver=${driver}`;
16
16
  }
17
- async function checkBrowserReadiness(cfg) {
17
+ async function checkBrowserReadiness(cfg, options = {}) {
18
18
  if (!cfg?.browser.enabled) return null;
19
19
  const driver = cfg.browser.driver;
20
20
  let detail = null;
21
21
  let reason = null;
22
22
  try {
23
23
  if (driver.kind === "extension") {
24
- const { browserExtDoctor } = await import("./providers/browser-ext-install.js");
25
- if (!(await browserExtDoctor()).installed) {
26
- reason = "extension_not_installed";
27
- detail = "Chrome extension artifacts are not installed.";
24
+ if (options.extensionConnected) return null;
25
+ if (options.checkExtensionInstall === false) {
26
+ reason = "extension_not_connected";
27
+ detail = "No authenticated Chrome extension endpoint is connected.";
28
+ } else {
29
+ const { browserExtDoctor } = await import("./providers/browser-ext-install.js");
30
+ if (!(await browserExtDoctor()).installed) {
31
+ reason = "extension_not_installed";
32
+ detail = "Chrome extension artifacts are not installed.";
33
+ }
28
34
  }
29
35
  } else if (driver.kind === "playwright") if (driver.executablePath) await access(driver.executablePath);
30
36
  else {
@@ -4,8 +4,8 @@ import { saveConfig } from "../../config/loader.js";
4
4
  import { resolveGatewayLocalClientHost } from "../../config/gateway-bind.js";
5
5
  import { formatExamples, register } from "../registry.js";
6
6
  import "../../config/index.js";
7
- import { provisionEagerRuntimes } from "../../runtime-tools/bootstrap.js";
8
7
  import { colors } from "../utils/colors.js";
8
+ import { provisionEagerRuntimes } from "../../runtime-tools/bootstrap.js";
9
9
  import { initWorkspace } from "../utils/init-workspace.js";
10
10
  import { setupModel } from "./onboard/model.js";
11
11
  import { getChannelConfigurators } from "./onboard/channels/registry.js";
@@ -1,4 +1,5 @@
1
1
  import type { Config } from '../config/schema.js';
2
+ import type { EndpointToolRuntime } from '../endpoint-tools/index.js';
2
3
  import type { MessageBus } from '../infra/bus/index.js';
3
4
  import type { SessionStore } from '../session/store.js';
4
5
  export interface GatewayWorkflowAgentSurface {
@@ -10,6 +11,7 @@ export interface GatewayWorkflowHost {
10
11
  readonly currentWorkspacePath: string;
11
12
  readonly messageBusInstance: MessageBus;
12
13
  readonly agentService: GatewayWorkflowAgentSurface;
14
+ readonly endpointTools?: EndpointToolRuntime;
13
15
  emit(event: string, payload: unknown): void;
14
16
  readonly sessionIndexInstance: {
15
17
  getStore(): SessionStore;
@@ -1,9 +1,9 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { shouldSilence, stripHeartbeatToken } from "../../heartbeat/tokens.js";
4
- import { appendCronEventLines } from "../../heartbeat/event-prompt.js";
5
4
  import { isWithinActiveHours } from "../../heartbeat/active-hours.js";
6
5
  import { isHeartbeatContentEmpty } from "../../heartbeat/content-check.js";
6
+ import { appendCronEventLines } from "../../heartbeat/event-prompt.js";
7
7
  import { createHeartbeatWake } from "../../heartbeat/wake.js";
8
8
  import { resolveHeartbeatMdPath } from "../workspace-heartbeat-path.js";
9
9
  import { readFile } from "fs/promises";
@@ -10,12 +10,12 @@ import { getGatewayPrincipal } from "../../security/gateway-principal.js";
10
10
  import { getConnInfo } from "@hono/node-server/conninfo";
11
11
  //#region src/gateway/hono/routes/browser.ts
12
12
  /** Browser Control status, approvals, and driver diagnostics. */
13
- async function extensionStatus(service) {
14
- const endpoint = service.endpointTools.registry.list().filter((item) => item.kind === "browser" && item.tools.some((tool) => tool.descriptor.name === "browser.control")).sort((left, right) => right.lastHeartbeatAt - left.lastHeartbeatAt)[0];
15
- const connected = Boolean(endpoint);
13
+ async function extensionStatus(service, includeLocalArtifacts) {
14
+ const endpoints = service.endpointTools.registry.list().filter((item) => item.kind === "browser" && item.tools.some((tool) => tool.descriptor.name === "browser.control")).sort((left, right) => right.lastHeartbeatAt - left.lastHeartbeatAt);
15
+ const endpoint = endpoints[0];
16
+ const connected = endpoints.length > 0;
16
17
  const extensionVersion = endpoint?.appVersion ?? null;
17
- const { browserExtDoctor } = await import("../../../browser/providers/browser-ext-install.js");
18
- const doctor = await browserExtDoctor({ runtimeExtensionVersion: extensionVersion ?? void 0 });
18
+ const doctor = includeLocalArtifacts ? await import("../../../browser/providers/browser-ext-install.js").then(({ browserExtDoctor }) => browserExtDoctor({ runtimeExtensionVersion: extensionVersion ?? void 0 })) : void 0;
19
19
  return {
20
20
  running: true,
21
21
  socketConnected: connected,
@@ -24,7 +24,15 @@ async function extensionStatus(service) {
24
24
  protocolVersion: connected ? 4 : null,
25
25
  expectedProtocolVersion: 4,
26
26
  extensionVersion,
27
- artifacts: {
27
+ endpoints: endpoints.map((item) => ({
28
+ endpointId: item.endpointId,
29
+ principalId: item.principalId,
30
+ displayName: item.displayName,
31
+ platform: item.platform,
32
+ appVersion: item.appVersion,
33
+ lastHeartbeatAt: item.lastHeartbeatAt
34
+ })),
35
+ artifacts: { ...doctor ? {
28
36
  installed: doctor.installed,
29
37
  bundledAvailable: doctor.bundledAvailable,
30
38
  extensionDir: doctor.extensionDir,
@@ -33,9 +41,9 @@ async function extensionStatus(service) {
33
41
  needsRefresh: doctor.needsRefresh,
34
42
  needsChromeReload: doctor.needsChromeReload,
35
43
  nativeHost: doctor.nativeHost
36
- },
44
+ } : {} },
37
45
  bridgeHeld: false,
38
- refCount: connected ? 1 : 0,
46
+ refCount: endpoints.length,
39
47
  transport: "gateway-realtime"
40
48
  };
41
49
  }
@@ -148,7 +156,7 @@ function registerBrowserRoutes(authenticated, deps) {
148
156
  });
149
157
  authenticated.get("/api/browser/extension-status", async (c) => {
150
158
  try {
151
- return c.json(await extensionStatus(service));
159
+ return c.json(await extensionStatus(service, isLocalOwnerRequest(c, service)));
152
160
  } catch (error) {
153
161
  return c.json({
154
162
  running: false,
@@ -160,6 +168,7 @@ function registerBrowserRoutes(authenticated, deps) {
160
168
  });
161
169
  authenticated.get("/api/browser/status", async (c) => {
162
170
  const config = service.currentConfig.browser;
171
+ const localManagementAvailable = isLocalOwnerRequest(c, service);
163
172
  if (!config.enabled) return c.json({
164
173
  ok: true,
165
174
  payload: {
@@ -168,15 +177,19 @@ function registerBrowserRoutes(authenticated, deps) {
168
177
  state: "disabled"
169
178
  }
170
179
  });
171
- const readiness = await checkBrowserReadiness(service.currentConfig);
172
- const driverStatus = config.driver.kind === "extension" ? await extensionStatus(service).catch((error) => ({ error: error instanceof Error ? error.message : String(error) })) : config.driver.kind === "playwright" ? await import("../../../browser/providers/playwright-doctor.js").then(({ playwrightChromiumDoctor }) => playwrightChromiumDoctor()) : void 0;
180
+ const driverStatus = config.driver.kind === "extension" ? await extensionStatus(service, localManagementAvailable).catch((error) => ({ error: error instanceof Error ? error.message : String(error) })) : config.driver.kind === "playwright" ? await import("../../../browser/providers/playwright-doctor.js").then(({ playwrightChromiumDoctor }) => playwrightChromiumDoctor()) : void 0;
173
181
  const extensionConnected = config.driver.kind === "extension" ? driverStatus.connected === true : true;
182
+ const readiness = await checkBrowserReadiness(service.currentConfig, {
183
+ extensionConnected,
184
+ checkExtensionInstall: localManagementAvailable
185
+ });
174
186
  const extensionProtocolDetail = config.driver.kind === "extension" && "socketConnected" in driverStatus && driverStatus.socketConnected && !driverStatus.connected ? `Chrome extension protocol ${driverStatus.protocolVersion ?? "unknown"} does not match ${driverStatus.expectedProtocolVersion ?? "the gateway"}. Reload the extension in Chrome.` : void 0;
175
187
  return c.json({
176
188
  ok: true,
177
189
  payload: {
178
190
  enabled: true,
179
191
  driverKind: config.driver.kind,
192
+ localManagementAvailable,
180
193
  state: !readiness && extensionConnected ? "ready" : "needs_attention",
181
194
  reason: readiness?.hint.reason ?? (extensionConnected ? void 0 : "extension_not_connected"),
182
195
  detail: readiness?.hint.detail ?? extensionProtocolDetail,
@@ -177,6 +177,15 @@ function registerEndpointToolRoutes(authenticated, deps) {
177
177
  message: "Invalid endpoint binding"
178
178
  }
179
179
  }, 400);
180
+ const gatewayPrincipal = getGatewayPrincipal(c);
181
+ const endpoint = deps.service.endpointTools.registry.get(parsed.data.endpointId);
182
+ if (gatewayPrincipal.kind === "device" && (!endpoint || !gatewayPrincipal.deviceId || endpoint.principalId !== gatewayPrincipal.deviceId)) return c.json({
183
+ ok: false,
184
+ error: {
185
+ code: "FORBIDDEN",
186
+ message: "Endpoint does not belong to this device"
187
+ }
188
+ }, 403);
180
189
  try {
181
190
  const binding = deps.service.endpointTools.bindings.bind(c.req.param("sessionKey"), parsed.data.endpointId);
182
191
  return c.json({
@@ -28,6 +28,10 @@ init_providers();
28
28
  init_credentials();
29
29
  init_model_catalog_store();
30
30
  init_plugin_registry();
31
+ function catalogDisplayNames(providerId, modelId) {
32
+ const model = getModelCatalogStore().getSource(providerId)?.models.find((item) => item.id === modelId);
33
+ return model?.displayNames ? { displayNames: model.displayNames } : {};
34
+ }
31
35
  function readModelsJsonProviderApiKey(providerId) {
32
36
  const { config } = loadModelsJson(resolveModelsJsonPath());
33
37
  const key = (config.providers?.[providerId.trim()])?.apiKey;
@@ -292,6 +296,7 @@ function registerModelsRoutes(authenticated, deps) {
292
296
  const models = sortModelsForPicker(await getAvailableModels()).map((m) => ({
293
297
  id: `${m.provider}/${m.id}`,
294
298
  name: m.name,
299
+ ...catalogDisplayNames(m.provider, m.id),
295
300
  provider: m.provider,
296
301
  contextWindow: m.contextWindow ?? 128e3,
297
302
  maxTokens: m.maxTokens ?? 4096,
@@ -656,6 +661,7 @@ function registerModelsRoutes(authenticated, deps) {
656
661
  const models = sortModelsForPicker(allModels).map((m) => ({
657
662
  id: `${m.provider}/${m.id}`,
658
663
  name: m.name,
664
+ ...catalogDisplayNames(m.provider, m.id),
659
665
  provider: m.provider,
660
666
  contextWindow: m.contextWindow ?? 128e3,
661
667
  maxTokens: m.maxTokens ?? 4096,
@@ -19,8 +19,8 @@ import { resolveOmniRoute } from "../../../voice/realtime/omniRoute.js";
19
19
  import { VoiceSessionCreationError, resolveStreamingStt, resolveStreamingTts } from "../../../voice/realtime/runtime.js";
20
20
  import { getGatewayPrincipal } from "../../security/gateway-principal.js";
21
21
  import { createGatewayRouteLogger } from "../lib/route-logger.js";
22
- import { listLocalVoiceModelStatuses, removeLocalVoiceModel, startLocalVoiceModelInstall } from "../../../voice/local/model-manager.js";
23
22
  import { listTtsProvidersForApi } from "../../../voice/tts/list-providers.js";
23
+ import { listLocalVoiceModelStatuses, removeLocalVoiceModel, startLocalVoiceModelInstall } from "../../../voice/local/model-manager.js";
24
24
  import { z } from "zod";
25
25
  //#region src/gateway/hono/routes/voice.ts
26
26
  init_providers();
@@ -1,6 +1,6 @@
1
1
  import { DEFAULT_ACK_MAX_CHARS, HEARTBEAT_OK, NO_REPLY, shouldSilence, stripHeartbeatToken } from "./tokens.js";
2
- import { appendCronEventLines } from "./event-prompt.js";
3
2
  import { isWithinActiveHours } from "./active-hours.js";
4
3
  import { isHeartbeatContentEmpty } from "./content-check.js";
4
+ import { appendCronEventLines } from "./event-prompt.js";
5
5
  import { createHeartbeatWake } from "./wake.js";
6
6
  export { DEFAULT_ACK_MAX_CHARS, HEARTBEAT_OK, NO_REPLY, appendCronEventLines, createHeartbeatWake, isHeartbeatContentEmpty, isWithinActiveHours, shouldSilence, stripHeartbeatToken };
@@ -62,6 +62,10 @@ var init_model_catalog_persistence = __esmMin((() => {
62
62
  catalogModelSchema = z.object({
63
63
  id: z.string().min(1),
64
64
  name: z.string().min(1),
65
+ displayNames: z.object({
66
+ "zh-CN": z.string().min(1).optional(),
67
+ en: z.string().min(1).optional()
68
+ }).strict().optional(),
65
69
  availability: z.enum(["available", "unavailable"]),
66
70
  kind: z.enum([
67
71
  "language",
@@ -1,6 +1,7 @@
1
1
  export interface CatalogModel {
2
2
  id: string;
3
3
  name: string;
4
+ displayNames?: Partial<Record<'zh-CN' | 'en', string>>;
4
5
  availability: 'available' | 'unavailable';
5
6
  kind: 'language' | 'image' | 'stt' | 'tts';
6
7
  input: Array<'text' | 'image' | 'audio'>;
@@ -52,7 +52,8 @@ var XopcCloudModelSource = class {
52
52
  const tts = kind === "tts" ? parseTtsCapabilities(model.xopc?.capabilities, model.xopc?.defaultVoice) : void 0;
53
53
  const catalogModel = {
54
54
  id: model.id,
55
- name: model.id,
55
+ name: typeof model.xopc?.displayName === "string" && model.xopc.displayName.trim() ? model.xopc.displayName.trim() : model.id,
56
+ ...parseDisplayNames(model.xopc?.displayNames),
56
57
  kind,
57
58
  input,
58
59
  output,
@@ -180,5 +181,15 @@ function parseImageGenerationCapabilities(value) {
180
181
  maxInputImages: Number.isSafeInteger(raw.maxInputImages) && Number(raw.maxInputImages) > 0 ? Number(raw.maxInputImages) : 0
181
182
  };
182
183
  }
184
+ function parseDisplayNames(value) {
185
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
186
+ const raw = value;
187
+ const displayNames = {};
188
+ for (const locale of ["zh-CN", "en"]) {
189
+ const name = raw[locale];
190
+ if (typeof name === "string" && name.trim()) displayNames[locale] = name.trim();
191
+ }
192
+ return Object.keys(displayNames).length ? { displayNames } : {};
193
+ }
183
194
  //#endregion
184
195
  export { XopcCloudModelError, XopcCloudModelSource };
@@ -6,3 +6,4 @@ export interface StoredEndpointSessionBinding {
6
6
  export declare function getEndpointSessionBinding(sessionKey: string): StoredEndpointSessionBinding | undefined;
7
7
  export declare function setEndpointSessionBinding(binding: StoredEndpointSessionBinding): StoredEndpointSessionBinding;
8
8
  export declare function deleteEndpointSessionBinding(sessionKey: string): boolean;
9
+ export declare function deleteEndpointSessionBindingsByPrincipal(principalId: string): number;
@@ -28,5 +28,13 @@ function setEndpointSessionBinding(binding) {
28
28
  function deleteEndpointSessionBinding(sessionKey) {
29
29
  return getSqliteDatabase().prepare("DELETE FROM endpoint_session_bindings WHERE session_key = ?").run(sessionKey).changes > 0;
30
30
  }
31
+ function deleteEndpointSessionBindingsByPrincipal(principalId) {
32
+ return Number(getSqliteDatabase().prepare(`
33
+ DELETE FROM endpoint_session_bindings
34
+ WHERE endpoint_id IN (
35
+ SELECT endpoint_id FROM endpoint_instance_bindings WHERE principal_id = ?
36
+ )
37
+ `).run(principalId).changes);
38
+ }
31
39
  //#endregion
32
- export { deleteEndpointSessionBinding, getEndpointSessionBinding, setEndpointSessionBinding };
40
+ export { deleteEndpointSessionBinding, deleteEndpointSessionBindingsByPrincipal, getEndpointSessionBinding, setEndpointSessionBinding };
@@ -5,7 +5,7 @@ export { DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, } from './m
5
5
  export { discoverSqlMigrations, listRegisteredMigrationTargets } from './migrations/discover.js';
6
6
  export { closeXopcDatabase, getXopcDatabase, isXopcDatabaseOpen, openXopcDatabase, requireXopcDatabase, resetXopcDatabaseSingletonForTest, type OpenXopcDatabaseOptions, type XopcDatabase, } from './connection.js';
7
7
  export { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';
8
- export { deleteEndpointSessionBinding, getEndpointSessionBinding, setEndpointSessionBinding, type StoredEndpointSessionBinding, } from './endpoint-session-binding-repository.js';
8
+ export { deleteEndpointSessionBinding, deleteEndpointSessionBindingsByPrincipal, getEndpointSessionBinding, setEndpointSessionBinding, type StoredEndpointSessionBinding, } from './endpoint-session-binding-repository.js';
9
9
  export { deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, getBrowserTabBinding, getBrowserTabBindingById, setBrowserTabBinding, } from './browser-tab-binding-repository.js';
10
10
  export { authenticateDeviceAccessToken, buildRefreshProofMessage, createDevice, getDevice, issueDeviceTokenPair, listDevices, revokeDevice, rotateDeviceRefreshToken, type DeviceAccessIdentity, type DevicePlatform, type DevicePublicKeyJwk, type DeviceRecord, type DeviceTokenPair, } from './device-access-repository.js';
11
11
  export { clearGatewayIdentityForTest, getOrCreateGatewayIdentity, signGatewayPayload, type GatewayIdentity, } from './gateway-identity-repository.js';
@@ -6,7 +6,7 @@ import { XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_SCHEMA_VERSION, applyPendingMi
6
6
  import { ensureXopcDatabaseSchema } from "./schema.js";
7
7
  import { closeXopcDatabase, getXopcDatabase, isXopcDatabaseOpen, openXopcDatabase, requireXopcDatabase, resetXopcDatabaseSingletonForTest } from "./connection.js";
8
8
  import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
9
- import { deleteEndpointSessionBinding, getEndpointSessionBinding, setEndpointSessionBinding } from "./endpoint-session-binding-repository.js";
9
+ import { deleteEndpointSessionBinding, deleteEndpointSessionBindingsByPrincipal, getEndpointSessionBinding, setEndpointSessionBinding } from "./endpoint-session-binding-repository.js";
10
10
  import { deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, getBrowserTabBinding, getBrowserTabBindingById, setBrowserTabBinding } from "./browser-tab-binding-repository.js";
11
11
  import { authenticateDeviceAccessToken, buildRefreshProofMessage, createDevice, getDevice, issueDeviceTokenPair, listDevices, revokeDevice, rotateDeviceRefreshToken } from "./device-access-repository.js";
12
12
  import { clearGatewayIdentityForTest, getOrCreateGatewayIdentity, signGatewayPayload } from "./gateway-identity-repository.js";
@@ -40,4 +40,4 @@ import { appendConnectorExecutionAudit, claimConnectorWebhookDelivery, completeC
40
40
  import { getConnectorAccount, listConnectorAccounts, reconcileConnectorAccount, refreshConnectorAccountCurrent } from "./connector-account-repository.js";
41
41
  import { getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, listConnectorSyncPolicies, upsertConnectorSyncPolicy } from "./connector-sync-policy-repository.js";
42
42
  import { getUserTrustPolicy, setUserTrustPolicy } from "./user-trust-repository.js";
43
- export { COMPOSER_INPUT_HISTORY_LIMIT, DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, SCHEMA_META_SCHEMA_VERSION_KEY, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, acknowledgeHomeAttention, appendCompactionBoundaryIfUnchanged, appendComposerInputHistory, appendConnectorExecutionAudit, appendTranscriptEntry, applyPendingMigrations, authenticateDeviceAccessToken, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRefreshProofMessage, buildRelationshipPrompt, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimContextExtractionRun, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, classifyStoredRow, clearComposerInputHistory, clearGatewayIdentityForTest, closeTemporalAssertions, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeClarificationApproval, consumeClarificationResume, consumeConnectorApproval, countKnowledgeSourceItems, createClarificationWait, createCollaborationRule, createConnectorApproval, createContextEvidence, createDevice, createDevicePairingSetup, createEndpointPrincipal, createObjectLinkRecord, createTemporalAssertion, decideConnectorApproval, deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, deleteConnectorConnection, deleteConnectorInstallation, deleteEndpointSessionBinding, deleteKnowledgeSourceItems, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, discoverSqlMigrations, enqueueConnectorLearningJob, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findSessionInput, findSessionKeyBySessionId, finishContextExtractionRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishSessionInputRun, getActiveClarification, getActivityEventRecord, getBrowserTabBinding, getBrowserTabBindingById, getCachedConnectorCatalogEntry, getClarification, getClarificationResumeInput, getClarificationSnapshot, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextExtractionRun, getCurrentSessionId, getDevice, getEndpointPrincipal, getEndpointSessionBinding, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getNoteAgentContextRecord, getNoteRecord, getOrCreateGatewayIdentity, getRelationshipSettings, getSessionConfig, getSessionInputById, getSessionInputState, getSessionMetadata, getSessionPersistedLevels, getSessionTaskPlan, getSqliteDatabase, getUserPeopleIndexState, getUserPerson, getUserTrustPolicy, getXopcDatabase, hasIndependentExtractionOutput, hasSessionConfig, incrementSessionStatsOnAppend, insertSessionInput, inspectSchemaMigrationStatus, isClarificationSuspended, isDevicePairingSetupActive, isHomeAttentionAcknowledged, isProactiveSupportAllowed, isXopcDatabaseOpen, issueDeviceTokenPair, linkContextObjects, listActiveSessionInputRuns, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextExtractionOutputs, listContextExtractionRuns, listContextObjectRelations, listDevices, listEndpointPrincipals, listEndpointToolInvocationAudits, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listTemporalAssertions, listUserPeople, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, mergeUserPeople, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceLatestSessionTurnAndQueueInput, replaceTranscriptRows, replaceUserPeopleIndex, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveClarification, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, revokeDevice, revokeEndpointPrincipal, rotateDeviceRefreshToken, runSqliteWriteTransaction, searchSessionTranscript, sessionConfigRowToConfig, sessionRowToMetadata, setBrowserTabBinding, setCollaborationRuleStatus, setConnectorLearningPaused, setEndpointSessionBinding, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUserTrustPolicy, signGatewayPayload, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeUserPeople, supersedeActiveClarification, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateRelationshipSettings, updateSessionConfig, updateSessionStats, updateUserPerson, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertNoteAgentContextRecord, upsertNoteRecord, validateLatestSessionTurnTarget };
43
+ export { COMPOSER_INPUT_HISTORY_LIMIT, DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, SCHEMA_META_SCHEMA_VERSION_KEY, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, acknowledgeHomeAttention, appendCompactionBoundaryIfUnchanged, appendComposerInputHistory, appendConnectorExecutionAudit, appendTranscriptEntry, applyPendingMigrations, authenticateDeviceAccessToken, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRefreshProofMessage, buildRelationshipPrompt, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimContextExtractionRun, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, classifyStoredRow, clearComposerInputHistory, clearGatewayIdentityForTest, closeTemporalAssertions, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeClarificationApproval, consumeClarificationResume, consumeConnectorApproval, countKnowledgeSourceItems, createClarificationWait, createCollaborationRule, createConnectorApproval, createContextEvidence, createDevice, createDevicePairingSetup, createEndpointPrincipal, createObjectLinkRecord, createTemporalAssertion, decideConnectorApproval, deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, deleteConnectorConnection, deleteConnectorInstallation, deleteEndpointSessionBinding, deleteEndpointSessionBindingsByPrincipal, deleteKnowledgeSourceItems, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, discoverSqlMigrations, enqueueConnectorLearningJob, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findSessionInput, findSessionKeyBySessionId, finishContextExtractionRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishSessionInputRun, getActiveClarification, getActivityEventRecord, getBrowserTabBinding, getBrowserTabBindingById, getCachedConnectorCatalogEntry, getClarification, getClarificationResumeInput, getClarificationSnapshot, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextExtractionRun, getCurrentSessionId, getDevice, getEndpointPrincipal, getEndpointSessionBinding, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getNoteAgentContextRecord, getNoteRecord, getOrCreateGatewayIdentity, getRelationshipSettings, getSessionConfig, getSessionInputById, getSessionInputState, getSessionMetadata, getSessionPersistedLevels, getSessionTaskPlan, getSqliteDatabase, getUserPeopleIndexState, getUserPerson, getUserTrustPolicy, getXopcDatabase, hasIndependentExtractionOutput, hasSessionConfig, incrementSessionStatsOnAppend, insertSessionInput, inspectSchemaMigrationStatus, isClarificationSuspended, isDevicePairingSetupActive, isHomeAttentionAcknowledged, isProactiveSupportAllowed, isXopcDatabaseOpen, issueDeviceTokenPair, linkContextObjects, listActiveSessionInputRuns, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextExtractionOutputs, listContextExtractionRuns, listContextObjectRelations, listDevices, listEndpointPrincipals, listEndpointToolInvocationAudits, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listTemporalAssertions, listUserPeople, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, mergeUserPeople, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceLatestSessionTurnAndQueueInput, replaceTranscriptRows, replaceUserPeopleIndex, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveClarification, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, revokeDevice, revokeEndpointPrincipal, rotateDeviceRefreshToken, runSqliteWriteTransaction, searchSessionTranscript, sessionConfigRowToConfig, sessionRowToMetadata, setBrowserTabBinding, setCollaborationRuleStatus, setConnectorLearningPaused, setEndpointSessionBinding, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUserTrustPolicy, signGatewayPayload, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeUserPeople, supersedeActiveClarification, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateRelationshipSettings, updateSessionConfig, updateSessionStats, updateUserPerson, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertNoteAgentContextRecord, upsertNoteRecord, validateLatestSessionTurnTarget };
@@ -567,7 +567,10 @@ var WorkflowRunService = class {
567
567
  getDefaultModel: () => resolveModel(gatewayService.agentService.getModelForSession(params.sessionKey)),
568
568
  getConfig: () => gatewayService.currentConfig,
569
569
  sessionStore: gatewayService.sessionIndexInstance.getStore(),
570
- buildChildTools: (childOptions) => this.options.buildChildTools(childOptions)
570
+ buildChildTools: (childOptions) => this.options.buildChildTools({
571
+ ...childOptions,
572
+ endpointTools: gatewayService.endpointTools
573
+ })
571
574
  });
572
575
  return new WorkflowEngine({
573
576
  cwd: workspace,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.274",
3
+ "version": "0.0.275",
4
4
  "description": "Local-first personal AI assistant with reviewable user understanding, durable tasks, workflows, automations, and local or cloud models.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -167,9 +167,9 @@
167
167
  "vue": "^3.5.35",
168
168
  "@xopcai/browser-control-contract": "0.1.0",
169
169
  "@xopcai/endpoint-tools-protocol": "0.0.0",
170
+ "@xopcai/gateway-contract": "0.0.0",
170
171
  "@xopcai/realtime-client": "0.0.0",
171
- "@xopcai/realtime-protocol": "0.0.0",
172
- "@xopcai/gateway-contract": "0.0.0"
172
+ "@xopcai/realtime-protocol": "0.0.0"
173
173
  },
174
174
  "scripts": {
175
175
  "assets:brand": "node scripts/generate-brand-assets.mjs",
@@ -1 +0,0 @@
1
- import{i as e}from"./rolldown-runtime-aKtaBQYM.js";import{a as t,n,t as r}from"./vendor-react-BOUWij0V.js";import{h as i,t as a}from"./chunk-KS7C4IRE-Cq1tE_3b.js";import{a as o,i as s,o as c,r as l,s as u,t as d}from"./dist-CpzYSoz7.js";import{t as f}from"./check-DUBLcKHA.js";import{t as p}from"./external-link-DjqjBmc3.js";import{t as m}from"./markdown-view-B2IR4E2r.js";import{t as h}from"./loader-circle-CifKLtgG.js";import{t as g}from"./plus-Q2yW6OE7.js";import{t as _}from"./x-B_N4OPjy.js";import{t as v}from"./messages-BGc-OJWg.js";import{a as y,c as b,i as x,n as S,r as C}from"./locale-store-BkJ7g35d.js";import{t as w}from"./cn-JdwAhgNB.js";import{a as T,i as E}from"./vendor-swr-BIWyz7Rc.js";import{t as D}from"./button-B11EPpor.js";import{t as O}from"./skeleton-BwbyijEw.js";import{Ba as k,Ga as A,Ha as j,Hs as ee,Ic as M,La as N,Ou as te,Va as P,Vs as ne,Yi as F,gu as I,lc as L,ou as R,pc as z,sc as re,so as B,za as V}from"./index-SxqsTD4i.js";import{t as H}from"./page-tabs-CRombigq.js";var U=e(t(),1),W=n();function G(e){return e===`builtin`||e===`user`?e:`marketplace`}async function K(e){try{let t=await e.json();if(typeof t.error==`string`)return t.error;if(t.error&&typeof t.error==`object`&&typeof t.error.message==`string`)return t.error.message;if(typeof t.message==`string`)return t.message}catch{}return e.statusText||`HTTP ${e.status}`}async function ie(e){let t=await x(C(`/api/marketplace/packages/${encodeURIComponent(e.trim())}`),{cache:`no-store`});if(!t.ok)throw Error(await K(t));let n=await t.json();if(!n.ok||!n.payload?.id)throw Error(n.error??`Invalid response`);return n.payload}async function q(e){let t=await x(C(`/api/marketplace/install`),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok)throw Error(await K(t));let n=await t.json();if(!n.ok||!n.payload?.extensionId)throw Error(n.error??`Invalid response`);return n.payload}async function J(e){let t=await x(C(`/api/extensions/bundled/activation`),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({extensionId:e.extensionId.trim(),enabled:e.enabled})});if(!t.ok)throw Error(await K(t));let n=await t.json();if(!n.ok||!n.payload)throw Error(n.error?.message??`Invalid response`);return n.payload}async function Y(e){let t=await x(C(`/api/marketplace/uninstall`),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({extensionId:e})});if(!t.ok)throw Error(await K(t));let n=await t.json();if(!n.ok||!n.payload)throw Error(n.error??`Invalid response`);return n.payload}var X=r();function ae(e,t){let n=e.find(e=>e.id===t);return n?n.source===`bundled`?`bundled`:`user`:`absent`}var Z={q:``,debounced:``,detailPkg:null,rowBusy:null,actionError:null,restartHint:null};function Q({className:e}){let t=v(S(e=>e.language)).extensionsPage,n=b(e=>!!e.sessionKey),r=V(),{mutate:i}=T(),[a,o]=(0,U.useReducer)(F,Z),{q:s,debounced:c,detailPkg:l,rowBusy:u,actionError:d,restartHint:f}=a,p=n?`marketplace-${c}`:null;(0,U.useEffect)(()=>{let e=window.setTimeout(()=>o({type:`patch`,patch:{debounced:s.trim()}}),300);return()=>window.clearTimeout(e)},[s]);let{data:m,isLoading:g,error:_}=E(p,async()=>y(c.length>0?C(`/api/marketplace?q=${encodeURIComponent(c)}`):C(`/api/marketplace`)),{revalidateOnFocus:!1}),x=(0,U.useCallback)(()=>{i(`gateway-extensions-list`),A()},[i]),D=(0,U.useCallback)(async(e,n)=>{o({type:`patch`,patch:{actionError:null,restartHint:null,rowBusy:e}});try{let r=await q({name:e,overwrite:n});x(),r.requiresGatewayRestart&&o({type:`patch`,patch:{restartHint:t.marketplaceRestartHint}})}catch(e){throw o({type:`patch`,patch:{actionError:e instanceof Error?e.message:t.marketplaceInstallFailed}}),e}finally{o({type:`patch`,patch:{rowBusy:null}})}},[t.marketplaceInstallFailed,t.marketplaceRestartHint,x]),k=(0,U.useCallback)(async e=>{o({type:`patch`,patch:{actionError:null,restartHint:null,rowBusy:e}});try{let n=await Y(e);x(),n.requiresGatewayRestart&&o({type:`patch`,patch:{restartHint:t.marketplaceRestartHint}})}catch(e){throw o({type:`patch`,patch:{actionError:e instanceof Error?e.message:t.marketplaceUninstallFailed}}),e}finally{o({type:`patch`,patch:{rowBusy:null}})}},[t.marketplaceRestartHint,t.marketplaceUninstallFailed,x]),j=m?.extensions??[];return(0,X.jsxs)(`div`,{className:w(`flex flex-col gap-4`,e),children:[(0,X.jsxs)(`div`,{className:`relative`,children:[(0,X.jsx)(z,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-muted`,strokeWidth:1.75,"aria-hidden":!0}),(0,X.jsx)(`input`,{type:`search`,value:s,onChange:e=>o({type:`patch`,patch:{q:e.target.value}}),placeholder:t.marketplaceSearchPlaceholder,className:`ui-input h-10 w-full rounded-lg border border-edge bg-surface-base pl-9 pr-3 text-sm text-fg placeholder:text-fg-muted`})]}),_?(0,X.jsx)(`p`,{className:`text-sm text-fg-muted`,children:_ instanceof Error?_.message:t.marketplaceLoadFailed}):null,d?(0,X.jsx)(`p`,{className:`text-sm text-red-600 dark:text-red-400`,children:d}):null,f?(0,X.jsx)(`p`,{className:`text-sm text-fg-muted`,children:f}):null,g&&!m?(0,X.jsx)(`ul`,{className:`flex flex-col gap-3`,"aria-label":t.marketplaceLoading,children:[0,1,2].map(e=>(0,X.jsx)(`li`,{className:`rounded-xl bg-surface-panel p-4 shadow-surface`,children:(0,X.jsxs)(`div`,{className:`flex items-start justify-between gap-4`,children:[(0,X.jsxs)(`div`,{className:`min-w-0 flex-1 space-y-2.5`,children:[(0,X.jsx)(O,{className:`h-5 w-40`}),(0,X.jsx)(O,{className:`h-4 w-full max-w-xl`}),(0,X.jsx)(O,{className:`h-4 w-2/3 max-w-md`})]}),(0,X.jsx)(O,{className:`h-8 w-20`})]})},e))}):(0,X.jsx)(`ul`,{className:`flex flex-col gap-3`,children:j.length===0?(0,X.jsx)(`li`,{className:`text-sm text-fg-muted`,children:t.marketplaceEmpty}):j.map(e=>{let n=ae(r,e.id),i=u===e.id;return(0,X.jsx)(`li`,{className:`list-none`,children:(0,X.jsxs)(`div`,{role:`button`,tabIndex:0,"aria-label":`${e.name}, ${t.marketplaceDetailTitle}`,onClick:()=>o({type:`patch`,patch:{detailPkg:e.id}}),onKeyDown:t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),o({type:`patch`,patch:{detailPkg:e.id}}))},className:w(`flex w-full cursor-pointer flex-wrap items-start gap-3 rounded-xl bg-surface-panel p-4 text-left shadow-surface`,`transition-[transform,background-color,box-shadow] duration-150 ease-out`,`hover:bg-surface-hover/40`,`active:scale-[0.992] active:bg-surface-hover/55`,`focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel`,`dark:hover:bg-surface-hover/25 dark:active:bg-surface-hover/35`),children:[(0,X.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,X.jsx)(`h3`,{className:`font-semibold text-fg`,children:e.name}),e.verified?(0,X.jsx)(R,{className:`size-4 shrink-0 text-emerald-600 dark:text-emerald-400`,strokeWidth:1.75,"aria-label":`Verified`}):null,e.version?(0,X.jsx)(`span`,{className:`text-xs text-fg-muted`,children:e.version}):null]}),e.description?(0,X.jsx)(`p`,{className:`mt-1 line-clamp-2 text-sm text-fg-muted`,children:e.description}):null,(0,X.jsx)(`div`,{className:`mt-2 flex flex-wrap gap-1.5`,children:(e.categories??[]).map(e=>(0,X.jsx)(`span`,{className:`rounded-md border border-edge bg-surface-panel px-2 py-0.5 text-[11px] text-fg-muted`,children:e},e))}),(0,X.jsxs)(`p`,{className:`mt-2 flex items-center gap-1.5 text-xs text-fg-muted`,children:[(0,X.jsx)(M,{className:`size-3.5 shrink-0`,strokeWidth:1.75,"aria-hidden":!0}),(0,X.jsx)(`code`,{className:`rounded bg-surface-panel px-1 py-0.5`,children:e.npmPackage})]})]}),(0,X.jsx)(`div`,{role:`group`,className:`flex shrink-0 flex-col items-end gap-2 sm:min-w-[9rem]`,onClick:e=>e.stopPropagation(),onKeyDown:e=>e.stopPropagation(),children:n===`bundled`?(0,X.jsx)(`span`,{className:`rounded-md bg-surface-hover px-2 py-1 text-[11px] font-medium text-fg-muted`,children:t.marketplaceBuiltin}):n===`user`?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(`span`,{className:`text-[11px] font-medium text-fg-muted`,children:t.marketplaceInstalled}),(0,X.jsxs)(`button`,{type:`button`,disabled:i,onClick:()=>{window.confirm(t.marketplaceUninstallConfirm)&&k(e.id).catch(()=>{})},className:w(`inline-flex items-center justify-center gap-1.5 rounded-lg border border-edge px-3 py-2 text-xs font-medium text-fg`,`transition-colors active:scale-[0.98] active:bg-surface-hover/80`,`hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,`disabled:pointer-events-none disabled:opacity-50`),children:[i?(0,X.jsx)(h,{className:`size-3.5 animate-spin`,"aria-hidden":!0}):(0,X.jsx)(ee,{className:`size-3.5`,strokeWidth:2,"aria-hidden":!0}),t.marketplaceUninstall]})]}):(0,X.jsx)(`button`,{type:`button`,onClick:()=>o({type:`patch`,patch:{detailPkg:e.id}}),className:w(`inline-flex w-full items-center justify-center rounded-lg border border-edge px-3 py-2 text-xs font-medium text-fg`,`transition-[transform,background-color] active:scale-[0.98]`,`hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`),children:t.marketplaceReview})})]})},e.id)})}),l?(0,X.jsx)($,{packageName:l,copy:t,extensions:r,onClose:()=>o({type:`patch`,patch:{detailPkg:null}}),onInstall:D,onUninstall:k}):null]})}function $(e){let t=(0,W.c)(102),{packageName:n,copy:r,extensions:i,onClose:s,onInstall:f,onUninstall:p}=e,[g,v]=(0,U.useState)(!1),[y,x]=(0,U.useState)(!1),S=b(ue)?`ext-mp-detail-${n}`:null,C;t[0]===n?C=t[1]:(C=async()=>ie(n),t[0]=n,t[1]=C);let T;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(T={revalidateOnFocus:!1},t[2]=T):T=t[2];let{data:D,error:k,isLoading:A}=E(S,C,T),j;t[3]!==i||t[4]!==n?(j=ae(i,n),t[3]=i,t[4]=n,t[5]=j):j=t[5];let M=j,N=M===`user`,P=D?.manifest?.permissions,F,I,L,R,z,B,V,H,G,K,q;if(t[6]!==r.detailBack||t[7]!==r.detailClose||t[8]!==r.marketplaceAuthor||t[9]!==r.marketplaceCodeRisk||t[10]!==r.marketplaceDependencies||t[11]!==r.marketplaceDetailLoadFailed||t[12]!==r.marketplaceDetailReadmeHeading||t[13]!==r.marketplaceDetailTitle||t[14]!==r.marketplaceDownloads||t[15]!==r.marketplaceIntegrity||t[16]!==r.marketplaceIntegrityVerified||t[17]!==r.marketplaceLifecycleScripts||t[18]!==r.marketplaceLoadFailed||t[19]!==r.marketplaceLoading||t[20]!==r.marketplaceNoReadme||t[21]!==r.marketplacePermissions||t[22]!==r.marketplacePermissionsNone||t[23]!==r.marketplaceRiskConfirm||t[24]!==r.marketplaceRiskTitle||t[25]!==r.marketplaceUnavailableBody||t[26]!==r.marketplaceUnavailableTitle||t[27]!==r.marketplaceVersion||t[28]!==D||t[29]!==k||t[30]!==M||t[31]!==A||t[32]!==s||t[33]!==P||t[34]!==y){let e=P&&typeof P==`object`&&!Array.isArray(P)?Object.entries(P):[],n;t[46]!==r.marketplaceNoReadme||t[47]!==D?(n=D?.readme?.trim()||(D?.description?.trim()?`### ${D.name}\n\n${D.description}`:`*${r.marketplaceNoReadme}*`),t[46]=r.marketplaceNoReadme,t[47]=D,t[48]=n):n=t[48];let i=n;L=d,R=!0,t[49]===s?z=t[50]:(z=e=>!e&&s(),t[49]=s,t[50]=z),I=c,t[51]===Symbol.for(`react.memo_cache_sentinel`)?(q=(0,X.jsx)(o,{className:`xopc-dialog-overlay fixed inset-0 z-[130] bg-scrim`}),t[51]=q):q=t[51],F=l,H=`fixed left-1/2 top-1/2 z-[131] flex h-[min(44rem,calc(100vh-1.5rem))] w-[min(42rem,calc(100vw-1.5rem))] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl border border-edge bg-surface-panel shadow-elevated`,G=le;let a;t[52]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,X.jsx)(te,{className:`size-5`}),t[52]=a):a=t[52];let f;t[53]!==r.detailBack||t[54]!==s?(f=(0,X.jsx)(`button`,{type:`button`,onClick:s,className:`inline-flex size-9 items-center justify-center rounded-lg text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,"aria-label":r.detailBack,children:a}),t[53]=r.detailBack,t[54]=s,t[55]=f):f=t[55];let p;t[56]===r.marketplaceDetailTitle?p=t[57]:(p=(0,X.jsx)(u,{className:`min-w-0 flex-1 truncate text-center text-sm font-semibold text-fg`,children:r.marketplaceDetailTitle}),t[56]=r.marketplaceDetailTitle,t[57]=p);let h;t[58]===Symbol.for(`react.memo_cache_sentinel`)?(h=(0,X.jsx)(_,{className:`size-5`}),t[58]=h):h=t[58];let g;t[59]!==r.detailClose||t[60]!==s?(g=(0,X.jsx)(`button`,{type:`button`,onClick:s,className:`inline-flex size-9 items-center justify-center rounded-lg text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,"aria-label":r.detailClose,children:h}),t[59]=r.detailClose,t[60]=s,t[61]=g):g=t[61],t[62]!==f||t[63]!==p||t[64]!==g?(K=(0,X.jsxs)(`div`,{className:`flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3`,children:[f,p,g]}),t[62]=f,t[63]=p,t[64]=g,t[65]=K):K=t[65],B=`min-h-0 flex-1 overflow-y-auto p-5`,V=A&&!D?(0,X.jsxs)(`div`,{className:`space-y-4`,"aria-label":r.marketplaceLoading,children:[(0,X.jsx)(O,{className:`h-6 w-48`}),(0,X.jsx)(O,{className:`h-4 w-28`}),(0,X.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,X.jsx)(O,{className:`h-12`}),(0,X.jsx)(O,{className:`h-12`})]}),(0,X.jsx)(O,{className:`h-28 w-full`}),(0,X.jsx)(O,{className:`h-36 w-full`})]}):k?(0,X.jsxs)(`div`,{className:`rounded-lg border border-red-300/70 bg-red-50 p-4 text-sm dark:border-red-900 dark:bg-red-950/30`,children:[(0,X.jsx)(`p`,{className:`font-medium text-red-700 dark:text-red-300`,children:r.marketplaceDetailLoadFailed}),(0,X.jsx)(`p`,{className:`mt-1 break-words text-red-600 dark:text-red-400`,children:k instanceof Error?k.message:r.marketplaceLoadFailed})]}):D?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(`h3`,{className:`text-lg font-semibold text-fg`,children:D.name}),(0,X.jsx)(`p`,{className:`mt-1 text-xs text-fg-muted`,children:(0,X.jsx)(`code`,{className:`rounded bg-surface-panel px-1 py-0.5`,children:D.id})}),(0,X.jsxs)(`dl`,{className:`mt-3 grid gap-2 text-xs text-fg-muted sm:grid-cols-2`,children:[(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`dt`,{className:`font-medium text-fg`,children:r.marketplaceAuthor}),(0,X.jsx)(`dd`,{children:D.author.username})]}),(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`dt`,{className:`font-medium text-fg`,children:r.marketplaceVersion}),(0,X.jsx)(`dd`,{children:D.latestVersion.version})]}),(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`dt`,{className:`font-medium text-fg`,children:r.marketplaceDownloads}),(0,X.jsx)(`dd`,{children:D.downloads})]})]}),M===`bundled`?null:(0,X.jsxs)(`section`,{className:`mt-5 space-y-3 rounded-lg border border-edge bg-surface-base p-4`,children:[(0,X.jsxs)(`div`,{className:`flex items-start gap-2.5`,children:[D.installability.available?(0,X.jsx)(re,{className:`mt-0.5 size-5 shrink-0 text-emerald-600 dark:text-emerald-400`,"aria-hidden":!0}):(0,X.jsx)(ne,{className:`mt-0.5 size-5 shrink-0 text-amber-600 dark:text-amber-400`,"aria-hidden":!0}),(0,X.jsxs)(`div`,{className:`min-w-0`,children:[(0,X.jsx)(`h4`,{className:`text-sm font-semibold text-fg`,children:D.installability.available?r.marketplaceRiskTitle:r.marketplaceUnavailableTitle}),(0,X.jsx)(`p`,{className:`mt-1 text-xs leading-relaxed text-fg-muted`,children:D.installability.available?r.marketplaceCodeRisk:D.installability.reason??r.marketplaceUnavailableBody})]})]}),D.installability.available?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`dl`,{className:`grid gap-2 text-xs text-fg-muted sm:grid-cols-2`,children:[(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`dt`,{className:`font-medium text-fg`,children:r.marketplaceIntegrity}),(0,X.jsx)(`dd`,{children:r.marketplaceIntegrityVerified})]}),(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`dt`,{className:`font-medium text-fg`,children:r.marketplaceDependencies}),(0,X.jsx)(`dd`,{children:D.packageSummary?.dependencyCount??0})]})]}),(0,X.jsxs)(`div`,{className:`text-xs text-fg-muted`,children:[(0,X.jsx)(`p`,{className:`font-medium text-fg`,children:r.marketplacePermissions}),e.length>0?(0,X.jsx)(`ul`,{className:`mt-1 space-y-1`,children:e.map(ce)}):(0,X.jsx)(`p`,{className:`mt-1`,children:r.marketplacePermissionsNone})]}),(D.packageSummary?.lifecycleScripts.length??0)>0?(0,X.jsxs)(`p`,{className:`text-xs leading-relaxed text-amber-700 dark:text-amber-300`,children:[r.marketplaceLifecycleScripts,`: `,D.packageSummary?.lifecycleScripts.join(`, `)]}):null,(0,X.jsxs)(`label`,{className:`flex cursor-pointer items-start gap-2 text-sm text-fg`,children:[(0,X.jsx)(`input`,{type:`checkbox`,checked:y,onChange:e=>x(e.target.checked),className:`mt-0.5 size-4 rounded border-edge accent-[var(--color-accent)]`}),(0,X.jsx)(`span`,{children:r.marketplaceRiskConfirm})]})]}):null]}),D.readme?.trim()?(0,X.jsx)(`h4`,{className:`mb-2 mt-6 text-sm font-semibold text-fg`,children:r.marketplaceDetailReadmeHeading}):null,(0,X.jsx)(`div`,{className:`markdown-content min-w-0 break-words text-sm`,children:(0,X.jsx)(m,{content:i})})]}):null,t[6]=r.detailBack,t[7]=r.detailClose,t[8]=r.marketplaceAuthor,t[9]=r.marketplaceCodeRisk,t[10]=r.marketplaceDependencies,t[11]=r.marketplaceDetailLoadFailed,t[12]=r.marketplaceDetailReadmeHeading,t[13]=r.marketplaceDetailTitle,t[14]=r.marketplaceDownloads,t[15]=r.marketplaceIntegrity,t[16]=r.marketplaceIntegrityVerified,t[17]=r.marketplaceLifecycleScripts,t[18]=r.marketplaceLoadFailed,t[19]=r.marketplaceLoading,t[20]=r.marketplaceNoReadme,t[21]=r.marketplacePermissions,t[22]=r.marketplacePermissionsNone,t[23]=r.marketplaceRiskConfirm,t[24]=r.marketplaceRiskTitle,t[25]=r.marketplaceUnavailableBody,t[26]=r.marketplaceUnavailableTitle,t[27]=r.marketplaceVersion,t[28]=D,t[29]=k,t[30]=M,t[31]=A,t[32]=s,t[33]=P,t[34]=y,t[35]=F,t[36]=I,t[37]=L,t[38]=R,t[39]=z,t[40]=B,t[41]=V,t[42]=H,t[43]=G,t[44]=K,t[45]=q}else F=t[35],I=t[36],L=t[37],R=t[38],z=t[39],B=t[40],V=t[41],H=t[42],G=t[43],K=t[44],q=t[45];let J;t[66]!==B||t[67]!==V?(J=(0,X.jsx)(`div`,{className:B,children:V}),t[66]=B,t[67]=V,t[68]=J):J=t[68];let Y;t[69]!==g||t[70]!==r.marketplaceBuiltinGoBuiltin||t[71]!==r.marketplaceBuiltinManageHint||t[72]!==r.marketplaceInstall||t[73]!==r.marketplaceReinstall||t[74]!==r.marketplaceReinstallConfirm||t[75]!==r.marketplaceUninstall||t[76]!==r.marketplaceUninstallConfirm||t[77]!==D||t[78]!==M||t[79]!==s||t[80]!==f||t[81]!==p||t[82]!==n||t[83]!==y||t[84]!==N?(Y=D?(0,X.jsx)(`div`,{className:`flex shrink-0 flex-wrap items-center justify-end gap-2 border-t border-edge-subtle px-5 py-4`,children:M===`bundled`?(0,X.jsxs)(`div`,{className:`flex w-full flex-col items-stretch gap-2`,children:[(0,X.jsx)(`p`,{className:`text-sm leading-relaxed text-fg-muted`,children:r.marketplaceBuiltinManageHint}),(0,X.jsx)(a,{to:`/extensions?tab=builtin`,onClick:s,className:`inline-flex w-fit items-center justify-center rounded-lg border border-edge px-3 py-2 text-sm font-medium text-fg hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,children:r.marketplaceBuiltinGoBuiltin})]}):(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`button`,{type:`button`,disabled:g||!D.installability.available||!y,onClick:()=>{N&&!window.confirm(r.marketplaceReinstallConfirm)||(v(!0),f(n,N).catch(se).finally(()=>v(!1)))},className:w(`inline-flex items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium`,`bg-accent text-white shadow-surface hover:bg-accent-hover`,`focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-surface-panel`,`disabled:pointer-events-none disabled:opacity-50`),children:[g?(0,X.jsx)(h,{className:`size-4 animate-spin`,"aria-hidden":!0}):null,N?r.marketplaceReinstall:r.marketplaceInstall]}),N?(0,X.jsxs)(`button`,{type:`button`,disabled:g,onClick:()=>{window.confirm(r.marketplaceUninstallConfirm)&&(v(!0),p(n).then(()=>s()).catch(oe).finally(()=>v(!1)))},className:w(`inline-flex items-center justify-center gap-1.5 rounded-lg border border-edge px-3 py-2 text-sm font-medium text-fg`,`hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,`disabled:pointer-events-none disabled:opacity-50`),children:[(0,X.jsx)(ee,{className:`size-4 shrink-0`,"aria-hidden":!0}),r.marketplaceUninstall]}):null]})}):null,t[69]=g,t[70]=r.marketplaceBuiltinGoBuiltin,t[71]=r.marketplaceBuiltinManageHint,t[72]=r.marketplaceInstall,t[73]=r.marketplaceReinstall,t[74]=r.marketplaceReinstallConfirm,t[75]=r.marketplaceUninstall,t[76]=r.marketplaceUninstallConfirm,t[77]=D,t[78]=M,t[79]=s,t[80]=f,t[81]=p,t[82]=n,t[83]=y,t[84]=N,t[85]=Y):Y=t[85];let Z;t[86]!==F||t[87]!==J||t[88]!==Y||t[89]!==H||t[90]!==G||t[91]!==K?(Z=(0,X.jsxs)(F,{className:H,onOpenAutoFocus:G,children:[K,J,Y]}),t[86]=F,t[87]=J,t[88]=Y,t[89]=H,t[90]=G,t[91]=K,t[92]=Z):Z=t[92];let Q;t[93]!==I||t[94]!==Z||t[95]!==q?(Q=(0,X.jsxs)(I,{children:[q,Z]}),t[93]=I,t[94]=Z,t[95]=q,t[96]=Q):Q=t[96];let $;return t[97]!==L||t[98]!==R||t[99]!==z||t[100]!==Q?($=(0,X.jsx)(L,{defaultOpen:R,onOpenChange:z,children:Q}),t[97]=L,t[98]=R,t[99]=z,t[100]=Q,t[101]=$):$=t[101],$}function oe(){}function se(){}function ce(e){let[t,n]=e;return(0,X.jsxs)(`li`,{className:`break-words`,children:[(0,X.jsx)(`code`,{children:t}),`: `,Array.isArray(n)?n.join(`, `):String(n)]},t)}function le(e){return e.preventDefault()}function ue(e){return!!e.sessionKey}function de(){let e=S(e=>e.language),t=v(e),n=B(e=>e.setPageHeader),r=B(e=>e.clearPageHeader),o=V(),s=k(),[c,l]=i(),u=G(c.get(`tab`)),d=c.get(`q`)??``,[f,p]=(0,U.useState)(u),[m,h]=(0,U.useState)(d),[_,y]=(0,U.useState)(null),b=c.toString(),x=(0,U.useRef)(b);if(x.current!==b){x.current=b;let e=G(c.get(`tab`)),t=c.get(`q`)??``;p(t=>t===e?t:e),h(e=>e===t?e:t)}(0,U.useEffect)(()=>{l(e=>{let t=new URLSearchParams(e),n=m.trim();return n?t.set(`q`,n):t.delete(`q`),f===`marketplace`?t.delete(`tab`):t.set(`tab`,f),t.toString()===e.toString()?e:t},{replace:!0})},[f,m,l]);let C=(0,U.useMemo)(()=>o.filter(e=>e.source===`bundled`),[o]),w=(0,U.useMemo)(()=>o.filter(e=>e.source!==`bundled`),[o]),T=f===`builtin`?C:w,E=(0,U.useMemo)(()=>{let t=m.trim().toLowerCase(),n=T;return t&&(n=n.filter(e=>(e.name??``).toLowerCase().includes(t)||e.id.toLowerCase().includes(t)||(e.description??``).toLowerCase().includes(t))),n.toSorted((t,n)=>t.hasUi===n.hasUi?(t.name||t.id).localeCompare(n.name||n.id,e):t.hasUi?-1:1)},[T,m,e]);if((0,U.useEffect)(()=>{y(e=>{if(!e)return e;let t=o.find(t=>t.id===e.id);return t?fe(e)===fe(t)&&e.active===t.active?e:t:null})},[o]),(0,U.useLayoutEffect)(()=>(n({startExtra:null,main:(0,X.jsx)(`div`,{className:`min-w-0`,children:(0,X.jsx)(`h1`,{className:`truncate text-base font-semibold tracking-tight text-fg`,children:t.extensionsPage.title})}),end:(0,X.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,X.jsx)(D,{asChild:!0,variant:`secondary`,className:`h-9`,children:(0,X.jsxs)(a,{to:`/local-apps`,"aria-label":t.extensionsPage.openLocalApps,title:t.extensionsPage.openLocalApps,children:[(0,X.jsx)(I,{className:`size-4`}),(0,X.jsx)(`span`,{className:`hidden sm:inline`,children:t.extensionsPage.openLocalApps})]})}),(0,X.jsx)(D,{asChild:!0,variant:`primary`,className:`h-9`,children:(0,X.jsxs)(a,{to:`/local-apps/new`,children:[(0,X.jsx)(g,{className:`size-4`}),t.extensionsPage.createLocalApp]})})]})}),()=>r()),[r,t.extensionsPage.createLocalApp,t.extensionsPage.openLocalApps,t.extensionsPage.title,n]),s&&f!==`marketplace`)return(0,X.jsx)(ye,{});let O=f!==`marketplace`&&T.length>0;return(0,X.jsxs)(`div`,{className:`flex min-h-0 min-w-0 flex-1 flex-col bg-surface-panel`,children:[(0,X.jsxs)(`div`,{className:`mx-auto w-full max-w-7xl px-4 py-7 sm:px-6 lg:px-8 lg:py-9`,children:[(0,X.jsxs)(`div`,{className:`mb-6 flex flex-col gap-3 border-b border-edge-subtle pb-4 sm:flex-row sm:items-center sm:justify-between`,children:[(0,X.jsx)(H,{items:[{id:`marketplace`,label:t.extensionsPage.tabMarketplace},{id:`builtin`,label:t.extensionsPage.tabBuiltin,count:C.length},{id:`user`,label:t.extensionsPage.tabUser,count:w.length}],activeTab:f,onChange:p,ariaLabel:t.extensionsPage.extensionsNavAria,tabIdPrefix:`extensions-tab`,panelIdPrefix:`extensions-panel`,className:`flex-wrap`}),O?(0,X.jsxs)(`div`,{className:`relative w-full min-w-0 sm:max-w-xs`,children:[(0,X.jsx)(z,{className:`pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-fg-muted`,"aria-hidden":!0}),(0,X.jsx)(`input`,{type:`search`,value:m,onChange:e=>h(e.target.value),placeholder:t.extensionsPage.searchPlaceholder,className:`w-full rounded-lg border border-edge bg-surface-base py-2 pl-9 pr-3 text-sm text-fg placeholder:text-fg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,autoComplete:`off`})]}):null]}),f===`marketplace`?(0,X.jsx)(Q,{}):f===`builtin`&&C.length===0?(0,X.jsx)(xe,{message:t.extensionsPage.emptyBuiltin}):f===`user`&&w.length===0?(0,X.jsx)(xe,{message:t.extensionsPage.emptyUser}):E.length===0?(0,X.jsx)(`p`,{className:`px-3 py-14 text-center text-sm text-fg-muted sm:px-5 xl:px-6`,children:t.extensionsPage.noSearchResults}):(0,X.jsx)(`div`,{className:`grid gap-4 sm:grid-cols-2 lg:grid-cols-3`,children:E.map(e=>(0,X.jsx)(ge,{extension:e,copy:t.extensionsPage,showSourceBadge:f===`user`,onOpen:()=>y(e)},e.id))})]}),_?(0,X.jsx)(_e,{extension:_,copy:t.extensionsPage,onClose:()=>y(null)},_.id):null]})}function fe(e){return e.activationEligible??e.active}function pe(e,t){return e.source===`bundled`?t.providerBundled:e.source===`global`?t.providerGlobal:e.source===`workspace`?t.providerWorkspace:t.providerOther}function me(e,t){return e.source===`global`?t.badgeSourceGlobal:e.source===`workspace`?t.badgeSourceWorkspace:t.badgeSourceOther}function he(e,t){let n=fe(e);return n&&e.active?t.runStateLive:n&&!e.active?t.runStatePendingOn:!n&&e.active?t.runStatePendingOff:t.runStateOff}function ge(e){let t=(0,W.c)(45),{extension:n,copy:r,showSourceBadge:i,onOpen:a}=e,o;t[0]===n?o=t[1]:(o=fe(n),t[0]=n,t[1]=o);let s=o,c=n.hasUi?r.cardTooltipHasUi:r.cardTooltipNoUi,l;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(l=w(`group flex w-full flex-col rounded-xl border border-edge-subtle bg-surface-base p-4 text-left shadow-surface transition-colors`,`hover:bg-surface-hover/40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,`dark:hover:bg-surface-hover/25`),t[2]=l):l=t[2];let u=n.name||n.id,d;t[3]===u?d=t[4]:(d=u.charAt(0).toUpperCase(),t[3]=u,t[4]=d);let p;t[5]===d?p=t[6]:(p=(0,X.jsx)(`div`,{className:`flex size-12 shrink-0 items-center justify-center rounded-xl bg-accent-soft text-base font-semibold text-accent-fg`,"aria-hidden":!0,children:d}),t[5]=d,t[6]=p);let m;t[7]===n.name?m=t[8]:(m=(0,X.jsx)(`h2`,{className:`truncate text-sm font-semibold text-fg`,children:n.name}),t[7]=n.name,t[8]=m);let h;t[9]===n.version?h=t[10]:(h=n.version?(0,X.jsxs)(`span`,{className:`text-[11px] text-fg-muted`,children:[`v`,n.version]}):null,t[9]=n.version,t[10]=h);let _;t[11]!==m||t[12]!==h?(_=(0,X.jsxs)(`div`,{className:`min-w-0`,children:[m,h]}),t[11]=m,t[12]=h,t[13]=_):_=t[13];let v;t[14]!==r.statusEnabled||t[15]!==s?(v=s?(0,X.jsxs)(`span`,{className:`inline-flex shrink-0 items-center gap-1 rounded-full bg-surface-hover px-2 py-0.5 text-[11px] font-medium text-fg-muted`,children:[(0,X.jsx)(f,{className:`size-3`,strokeWidth:2.5,"aria-hidden":!0}),r.statusEnabled]}):(0,X.jsx)(`span`,{className:`flex size-8 shrink-0 items-center justify-center rounded-full border-2 border-accent text-accent`,"aria-hidden":!0,children:(0,X.jsx)(g,{className:`size-4`,strokeWidth:2.5})}),t[14]=r.statusEnabled,t[15]=s,t[16]=v):v=t[16];let y;t[17]!==_||t[18]!==v?(y=(0,X.jsxs)(`div`,{className:`flex items-start justify-between gap-2`,children:[_,v]}),t[17]=_,t[18]=v,t[19]=y):y=t[19];let b;t[20]!==r.cardNoDescription||t[21]!==n.description?(b=n.description?.trim()||r.cardNoDescription,t[20]=r.cardNoDescription,t[21]=n.description,t[22]=b):b=t[22];let x;t[23]===b?x=t[24]:(x=(0,X.jsx)(`p`,{className:`mt-2 line-clamp-2 text-xs leading-relaxed text-fg-muted`,children:b}),t[23]=b,t[24]=x);let S=n.hasUi?r.badgeKindUi:r.badgeKindBackend,C;t[25]!==S||t[26]!==c?(C=(0,X.jsx)(`span`,{title:c,className:`rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted`,children:S}),t[25]=S,t[26]=c,t[27]=C):C=t[27];let T;t[28]!==r||t[29]!==n||t[30]!==i?(T=n.source===`bundled`?(0,X.jsx)(`span`,{className:`rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted`,children:r.badgeBundled}):i?(0,X.jsx)(`span`,{title:pe(n,r),className:`rounded-md bg-surface-hover px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-fg-muted`,children:me(n,r)}):null,t[28]=r,t[29]=n,t[30]=i,t[31]=T):T=t[31];let E;t[32]!==C||t[33]!==T?(E=(0,X.jsxs)(`div`,{className:`mt-2 flex flex-wrap gap-1.5`,children:[C,T]}),t[32]=C,t[33]=T,t[34]=E):E=t[34];let D;t[35]!==y||t[36]!==x||t[37]!==E?(D=(0,X.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[y,x,E]}),t[35]=y,t[36]=x,t[37]=E,t[38]=D):D=t[38];let O;t[39]!==D||t[40]!==p?(O=(0,X.jsxs)(`div`,{className:`flex gap-3`,children:[p,D]}),t[39]=D,t[40]=p,t[41]=O):O=t[41];let k;return t[42]!==a||t[43]!==O?(k=(0,X.jsx)(`button`,{type:`button`,onClick:a,className:l,children:O}),t[42]=a,t[43]=O,t[44]=k):k=t[44],k}function _e({extension:e,copy:t,onClose:n}){let{mutate:r}=T(),[i,f]=(0,U.useState)(!1),[m,g]=(0,U.useState)(null),[v,y]=(0,U.useState)(!1),b=e.activationEligible===!0,x=(0,U.useCallback)(async()=>{if(e.source===`bundled`){g(null),y(!1),f(!0);try{let{requiresGatewayRestart:t}=await J({extensionId:e.id,enabled:!b});await r(`gateway-extensions-list`),A(),y(t)}catch(e){g(e instanceof Error?e.message:t.builtinToggleFailed)}finally{f(!1)}}},[b,t.builtinToggleFailed,e.id,e.source,r]),S=e.ui?.contributions?.pages??[],C=e.ui?.contributions?.settingsPanels??[],E=e.ui?.contributions?.chatWidgets??[],O=e.ui?.contributions?.sidebarPanels??[],k=S.find(e=>e.showInNav)??S[0],ee=C[0],M=k?N(e.id,k):null,ne=ee?`/settings/ext/${e.id}/${ee.id}`:e.hasConfigSchema||P(e)?`/settings/ext/${e.id}`:null;return(0,X.jsx)(d,{defaultOpen:!0,onOpenChange:e=>!e&&n(),children:(0,X.jsxs)(c,{children:[(0,X.jsx)(o,{className:`xopc-dialog-overlay fixed inset-0 z-[130] bg-scrim`}),(0,X.jsxs)(l,{className:`fixed left-1/2 top-1/2 z-[131] flex max-h-[min(90vh,44rem)] w-[min(42rem,calc(100vw-1.5rem))] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-xl border border-edge bg-surface-panel shadow-elevated`,onOpenAutoFocus:e=>e.preventDefault(),children:[(0,X.jsxs)(`div`,{className:`flex shrink-0 items-center justify-between gap-2 border-b border-edge px-4 py-3`,children:[(0,X.jsx)(`button`,{type:`button`,onClick:n,className:`inline-flex size-9 items-center justify-center rounded-lg text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,"aria-label":t.detailBack,children:(0,X.jsx)(te,{className:`size-5`})}),(0,X.jsx)(u,{className:`min-w-0 flex-1 truncate text-center text-sm font-semibold text-fg`,children:t.detailTitle}),(0,X.jsxs)(s,{className:`sr-only`,children:[e.name,` (`,e.id,`)`]}),(0,X.jsx)(`button`,{type:`button`,onClick:n,className:`inline-flex size-9 items-center justify-center rounded-lg text-fg-muted hover:bg-surface-hover hover:text-fg focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`,"aria-label":t.detailClose,children:(0,X.jsx)(_,{className:`size-5`})})]}),(0,X.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto p-5`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap items-start gap-4`,children:[(0,X.jsx)(`div`,{className:`flex size-16 shrink-0 items-center justify-center rounded-2xl bg-accent-soft text-xl font-semibold text-accent-fg`,"aria-hidden":!0,children:(e.name||e.id).charAt(0).toUpperCase()}),(0,X.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,X.jsx)(`h3`,{className:`text-lg font-semibold text-fg`,children:e.name}),(0,X.jsxs)(`p`,{className:`mt-0.5 text-sm text-fg-muted`,children:[t.detailProviderPrefix,` `,pe(e,t)]}),e.version?(0,X.jsxs)(`p`,{className:`mt-1 text-xs text-fg-muted`,children:[`v`,e.version]}):null]})]}),(0,X.jsx)(`p`,{className:`mt-5 text-sm leading-relaxed text-fg`,children:e.description?.trim()||t.detailNoDescription}),e.hasUi?null:(0,X.jsx)(`p`,{className:`mt-3 text-xs text-fg-muted`,children:t.backendOnlyHint}),(0,X.jsx)(`p`,{className:`mt-2 text-xs text-fg-muted`,children:he(e,t)}),e.source===`bundled`?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(`p`,{className:`mt-4 rounded-lg bg-surface-hover/40 px-3 py-2 text-xs text-fg-muted shadow-surface dark:bg-surface-hover/20`,children:t.builtinConfigHint}),(0,X.jsxs)(`div`,{className:`mt-3 rounded-lg bg-surface-hover/40 p-3 shadow-surface dark:bg-surface-hover/20`,children:[(0,X.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,X.jsx)(`span`,{className:`text-xs font-medium text-fg`,children:t.builtinRuntimeToggle}),(0,X.jsx)(D,{type:`button`,variant:`secondary`,disabled:i,onClick:()=>void x(),className:`shrink-0 py-1.5 text-xs`,children:i?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(h,{className:`mr-1.5 size-3.5 shrink-0 animate-spin`,"aria-hidden":!0}),t.builtinToggleBusy]}):b?t.builtinToggleDisable:t.builtinToggleEnable})]}),m?(0,X.jsx)(`p`,{className:`mt-2 text-xs text-rose-600 dark:text-rose-400`,children:m}):null,v?(0,X.jsx)(`p`,{className:`mt-2 text-xs text-fg-muted`,children:t.builtinToggleRestartHint}):null]})]}):(0,X.jsx)(`p`,{className:`mt-4 rounded-lg bg-surface-hover/40 px-3 py-2 text-xs text-fg-muted shadow-surface dark:bg-surface-hover/20`,children:t.cliManageHint}),e.hasUi&&(S.length>0||C.length>0||E.length>0)?(0,X.jsxs)(`section`,{className:`mt-8`,children:[(0,X.jsx)(`h4`,{className:`mb-3 text-sm font-semibold text-fg`,children:t.detailSectionFeatures}),(0,X.jsxs)(`div`,{className:`flex flex-wrap gap-1.5`,children:[(0,X.jsx)(ve,{template:t.badgePages,count:S.length,hidden:S.length===0}),(0,X.jsx)(ve,{template:t.badgeSettings,count:C.length,hidden:C.length===0}),(0,X.jsx)(ve,{template:t.badgeWidgets,count:E.length,hidden:E.length===0}),(0,X.jsx)(ve,{template:t.badgeSidebar,count:O.length,hidden:O.length===0})]})]}):null,j(e)&&(M||ne)?(0,X.jsxs)(`div`,{className:`mt-6 flex flex-wrap gap-2 border-t border-edge-subtle pt-4`,children:[M?(0,X.jsxs)(a,{to:M,onClick:n,className:w(`inline-flex items-center gap-1.5 rounded-lg border border-edge px-3 py-2 text-sm font-medium text-fg`,`hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`),children:[(0,X.jsx)(p,{className:`size-4 shrink-0 opacity-80`,"aria-hidden":!0}),t.open]}):null,ne?(0,X.jsxs)(a,{to:ne,onClick:n,className:w(`inline-flex items-center gap-1.5 rounded-lg border border-edge px-3 py-2 text-sm font-medium text-fg`,`hover:bg-surface-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent`),children:[(0,X.jsx)(L,{className:`size-4 shrink-0 opacity-80`,"aria-hidden":!0}),t.openSettings]}):null]}):null,(0,X.jsx)(`p`,{className:`mt-6 text-[11px] leading-relaxed text-fg-muted`,children:t.restartNote})]})]})]})})}function ve(e){let t=(0,W.c)(6),{template:n,count:r,hidden:i}=e;if(i||r===0)return null;let a;if(t[0]!==r||t[1]!==n){let e;t[3]===Symbol.for(`react.memo_cache_sentinel`)?(e=/\{\{count\}\}/g,t[3]=e):e=t[3],a=n.replace(e,String(r)),t[0]=r,t[1]=n,t[2]=a}else a=t[2];let o;return t[4]===a?o=t[5]:(o=(0,X.jsx)(`span`,{className:`inline-flex items-center rounded-md bg-surface-hover px-2 py-0.5 text-[11px] font-medium text-fg-muted`,children:a}),t[4]=a,t[5]=o),o}function ye(){let e=(0,W.c)(5),t,n,r;e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,X.jsx)(`div`,{className:`mb-6 h-8 w-40 max-w-full animate-pulse rounded-md bg-surface-hover`}),n=(0,X.jsx)(`div`,{className:`mb-2 h-4 w-full max-w-md animate-pulse rounded bg-surface-hover`}),r=(0,X.jsx)(`div`,{className:`mb-5 h-9 w-full max-w-lg animate-pulse rounded-full bg-surface-hover`}),e[0]=t,e[1]=n,e[2]=r):(t=e[0],n=e[1],r=e[2]);let i;e[3]===Symbol.for(`react.memo_cache_sentinel`)?(i=[`ap0`,`ap1`,`ap2`,`ap3`,`ap4`,`ap5`],e[3]=i):i=e[3];let a;return e[4]===Symbol.for(`react.memo_cache_sentinel`)?(a=(0,X.jsx)(`div`,{className:`flex min-h-0 min-w-0 flex-1 flex-col bg-surface-panel`,children:(0,X.jsxs)(`div`,{className:`w-full px-3 py-8 sm:px-5 xl:px-6`,children:[t,n,r,(0,X.jsx)(`div`,{className:`mt-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-3`,children:i.map(be)})]})}),e[4]=a):a=e[4],a}function be(e){return(0,X.jsx)(`div`,{className:`h-36 animate-pulse rounded-xl border border-edge-subtle bg-surface-base shadow-surface`},e)}function xe(e){let t=(0,W.c)(2),{message:n}=e,r;return t[0]===n?r=t[1]:(r=(0,X.jsx)(`div`,{className:`flex min-h-[min(40vh,16rem)] flex-col items-center justify-center rounded-xl border border-edge-subtle bg-surface-base px-4 py-12 text-center shadow-surface`,children:(0,X.jsx)(`p`,{className:`text-sm text-fg-muted`,children:n})}),t[0]=n,t[1]=r),r}export{de as ExtensionsPage};