@xopcai/xopc 0.0.347 → 0.0.349

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 (124) hide show
  1. package/dist/browser-ext/_locales/en/messages.json +3 -2
  2. package/dist/browser-ext/_locales/zh_CN/messages.json +3 -2
  3. package/dist/browser-ext/dist/assets/{auth-CFiOJ_rf.js → auth-beGtbLPS.js} +47 -33
  4. package/dist/browser-ext/dist/assets/{sidepanel-DD6GEMvc.css → sidepanel-BT0ojEzG.css} +2 -0
  5. package/dist/browser-ext/dist/background.js +5 -3
  6. package/dist/browser-ext/dist/sidepanel.html +2 -2
  7. package/dist/browser-ext/dist/sidepanel.js +34 -10
  8. package/dist/browser-ext/manifest.json +1 -1
  9. package/dist/extensions/telegram/xopc.extension.json +1 -1
  10. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CoiIwwcu.js → agent-avatar-dicebear-CiOc0zWr.js} +1 -1
  11. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-BvL4FTKi.js +1 -0
  12. package/dist/gateway/static/root/assets/{agent-plugin-dialog-SJIZZLqo.js → agent-plugin-dialog-BOzZvojX.js} +1 -1
  13. package/dist/gateway/static/root/assets/agents-BrPqEJm5.js +70 -0
  14. package/dist/gateway/static/root/assets/{app-management-settings-panel-6zwkqMLD.js → app-management-settings-panel-BY7yVNOc.js} +1 -1
  15. package/dist/gateway/static/root/assets/{appearance-settings-DiWUyQlA.js → appearance-settings-Cqk9QUWY.js} +1 -1
  16. package/dist/gateway/static/root/assets/apps-page-DH1ZZh_x.js +1 -0
  17. package/dist/gateway/static/root/assets/{archive-plugin-12JlrV5S.js → archive-plugin-CClKYiZH.js} +1 -1
  18. package/dist/gateway/static/root/assets/{automations-page-DkCvD50d.js → automations-page-DqtZazSc.js} +1 -1
  19. package/dist/gateway/static/root/assets/automations-workspace-BN0s1ILZ.js +7 -0
  20. package/dist/gateway/static/root/assets/{binary-plugins-PhtCEjXI.js → binary-plugins-C680MkH2.js} +1 -1
  21. package/dist/gateway/static/root/assets/{block-editor-ClfFgVfs.js → block-editor-B4lDSWIv.js} +29 -29
  22. package/dist/gateway/static/root/assets/{browser-automations-page-Cln2uM_F.js → browser-automations-page-B0FqXGpQ.js} +2 -2
  23. package/dist/gateway/static/root/assets/browser-settings-page-CNVdAeRH.js +3 -0
  24. package/dist/gateway/static/root/assets/{capabilities-page-eKbC_K_v.js → capabilities-page-DqDP04o0.js} +2 -2
  25. package/dist/gateway/static/root/assets/capabilities-settings-panel-Dd1xjlpb.js +8 -0
  26. package/dist/gateway/static/root/assets/{capability-header-actions-BlSn4DO-.js → capability-header-actions-CHokFPVe.js} +1 -1
  27. package/dist/gateway/static/root/assets/channels-aemisJsK.js +1 -0
  28. package/dist/gateway/static/root/assets/{chat-terminal-dock-CjJ3yFld.js → chat-terminal-dock-C9zgTx4N.js} +2 -2
  29. package/dist/gateway/static/root/assets/{computer-settings-page-L7oHWFBe.js → computer-settings-page-DzIVWHw5.js} +1 -1
  30. package/dist/gateway/static/root/assets/{connector-service-page-5522WTzU.js → connector-service-page-B_9tzNtD.js} +1 -1
  31. package/dist/gateway/static/root/assets/connectors-page-D0qvb3mB.js +2 -0
  32. package/dist/gateway/static/root/assets/{date-picker-CX-fcLaj.js → date-picker-B_hPKrIP.js} +1 -1
  33. package/dist/gateway/static/root/assets/{dependency-picker-aQFvZft6.js → dependency-picker-BPAS7Ee7.js} +1 -1
  34. package/dist/gateway/static/root/assets/{desktop-pet-C4Uhyxe8.js → desktop-pet-XzkMTcLt.js} +1 -1
  35. package/dist/gateway/static/root/assets/{desktop-pet-settings-Cfe9_J1_.js → desktop-pet-settings-CmhF1kse.js} +1 -1
  36. package/dist/gateway/static/root/assets/device-pairing-wizard-BcptV-hP.js +1 -0
  37. package/dist/gateway/static/root/assets/{directory-picker-path-field-C8SJyIWD.js → directory-picker-path-field-CHbRbJZj.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-debug-page-D6cI3rxD.js → extension-debug-page-CNsneD82.js} +1 -1
  39. package/dist/gateway/static/root/assets/{extension-page-hAhyhLBd.js → extension-page-DxiiQ_-P.js} +1 -1
  40. package/dist/gateway/static/root/assets/{extension-settings-page-BaVBR7JT.js → extension-settings-page-DIh4aO4j.js} +1 -1
  41. package/dist/gateway/static/root/assets/gateway-settings-BNcafQJB.js +1 -0
  42. package/dist/gateway/static/root/assets/home-page-BvZcBNhP.js +1 -0
  43. package/dist/gateway/static/root/assets/{imports-page-B86kmOio.js → imports-page-DgUrv_Rh.js} +1 -1
  44. package/dist/gateway/static/root/assets/index-Cfg6ma6d.css +1 -0
  45. package/dist/gateway/static/root/assets/index-oJE8g8BL.js +106 -0
  46. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-hrPwzRF0.js → keyboard-shortcuts-settings-CuQZEmVh.js} +1 -1
  47. package/dist/gateway/static/root/assets/{local-app-workbench-page-xxr8vk61.js → local-app-workbench-page-BLbLqWVm.js} +1 -1
  48. package/dist/gateway/static/root/assets/{local-apps-page-DjGpad5m.js → local-apps-page-CErGXyIl.js} +1 -1
  49. package/dist/gateway/static/root/assets/{logs-page-BaNpykh9.js → logs-page-flTbDuMT.js} +2 -2
  50. package/dist/gateway/static/root/assets/management-settings-QQT6byMB.js +1 -0
  51. package/dist/gateway/static/root/assets/{media-plugins-N8-QJc33.js → media-plugins-Y1tnLGkI.js} +1 -1
  52. package/dist/gateway/static/root/assets/note-detail-panel-B7HS4oqs.js +5 -0
  53. package/dist/gateway/static/root/assets/notes-page-BYpUaCxU.js +8 -0
  54. package/dist/gateway/static/root/assets/{page-context-capture-button-BmgyQ8lB.js → page-context-capture-button-DOcROUXS.js} +1 -1
  55. package/dist/gateway/static/root/assets/{page-tabs-yZZdLTLc.js → page-tabs-CU8zjRtM.js} +1 -1
  56. package/dist/gateway/static/root/assets/{preview-open-alternatives-BWqdZ75S.js → preview-open-alternatives-BoZWmgG_.js} +1 -1
  57. package/dist/gateway/static/root/assets/{product-open-page-ysuSrfYK.js → product-open-page-C0pJaYJB.js} +1 -1
  58. package/dist/gateway/static/root/assets/project-detail-page-xrlYOZ7-.js +1 -0
  59. package/dist/gateway/static/root/assets/projects-page--OYwmNEy.js +1 -0
  60. package/dist/gateway/static/root/assets/remote-access-hub-6qkix2R1.js +1 -0
  61. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-C8OZvZxC.js → runtime-tools-settings-panel-C06BmltI.js} +2 -2
  62. package/dist/gateway/static/root/assets/{scenes-page-R9FSDMyC.js → scenes-page-BTRh_BNJ.js} +2 -2
  63. package/dist/gateway/static/root/assets/{schema-form-DEK9fasz.js → schema-form-Dl0j1Pjj.js} +1 -1
  64. package/dist/gateway/static/root/assets/{session-manager-B9ZJw1W4.js → session-manager-B6_KNduD.js} +1 -1
  65. package/dist/gateway/static/root/assets/sessions-page-BDqe_-Sr.js +1 -0
  66. package/dist/gateway/static/root/assets/settings-advanced-gate-aDIE1Okc.js +1 -0
  67. package/dist/gateway/static/root/assets/{settings-form-section-DEWe2yXX.js → settings-form-section-DX9Q7-oB.js} +1 -1
  68. package/dist/gateway/static/root/assets/{settings-page-J9m511lP.js → settings-page-DyjpNUtv.js} +1 -1
  69. package/dist/gateway/static/root/assets/setup-status-panel-D7CPCTs-.js +1 -0
  70. package/dist/gateway/static/root/assets/{share-preview-page-CfN124hX.js → share-preview-page-NXyrys7a.js} +1 -1
  71. package/dist/gateway/static/root/assets/shares-settings-C7APzUWD.js +1 -0
  72. package/dist/gateway/static/root/assets/{skill-api-DKKacicr.js → skill-api-D2Zav1-k.js} +1 -1
  73. package/dist/gateway/static/root/assets/{skill-reload-api-CPUdkUW4.js → skill-reload-api-C7-ZWRB-.js} +1 -1
  74. package/dist/gateway/static/root/assets/skills-page-C8XzNFai.js +2 -0
  75. package/dist/gateway/static/root/assets/{system-settings-panel-CBABQnDB.js → system-settings-panel-CjAKelf_.js} +1 -1
  76. package/dist/gateway/static/root/assets/task-detail-page-C2tCewyf.js +1 -0
  77. package/dist/gateway/static/root/assets/{tunnel-api-h8J8sWvL.js → tunnel-api-RsRe1MVk.js} +1 -1
  78. package/dist/gateway/static/root/assets/{usage-page-BqN4hLxa.js → usage-page-Cz8WM0U_.js} +1 -1
  79. package/dist/gateway/static/root/assets/{use-autosave-DAYoOcKf.js → use-autosave-Bs2Zw_LW.js} +1 -1
  80. package/dist/gateway/static/root/assets/user-model-page-BQ4P1A_c.js +2 -0
  81. package/dist/gateway/static/root/assets/{voice-api-key-field-C2SX3Gb3.js → voice-api-key-field-CCznhcKT.js} +1 -1
  82. package/dist/gateway/static/root/assets/{work-discovery-overlay-F0tCV50t.js → work-discovery-overlay-DzllwGa7.js} +1 -1
  83. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BWyDzuu9.js → workflow-run-setup-panel-C8Q_04la.js} +2 -2
  84. package/dist/gateway/static/root/assets/workflows-page-3724WDyr.js +6 -0
  85. package/dist/gateway/static/root/index.html +3 -3
  86. package/dist/package.js +1 -1
  87. package/dist/src/backup/archive.d.ts +33 -0
  88. package/dist/src/backup/archive.js +322 -0
  89. package/dist/src/cli/command-loaders.js +1 -0
  90. package/dist/src/cli/command-manifest.js +4 -0
  91. package/dist/src/cli/commands/backup.d.ts +1 -0
  92. package/dist/src/cli/commands/backup.js +84 -0
  93. package/dist/src/cli/index.js +3 -2
  94. package/dist/src/gateway/service.js +4 -4
  95. package/dist/src/gateway/session-context-summary.js +113 -5
  96. package/dist/src/home-intelligence/host.js +2 -2
  97. package/package.json +2 -2
  98. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CMnbBav3.js +0 -1
  99. package/dist/gateway/static/root/assets/agents-CB-eDUCf.js +0 -70
  100. package/dist/gateway/static/root/assets/apps-page-Dhtxj66a.js +0 -1
  101. package/dist/gateway/static/root/assets/automations-workspace-BWrYnsIk.js +0 -7
  102. package/dist/gateway/static/root/assets/browser-settings-page-BtqTwprD.js +0 -3
  103. package/dist/gateway/static/root/assets/capabilities-settings-panel-Cga_BvtH.js +0 -8
  104. package/dist/gateway/static/root/assets/channels-CUNI7YuR.js +0 -1
  105. package/dist/gateway/static/root/assets/connectors-page-C2AUOcWz.js +0 -2
  106. package/dist/gateway/static/root/assets/device-pairing-wizard-CKpSUyhq.js +0 -1
  107. package/dist/gateway/static/root/assets/gateway-settings-CDbZ2_6H.js +0 -1
  108. package/dist/gateway/static/root/assets/home-page-B7KbsJKW.js +0 -1
  109. package/dist/gateway/static/root/assets/index-BXK396ki.js +0 -106
  110. package/dist/gateway/static/root/assets/index-DUAz4R7d.css +0 -1
  111. package/dist/gateway/static/root/assets/management-settings-BFX3uxYe.js +0 -1
  112. package/dist/gateway/static/root/assets/note-detail-panel-Cd2Xn69o.js +0 -5
  113. package/dist/gateway/static/root/assets/notes-page-Bsl4HbT9.js +0 -8
  114. package/dist/gateway/static/root/assets/project-detail-page-Cw4eSr4K.js +0 -1
  115. package/dist/gateway/static/root/assets/projects-page-B2Y4n5sK.js +0 -1
  116. package/dist/gateway/static/root/assets/remote-access-hub-DYwr2taY.js +0 -1
  117. package/dist/gateway/static/root/assets/sessions-page-BpFoEKF1.js +0 -1
  118. package/dist/gateway/static/root/assets/settings-advanced-gate-DjmP_P8-.js +0 -1
  119. package/dist/gateway/static/root/assets/setup-status-panel-CzXfd8sp.js +0 -1
  120. package/dist/gateway/static/root/assets/shares-settings-CTsg7oUv.js +0 -1
  121. package/dist/gateway/static/root/assets/skills-page-DaehgBFO.js +0 -2
  122. package/dist/gateway/static/root/assets/task-detail-page-C7Vpoc1R.js +0 -1
  123. package/dist/gateway/static/root/assets/user-model-page-Bog1W3OS.js +0 -2
  124. package/dist/gateway/static/root/assets/workflows-page-ClBQeXmf.js +0 -6
@@ -165,8 +165,9 @@
165
165
  "placeholders": { "host": { "content": "$1" } }
166
166
  },
167
167
  "errorSelectText": { "message": "Select text on the page first" },
168
- "errorNoReadableContent": { "message": "This page has no readable content" },
169
- "errorReadPage": { "message": "Could not read this page" },
168
+ "errorNoReadableContent": { "message": "No readable text was found. Select text or attach a screenshot instead." },
169
+ "errorReadPage": { "message": "Chrome returned no page data. Reload the tab and try again, or attach a screenshot." },
170
+ "attachScreenshotInstead": { "message": "Attach screenshot" },
170
171
  "errorPageChangedReading": { "message": "The page changed while xopc was reading it. Try again." },
171
172
  "errorPageChangedConnecting": { "message": "The page changed while xopc was connecting to it. Try again." },
172
173
  "errorIdentifyPage": { "message": "Could not identify this page" },
@@ -165,8 +165,9 @@
165
165
  "placeholders": { "host": { "content": "$1" } }
166
166
  },
167
167
  "errorSelectText": { "message": "请先在页面上选择文本" },
168
- "errorNoReadableContent": { "message": "此页面没有可读内容" },
169
- "errorReadPage": { "message": "无法读取此页面" },
168
+ "errorNoReadableContent": { "message": "未找到可读文本。可选择文本或附加截图。" },
169
+ "errorReadPage": { "message": "Chrome 未返回页面数据。请刷新标签页后重试,或附加截图。" },
170
+ "attachScreenshotInstead": { "message": "附加截图" },
170
171
  "errorPageChangedReading": { "message": "xopc 读取页面时页面发生了变化,请重试。" },
171
172
  "errorPageChangedConnecting": { "message": "xopc 连接页面时页面发生了变化,请重试。" },
172
173
  "errorIdentifyPage": { "message": "无法识别此页面" },
@@ -5916,6 +5916,27 @@ function initializeDocumentLocale() {
5916
5916
 
5917
5917
  const PENDING_CONTEXT_KEY = "xopc.browser.pending-context";
5918
5918
  const TAB_BINDING_PREFIX = "xopc.browser.tab-binding.";
5919
+ async function buildPageContext(raw, pageUrl) {
5920
+ const url = sanitizedUrl(pageUrl);
5921
+ const selected = raw.selection ? truncateUtf8(raw.selection, MAX_BROWSER_SELECTION_BYTES) : void 0;
5922
+ const page = raw.text ? truncateUtf8(raw.text, MAX_BROWSER_PAGE_TEXT_BYTES) : void 0;
5923
+ const canonical = {
5924
+ title: raw.title.trim() || new URL(url).hostname,
5925
+ url,
5926
+ capturedAt: Date.now(),
5927
+ documentId: await sha256(`${url}
5928
+ ${raw.timeOrigin}`),
5929
+ selection: selected?.value,
5930
+ text: page?.value
5931
+ };
5932
+ return {
5933
+ kind: "browser_page",
5934
+ sourceId: crypto.randomUUID(),
5935
+ version: await sha256(JSON.stringify(canonical)),
5936
+ ...canonical,
5937
+ truncated: selected?.truncated === true || page?.truncated === true
5938
+ };
5939
+ }
5919
5940
  function truncateUtf8(value, maxBytes) {
5920
5941
  const encoder = new TextEncoder();
5921
5942
  if (encoder.encode(value).byteLength <= maxBytes) return { value, truncated: false };
@@ -5984,15 +6005,16 @@ async function sha256(value) {
5984
6005
  const bytes = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
5985
6006
  return [...new Uint8Array(bytes)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
5986
6007
  }
5987
- function extractPage(mode, messages) {
6008
+ function extractPage(mode) {
5988
6009
  const normalize = (value) => value.replace(/\s+/g, " ").trim();
5989
- const selection = normalize(window.getSelection()?.toString() ?? "");
5990
6010
  if (mode === "selection") {
5991
- if (!selection) throw new Error(messages.selectText);
6011
+ const focused = document.activeElement;
6012
+ const fieldSelection = focused instanceof HTMLTextAreaElement || focused instanceof HTMLInputElement && ["text", "search", "url", "email", "tel"].includes(focused.type) ? focused.value.slice(focused.selectionStart ?? 0, focused.selectionEnd ?? 0) : "";
6013
+ const selection = normalize(fieldSelection || window.getSelection()?.toString() || "");
5992
6014
  return { title: document.title, url: location.href, timeOrigin: performance.timeOrigin, selection };
5993
6015
  }
5994
6016
  const source = document.querySelector("article, main") ?? document.body;
5995
- if (!source) throw new Error(messages.noReadableContent);
6017
+ if (!source) return { title: document.title, url: location.href, timeOrigin: performance.timeOrigin };
5996
6018
  const clone = source.cloneNode(true);
5997
6019
  clone.querySelectorAll([
5998
6020
  "script",
@@ -6014,45 +6036,37 @@ function extractPage(mode, messages) {
6014
6036
  "[inert]"
6015
6037
  ].join(",")).forEach((element) => element.remove());
6016
6038
  const text = normalize(clone.innerText || clone.textContent || "");
6017
- if (!text) throw new Error(messages.noReadableContent);
6018
6039
  return { title: document.title, url: location.href, timeOrigin: performance.timeOrigin, text };
6019
6040
  }
6041
+ async function captureContextMenuSelection(tabId, selectionText, pageUrl) {
6042
+ const tab = await chrome.tabs.get(tabId);
6043
+ if (!tab.url) throw new Error(t("errorTabUnavailable"));
6044
+ const url = sanitizedUrl(tab.url);
6045
+ if (pageUrl && sanitizedUrl(pageUrl) !== url) throw new Error(t("errorPageChangedReading"));
6046
+ const selection = selectionText.replace(/\s+/g, " ").trim();
6047
+ if (!selection) throw new Error(t("errorSelectText"));
6048
+ return buildPageContext({ title: tab.title ?? "", timeOrigin: Date.now(), selection }, url);
6049
+ }
6020
6050
  async function captureTabPage(tabId, mode) {
6021
6051
  const tab = await chrome.tabs.get(tabId);
6022
6052
  if (!tab.url) throw new Error(t("errorTabUnavailable"));
6023
6053
  sanitizedUrl(tab.url);
6024
6054
  const result = await chrome.scripting.executeScript({
6025
- target: { tabId },
6055
+ target: { tabId, allFrames: true },
6026
6056
  func: extractPage,
6027
- args: [mode, {
6028
- selectText: t("errorSelectText"),
6029
- noReadableContent: t("errorNoReadableContent")
6030
- }]
6057
+ args: [mode]
6031
6058
  });
6032
- const raw = result[0]?.result;
6033
- if (!raw) throw new Error(t("errorReadPage"));
6034
- const url = sanitizedUrl(raw.url);
6035
- if (new URL(url).origin !== new URL(sanitizedUrl(tab.url)).origin) {
6059
+ const main = result[0]?.result;
6060
+ if (!main) throw new Error(t("errorReadPage"));
6061
+ const currentTab = await chrome.tabs.get(tabId);
6062
+ if (!currentTab.url || sanitizedUrl(main.url) !== sanitizedUrl(tab.url) || sanitizedUrl(main.url) !== sanitizedUrl(currentTab.url)) {
6036
6063
  throw new Error(t("errorPageChangedReading"));
6037
6064
  }
6038
- const selected = raw.selection ? truncateUtf8(raw.selection, MAX_BROWSER_SELECTION_BYTES) : void 0;
6039
- const page = raw.text ? truncateUtf8(raw.text, MAX_BROWSER_PAGE_TEXT_BYTES) : void 0;
6040
- const canonical = {
6041
- title: raw.title.trim() || new URL(url).hostname,
6042
- url,
6043
- capturedAt: Date.now(),
6044
- documentId: await sha256(`${url}
6045
- ${raw.timeOrigin}`),
6046
- selection: selected?.value,
6047
- text: page?.value
6048
- };
6049
- return {
6050
- kind: "browser_page",
6051
- sourceId: crypto.randomUUID(),
6052
- version: await sha256(JSON.stringify(canonical)),
6053
- ...canonical,
6054
- truncated: selected?.truncated === true || page?.truncated === true
6055
- };
6065
+ const content = result.map((item) => item.result).find((item) => mode === "selection" ? item?.selection : item?.text);
6066
+ if (!content?.selection && !content?.text) {
6067
+ throw new Error(t(mode === "selection" ? "errorSelectText" : "errorNoReadableContent"));
6068
+ }
6069
+ return buildPageContext({ ...main, selection: content.selection, text: content.text }, main.url);
6056
6070
  }
6057
6071
  async function captureTabWithPermission(tabId, mode) {
6058
6072
  return runWithTabSiteAccess(tabId, () => captureTabPage(tabId, mode));
@@ -6752,4 +6766,4 @@ async function revokeAndForgetProfile() {
6752
6766
  }
6753
6767
  }
6754
6768
 
6755
- export { runWithTabSiteAccess as A, saveExtensionLocalePreference as B, setAutoConnectEnabled as C, strictObject as D, ENDPOINT_PROTOCOL_VERSION as E, string as F, t as G, MAX_BROWSER_CONTEXTS_PER_TURN as M, PENDING_CONTEXT_KEY as P, REALTIME_PROTOCOL_VERSION as R, TAB_BINDING_PREFIX as T, _enum as _, RealtimeClient as a, activeTabId as b, array as c, boolean as d, browserPageContextsInputSchema as e, cancelPendingBrowserPairing as f, canonicalJson as g, captureTabWithPermission as h, createBrowserEndpointHello as i, currentTabDescriptor as j, discoverLocalGateway as k, discriminatedUnion as l, endpointToolContentSchema as m, extensionLocale as n, gatewayFetch as o, getAccessProfile as p, literal as q, loadExtensionLocalePreference as r, number as s, object as t, openDatabase as u, pairGateway as v, readPendingBrowserPairing as w, readProfile as x, registerBrowserEndpoint as y, revokeAndForgetProfile as z };
6769
+ export { revokeAndForgetProfile as A, runWithTabSiteAccess as B, saveExtensionLocalePreference as C, setAutoConnectEnabled as D, ENDPOINT_PROTOCOL_VERSION as E, strictObject as F, string as G, t as H, MAX_BROWSER_CONTEXTS_PER_TURN as M, PENDING_CONTEXT_KEY as P, REALTIME_PROTOCOL_VERSION as R, TAB_BINDING_PREFIX as T, _enum as _, RealtimeClient as a, activeTabId as b, array as c, boolean as d, browserPageContextsInputSchema as e, cancelPendingBrowserPairing as f, canonicalJson as g, captureContextMenuSelection as h, captureTabWithPermission as i, createBrowserEndpointHello as j, currentTabDescriptor as k, discoverLocalGateway as l, discriminatedUnion as m, endpointToolContentSchema as n, extensionLocale as o, gatewayFetch as p, getAccessProfile as q, literal as r, loadExtensionLocalePreference as s, number as t, object as u, openDatabase as v, pairGateway as w, readPendingBrowserPairing as x, readProfile as y, registerBrowserEndpoint as z };
@@ -292,6 +292,8 @@ svg { display: block; }
292
292
  .file-input { display: none; }
293
293
  .composer-error { display: flex; align-items: flex-start; gap: 6px; margin: 0 2px 7px; border-radius: 8px; padding: 7px 8px; background: var(--danger-soft); color: var(--danger); font-size: 10px; line-height: 1.4; }
294
294
  .composer-error svg { width: 13px; height: 13px; flex: 0 0 auto; }
295
+ .composer-error span { flex: 1; }
296
+ .composer-error button { border: 0; background: none; color: inherit; font: inherit; font-weight: 600; text-decoration: underline; cursor: pointer; }
295
297
  .composer-notice { margin: 0 2px 7px; border-radius: 8px; padding: 7px 8px; background: var(--warning-soft); color: color-mix(in srgb, var(--warning) 72%, var(--fg)); font-size: 10px; line-height: 1.4; }
296
298
 
297
299
  .tab-mention-menu { position: absolute; z-index: 13; left: 0; right: 0; bottom: calc(100% + 8px); max-height: min(45vh, 320px); overflow-y: auto; border: 1px solid var(--edge-strong); border-radius: 12px; background: var(--surface-panel); padding: 5px; box-shadow: var(--shadow-popover); }
@@ -1,4 +1,4 @@
1
- import { m as endpointToolContentSchema, E as ENDPOINT_PROTOCOL_VERSION, g as canonicalJson, T as TAB_BINDING_PREFIX, h as captureTabWithPermission, P as PENDING_CONTEXT_KEY, G as t, x as readProfile, y as registerBrowserEndpoint, p as getAccessProfile, a as RealtimeClient, i as createBrowserEndpointHello, o as gatewayFetch, R as REALTIME_PROTOCOL_VERSION } from './assets/auth-CFiOJ_rf.js';
1
+ import { n as endpointToolContentSchema, E as ENDPOINT_PROTOCOL_VERSION, g as canonicalJson, T as TAB_BINDING_PREFIX, h as captureContextMenuSelection, P as PENDING_CONTEXT_KEY, H as t, y as readProfile, z as registerBrowserEndpoint, q as getAccessProfile, a as RealtimeClient, j as createBrowserEndpointHello, p as gatewayFetch, R as REALTIME_PROTOCOL_VERSION } from './assets/auth-beGtbLPS.js';
2
2
 
3
3
  const BROWSER_EXTENSION_PROTOCOL_VERSION = 5;
4
4
  const BROWSER_CONTROL_ENDPOINT_TOOL_NAME = "browser.control";
@@ -1355,11 +1355,13 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1355
1355
  chrome.contextMenus.onClicked.addListener((info, tab) => {
1356
1356
  if (info.menuItemId !== "xopc-ask-selection" || !tab?.id) return;
1357
1357
  const tabId = tab.id;
1358
- void captureTabWithPermission(tabId, "selection").then(async (context) => {
1358
+ void chrome.sidePanel.open({ tabId }).catch((error) => log.warn("Could not open the side panel", {
1359
+ error: error instanceof Error ? error.message : String(error)
1360
+ }));
1361
+ void captureContextMenuSelection(tabId, info.selectionText ?? "", info.pageUrl).then(async (context) => {
1359
1362
  await chrome.storage.session.set({
1360
1363
  [PENDING_CONTEXT_KEY]: { context, tabId, source: "current_selection" }
1361
1364
  });
1362
- await chrome.sidePanel.open({ tabId });
1363
1365
  }).catch((error) => log.warn("Could not attach selected page text", {
1364
1366
  error: error instanceof Error ? error.message : String(error)
1365
1367
  }));
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>xopc</title>
7
7
  <script type="module" crossorigin src="./sidepanel.js"></script>
8
- <link rel="modulepreload" crossorigin href="./assets/auth-CFiOJ_rf.js">
9
- <link rel="stylesheet" crossorigin href="./assets/sidepanel-DD6GEMvc.css">
8
+ <link rel="modulepreload" crossorigin href="./assets/auth-beGtbLPS.js">
9
+ <link rel="stylesheet" crossorigin href="./assets/sidepanel-BT0ojEzG.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
@@ -1,4 +1,4 @@
1
- import { D as strictObject, s as number, d as boolean, F as string, c as array, _ as _enum, q as literal, t as object, l as discriminatedUnion, e as browserPageContextsInputSchema, G as t, M as MAX_BROWSER_CONTEXTS_PER_TURN, o as gatewayFetch, n as extensionLocale, u as openDatabase, a as RealtimeClient, R as REALTIME_PROTOCOL_VERSION, b as activeTabId, j as currentTabDescriptor, T as TAB_BINDING_PREFIX, p as getAccessProfile, x as readProfile, A as runWithTabSiteAccess, P as PENDING_CONTEXT_KEY, h as captureTabWithPermission, v as pairGateway, C as setAutoConnectEnabled, w as readPendingBrowserPairing, k as discoverLocalGateway, B as saveExtensionLocalePreference, z as revokeAndForgetProfile, f as cancelPendingBrowserPairing, r as loadExtensionLocalePreference } from './assets/auth-CFiOJ_rf.js';
1
+ import { F as strictObject, t as number, d as boolean, G as string, c as array, _ as _enum, r as literal, u as object, m as discriminatedUnion, e as browserPageContextsInputSchema, H as t, M as MAX_BROWSER_CONTEXTS_PER_TURN, p as gatewayFetch, o as extensionLocale, v as openDatabase, a as RealtimeClient, R as REALTIME_PROTOCOL_VERSION, b as activeTabId, k as currentTabDescriptor, T as TAB_BINDING_PREFIX, q as getAccessProfile, y as readProfile, B as runWithTabSiteAccess, P as PENDING_CONTEXT_KEY, i as captureTabWithPermission, w as pairGateway, D as setAutoConnectEnabled, x as readPendingBrowserPairing, l as discoverLocalGateway, C as saveExtensionLocalePreference, A as revokeAndForgetProfile, f as cancelPendingBrowserPairing, s as loadExtensionLocalePreference } from './assets/auth-beGtbLPS.js';
2
2
 
3
3
  const AppContextResourceSchema = strictObject({
4
4
  kind: _enum(["note", "task", "project", "scene", "local_app"]),
@@ -28357,6 +28357,7 @@ function ChatPanel({ gatewayId, deviceId }) {
28357
28357
  const [menuOpen, setMenuOpen] = reactExports.useState(false);
28358
28358
  const [toolsOpen, setToolsOpen] = reactExports.useState(false);
28359
28359
  const [error, setError] = reactExports.useState("");
28360
+ const [screenshotFallbackError, setScreenshotFallbackError] = reactExports.useState("");
28360
28361
  const [copiedMessageId, setCopiedMessageId] = reactExports.useState("");
28361
28362
  const [clarificationAnswer, setClarificationAnswer] = reactExports.useState("");
28362
28363
  const [clarificationSubmitting, setClarificationSubmitting] = reactExports.useState(false);
@@ -28394,22 +28395,38 @@ function ChatPanel({ gatewayId, deviceId }) {
28394
28395
  }, []);
28395
28396
  reactExports.useEffect(() => {
28396
28397
  let active = true;
28398
+ let readyForPending = false;
28399
+ const applied = /* @__PURE__ */ new Set();
28397
28400
  const unsubscribe = client.subscribe(setSnapshot);
28401
+ const attachPending = async (pending) => {
28402
+ if (!pending || !active || !readyForPending || applied.has(pending.context.sourceId)) return;
28403
+ applied.add(pending.context.sourceId);
28404
+ try {
28405
+ const key = keyForSession(client.currentConversationId);
28406
+ await drafts.load(key);
28407
+ if (!active) return;
28408
+ drafts.update(key, (current) => ({ ...current, pages: appendPageContext(current.pages, pending) }));
28409
+ await chrome.storage.session.remove(PENDING_CONTEXT_KEY);
28410
+ } catch (cause) {
28411
+ applied.delete(pending.context.sourceId);
28412
+ if (active) setError(cause instanceof Error ? cause.message : String(cause));
28413
+ }
28414
+ };
28415
+ const onStorageChanged = (changes, area) => {
28416
+ if (area === "session") void attachPending(changes[PENDING_CONTEXT_KEY]?.newValue);
28417
+ };
28418
+ chrome.storage.onChanged.addListener(onStorageChanged);
28398
28419
  void client.start().then(async () => {
28399
28420
  if (!active) return;
28421
+ readyForPending = true;
28400
28422
  const stored = await chrome.storage.session.get(PENDING_CONTEXT_KEY);
28401
- const pending = stored[PENDING_CONTEXT_KEY];
28402
- if (!pending || !active) return;
28403
- const key = keyForSession(client.currentConversationId);
28404
- await drafts.load(key);
28405
- if (!active) return;
28406
- drafts.update(key, (current) => ({ ...current, pages: appendPageContext(current.pages, pending) }));
28407
- await chrome.storage.session.remove(PENDING_CONTEXT_KEY);
28423
+ await attachPending(stored[PENDING_CONTEXT_KEY]);
28408
28424
  }).catch((cause) => {
28409
28425
  if (active) setError(cause instanceof Error ? cause.message : String(cause));
28410
28426
  });
28411
28427
  return () => {
28412
28428
  active = false;
28429
+ chrome.storage.onChanged.removeListener(onStorageChanged);
28413
28430
  unsubscribe();
28414
28431
  client.stop();
28415
28432
  };
@@ -28642,6 +28659,7 @@ function ChatPanel({ gatewayId, deviceId }) {
28642
28659
  attachmentTask.current = true;
28643
28660
  setProcessing(true);
28644
28661
  setError("");
28662
+ setScreenshotFallbackError("");
28645
28663
  try {
28646
28664
  const tabId = await activeTabId();
28647
28665
  if (tabId === void 0) throw new Error(t("errorNoActivePage"));
@@ -28652,7 +28670,9 @@ function ChatPanel({ gatewayId, deviceId }) {
28652
28670
  });
28653
28671
  return true;
28654
28672
  } catch (cause) {
28655
- setError(cause instanceof Error ? cause.message : String(cause));
28673
+ const message = cause instanceof Error ? cause.message : String(cause);
28674
+ setError(message);
28675
+ setScreenshotFallbackError(mode === "page" ? message : "");
28656
28676
  return false;
28657
28677
  } finally {
28658
28678
  attachmentTask.current = false;
@@ -28956,7 +28976,11 @@ function ChatPanel({ gatewayId, deviceId }) {
28956
28976
  snapshot.pendingDelivery ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "composer-notice", role: "status", children: t("queuedMessageNotice") }) : null,
28957
28977
  error || !connectionProblem && snapshot.error ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "composer-error", role: "alert", children: [
28958
28978
  /* @__PURE__ */ jsxRuntimeExports.jsx(AlertIcon, {}),
28959
- error || snapshot.error
28979
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: error || snapshot.error }),
28980
+ error && error === screenshotFallbackError ? /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", disabled: processing, onClick: () => {
28981
+ setScreenshotFallbackError("");
28982
+ void addScreenshot();
28983
+ }, children: t("attachScreenshotInstead") }) : null
28960
28984
  ] }) : null,
28961
28985
  pageContexts.length || attachments.length ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "composer-contexts", children: [
28962
28986
  pageContexts.map((pageContext) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `context-chip${pageContext.stale ? " stale" : ""}`, children: [
@@ -3,7 +3,7 @@
3
3
  "minimum_chrome_version": "120",
4
4
  "default_locale": "en",
5
5
  "name": "__MSG_appName__",
6
- "version": "0.0.347",
6
+ "version": "0.0.349",
7
7
  "description": "__MSG_appDescription__",
8
8
  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqnpr4vpLC/nmvy+wiOWk3SWlp2nEZkFijfk8ivGw7StNZgCK90nOMvwhdEtlkk3GOWDvdVnq8HxCsM3UNQ8FnGUyerpH1FJXqXuradxeHf8ZxFjiQU/mIWfnKbUuONWQORon3/pigyoXoK/VUXgg0Wbm/rbVwsS0bv+25R6m+mZgBspOLeKuoH7ivhL+48WV6POtMBsFPZweY26477EM7ukh+56Ff5ENevB8ymxBBn7qK5ZoeZd2a23U8ioX5TsHfe6fnrjitPWjIxD8G0NoKQxcaa/Mo+xs+T6UiLKxP0wjz5bm7jB5H+CXtkRJqzBWUB0h+RSLJckzZfA8BAJrRwIDAQAB",
9
9
  "permissions": [
@@ -2,7 +2,7 @@
2
2
  "id": "telegram",
3
3
  "name": "Telegram Channel",
4
4
  "description": "Bundled Telegram Bot channel (private workspace sources; ships inside @xopcai/xopc dist/)",
5
- "version": "0.0.347",
5
+ "version": "0.0.349",
6
6
  "kind": "channel",
7
7
  "main": "src/index.js",
8
8
  "channels": [