@xopcai/xopc 0.0.274 → 0.0.276
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.
- package/dist/browser-ext/_locales/en/messages.json +215 -0
- package/dist/browser-ext/_locales/zh_CN/messages.json +215 -0
- package/dist/browser-ext/dist/assets/{auth-O8RiOF3l.js → auth-ClQTK565.js} +97 -38
- package/dist/browser-ext/dist/assets/{sidepanel-C86O7q5Y.css → sidepanel-CeGqObOa.css} +41 -20
- package/dist/browser-ext/dist/background.js +36 -4
- package/dist/browser-ext/dist/sidepanel.html +2 -2
- package/dist/browser-ext/dist/sidepanel.js +416 -299
- package/dist/browser-ext/manifest.json +6 -4
- package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BckaANxj.js → agent-avatar-dicebear-sj_1IC5H.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-B8eyC6K1.js → agent-defaults-settings-panel-B5MRLEy8.js} +1 -1
- package/dist/gateway/static/root/assets/{agents-CSWj_yo1.js → agents-CIzev0Qj.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-DY-Zbgmt.js → app-management-settings-panel-DY3Vwxjq.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-CoJR7ZRl.js → appearance-settings-BeXvF-dZ.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-Ch_9Ffgk.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-BwAlRT53.js → archive-plugin-BSgaIIGE.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-R835uxgL.js → attachment-load-CGNt02hP.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-BEZy0P_u.js → automations-page-DoafJiVA.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-MACr99IO.js +6 -0
- package/dist/gateway/static/root/assets/{binary-plugins-CESFx3yb.js → binary-plugins-BsAL26Aq.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-DDJcf2wR.js → block-editor-BxB7m8aI.js} +3 -3
- package/dist/gateway/static/root/assets/{browser-automations-page-BH4lSfr5.js → browser-automations-page-BNsO-Ip2.js} +2 -2
- package/dist/gateway/static/root/assets/browser-settings-page-Nvdoi0B1.js +8 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-BluLJq5I.js +8 -0
- package/dist/gateway/static/root/assets/channels-settings-DYxxhcjb.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-D8U97O95.js → chat-terminal-dock-ZCFwco1W.js} +2 -2
- package/dist/gateway/static/root/assets/connectors-page-Bpcp8UyE.js +2 -0
- package/dist/gateway/static/root/assets/{date-picker-7sDSMswL.js → date-picker-CpxFfgpg.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-DMIC86ZW.js → dependency-picker-eCIGAfHa.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-BtdiY5jK.js → desktop-pet-_MSZvIDO.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-D_B8azDH.js → desktop-pet-settings-feBnJWkV.js} +1 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-D_fB0fml.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-CoFKb01d.js → extension-debug-page-CotBlxJ-.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CEkNsCAY.js → extension-page-CFBmQ7U3.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-Bi2R8P5j.js → extension-settings-page-Cd1lfh8z.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-BH35C8RI.js +1 -0
- package/dist/gateway/static/root/assets/{heartbeat-settings-DQtelFiU.js → heartbeat-settings-DRG0u1ON.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-BlZk-aD4.js +1 -0
- package/dist/gateway/static/root/assets/{index-SxqsTD4i.js → index-CfQor-TM.js} +34 -34
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BuYmZS1K.js → keyboard-shortcuts-settings-BLHsdFIQ.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-DJd71FlC.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-CExnZyGZ.js → local-apps-page-BjAj1xhq.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-CA5ArMoN.js → logs-page-5MWeZ6Ae.js} +2 -2
- package/dist/gateway/static/root/assets/{management-settings-1UiJPrkX.js → management-settings-CPHxDaOw.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-nNFOk9HL.js → media-plugins-BUOzcXCL.js} +1 -1
- package/dist/gateway/static/root/assets/note-detail-panel-Bch98ut3.js +5 -0
- package/dist/gateway/static/root/assets/notes-page-CWO5dQKN.js +8 -0
- package/dist/gateway/static/root/assets/{page-tabs-CRombigq.js → page-tabs-BgEYFhqS.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-Bcuj43lk.js → preview-open-alternatives-C-pQIx6W.js} +1 -1
- package/dist/gateway/static/root/assets/{proactive-card-Cb3Xeoyx.js → proactive-card-DfjMVJUW.js} +1 -1
- package/dist/gateway/static/root/assets/{proactive-page-TbF9KVpm.js → proactive-page-BGVcVsbd.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-DZFVirjV.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-B2g6inq-.js +1 -0
- package/dist/gateway/static/root/assets/remote-access-hub-CbkUOkQY.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-BudlvBu-.js → runtime-tools-settings-panel-DkAjFJ-9.js} +2 -2
- package/dist/gateway/static/root/assets/{schema-form-Ch3MEX4h.js → schema-form-BpDcuSsl.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page--7-w-0WS.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BvZrH_sp.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-CIA1AA-A.js → settings-form-section-RElRijJw.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-B0Khoduh.js → settings-page-CaixunoA.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Ul06Y5YX.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-Cj9XWg-X.js → share-preview-page-CC-bFOTf.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-DwV2Wh7S.js +1 -0
- package/dist/gateway/static/root/assets/{skill-reload-api-BM4Ezjbx.js → skill-reload-api-CcOtxf53.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-Dyh1kf9t.js → skills-page-DmRvRxtY.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-DsQZkMti.js → skills-page.utils-CT0-daZD.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-BSho_Tpk.js → system-settings-panel-DRIJ5mXq.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-BQjLHqSk.js +1 -0
- package/dist/gateway/static/root/assets/{tunnel-api-4DUHxSQG.js → tunnel-api-IvWcgZdD.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-BG8Yx7hj.js → use-autosave-Cq4--C1i.js} +1 -1
- package/dist/gateway/static/root/assets/user-model-page-hwc5-nqV.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-DYXwDhHq.js → voice-api-key-field-CbJ6tKGI.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-CQqjzaRo.js → work-discovery-overlay-BG2pmXL3.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-C5H-Fd-U.js → workflow-run-setup-panel-vw1229Fh.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-DZWpJHDr.js +6 -0
- package/dist/gateway/static/root/index.html +1 -1
- package/dist/package.js +1 -1
- package/dist/src/agent/child-agent-factory.d.ts +3 -0
- package/dist/src/agent/child-agent-factory.js +2 -1
- package/dist/src/agent/external-tools/endpoint-provider.js +1 -1
- package/dist/src/agent/tools/factory.d.ts +1 -0
- package/dist/src/agent/tools/factory.js +21 -4
- package/dist/src/agent/workflow/workflow-child-tools.js +2 -0
- package/dist/src/browser/providers/browser-ext-install.d.ts +1 -1
- package/dist/src/browser/providers/browser-ext-install.js +86 -14
- package/dist/src/browser/providers/realtime-extension.d.ts +4 -1
- package/dist/src/browser/providers/realtime-extension.js +26 -10
- package/dist/src/browser/readiness.d.ts +4 -1
- package/dist/src/browser/readiness.js +11 -5
- package/dist/src/cli/commands/channels.js +1 -1
- package/dist/src/cli/commands/connectors.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +2 -2
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/extensions/sdk/index.js +1 -1
- package/dist/src/extensions/update.js +1 -1
- package/dist/src/gateway/gateway-workflow-host.types.d.ts +2 -0
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/browser.js +24 -11
- package/dist/src/gateway/hono/routes/endpoint-tools.js +9 -0
- package/dist/src/gateway/hono/routes/models.js +6 -0
- package/dist/src/gateway/service/config-coordinator.js +1 -1
- package/dist/src/gateway/service.js +3 -3
- package/dist/src/infra/update-runner.js +1 -1
- package/dist/src/providers/model-catalog-persistence.js +4 -0
- package/dist/src/providers/model-catalog-types.d.ts +1 -0
- package/dist/src/providers/xopc-cloud-model-source.js +12 -1
- package/dist/src/storage/sqlite/endpoint-session-binding-repository.d.ts +1 -0
- package/dist/src/storage/sqlite/endpoint-session-binding-repository.js +9 -1
- package/dist/src/storage/sqlite/index.d.ts +1 -1
- package/dist/src/storage/sqlite/index.js +2 -2
- package/dist/src/tui/backends/embedded-backend.js +1 -1
- package/dist/src/workflows/service/workflow-run-service.js +4 -1
- package/package.json +4 -4
- package/dist/gateway/static/root/assets/apps-page-CSMvkuot.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-CpaI13J7.js +0 -6
- package/dist/gateway/static/root/assets/browser-settings-page-CbTooPd2.js +0 -8
- package/dist/gateway/static/root/assets/capabilities-settings-panel-C4LZWHhv.js +0 -8
- package/dist/gateway/static/root/assets/channels-settings-BAljmSa7.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-CVRMjNNr.js +0 -2
- package/dist/gateway/static/root/assets/device-pairing-wizard-Dmh3Nh4d.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-q9p3sduo.js +0 -1
- package/dist/gateway/static/root/assets/home-page-COpGnTFZ.js +0 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-DV_17Zxc.js +0 -2
- package/dist/gateway/static/root/assets/note-detail-panel-B5OQ0fBY.js +0 -5
- package/dist/gateway/static/root/assets/notes-page-CVPPMVDl.js +0 -8
- package/dist/gateway/static/root/assets/project-detail-page-B9OQ2l9x.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-DCqSTNkY.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-d9Fg70gX.js +0 -1
- package/dist/gateway/static/root/assets/sessions-page-D8RiQ-ag.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-DVH_l6Hr.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-COJFl4N_.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-_OuE6A0G.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-B5HWM12k.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-IjVyv5jj.js +0 -2
- package/dist/gateway/static/root/assets/workflows-page-D1hMyPsY.js +0 -6
|
@@ -11,7 +11,7 @@ import { resolvePackageRoot } from "../../infra/update-check.js";
|
|
|
11
11
|
import { dirname, join } from "node:path";
|
|
12
12
|
import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
13
13
|
import { fileURLToPath } from "node:url";
|
|
14
|
-
import { spawn } from "node:child_process";
|
|
14
|
+
import { execFileSync, spawn } from "node:child_process";
|
|
15
15
|
import { createHash } from "node:crypto";
|
|
16
16
|
import { readFile, readdir, rm } from "node:fs/promises";
|
|
17
17
|
import AdmZip from "adm-zip";
|
|
@@ -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));
|
|
@@ -315,6 +320,42 @@ async function ensureBrowserExtensionArtifacts(opts) {
|
|
|
315
320
|
function shellQuote(value) {
|
|
316
321
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
317
322
|
}
|
|
323
|
+
const WINDOWS_NATIVE_HOST_KEYS = [
|
|
324
|
+
"Google\\Chrome",
|
|
325
|
+
"Chromium",
|
|
326
|
+
"Microsoft\\Edge",
|
|
327
|
+
"BraveSoftware\\Brave-Browser"
|
|
328
|
+
].map((browser) => `HKCU\\Software\\${browser}\\NativeMessagingHosts\\${BROWSER_NATIVE_HOST_NAME}`);
|
|
329
|
+
function runNativeHostRegistry(args) {
|
|
330
|
+
return execFileSync("reg.exe", args, {
|
|
331
|
+
encoding: "utf8",
|
|
332
|
+
windowsHide: true,
|
|
333
|
+
stdio: [
|
|
334
|
+
"ignore",
|
|
335
|
+
"pipe",
|
|
336
|
+
"pipe"
|
|
337
|
+
]
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
function windowsRegisteredNativeManifests() {
|
|
341
|
+
return [...new Set(WINDOWS_NATIVE_HOST_KEYS.flatMap((key) => {
|
|
342
|
+
try {
|
|
343
|
+
const path = runNativeHostRegistry([
|
|
344
|
+
"query",
|
|
345
|
+
key,
|
|
346
|
+
"/ve",
|
|
347
|
+
"/reg:32"
|
|
348
|
+
]).match(/REG_SZ\s+([^\r\n]+)/)?.[1]?.trim();
|
|
349
|
+
return path ? [path] : [];
|
|
350
|
+
} catch {
|
|
351
|
+
return [];
|
|
352
|
+
}
|
|
353
|
+
}))];
|
|
354
|
+
}
|
|
355
|
+
function batchQuote(value) {
|
|
356
|
+
if (/["\r\n\0]/.test(value)) throw new Error("Invalid path in Windows native host launcher");
|
|
357
|
+
return `"${value.replaceAll("%", "%%")}"`;
|
|
358
|
+
}
|
|
318
359
|
function browserNativeManifestDirectories(platform = process.platform, home = process.env.HOME || process.env.USERPROFILE || "") {
|
|
319
360
|
if (!home) return [];
|
|
320
361
|
if (platform === "darwin") return [
|
|
@@ -335,12 +376,12 @@ function browserNativeManifestDirectories(platform = process.platform, home = pr
|
|
|
335
376
|
}
|
|
336
377
|
function browserNativeHostDoctor(platform = process.platform, home = process.env.HOME || process.env.USERPROFILE || "") {
|
|
337
378
|
const directories = browserNativeManifestDirectories(platform, home);
|
|
338
|
-
if (directories.length === 0) return {
|
|
379
|
+
if (platform !== "win32" && directories.length === 0) return {
|
|
339
380
|
installed: false,
|
|
340
381
|
manifestPaths: [],
|
|
341
|
-
reason: "Automatic local Gateway discovery is supported on macOS and Linux"
|
|
382
|
+
reason: "Automatic local Gateway discovery is supported on Windows, macOS and Linux"
|
|
342
383
|
};
|
|
343
|
-
const manifestPaths = directories.map((directory) => join(directory, `${BROWSER_NATIVE_HOST_NAME}.json`)).filter((manifestPath) => {
|
|
384
|
+
const manifestPaths = (platform === "win32" ? windowsRegisteredNativeManifests() : directories.map((directory) => join(directory, `${BROWSER_NATIVE_HOST_NAME}.json`))).filter((manifestPath) => {
|
|
344
385
|
try {
|
|
345
386
|
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
346
387
|
return manifest.name === "ai.xopc.browser" && typeof manifest.path === "string" && existsSync(manifest.path) && Array.isArray(manifest.allowed_origins) && manifest.allowed_origins.includes(`chrome-extension://gopbfhaojnnhiheiikblejnpgmfmkmgd/`);
|
|
@@ -356,11 +397,12 @@ function browserNativeHostDoctor(platform = process.platform, home = process.env
|
|
|
356
397
|
}
|
|
357
398
|
/** Install the local-only bootstrap host used to discover and pair with a Gateway. */
|
|
358
399
|
async function installBrowserNativeMessagingHost(opts) {
|
|
359
|
-
const
|
|
360
|
-
|
|
400
|
+
const platform = opts?.platform ?? process.platform;
|
|
401
|
+
const directories = browserNativeManifestDirectories(platform, opts?.home);
|
|
402
|
+
if (platform !== "win32" && directories.length === 0) return {
|
|
361
403
|
installed: false,
|
|
362
404
|
manifestPaths: [],
|
|
363
|
-
reason: "Automatic local Gateway discovery is supported on macOS and Linux"
|
|
405
|
+
reason: "Automatic local Gateway discovery is supported on Windows, macOS and Linux"
|
|
364
406
|
};
|
|
365
407
|
const cliPath = opts?.cliPath ?? process.argv[1];
|
|
366
408
|
if (!cliPath) throw new Error("Unable to resolve the xopc CLI entry point");
|
|
@@ -376,12 +418,23 @@ async function installBrowserNativeMessagingHost(opts) {
|
|
|
376
418
|
if (!existsSync(tsxPath)) throw new Error("Unable to install the browser native host in development: the tsx CLI entry was not found");
|
|
377
419
|
executableArgs = [realpathSync(tsxPath), ...executableArgs];
|
|
378
420
|
}
|
|
379
|
-
const hostPath = join((opts?.cacheDir?.trim() ? assertCacheDir(opts.cacheDir) : resolveBinDir()) || resolveBinDir(), "browser-native-host");
|
|
421
|
+
const hostPath = join((opts?.cacheDir?.trim() ? assertCacheDir(opts.cacheDir) : resolveBinDir()) || resolveBinDir(), platform === "win32" ? "browser-native-host.cmd" : "browser-native-host");
|
|
380
422
|
mkdirSync(dirname(hostPath), { recursive: true });
|
|
381
423
|
const stateDir = opts?.stateDir ?? resolveStateDir();
|
|
382
424
|
const configPath = opts?.configPath ?? resolveConfigPath();
|
|
383
|
-
await writeTextAtomic(hostPath,
|
|
384
|
-
|
|
425
|
+
await writeTextAtomic(hostPath, platform === "win32" ? [
|
|
426
|
+
"@echo off",
|
|
427
|
+
"setlocal DisableDelayedExpansion",
|
|
428
|
+
"chcp 65001 >nul",
|
|
429
|
+
"set \"ELECTRON_RUN_AS_NODE=1\"",
|
|
430
|
+
`set ${batchQuote(`XOPC_STATE_DIR=${stateDir}`)}`,
|
|
431
|
+
`set ${batchQuote(`XOPC_CONFIG_PATH=${configPath}`)}`,
|
|
432
|
+
"set \"XOPC_LOG_CONSOLE=false\"",
|
|
433
|
+
`${batchQuote(executablePath)} ${executableArgs.map(batchQuote).join(" ")}`,
|
|
434
|
+
"exit /b %errorlevel%",
|
|
435
|
+
""
|
|
436
|
+
].join("\r\n") : `#!/bin/sh\nexec env ELECTRON_RUN_AS_NODE=1 XOPC_STATE_DIR=${shellQuote(stateDir)} XOPC_CONFIG_PATH=${shellQuote(configPath)} XOPC_LOG_CONSOLE=false ${shellQuote(executablePath)} ${executableArgs.map(shellQuote).join(" ")}\n`);
|
|
437
|
+
if (platform !== "win32") chmodSync(hostPath, 493);
|
|
385
438
|
const manifest = JSON.stringify({
|
|
386
439
|
name: BROWSER_NATIVE_HOST_NAME,
|
|
387
440
|
description: "xopc local browser pairing bootstrap",
|
|
@@ -390,12 +443,31 @@ async function installBrowserNativeMessagingHost(opts) {
|
|
|
390
443
|
allowed_origins: [`chrome-extension://${BROWSER_EXTENSION_ID}/`]
|
|
391
444
|
}, null, 2);
|
|
392
445
|
const manifestPaths = [];
|
|
393
|
-
for (const directory of directories) {
|
|
446
|
+
for (const directory of platform === "win32" ? [dirname(hostPath)] : directories) {
|
|
394
447
|
mkdirSync(directory, { recursive: true });
|
|
395
448
|
const manifestPath = join(directory, `${BROWSER_NATIVE_HOST_NAME}.json`);
|
|
396
449
|
await writeTextAtomic(manifestPath, manifest);
|
|
397
450
|
manifestPaths.push(manifestPath);
|
|
398
451
|
}
|
|
452
|
+
if (platform === "win32") try {
|
|
453
|
+
for (const key of WINDOWS_NATIVE_HOST_KEYS) runNativeHostRegistry([
|
|
454
|
+
"add",
|
|
455
|
+
key,
|
|
456
|
+
"/ve",
|
|
457
|
+
"/t",
|
|
458
|
+
"REG_SZ",
|
|
459
|
+
"/d",
|
|
460
|
+
manifestPaths[0],
|
|
461
|
+
"/f",
|
|
462
|
+
"/reg:32"
|
|
463
|
+
]);
|
|
464
|
+
} catch (error) {
|
|
465
|
+
return {
|
|
466
|
+
installed: false,
|
|
467
|
+
manifestPaths,
|
|
468
|
+
reason: `Windows native host registration failed: ${error instanceof Error ? error.message : String(error)}`
|
|
469
|
+
};
|
|
470
|
+
}
|
|
399
471
|
return {
|
|
400
472
|
installed: true,
|
|
401
473
|
manifestPaths
|
|
@@ -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
|
|
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 (
|
|
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)
|
|
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
|
|
58
|
+
return this.browserEndpoints().length > 0;
|
|
55
59
|
}
|
|
56
60
|
getConnectionStatus() {
|
|
57
|
-
const
|
|
61
|
+
const endpoints = this.browserEndpoints();
|
|
62
|
+
const endpoint = endpoints.length === 1 ? endpoints[0] : void 0;
|
|
58
63
|
return {
|
|
59
|
-
socketConnected:
|
|
60
|
-
connected:
|
|
61
|
-
protocolVersion:
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
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
|
|
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
|
-
|
|
25
|
-
if (
|
|
26
|
-
reason = "
|
|
27
|
-
detail = "Chrome extension
|
|
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 {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { buildChannelCatalogForConfig, init_channel_catalog_service } from "../../channels/catalog/channel-catalog-service.js";
|
|
2
2
|
import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
|
|
3
|
+
import { formatExamples, register } from "../registry.js";
|
|
3
4
|
import { listChannelPairingState } from "../../channels/pairing/pairing-service.js";
|
|
4
5
|
import { approveChannelPairingFromCli } from "../../channels/pairing/approve-cli.js";
|
|
5
|
-
import { formatExamples, register } from "../registry.js";
|
|
6
6
|
import { colors } from "../utils/colors.js";
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
//#region src/cli/commands/channels.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
|
|
2
2
|
import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../capabilities/store-connector.js";
|
|
3
3
|
import { register } from "../registry.js";
|
|
4
|
-
import { confirm } from "@inquirer/prompts";
|
|
5
4
|
import { Command } from "commander";
|
|
5
|
+
import { confirm } from "@inquirer/prompts";
|
|
6
6
|
//#region src/cli/commands/connectors.ts
|
|
7
7
|
init_loader();
|
|
8
8
|
function parsePairs(values, option) {
|
|
@@ -3,9 +3,9 @@ import { init_loader, loadConfig } from "../../config/loader.js";
|
|
|
3
3
|
import { downloadExtensionStoreZipBuffer, resolveExtensionZipDownloadUrl, resolveExtensionsStoreBaseUrl, verifyStoreArtifactSha256 } from "../../agent/skills/marketplace/adapters/store/store-api-client.js";
|
|
4
4
|
import { getContextWithOpts } from "../context.js";
|
|
5
5
|
import { getExtensionLockfileManager } from "../../extensions/lockfile.js";
|
|
6
|
+
import { fetchRegistry, findExtension, getExtensionMarketplaceStoreBaseUrl, listExtensions, searchExtensions } from "../../extensions/marketplace.js";
|
|
6
7
|
import { installFromLocal, installFromNpm, peekExtensionManifestFromStoreZip } from "../../extensions/install.js";
|
|
7
8
|
import { commitStagedExtensionInstall, finalizeStagedExtensionInstall, rollbackStagedExtensionInstall, stageExtensionStoreZip } from "../../extensions/install-transaction.js";
|
|
8
|
-
import { fetchRegistry, findExtension, getExtensionMarketplaceStoreBaseUrl, listExtensions, searchExtensions } from "../../extensions/marketplace.js";
|
|
9
9
|
import { colors } from "../utils/colors.js";
|
|
10
10
|
import { validateExtensionPackageDirectory } from "./extension-pack.js";
|
|
11
11
|
import { join, resolve } from "node:path";
|
|
@@ -13,8 +13,8 @@ import { existsSync, readFileSync, rmSync, statSync } from "node:fs";
|
|
|
13
13
|
import { execSync } from "node:child_process";
|
|
14
14
|
import { createHash } from "node:crypto";
|
|
15
15
|
import semver from "semver";
|
|
16
|
-
import { confirm } from "@inquirer/prompts";
|
|
17
16
|
import { Command } from "commander";
|
|
17
|
+
import { confirm } from "@inquirer/prompts";
|
|
18
18
|
//#region src/cli/commands/extension-marketplace.ts
|
|
19
19
|
init_loader();
|
|
20
20
|
init_paths();
|
|
@@ -9,8 +9,8 @@ import { prepareUpdateGlobalDefaults } from "../../gateway/global-defaults-admin
|
|
|
9
9
|
import { disconnectProvider } from "../../providers/provider-disconnect.js";
|
|
10
10
|
import { colors } from "../utils/colors.js";
|
|
11
11
|
import { runCliOAuthLogin } from "../utils/oauth-login.js";
|
|
12
|
-
import { input } from "@inquirer/prompts";
|
|
13
12
|
import { Command } from "commander";
|
|
13
|
+
import { input } from "@inquirer/prompts";
|
|
14
14
|
//#region src/cli/commands/models.ts
|
|
15
15
|
init_credentials();
|
|
16
16
|
init_schema();
|
|
@@ -10,8 +10,8 @@ import { initWorkspace } from "../utils/init-workspace.js";
|
|
|
10
10
|
import { setupModel } from "./onboard/model.js";
|
|
11
11
|
import { getChannelConfigurators } from "./onboard/channels/registry.js";
|
|
12
12
|
import { setupChannels } from "./onboard/channels/index.js";
|
|
13
|
-
import { select } from "@inquirer/prompts";
|
|
14
13
|
import { Command } from "commander";
|
|
14
|
+
import { select } from "@inquirer/prompts";
|
|
15
15
|
//#region src/cli/commands/onboard.ts
|
|
16
16
|
init_schema();
|
|
17
17
|
init_paths_state();
|
|
@@ -7,8 +7,8 @@ import { SlotRegistry, getSlotRegistry, registerSlotType } from "../slots.js";
|
|
|
7
7
|
import { ExtensionDiagnostics, ExtensionLoaderCacheImpl, getExtensionCache, getExtensionDiagnostics } from "../diagnostics.js";
|
|
8
8
|
import "../loader.js";
|
|
9
9
|
import { ExtensionHookRunner, createHookContext, isHookEvent } from "../hooks.js";
|
|
10
|
-
import { defineChannelPluginEntry } from "./channel-entry.js";
|
|
11
10
|
import { registerExtensionCliProgram } from "./channel-helpers.js";
|
|
11
|
+
import { defineChannelPluginEntry } from "./channel-entry.js";
|
|
12
12
|
import { lazyFunction, lazyModule } from "./lazy.js";
|
|
13
13
|
import { createMockExtensionApi, createTestGateway } from "./testing.js";
|
|
14
14
|
//#region src/extensions/sdk/index.ts
|
|
@@ -4,8 +4,8 @@ import { init_paths, resolveBundledExtensionsDir, resolveExtensionsDir } from ".
|
|
|
4
4
|
import { init_loader, loadConfig } from "../config/loader.js";
|
|
5
5
|
import { downloadExtensionStoreZipBuffer, resolveExtensionZipDownloadUrl, resolveExtensionsStoreBaseUrl, verifyStoreArtifactSha256 } from "../agent/skills/marketplace/adapters/store/store-api-client.js";
|
|
6
6
|
import { getExtensionLockfileManager } from "./lockfile.js";
|
|
7
|
-
import { installExtensionFromStoreZip, installFromNpm } from "./install.js";
|
|
8
7
|
import { findExtension } from "./marketplace.js";
|
|
8
|
+
import { installExtensionFromStoreZip, installFromNpm } from "./install.js";
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
import { existsSync, readFileSync, readdirSync, rmSync } from "node:fs";
|
|
11
11
|
import semver from "semver";
|
|
@@ -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,8 +1,8 @@
|
|
|
1
1
|
import { getAllModels, getAvailableModels, init_providers } from "../../../providers/index.js";
|
|
2
2
|
import { ActivationPlanner } from "../../../extensions/activation-planner.js";
|
|
3
3
|
import { mergeActivationContext } from "../../../extensions/activation-context.js";
|
|
4
|
-
import { fetchRegistry, listExtensions, searchExtensions } from "../../../extensions/marketplace.js";
|
|
5
4
|
import { buildWhenContextSnapshot } from "../../../extensions/when-context.js";
|
|
5
|
+
import { fetchRegistry, listExtensions, searchExtensions } from "../../../extensions/marketplace.js";
|
|
6
6
|
import { createOAuthAsyncHandler } from "../oauth-async.js";
|
|
7
7
|
import { createOAuthHandler } from "../oauth.js";
|
|
8
8
|
import { extensionAssetMimeType } from "../lib/extension-assets.js";
|
|
@@ -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
|
|
15
|
-
const
|
|
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
|
|
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
|
-
|
|
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:
|
|
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
|
|
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,
|
|
@@ -8,8 +8,8 @@ import { reloadImageGenerationProviders } from "../../agent/image/generation/pro
|
|
|
8
8
|
import "../../agent/mcp/bundle-mcp-tools.js";
|
|
9
9
|
import { ConfigHotReloader } from "../../config/reload.js";
|
|
10
10
|
import "../../config/index.js";
|
|
11
|
-
import { computeBundledExtensionExtensionsPatch } from "../../extensions/bundled-extension-activation.js";
|
|
12
11
|
import { sanitizeTunnelConfig } from "../../tunnel/tunnel-config.js";
|
|
12
|
+
import { computeBundledExtensionExtensionsPatch } from "../../extensions/bundled-extension-activation.js";
|
|
13
13
|
//#region src/gateway/service/config-coordinator.ts
|
|
14
14
|
init_providers();
|
|
15
15
|
init_logger();
|
|
@@ -51,9 +51,6 @@ import { MessageBus, MessageBusShutdownError } from "../infra/bus/queue.js";
|
|
|
51
51
|
import "../infra/bus/index.js";
|
|
52
52
|
import { AgentService } from "../agent/service.js";
|
|
53
53
|
import { ensureStarterAgentsInitialized } from "../agent/starter-agents.js";
|
|
54
|
-
import { setPairingBroadcastSink } from "../channels/pairing/pairing-events.js";
|
|
55
|
-
import { registerClarificationChannelRuntime } from "./clarify-runtime.js";
|
|
56
|
-
import { ChannelManager } from "../channels/manager.js";
|
|
57
54
|
import { getWorkspacePath } from "../config/workspace-path-helpers.js";
|
|
58
55
|
import "../config/index.js";
|
|
59
56
|
import { ManagedComposioEventPoller } from "../connectors/composio-managed-events.js";
|
|
@@ -71,6 +68,9 @@ import { DiscussionSealer } from "../discussions/sealer.js";
|
|
|
71
68
|
import "../discussions/index.js";
|
|
72
69
|
import { EndpointToolRuntime } from "../endpoint-tools/runtime.js";
|
|
73
70
|
import "../endpoint-tools/index.js";
|
|
71
|
+
import { setPairingBroadcastSink } from "../channels/pairing/pairing-events.js";
|
|
72
|
+
import { registerClarificationChannelRuntime } from "./clarify-runtime.js";
|
|
73
|
+
import { ChannelManager } from "../channels/manager.js";
|
|
74
74
|
import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
|
|
75
75
|
import { prepareAutomationAgentSession } from "./automation-agent-session.js";
|
|
76
76
|
import { stopTailscaleExposure } from "./tailscale-lifecycle.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { runPostUpdateExtensionSync } from "../extensions/update.js";
|
|
2
1
|
import "./update-channels.js";
|
|
3
2
|
import { compareSemver, resolveNpmChannelTag } from "./update-check.js";
|
|
3
|
+
import { runPostUpdateExtensionSync } from "../extensions/update.js";
|
|
4
4
|
import { readPackageName, readPackageVersion } from "./package-json.js";
|
|
5
5
|
import { createDefaultCommandRunner, runCommandWithTimeout } from "./run-command.js";
|
|
6
6
|
import { XOPC_PACKAGE_NAME, cleanupGlobalRenameDirs, createGlobalInstallEnv, detectGlobalInstallManagerForRoot, resolveGlobalInstallSpec, resolveGlobalInstallTarget } from "./update-global.js";
|
|
@@ -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",
|
|
@@ -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 };
|