@xopcai/xopc 0.0.265 → 0.0.267
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/dist/assets/{auth-CknJ00ae.js → auth-D_IL6naL.js} +603 -203
- package/dist/browser-ext/dist/assets/sidepanel-CEPaVLjr.css +155 -0
- package/dist/browser-ext/dist/background.js +698 -169
- package/dist/browser-ext/dist/sidepanel.html +3 -3
- package/dist/browser-ext/dist/sidepanel.js +148 -391
- package/dist/browser-ext/manifest.json +3 -6
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DRTTU2H3.js → agent-avatar-dicebear-ZrSAMchm.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-BsXF7LVi.js → agent-defaults-settings-panel-DiNFN8qS.js} +1 -1
- package/dist/gateway/static/root/assets/{agents-DpjWfxYx.js → agents-Bu6Hf59K.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-33Mc81h2.js → app-management-settings-panel-D-L6yjS7.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-C8JECSiJ.js → appearance-settings-BW5eb53j.js} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-t64FcxIZ.js → apps-page-CiQIdz3N.js} +1 -1
- package/dist/gateway/static/root/assets/{archive-plugin-PzZ6SzfY.js → archive-plugin-DwXvu1p9.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-OhLL6K__.js → attachment-load-DqU2BYBp.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-BpAYwuvx.js → automations-page-C7qoj9Sd.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-workspace-B6aTT5IC.js → automations-workspace-CIARTLHO.js} +1 -1
- package/dist/gateway/static/root/assets/{binary-plugins-B5XpGsHg.js → binary-plugins-CfplDak2.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-BgEhoTnN.js → block-editor-CzLs38ru.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-CBLunDRH.js → browser-automations-page-_SKi8s9b.js} +1 -1
- package/dist/gateway/static/root/assets/browser-settings-page-DTdx66sX.js +8 -0
- package/dist/gateway/static/root/assets/{capabilities-settings-panel-DftNnICK.js → capabilities-settings-panel-Ck9U0Olx.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-settings-CpuWa5qu.js → channels-settings-I_vDpbnl.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-terminal-dock-mnPsS_GJ.js → chat-terminal-dock-snvAu3hJ.js} +1 -1
- package/dist/gateway/static/root/assets/{connectors-page-D3nHGnNV.js → connectors-page-BmKTnzo1.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-expression-NcGBvIfe.js → cron-expression-BhGZSbT6.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-BrVcl7H5.js → date-picker-Cep5f9b-.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker--edd48Y9.js → dependency-picker-BzSEBQku.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-vuyyb6I6.js → desktop-pet-BwX_6Gah.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-DWredJwO.js → desktop-pet-settings-WrbVsU2b.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-CtBW4ebj.js → extension-debug-page-BdXSwtAZ.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-CsUrmtW7.js → extension-page-I95ukbRb.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BUd31AuK.js → extension-settings-page-8zUisBay.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-C6FQv7op.js → gateway-settings-DGj5b9Yv.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-settings-CDo1Gjp2.js → heartbeat-settings-BGQxU-Ug.js} +1 -1
- package/dist/gateway/static/root/assets/{home-page-D3_uvVJY.js → home-page-BZPpK0A3.js} +1 -1
- package/dist/gateway/static/root/assets/{index-Dpu7EKTm.js → index-D2OtD9Wa.js} +8 -8
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CNVmrCrV.js → keyboard-shortcuts-settings-BUe_om99.js} +1 -1
- package/dist/gateway/static/root/assets/{local-app-workbench-page-B0IVDvs-.js → local-app-workbench-page-CbQnffS9.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-page-DvkarvLt.js → local-apps-page-BZaLzfms.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-BknY0vZf.js → logs-page-WWCHqW_x.js} +1 -1
- package/dist/gateway/static/root/assets/{management-settings-DW6hJINQ.js → management-settings-Duf8w-Bl.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-DYautOWY.js → media-plugins-2-QfzHmg.js} +1 -1
- package/dist/gateway/static/root/assets/{mobile-pairing-wizard-Dgu03cv-.js → mobile-pairing-wizard-DRaVIAt1.js} +1 -1
- package/dist/gateway/static/root/assets/{note-detail-panel-Cv9uH6Jq.js → note-detail-panel-BT-fWGxX.js} +3 -3
- package/dist/gateway/static/root/assets/{notes-page-DcIAiYJn.js → notes-page-C4705PzN.js} +1 -1
- package/dist/gateway/static/root/assets/{page-tabs-DF6Q5XvA.js → page-tabs-DaZ7QpNO.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-CQJH_jAN.js → preview-open-alternatives-CWEuqCmv.js} +1 -1
- package/dist/gateway/static/root/assets/{project-detail-page-D65JfNSw.js → project-detail-page-BZegJ6an.js} +1 -1
- package/dist/gateway/static/root/assets/{projects-page-BfWF7Sz-.js → projects-page-B7hUHeLI.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-DA1g4CUD.js → remote-access-hub-BE9hZpdh.js} +1 -1
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-0-bFSBB8.js → runtime-tools-settings-panel-CslkSM-m.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-csGbhTUr.js → schema-form-B2gvVrBq.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-DXPBNhrZ.js → sessions-page-DmAAPMo1.js} +1 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CvBocGDA.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-YdrdY8B3.js → settings-form-section-CmlnuSO3.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-Cv9waRn3.js → settings-page-DWWgyelT.js} +1 -1
- package/dist/gateway/static/root/assets/{setup-status-panel-DPf-_05Z.js → setup-status-panel-CJrN3m1o.js} +1 -1
- package/dist/gateway/static/root/assets/{share-preview-page-DBoEHTPn.js → share-preview-page-C12oyIKk.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-settings-BQP5yNcO.js → shares-settings-D4BtSiLq.js} +1 -1
- package/dist/gateway/static/root/assets/{skill-reload-api-B5T8cgjq.js → skill-reload-api-CzKGn056.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-D1G8h2Lt.js → skills-page-yhW7LLqk.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-BNZYTop7.js → skills-page.utils-FaTlq8t-.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-ByuppbHi.js → system-settings-panel-CMrkoJLN.js} +1 -1
- package/dist/gateway/static/root/assets/{task-detail-page-DNmkrF6y.js → task-detail-page-BUaO62cy.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-CxWGpbwr.js → tunnel-api-C2tAZaJz.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-B0l4qubU.js → use-autosave-BsDRt4QI.js} +1 -1
- package/dist/gateway/static/root/assets/{user-model-page-DMsI6YI7.js → user-model-page-Dy8h1SSJ.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-Bcz7boJg.js → voice-api-key-field-CS5heYMP.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-Dujq1j_u.js → work-discovery-overlay-BeSz5Th5.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-CxNYbLNB.js → workflow-run-setup-panel-BebW0CDK.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-Dk1jK2nv.js → workflows-page-CU8jFgPF.js} +1 -1
- package/dist/gateway/static/root/index.html +1 -1
- package/dist/package.js +1 -1
- package/dist/packages/browser-control-contract/src/index.js +30 -1
- package/dist/src/agent/agent-manager.js +4 -4
- package/dist/src/agent/background-review/run-background-review.js +1 -1
- package/dist/src/agent/embedded/model-runtime.js +1 -1
- package/dist/src/agent/embedded/run-for-session.js +1 -1
- package/dist/src/agent/external-tools/endpoint-provider.js +3 -1
- package/dist/src/agent/image/tool-model-config.js +1 -1
- package/dist/src/agent/mcp/oauth/mcp-oauth-store.js +1 -1
- package/dist/src/agent/service.js +2 -2
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/tasks/task-judge-service.js +3 -3
- package/dist/src/agent/tools/factory.js +1 -1
- package/dist/src/ai-assist/text-assist.js +1 -1
- package/dist/src/auth/credentials.js +2 -2
- package/dist/src/auth/oauth/xopc-cloud.js +1 -1
- package/dist/src/auth/profiles/store.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +2 -2
- package/dist/src/browser/automations/runtime-service.d.ts +2 -0
- package/dist/src/browser/automations/runtime-service.js +1 -1
- package/dist/src/browser/drivers/create-driver.d.ts +2 -1
- package/dist/src/browser/drivers/create-driver.js +4 -6
- package/dist/src/browser/drivers/extension-driver.d.ts +7 -2
- package/dist/src/browser/enrollment.d.ts +8 -0
- package/dist/src/browser/enrollment.js +25 -0
- package/dist/src/browser/extension-identity.d.ts +2 -0
- package/dist/src/browser/extension-identity.js +5 -0
- package/dist/src/browser/native-messaging-host.d.ts +6 -3
- package/dist/src/browser/native-messaging-host.js +23 -5
- package/dist/src/browser/providers/browser-ext-install.d.ts +4 -1
- package/dist/src/browser/providers/browser-ext-install.js +47 -8
- package/dist/src/browser/providers/extension.js +1 -1
- package/dist/src/browser/providers/realtime-extension.d.ts +29 -0
- package/dist/src/browser/providers/realtime-extension.js +83 -0
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/config/index.js +4 -4
- package/dist/src/config/loader.js +2 -2
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/endpoint-tools/policy.js +10 -3
- package/dist/src/extensions/lockfile.js +1 -1
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/file-path-classifier.js +1 -1
- package/dist/src/gateway/hono/app.js +6 -1
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/routes/browser.js +20 -30
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/security/origin-check.js +5 -0
- package/dist/src/gateway/service/config-coordinator.d.ts +0 -2
- package/dist/src/gateway/service/config-coordinator.js +1 -3
- package/dist/src/gateway/service.d.ts +0 -11
- package/dist/src/gateway/service.js +5 -83
- package/dist/src/providers/auth-runtime/resolve-auth.js +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/providers/register-runtime-providers.js +1 -1
- package/dist/src/storage/sqlite/device-pairing-approval.js +24 -3
- package/dist/src/storage/sqlite/device-pairing-repository.d.ts +10 -1
- package/dist/src/storage/sqlite/device-pairing-repository.js +6 -5
- package/dist/src/storage/sqlite/migrations/157_browser_endpoint_principals.sql +50 -0
- package/dist/src/storage/sqlite/migrations/158_browser_native_enrollment.sql +4 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +3 -3
- package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/tui/tui-startup-resources.js +1 -1
- package/dist/src/tui/tui.js +1 -1
- package/dist/src/work-discovery/service.js +1 -1
- package/dist/src/workflows/service/workflow-run-service.js +1 -1
- package/package.json +3 -3
- package/dist/browser-ext/dist/assets/sidepanel-C69P3v9u.css +0 -113
- package/dist/gateway/static/root/assets/browser-settings-page-CSfpPCuD.js +0 -8
- package/dist/gateway/static/root/assets/settings-advanced-gate-DxeZm67O.js +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
3
|
import { parseTurnOutcome } from "../../../packages/gateway-contract/src/turn-outcome.js";
|
|
4
|
-
import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
|
|
5
4
|
import { init_providers, resolveModel } from "../../providers/index.js";
|
|
5
|
+
import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
|
|
6
6
|
import { runWithEmbeddedExecutionSession } from "./execution-context.js";
|
|
7
7
|
import { resolveAgentTurnTimeoutMs } from "../orchestration/run-agent-turn-with-timeout.js";
|
|
8
8
|
import { resolvePromptCachePolicy } from "../../providers/prompt-cache-plan.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { externalToolRef, parseExternalToolRef } from "./refs.js";
|
|
2
|
+
import { BROWSER_CONTROL_ENDPOINT_TOOL_NAME } from "../../../packages/browser-control-contract/src/index.js";
|
|
2
3
|
//#region src/agent/external-tools/endpoint-provider.ts
|
|
3
4
|
function contentText(content) {
|
|
4
5
|
if (content.type === "text") return content.text;
|
|
@@ -13,7 +14,7 @@ var EndpointToolProvider = class {
|
|
|
13
14
|
async search(_query) {
|
|
14
15
|
const endpoint = this.currentEndpoint();
|
|
15
16
|
if (!endpoint) return [];
|
|
16
|
-
return endpoint.tools.map(({ descriptor }) => ({
|
|
17
|
+
return endpoint.tools.filter(({ descriptor }) => descriptor.name !== BROWSER_CONTROL_ENDPOINT_TOOL_NAME).map(({ descriptor }) => ({
|
|
17
18
|
toolRef: externalToolRef(this.source, endpoint.endpointId, descriptor.name),
|
|
18
19
|
source: this.source,
|
|
19
20
|
namespace: endpoint.endpointId,
|
|
@@ -86,6 +87,7 @@ var EndpointToolProvider = class {
|
|
|
86
87
|
const endpoint = this.currentEndpoint();
|
|
87
88
|
if (!endpoint || endpoint.endpointId !== parsed.namespace) return void 0;
|
|
88
89
|
const tool = this.deps.runtime.registry.getTool(endpoint.endpointId, parsed.toolName);
|
|
90
|
+
if (tool?.descriptor.name === "browser.control") return void 0;
|
|
89
91
|
return tool ? {
|
|
90
92
|
endpointId: endpoint.endpointId,
|
|
91
93
|
displayName: endpoint.displayName,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getAgentDefaultImageModelConfig, getAgentDefaultModelRef, init_schema, parseModelRef } from "../../config/schema.js";
|
|
2
2
|
import { init_agent_scope, resolveDefaultAgentId } from "../agent-scope.js";
|
|
3
|
-
import { resolveEffectiveAgentConfigForAgent } from "../../config/agent-profile.js";
|
|
4
3
|
import { getDefaultModelSync, getModelsByProvider, init_providers, isProviderConfiguredSync, resolveModel } from "../../providers/index.js";
|
|
4
|
+
import { resolveEffectiveAgentConfigForAgent } from "../../config/agent-profile.js";
|
|
5
5
|
import { resolveAgentModelFallbackValues, resolveAgentModelPrimaryValue } from "../../config/model-input.js";
|
|
6
6
|
import { buildCapabilityPlansForConfig } from "../../capabilities/readiness/from-config.js";
|
|
7
7
|
import "../../capabilities/readiness/index.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { init_paths, resolveMcpOAuthPath } from "../../../config/paths.js";
|
|
2
1
|
import { init_write_file_atomic, writeTextAtomic } from "../../../infra/write-file-atomic.js";
|
|
2
|
+
import { init_paths, resolveMcpOAuthPath } from "../../../config/paths.js";
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { readFile, rm } from "node:fs/promises";
|
|
5
5
|
//#region src/agent/mcp/oauth/mcp-oauth-store.ts
|
|
@@ -2,10 +2,10 @@ import { createLogger } from "../utils/logger/index.js";
|
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
3
|
import { parseNoteAttachmentTarget } from "../notes/attachment-ref.js";
|
|
4
4
|
import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
|
|
5
|
-
import { applyConfigOverrides } from "../config/runtime-overrides.js";
|
|
6
5
|
import { init_agent_scope, resolveAgentHomeDir, resolveDefaultAgentId } from "./agent-scope.js";
|
|
7
|
-
import { extractProfileAgentId } from "../config/agent-profile.js";
|
|
8
6
|
import { init_providers, resolveModel } from "../providers/index.js";
|
|
7
|
+
import { applyConfigOverrides } from "../config/runtime-overrides.js";
|
|
8
|
+
import { extractProfileAgentId } from "../config/agent-profile.js";
|
|
9
9
|
import { extractTextContent } from "./context/workspace.js";
|
|
10
10
|
import { effectiveWorkspacePathForSession } from "../session/session-workspace.js";
|
|
11
11
|
import { getProjectForSession } from "../projects/workspace.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
3
|
import { init_workspace_defaults, resolveDefaultAgentWorkspaceDir } from "../../config/workspace-defaults.js";
|
|
4
|
-
import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
|
|
5
4
|
import { init_providers, resolveModel } from "../../providers/index.js";
|
|
5
|
+
import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
|
|
6
6
|
import { getExecutionEnvironmentForSession } from "../../execution-environments/subject.js";
|
|
7
7
|
import { effectiveWorkspacePathForSession, projectWorkspacePath } from "../../session/session-workspace.js";
|
|
8
8
|
import { getProjectForSession } from "../../projects/workspace.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { init_paths, resolveSkillsLockPath } from "../../config/paths.js";
|
|
2
1
|
import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
|
|
2
|
+
import { init_paths, resolveSkillsLockPath } from "../../config/paths.js";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
//#region src/agent/skills/hub-lock.ts
|
|
5
5
|
/**
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
3
|
import { TaskRunRepository } from "../../tasks/task-run-repository.js";
|
|
4
|
+
import { extractAssistantText, getAssistantMessageErrorReason, stripCodeFences } from "../../providers/model-response.js";
|
|
4
5
|
import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
|
|
5
|
-
import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
|
|
6
6
|
import { getApiKey, init_providers, resolveModel } from "../../providers/index.js";
|
|
7
|
+
import { completeWithResolvedCredentials } from "../../providers/model-call.js";
|
|
8
|
+
import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
|
|
7
9
|
import { TaskRepository } from "../../tasks/task-repository.js";
|
|
8
10
|
import { TaskConversationRepository } from "../../tasks/task-conversation-repository.js";
|
|
9
11
|
import { readWorkspaceRevision } from "../coding/workspace-revision.js";
|
|
10
|
-
import { completeWithResolvedCredentials } from "../../providers/model-call.js";
|
|
11
12
|
import { TaskApplicationService } from "../../tasks/task-application-service.js";
|
|
12
|
-
import { extractAssistantText, getAssistantMessageErrorReason, stripCodeFences } from "../../providers/model-response.js";
|
|
13
13
|
//#region src/agent/tasks/task-judge-service.ts
|
|
14
14
|
init_schema();
|
|
15
15
|
init_providers();
|
|
@@ -140,7 +140,7 @@ var AgentToolsFactory = class AgentToolsFactory {
|
|
|
140
140
|
createDriver: async () => {
|
|
141
141
|
const config = this.deps.getConfig?.();
|
|
142
142
|
if (!config) throw new Error("Browser configuration is unavailable");
|
|
143
|
-
return createBrowserDriver(config.browser);
|
|
143
|
+
return createBrowserDriver(config.browser, this.deps.endpointTools);
|
|
144
144
|
},
|
|
145
145
|
allowedUploadRoots: [this.deps.workspace],
|
|
146
146
|
emit: this.deps.emitBrowserEvent,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
|
+
import { getAssistantMessageErrorReason, stripCodeFences } from "../providers/model-response.js";
|
|
3
4
|
import { getDefaultModelSync, init_providers, resolveModel } from "../providers/index.js";
|
|
4
5
|
import { createExtensionAwareStreamFn } from "../providers/extension-stream-bridge.js";
|
|
5
6
|
import { isLocalModelBaseUrl, resolveModelCallApiKey, resolveModelCallOptions } from "../providers/model-call.js";
|
|
6
|
-
import { getAssistantMessageErrorReason, stripCodeFences } from "../providers/model-response.js";
|
|
7
7
|
//#region src/ai-assist/text-assist.ts
|
|
8
8
|
init_providers();
|
|
9
9
|
init_logger();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { createLogger } from "../utils/logger/index.js";
|
|
3
3
|
import { init_logger } from "../utils/logger.js";
|
|
4
|
-
import { init_paths, resolveAgentAuthProfilesPath, resolveAuthProfilesPath, resolveCredentialsDir, resolveOAuthPath } from "../config/paths.js";
|
|
5
4
|
import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
|
|
6
|
-
import {
|
|
5
|
+
import { init_paths, resolveAgentAuthProfilesPath, resolveAuthProfilesPath, resolveCredentialsDir, resolveOAuthPath } from "../config/paths.js";
|
|
7
6
|
import { getApiKeyFromEnv, init_env_keys } from "../providers/env-keys.js";
|
|
7
|
+
import { getOAuthProviderDefinition, init_registry } from "./oauth/registry.js";
|
|
8
8
|
import { init_oauth_provider_lock, withOAuthProviderLock } from "./oauth-provider-lock.js";
|
|
9
9
|
import { dirname, join } from "path";
|
|
10
10
|
import { mkdir, readFile, readdir, rm } from "fs/promises";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __esmMin } from "../../../_virtual/_rolldown/runtime.js";
|
|
2
|
-
import { init_resolution, resolveConnectedPlatformEndpoint } from "../../platform/resolution.js";
|
|
3
2
|
import { generatePKCE, init_pkce } from "./pkce.js";
|
|
3
|
+
import { init_resolution, resolveConnectedPlatformEndpoint } from "../../platform/resolution.js";
|
|
4
4
|
import { hostname } from "node:os";
|
|
5
5
|
import { randomBytes } from "node:crypto";
|
|
6
6
|
import http from "node:http";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { init_paths, resolveCredentialsDir } from "../../config/paths.js";
|
|
2
1
|
import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
|
|
2
|
+
import { init_paths, resolveCredentialsDir } from "../../config/paths.js";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { chmodSync, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
5
5
|
//#region src/auth/profiles/store.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
-
import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
|
|
3
2
|
import { init_paths, resolveAgentAuthProfilesPath, resolveAuthProfilesPath, resolveOAuthPath } from "../config/paths.js";
|
|
4
|
-
import { init_loader, loadConfig } from "../config/loader.js";
|
|
5
3
|
import { init_registry, isOAuthOnlyProvider } from "./oauth/registry.js";
|
|
4
|
+
import { init_loader, loadConfig } from "../config/loader.js";
|
|
5
|
+
import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
|
|
6
6
|
import { existsSync, readFileSync } from "node:fs";
|
|
7
7
|
//#region src/auth/sync-provider-auth.ts
|
|
8
8
|
/**
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Config } from '../../config/schema.js';
|
|
2
|
+
import type { EndpointToolRuntime } from '../../endpoint-tools/index.js';
|
|
2
3
|
import { BrowserAutomationService } from './service.js';
|
|
3
4
|
export declare function createRuntimeBrowserAutomationService(deps: {
|
|
4
5
|
getConfig: () => Config;
|
|
6
|
+
endpointTools?: EndpointToolRuntime;
|
|
5
7
|
emit?: (type: string, payload: unknown) => void;
|
|
6
8
|
}): BrowserAutomationService;
|
|
@@ -6,7 +6,7 @@ import { BrowserAutomationService } from "./service.js";
|
|
|
6
6
|
function createRuntimeBrowserAutomationService(deps) {
|
|
7
7
|
const runtime = new BrowserRuntime({
|
|
8
8
|
getConfig: () => deps.getConfig().browser,
|
|
9
|
-
createDriver: () => createBrowserDriver(deps.getConfig().browser),
|
|
9
|
+
createDriver: () => createBrowserDriver(deps.getConfig().browser, deps.endpointTools),
|
|
10
10
|
allowedUploadRoots: [process.cwd()],
|
|
11
11
|
emit: deps.emit
|
|
12
12
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { Config } from '../../config/schema.js';
|
|
2
|
+
import type { EndpointToolRuntime } from '../../endpoint-tools/index.js';
|
|
2
3
|
import type { BrowserDriver } from './browser-driver.js';
|
|
3
|
-
export declare function createBrowserDriver(config: Config['browser']): Promise<BrowserDriver>;
|
|
4
|
+
export declare function createBrowserDriver(config: Config['browser'], endpointTools: EndpointToolRuntime): Promise<BrowserDriver>;
|
|
@@ -3,22 +3,20 @@ import { init_logger } from "../../utils/logger.js";
|
|
|
3
3
|
import { loadPlaywrightCoreModule } from "../providers/playwright-doctor.js";
|
|
4
4
|
import { BrowserbaseProvider } from "../providers/browserbase.js";
|
|
5
5
|
import { BrowserUseProvider } from "../providers/browser-use.js";
|
|
6
|
-
import {
|
|
6
|
+
import { RealtimeExtensionBrowserProvider } from "../providers/realtime-extension.js";
|
|
7
7
|
import { ExtensionDriver } from "./extension-driver.js";
|
|
8
8
|
import { PlaywrightDriver } from "./playwright-driver.js";
|
|
9
9
|
//#region src/browser/drivers/create-driver.ts
|
|
10
10
|
init_logger();
|
|
11
11
|
const log = createLogger("BrowserDriverFactory");
|
|
12
|
-
async function createBrowserDriver(config) {
|
|
12
|
+
async function createBrowserDriver(config, endpointTools) {
|
|
13
13
|
const limits = config.limits;
|
|
14
14
|
if (config.driver.kind === "extension") {
|
|
15
|
-
const
|
|
16
|
-
host: "127.0.0.1",
|
|
17
|
-
port: 19820,
|
|
15
|
+
const provider = new RealtimeExtensionBrowserProvider(endpointTools, {
|
|
18
16
|
connectionTimeout: limits.actionTimeoutMs,
|
|
19
17
|
commandTimeout: limits.actionTimeoutMs
|
|
20
18
|
});
|
|
21
|
-
return new ExtensionDriver(provider, limits.actionTimeoutMs, config.observation.visualFallback,
|
|
19
|
+
return new ExtensionDriver(provider, limits.actionTimeoutMs, config.observation.visualFallback, () => provider.shutdown());
|
|
22
20
|
}
|
|
23
21
|
const driver = config.driver;
|
|
24
22
|
return new PlaywrightDriver({
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import type { BrowserControlResult, BrowserNavigateInput, BrowserObservation, BrowserObserveInput, BrowserTabsInput } from '@xopcai/browser-control-contract';
|
|
2
|
-
import type { ExtensionBrowserProvider } from '../providers/extension.js';
|
|
3
2
|
import type { BrowserDriver, BrowserPrimitiveInput } from './browser-driver.js';
|
|
3
|
+
type ExtensionProvider = {
|
|
4
|
+
start(): Promise<void>;
|
|
5
|
+
waitForConnection(timeoutMs?: number): Promise<void>;
|
|
6
|
+
send(input: import('@xopcai/browser-control-contract').BrowserActionInput, timeoutMs?: number, visualFallback?: boolean): Promise<import('@xopcai/browser-control-contract').BrowserWireResult>;
|
|
7
|
+
};
|
|
4
8
|
export declare class ExtensionDriver implements BrowserDriver {
|
|
5
9
|
private readonly provider;
|
|
6
10
|
private readonly timeoutMs;
|
|
7
11
|
private readonly visualFallback;
|
|
8
12
|
private readonly release;
|
|
9
13
|
readonly kind: "extension";
|
|
10
|
-
constructor(provider:
|
|
14
|
+
constructor(provider: ExtensionProvider, timeoutMs: number, visualFallback: boolean, release: () => Promise<void>);
|
|
11
15
|
connect(): Promise<void>;
|
|
12
16
|
disconnect(): Promise<void>;
|
|
13
17
|
createSession(_sessionId: string): Promise<void>;
|
|
@@ -18,3 +22,4 @@ export declare class ExtensionDriver implements BrowserDriver {
|
|
|
18
22
|
tabs(sessionId: string, input: BrowserTabsInput): Promise<BrowserControlResult>;
|
|
19
23
|
private send;
|
|
20
24
|
}
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type BrowserEnrollmentPublicKeyJwk = {
|
|
2
|
+
kty: 'EC';
|
|
3
|
+
crv: 'P-256';
|
|
4
|
+
x: string;
|
|
5
|
+
y: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function parseBrowserEnrollmentPublicKeyJwk(value: unknown): BrowserEnrollmentPublicKeyJwk;
|
|
8
|
+
export declare function browserEnrollmentPublicKeyThumbprint(value: unknown): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
//#region src/browser/enrollment.ts
|
|
3
|
+
function parseBrowserEnrollmentPublicKeyJwk(value) {
|
|
4
|
+
if (!value || typeof value !== "object") throw new Error("Browser enrollment public key is missing");
|
|
5
|
+
const key = value;
|
|
6
|
+
if (key.kty !== "EC" || key.crv !== "P-256" || typeof key.x !== "string" || !key.x || typeof key.y !== "string" || !key.y) throw new Error("Browser enrollment public key is invalid");
|
|
7
|
+
return {
|
|
8
|
+
kty: "EC",
|
|
9
|
+
crv: "P-256",
|
|
10
|
+
x: key.x,
|
|
11
|
+
y: key.y
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function browserEnrollmentPublicKeyThumbprint(value) {
|
|
15
|
+
const key = parseBrowserEnrollmentPublicKeyJwk(value);
|
|
16
|
+
const canonical = JSON.stringify({
|
|
17
|
+
crv: key.crv,
|
|
18
|
+
kty: key.kty,
|
|
19
|
+
x: key.x,
|
|
20
|
+
y: key.y
|
|
21
|
+
});
|
|
22
|
+
return crypto.createHash("sha256").update(canonical).digest("base64url");
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { browserEnrollmentPublicKeyThumbprint, parseBrowserEnrollmentPublicKeyJwk };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
export
|
|
2
|
-
export declare const BROWSER_EXTENSION_ID = "gopbfhaojnnhiheiikblejnpgmfmkmgd";
|
|
1
|
+
export { BROWSER_EXTENSION_ID, BROWSER_NATIVE_HOST_NAME } from './extension-identity.js';
|
|
3
2
|
export type BrowserNativeBootstrap = {
|
|
4
3
|
type: 'bootstrap';
|
|
4
|
+
extensionId: string;
|
|
5
|
+
publicKeyJwk: unknown;
|
|
6
|
+
publicKeyThumbprint: string;
|
|
7
|
+
nonce: string;
|
|
5
8
|
};
|
|
6
9
|
export type BrowserNativeBootstrapResult = {
|
|
7
10
|
ok: true;
|
|
@@ -11,5 +14,5 @@ export type BrowserNativeBootstrapResult = {
|
|
|
11
14
|
};
|
|
12
15
|
export declare function encodeNativeMessage(value: unknown): Buffer;
|
|
13
16
|
export declare function decodeNativeMessage(buffer: Buffer): unknown;
|
|
14
|
-
export declare function createBrowserNativeBootstrap(configPath: string): BrowserNativeBootstrapResult;
|
|
17
|
+
export declare function createBrowserNativeBootstrap(configPath: string, request: Omit<BrowserNativeBootstrap, 'type'>): BrowserNativeBootstrapResult;
|
|
15
18
|
export declare function runBrowserNativeMessagingHost(configPath: string): Promise<void>;
|
|
@@ -2,11 +2,11 @@ import { closeXopcDatabase, openXopcDatabase } from "../storage/sqlite/connectio
|
|
|
2
2
|
import { getGatewayIdentityPublicKeyRaw, getOrCreateGatewayIdentity } from "../storage/sqlite/gateway-identity-repository.js";
|
|
3
3
|
import { createDevicePairingSetup } from "../storage/sqlite/device-pairing-repository.js";
|
|
4
4
|
import { init_loader, loadConfig } from "../config/loader.js";
|
|
5
|
+
import { browserEnrollmentPublicKeyThumbprint } from "./enrollment.js";
|
|
6
|
+
import { BROWSER_EXTENSION_ID, BROWSER_NATIVE_HOST_NAME } from "./extension-identity.js";
|
|
5
7
|
import os from "node:os";
|
|
6
8
|
//#region src/browser/native-messaging-host.ts
|
|
7
9
|
init_loader();
|
|
8
|
-
const BROWSER_NATIVE_HOST_NAME = "ai.xopc.browser";
|
|
9
|
-
const BROWSER_EXTENSION_ID = "gopbfhaojnnhiheiikblejnpgmfmkmgd";
|
|
10
10
|
function gatewayLoopbackUrl(port) {
|
|
11
11
|
return `http://127.0.0.1:${port}`;
|
|
12
12
|
}
|
|
@@ -22,7 +22,11 @@ function decodeNativeMessage(buffer) {
|
|
|
22
22
|
if (length === 0 || length > 1024 * 1024 || buffer.length !== length + 4) throw new Error("Native message length is invalid");
|
|
23
23
|
return JSON.parse(buffer.subarray(4).toString("utf8"));
|
|
24
24
|
}
|
|
25
|
-
function createBrowserNativeBootstrap(configPath) {
|
|
25
|
+
function createBrowserNativeBootstrap(configPath, request) {
|
|
26
|
+
if (request.extensionId !== "gopbfhaojnnhiheiikblejnpgmfmkmgd") throw new Error("Browser extension identity is not trusted");
|
|
27
|
+
if (!/^[A-Za-z0-9_-]{24,160}$/.test(request.nonce)) throw new Error("Browser enrollment nonce is invalid");
|
|
28
|
+
const publicKeyThumbprint = browserEnrollmentPublicKeyThumbprint(request.publicKeyJwk);
|
|
29
|
+
if (request.publicKeyThumbprint !== publicKeyThumbprint) throw new Error("Browser enrollment key does not match");
|
|
26
30
|
const gatewayUrl = gatewayLoopbackUrl(loadConfig(configPath).gateway.port ?? 18790);
|
|
27
31
|
openXopcDatabase();
|
|
28
32
|
try {
|
|
@@ -31,7 +35,15 @@ function createBrowserNativeBootstrap(configPath) {
|
|
|
31
35
|
kind: "local-browser",
|
|
32
36
|
url: gatewayUrl
|
|
33
37
|
};
|
|
34
|
-
const setup = createDevicePairingSetup([route], Date.now(), 3
|
|
38
|
+
const setup = createDevicePairingSetup([route], Date.now(), 3, {
|
|
39
|
+
ttlMs: 6e4,
|
|
40
|
+
enrollment: {
|
|
41
|
+
issuer: "browser-native-host",
|
|
42
|
+
extensionId: request.extensionId,
|
|
43
|
+
publicKeyThumbprint,
|
|
44
|
+
nonce: request.nonce
|
|
45
|
+
}
|
|
46
|
+
});
|
|
35
47
|
const identity = getOrCreateGatewayIdentity();
|
|
36
48
|
return {
|
|
37
49
|
ok: true,
|
|
@@ -93,7 +105,13 @@ async function runBrowserNativeMessagingHost(configPath) {
|
|
|
93
105
|
try {
|
|
94
106
|
const request = decodeNativeMessage(await readOneNativeMessage(process.stdin));
|
|
95
107
|
if (!request || typeof request !== "object" || request.type !== "bootstrap") throw new Error("Unsupported native messaging request");
|
|
96
|
-
|
|
108
|
+
const bootstrap = request;
|
|
109
|
+
process.stdout.write(encodeNativeMessage(createBrowserNativeBootstrap(configPath, {
|
|
110
|
+
extensionId: bootstrap.extensionId,
|
|
111
|
+
publicKeyJwk: bootstrap.publicKeyJwk,
|
|
112
|
+
publicKeyThumbprint: bootstrap.publicKeyThumbprint,
|
|
113
|
+
nonce: bootstrap.nonce
|
|
114
|
+
})));
|
|
97
115
|
} catch (error) {
|
|
98
116
|
process.stdout.write(encodeNativeMessage({
|
|
99
117
|
ok: false,
|
|
@@ -26,6 +26,7 @@ export interface BrowserExtDoctor {
|
|
|
26
26
|
needsChromeReload?: boolean;
|
|
27
27
|
bundledFrom?: BrowserExtBundledFrom;
|
|
28
28
|
runtimeExtensionVersion?: string;
|
|
29
|
+
nativeHost: BrowserNativeHostInstallResult;
|
|
29
30
|
}
|
|
30
31
|
export interface EnsureBrowserExtResult {
|
|
31
32
|
extensionDir: string;
|
|
@@ -65,17 +66,19 @@ export declare function ensureBrowserExtensionArtifacts(opts?: {
|
|
|
65
66
|
cacheDir?: string;
|
|
66
67
|
}): Promise<EnsureBrowserExtResult>;
|
|
67
68
|
export declare function browserNativeManifestDirectories(platform?: NodeJS.Platform, home?: string): string[];
|
|
69
|
+
export declare function browserNativeHostDoctor(platform?: NodeJS.Platform, home?: string): BrowserNativeHostInstallResult;
|
|
68
70
|
/** Install the local-only bootstrap host used to discover and pair with a Gateway. */
|
|
69
71
|
export declare function installBrowserNativeMessagingHost(opts?: {
|
|
70
72
|
cacheDir?: string;
|
|
71
73
|
cliPath?: string;
|
|
72
74
|
nodePath?: string;
|
|
75
|
+
tsxCliPath?: string;
|
|
73
76
|
platform?: NodeJS.Platform;
|
|
74
77
|
home?: string;
|
|
75
78
|
configPath?: string;
|
|
76
79
|
stateDir?: string;
|
|
77
80
|
}): Promise<BrowserNativeHostInstallResult>;
|
|
78
|
-
/** Gateway startup hook:
|
|
81
|
+
/** Gateway startup hook: install/repair extension artifacts and its local enrollment host. */
|
|
79
82
|
export declare function ensureBrowserExtensionOnStartup(config: Config | undefined): Promise<void>;
|
|
80
83
|
export declare function readInstalledExtensionDir(cacheDir?: string): Promise<string | null>;
|
|
81
84
|
export type BrowserExtensionOpenAction = 'chrome' | 'folder' | 'both';
|
|
@@ -2,13 +2,14 @@ import { PACKAGE_VERSION, init_package_version } from "../../package-version.js"
|
|
|
2
2
|
import { resolveStateDir } from "../../config/paths-state.js";
|
|
3
3
|
import { createLogger } from "../../utils/logger/index.js";
|
|
4
4
|
import { init_logger } from "../../utils/logger.js";
|
|
5
|
-
import { init_paths, resolveBinDir, resolveConfigPath } from "../../config/paths.js";
|
|
6
5
|
import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
|
|
6
|
+
import { init_paths, resolveBinDir, resolveConfigPath } from "../../config/paths.js";
|
|
7
7
|
import { assertCacheDir } from "../cache-dir-policy.js";
|
|
8
|
-
import { BROWSER_EXTENSION_ID, BROWSER_NATIVE_HOST_NAME } from "../
|
|
8
|
+
import { BROWSER_EXTENSION_ID, BROWSER_NATIVE_HOST_NAME } from "../extension-identity.js";
|
|
9
|
+
import "../native-messaging-host.js";
|
|
9
10
|
import { resolvePackageRoot } from "../../infra/update-check.js";
|
|
10
11
|
import { dirname, join } from "node:path";
|
|
11
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
12
13
|
import { fileURLToPath } from "node:url";
|
|
13
14
|
import { spawn } from "node:child_process";
|
|
14
15
|
import { createHash } from "node:crypto";
|
|
@@ -240,7 +241,8 @@ async function browserExtDoctor(opts) {
|
|
|
240
241
|
needsRefresh,
|
|
241
242
|
needsChromeReload,
|
|
242
243
|
bundledFrom: bundled?.bundledFrom,
|
|
243
|
-
runtimeExtensionVersion: runtimeVer
|
|
244
|
+
runtimeExtensionVersion: runtimeVer,
|
|
245
|
+
nativeHost: browserNativeHostDoctor()
|
|
244
246
|
};
|
|
245
247
|
}
|
|
246
248
|
async function ensureBrowserExtensionArtifacts(opts) {
|
|
@@ -302,33 +304,68 @@ function browserNativeManifestDirectories(platform = process.platform, home = pr
|
|
|
302
304
|
if (!home) return [];
|
|
303
305
|
if (platform === "darwin") return [
|
|
304
306
|
join(home, "Library/Application Support/Google/Chrome/NativeMessagingHosts"),
|
|
307
|
+
join(home, "Library/Application Support/Google/ChromeForTesting/NativeMessagingHosts"),
|
|
305
308
|
join(home, "Library/Application Support/Chromium/NativeMessagingHosts"),
|
|
306
309
|
join(home, "Library/Application Support/Microsoft Edge/NativeMessagingHosts"),
|
|
307
310
|
join(home, "Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts")
|
|
308
311
|
];
|
|
309
312
|
if (platform === "linux") return [
|
|
310
313
|
join(home, ".config/google-chrome/NativeMessagingHosts"),
|
|
314
|
+
join(home, ".config/google-chrome-for-testing/NativeMessagingHosts"),
|
|
311
315
|
join(home, ".config/chromium/NativeMessagingHosts"),
|
|
312
316
|
join(home, ".config/microsoft-edge/NativeMessagingHosts"),
|
|
313
317
|
join(home, ".config/BraveSoftware/Brave-Browser/NativeMessagingHosts")
|
|
314
318
|
];
|
|
315
319
|
return [];
|
|
316
320
|
}
|
|
321
|
+
function browserNativeHostDoctor(platform = process.platform, home = process.env.HOME || process.env.USERPROFILE || "") {
|
|
322
|
+
const directories = browserNativeManifestDirectories(platform, home);
|
|
323
|
+
if (directories.length === 0) return {
|
|
324
|
+
installed: false,
|
|
325
|
+
manifestPaths: [],
|
|
326
|
+
reason: "Automatic local Gateway discovery is supported on macOS and Linux"
|
|
327
|
+
};
|
|
328
|
+
const manifestPaths = directories.map((directory) => join(directory, `${BROWSER_NATIVE_HOST_NAME}.json`)).filter((manifestPath) => {
|
|
329
|
+
try {
|
|
330
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
331
|
+
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/`);
|
|
332
|
+
} catch {
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
return {
|
|
337
|
+
installed: manifestPaths.length > 0,
|
|
338
|
+
manifestPaths,
|
|
339
|
+
...manifestPaths.length === 0 ? { reason: "Browser native enrollment host is not installed" } : {}
|
|
340
|
+
};
|
|
341
|
+
}
|
|
317
342
|
/** Install the local-only bootstrap host used to discover and pair with a Gateway. */
|
|
318
343
|
async function installBrowserNativeMessagingHost(opts) {
|
|
319
344
|
const directories = browserNativeManifestDirectories(opts?.platform ?? process.platform, opts?.home);
|
|
320
345
|
if (directories.length === 0) return {
|
|
321
346
|
installed: false,
|
|
322
347
|
manifestPaths: [],
|
|
323
|
-
reason: "
|
|
348
|
+
reason: "Automatic local Gateway discovery is supported on macOS and Linux"
|
|
324
349
|
};
|
|
325
350
|
const cliPath = opts?.cliPath ?? process.argv[1];
|
|
326
351
|
if (!cliPath) throw new Error("Unable to resolve the xopc CLI entry point");
|
|
352
|
+
const executablePath = opts?.nodePath ?? process.execPath;
|
|
353
|
+
let executableArgs = [
|
|
354
|
+
cliPath,
|
|
355
|
+
"browser",
|
|
356
|
+
"extension",
|
|
357
|
+
"native-host"
|
|
358
|
+
];
|
|
359
|
+
if (cliPath.endsWith(".ts")) {
|
|
360
|
+
const tsxPath = opts?.tsxCliPath ?? join(process.cwd(), "node_modules", "tsx", "dist", "cli.mjs");
|
|
361
|
+
if (!existsSync(tsxPath)) throw new Error("Unable to install the browser native host in development: the tsx CLI entry was not found");
|
|
362
|
+
executableArgs = [realpathSync(tsxPath), ...executableArgs];
|
|
363
|
+
}
|
|
327
364
|
const hostPath = join((opts?.cacheDir?.trim() ? assertCacheDir(opts.cacheDir) : resolveBinDir()) || resolveBinDir(), "browser-native-host");
|
|
328
365
|
mkdirSync(dirname(hostPath), { recursive: true });
|
|
329
366
|
const stateDir = opts?.stateDir ?? resolveStateDir();
|
|
330
367
|
const configPath = opts?.configPath ?? resolveConfigPath();
|
|
331
|
-
await writeTextAtomic(hostPath, `#!/bin/sh\nexec env XOPC_STATE_DIR=${shellQuote(stateDir)} XOPC_CONFIG_PATH=${shellQuote(configPath)} XOPC_LOG_CONSOLE=false ${shellQuote(
|
|
368
|
+
await writeTextAtomic(hostPath, `#!/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`);
|
|
332
369
|
chmodSync(hostPath, 493);
|
|
333
370
|
const manifest = JSON.stringify({
|
|
334
371
|
name: BROWSER_NATIVE_HOST_NAME,
|
|
@@ -349,10 +386,12 @@ async function installBrowserNativeMessagingHost(opts) {
|
|
|
349
386
|
manifestPaths
|
|
350
387
|
};
|
|
351
388
|
}
|
|
352
|
-
/** Gateway startup hook:
|
|
389
|
+
/** Gateway startup hook: install/repair extension artifacts and its local enrollment host. */
|
|
353
390
|
async function ensureBrowserExtensionOnStartup(config) {
|
|
354
391
|
if (config?.browser.enabled === false || config?.browser.driver.kind !== "extension") return;
|
|
355
392
|
await ensureBrowserExtensionArtifacts();
|
|
393
|
+
const nativeHost = await installBrowserNativeMessagingHost();
|
|
394
|
+
if (!nativeHost.installed) log.warn({ reason: nativeHost.reason }, "Browser native enrollment host was not installed");
|
|
356
395
|
}
|
|
357
396
|
async function readInstalledExtensionDir(cacheDir) {
|
|
358
397
|
const resolved = (cacheDir?.trim() ? assertCacheDir(cacheDir) : resolveBinDir()) || resolveBinDir();
|
|
@@ -432,4 +471,4 @@ async function openBrowserExtensionInstallUi(opts) {
|
|
|
432
471
|
};
|
|
433
472
|
}
|
|
434
473
|
//#endregion
|
|
435
|
-
export { BROWSER_EXT_REQUIRED_FILES, browserExtContentHash, browserExtDoctor, browserNativeManifestDirectories, computeNeedsRefresh, ensureBrowserExtensionArtifacts, ensureBrowserExtensionOnStartup, installBrowserNativeMessagingHost, openBrowserExtensionInstallUi, readInstalledExtensionDir, resolveBundledBrowserExtDir, resolveInstalledExtensionPath, resolveWindowsExtensionManager, validateBrowserExtLayout };
|
|
474
|
+
export { BROWSER_EXT_REQUIRED_FILES, browserExtContentHash, browserExtDoctor, browserNativeHostDoctor, browserNativeManifestDirectories, computeNeedsRefresh, ensureBrowserExtensionArtifacts, ensureBrowserExtensionOnStartup, installBrowserNativeMessagingHost, openBrowserExtensionInstallUi, readInstalledExtensionDir, resolveBundledBrowserExtDir, resolveInstalledExtensionPath, resolveWindowsExtensionManager, validateBrowserExtLayout };
|
|
@@ -2,8 +2,8 @@ import { createLogger } from "../../utils/logger/index.js";
|
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
3
|
import { deleteBrowserTabBindingsByPrincipal, getBrowserTabBindingById } from "../../storage/sqlite/browser-tab-binding-repository.js";
|
|
4
4
|
import { getDevice } from "../../storage/sqlite/device-access-repository.js";
|
|
5
|
-
import { isChromeExtensionOrigin } from "../../gateway/security/origin-check.js";
|
|
6
5
|
import { browserWireAuthenticationPayload } from "../../../packages/browser-control-contract/src/index.js";
|
|
6
|
+
import { isChromeExtensionOrigin } from "../../gateway/security/origin-check.js";
|
|
7
7
|
import crypto from "node:crypto";
|
|
8
8
|
//#region src/browser/providers/extension.ts
|
|
9
9
|
/**
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type BrowserActionInput, type BrowserWireResult } from '@xopcai/browser-control-contract';
|
|
2
|
+
import type { EndpointToolRuntime } from '../../endpoint-tools/index.js';
|
|
3
|
+
export interface RealtimeExtensionProviderConfig {
|
|
4
|
+
connectionTimeout?: number;
|
|
5
|
+
commandTimeout?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class RealtimeExtensionBrowserProvider {
|
|
8
|
+
private readonly runtime;
|
|
9
|
+
readonly name = "extension";
|
|
10
|
+
private readonly connectionTimeout;
|
|
11
|
+
private readonly commandTimeout;
|
|
12
|
+
constructor(runtime: EndpointToolRuntime, config?: RealtimeExtensionProviderConfig);
|
|
13
|
+
start(): Promise<void>;
|
|
14
|
+
waitForConnection(timeoutMs?: number): Promise<void>;
|
|
15
|
+
send(input: BrowserActionInput, timeoutMs?: number, visualFallback?: boolean): Promise<BrowserWireResult>;
|
|
16
|
+
isConnected(): boolean;
|
|
17
|
+
getConnectionStatus(): {
|
|
18
|
+
socketConnected: boolean;
|
|
19
|
+
connected: boolean;
|
|
20
|
+
protocolVersion: number;
|
|
21
|
+
expectedProtocolVersion: number;
|
|
22
|
+
extensionVersion: string;
|
|
23
|
+
principalId: string;
|
|
24
|
+
transport: "gateway-realtime";
|
|
25
|
+
};
|
|
26
|
+
shutdown(): Promise<void>;
|
|
27
|
+
private endpointForInput;
|
|
28
|
+
private currentEndpoint;
|
|
29
|
+
}
|