@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
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { getBrowserTabBindingById } from "../../storage/sqlite/browser-tab-binding-repository.js";
|
|
2
|
+
import { BROWSER_CONTROL_ENDPOINT_TOOL_NAME } from "../../../packages/browser-control-contract/src/index.js";
|
|
3
|
+
import crypto from "node:crypto";
|
|
4
|
+
//#region src/browser/providers/realtime-extension.ts
|
|
5
|
+
var RealtimeExtensionBrowserProvider = class {
|
|
6
|
+
name = "extension";
|
|
7
|
+
connectionTimeout;
|
|
8
|
+
commandTimeout;
|
|
9
|
+
constructor(runtime, config = {}) {
|
|
10
|
+
this.runtime = runtime;
|
|
11
|
+
this.connectionTimeout = config.connectionTimeout ?? 3e4;
|
|
12
|
+
this.commandTimeout = config.commandTimeout ?? 3e4;
|
|
13
|
+
}
|
|
14
|
+
async start() {}
|
|
15
|
+
async waitForConnection(timeoutMs = this.connectionTimeout) {
|
|
16
|
+
const deadline = Date.now() + timeoutMs;
|
|
17
|
+
while (!this.currentEndpoint()) {
|
|
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
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async send(input, timeoutMs = this.commandTimeout, visualFallback = true) {
|
|
23
|
+
const endpoint = this.endpointForInput(input);
|
|
24
|
+
if (!endpoint) throw new Error("Extension not connected to this Gateway. Open the xopc Chrome extension and connect it first.");
|
|
25
|
+
const tool = this.runtime.registry.getTool(endpoint.endpointId, BROWSER_CONTROL_ENDPOINT_TOOL_NAME);
|
|
26
|
+
if (!tool) throw new Error("Connected browser extension does not support authenticated Realtime browser control. Reload or update the extension.");
|
|
27
|
+
const id = crypto.randomUUID();
|
|
28
|
+
const controller = new AbortController();
|
|
29
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
30
|
+
try {
|
|
31
|
+
const value = (await this.runtime.invocations.invoke({
|
|
32
|
+
endpointId: endpoint.endpointId,
|
|
33
|
+
toolCallId: `browser-control:${id}`,
|
|
34
|
+
toolName: tool.descriptor.name,
|
|
35
|
+
arguments: {
|
|
36
|
+
input,
|
|
37
|
+
timeoutMs,
|
|
38
|
+
visualFallback
|
|
39
|
+
},
|
|
40
|
+
descriptorRevision: tool.revision,
|
|
41
|
+
signal: controller.signal
|
|
42
|
+
})).content.find((item) => item.type === "json");
|
|
43
|
+
if (!value || !value.value || typeof value.value !== "object") throw new Error("Browser extension returned an invalid Realtime result");
|
|
44
|
+
return {
|
|
45
|
+
id,
|
|
46
|
+
connectionId: endpoint.endpointId,
|
|
47
|
+
result: value.value
|
|
48
|
+
};
|
|
49
|
+
} finally {
|
|
50
|
+
clearTimeout(timer);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
isConnected() {
|
|
54
|
+
return Boolean(this.currentEndpoint());
|
|
55
|
+
}
|
|
56
|
+
getConnectionStatus() {
|
|
57
|
+
const endpoint = this.currentEndpoint();
|
|
58
|
+
return {
|
|
59
|
+
socketConnected: Boolean(endpoint),
|
|
60
|
+
connected: Boolean(endpoint),
|
|
61
|
+
protocolVersion: endpoint ? 4 : null,
|
|
62
|
+
expectedProtocolVersion: 4,
|
|
63
|
+
extensionVersion: endpoint?.appVersion ?? null,
|
|
64
|
+
principalId: endpoint?.principalId ?? null,
|
|
65
|
+
transport: "gateway-realtime"
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
async shutdown() {}
|
|
69
|
+
endpointForInput(input) {
|
|
70
|
+
if (input.target?.kind === "attached_tab") {
|
|
71
|
+
const binding = getBrowserTabBindingById(input.target.bindingId);
|
|
72
|
+
const endpoint = binding ? this.runtime.registry.get(binding.endpointId) : void 0;
|
|
73
|
+
if (!binding || !endpoint || endpoint.principalId !== binding.principalId) return void 0;
|
|
74
|
+
return endpoint;
|
|
75
|
+
}
|
|
76
|
+
return this.currentEndpoint();
|
|
77
|
+
}
|
|
78
|
+
currentEndpoint() {
|
|
79
|
+
return this.runtime.registry.list().filter((endpoint) => endpoint.kind === "browser" && endpoint.tools.some((tool) => tool.descriptor.name === "browser.control")).sort((left, right) => right.lastHeartbeatAt - left.lastHeartbeatAt)[0];
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
//#endregion
|
|
83
|
+
export { RealtimeExtensionBrowserProvider };
|
|
@@ -52,7 +52,7 @@ async function checkDatabaseSchema(ctx) {
|
|
|
52
52
|
id: "database-schema",
|
|
53
53
|
label: "Database schema",
|
|
54
54
|
status: "pass",
|
|
55
|
-
message: `SQLite schema v${status.dbVersion} (current release
|
|
55
|
+
message: `SQLite schema v${status.dbVersion} (current release v158).`,
|
|
56
56
|
hints: []
|
|
57
57
|
};
|
|
58
58
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getAgentDefaultModelRef, init_schema, parseModelRef } from "../../../../config/schema.js";
|
|
2
|
-
import { init_loader, loadConfig } from "../../../../config/loader.js";
|
|
3
2
|
import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "../../../../providers/env-keys.js";
|
|
3
|
+
import { init_loader, loadConfig } from "../../../../config/loader.js";
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
//#region src/cli/commands/doctor/checks/provider-auth.ts
|
|
6
6
|
init_loader();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
|
|
2
|
-
import { loadConfig, saveConfig } from "../../config/loader.js";
|
|
3
2
|
import { CredentialResolver, init_credentials } from "../../auth/credentials.js";
|
|
3
|
+
import { loadConfig, saveConfig } from "../../config/loader.js";
|
|
4
4
|
import { getAllModels, getAvailableModels, getConfiguredProviders, getProviderAuthState, getProviderDisplayName, init_providers, isProviderConfigured, providerSupportsApiKey, providerSupportsOAuth, resolveModel } from "../../providers/index.js";
|
|
5
5
|
import { formatExamples, register } from "../registry.js";
|
|
6
6
|
import { getContextWithOpts } from "../context.js";
|
package/dist/src/config/index.js
CHANGED
|
@@ -2,15 +2,15 @@ import { ENV_VARS, XOPC_DB_FILENAME, resolveHomeDir, resolveStateDir, resolveXop
|
|
|
2
2
|
import { TelegramAccountConfigSchema, TelegramConfigSchema, TelegramGroupConfigSchema, TelegramTopicConfigSchema } from "../../extensions/telegram/src/config-schema.js";
|
|
3
3
|
import { WeixinAccountConfigSchema, WeixinConfigSchema } from "../../extensions/weixin/src/config-schema.js";
|
|
4
4
|
import { AgentImageGenerationModelSchema, AgentModelRefSchema, AgentModelsSchema, AgentsConfigSchema, BindingMatchSchema, BindingRuleSchema, BindingsConfigSchema, BrowserConfigSchema, ChannelsConfigSchema, CommandsConfigSchema, ConfigSchema, ConnectorsConfigSchema, ExperimentalConfigSchema, ExtensionSecurityConfigSchema, ExtensionSlotsConfigSchema, ExtensionsConfigSchema, GatewayAuthRateLimitSchema, GatewayAuthSchema, GatewayBindModeSchema, GatewayChannelConnectDeferModeSchema, GatewayConfigSchema, GatewayModeSchema, GatewayRemoteSchema, GatewaySecuritySchema, GatewayTailscaleConsentSchema, GatewayTailscaleSchema, GatewayTlsSchema, GatewayTrustedProxySchema, GatewayWebchatConfigSchema, HeartbeatConfigSchema, McpConfigSchema, McpOAuthConfigSchema, McpServerSchema, MediaUnderstandingCapabilitiesSchema, MediaUnderstandingModelSchema, MessagesConfigSchema, ModelCatalogConfigSchema, ModelsDevConfigSchema, ProviderAuthConfigSchema, ProviderAzureConfigSchema, ProviderRequestOverridesSchema, ProvidersConfigSchema, RuntimeToolsConfigSchema, STTConfigSchema, STTFallbackConfigSchema, STTProviderConfigSchema, SearchProviderEntrySchema, SessionConfigSchema, SessionDmScopeSchema, SessionResetByTypeSchema, SessionResetConfigSchema, SessionResetModeSchema, SessionScopeSchema, SessionStorageConfigSchema, TTSConfigSchema, TTSEdgeConfigSchema, TTSFallbackConfigSchema, TTSModelOverridesConfigSchema, TTSProviderConfigSchema, TTSSummarizationConfigSchema, ToolsConfigSchema, ToolsMediaAudioConfigSchema, ToolsMediaConfigSchema, TuiConfigSchema, TunnelConfigSchema, TunnelConsentSchema, UpdateAutoConfigSchema, UpdateConfigSchema, VoiceConfigSchema, VoiceRefinementConfigSchema, WebSearchConfigSchema, WebToolsConfigSchema, WebsiteBlocklistSchema, WorkspaceConfigSchema, WorkspaceImportConfigSchema, getAgentDefaultImageGenerationModelConfig, getAgentDefaultImageModelConfig, getAgentDefaultModelRef, init_schema, parseModelRef } from "./schema.js";
|
|
5
|
-
import {
|
|
5
|
+
import { clearConfigValueCache, getAllowedCommands, getCacheStats, init_resolve_config_value, resolveConfigValue, resolveHeaders, testApiKeyResolution } from "./resolve-config-value.js";
|
|
6
6
|
import { expandWorkspacePathString, init_workspace_path, normalizeWorkspaceDir, resolveWorkspaceRoot } from "./workspace-path.js";
|
|
7
7
|
import { resolveDefaultAgentWorkspaceDir } from "./workspace-defaults.js";
|
|
8
8
|
import { resolveAgentDir as resolveAgentDir$1, resolveAgentHomeDir as resolveAgentHomeDir$1, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
|
|
9
|
-
import { extractProfileAgentId, resolveEffectiveAgentConfigForAgent, resolveEffectiveAgentConfigForSession, resolveEffectiveAgentProfile, resolveEffectiveAgentProfileForSession } from "./agent-profile.js";
|
|
10
9
|
import { FILENAMES, WORKSPACE_FILES, existsSync, hasBundledExtensionManifest, init_paths, resolveAgentAuthProfilesPath, resolveAgentDir, resolveAgentHomeDir, resolveAgentProfileDir, resolveAgentProfileMarkdownPath, resolveAuthProfilesPath, resolveBinDir, resolveBundledExtensionsDir, resolveBundledSkillsDir, resolveConfigPath, resolveCredentialsDir, resolveExtensionSdkPath, resolveExtensionsDir, resolveExtensionsLockPath, resolveInboxDir, resolveInboxMessagePath, resolveInboxPendingDir, resolveInboxProcessedDir, resolveLogPath, resolveLogsDir, resolveMcpOAuthPath, resolveModelsJsonPath, resolveNodeBinDir, resolveNodeBinPath, resolveNodeToolsDir, resolveNpmBinPath, resolveOAuthPath, resolvePidPath, resolveSkillPath, resolveSkillsCachePath, resolveSkillsDir, resolveSkillsLockPath, resolveSocketPath, resolveStatusPath, resolveToolsDir, resolveWorkspaceExtensionsDir, resolveWorkspaceFile, resolveWorkspaceStateDir, resolveWorkspaceStatePath, resolveXopcBinPath } from "./paths.js";
|
|
11
|
-
import { init_loader, loadConfig, saveConfig } from "./loader.js";
|
|
12
|
-
import { clearConfigValueCache, getAllowedCommands, getCacheStats, init_resolve_config_value, resolveConfigValue, resolveHeaders, testApiKeyResolution } from "./resolve-config-value.js";
|
|
13
10
|
import { CustomModelSchema, ImageGenerationCapabilitiesSchema, ImageGenerationModelSchema, ImageGenerationProviderSchema, ModelOverrideSchema, ModelsJsonSchema, OpenAICompatSchema, OpenAICompletionsCompatSchema, OpenAIResponsesCompatSchema, OpenRouterRoutingSchema, ProviderConfigSchema, VercelGatewayRoutingSchema, getDefaultModelValues, init_models_json, loadModelsJson, modelsJsonExists, saveModelsJson, validateModelsConfig } from "./models-json.js";
|
|
11
|
+
import { init_loader, loadConfig, saveConfig } from "./loader.js";
|
|
12
|
+
import { applyConfigOverrides, getConfigOverrides, resetConfigOverrides, setConfigOverride, unsetConfigOverride } from "./runtime-overrides.js";
|
|
13
|
+
import { extractProfileAgentId, resolveEffectiveAgentConfigForAgent, resolveEffectiveAgentConfigForSession, resolveEffectiveAgentProfile, resolveEffectiveAgentProfileForSession } from "./agent-profile.js";
|
|
14
14
|
import { canonicalizeConfiguredMcpServer, isKnownCliMcpTypeAlias, normalizeConfiguredMcpServers, resolveXopcMcpTransportAlias } from "./mcp-config-normalize.js";
|
|
15
15
|
import { formatThinkingLevels, listThinkingLevels, normalizeElevatedMode, normalizeReasoningLevel, normalizeThinkLevel, normalizeVerboseLevel, thinkLevelToNumber } from "../agent/transcript/thinking-types.js";
|
|
16
16
|
import { getWorkspacePath } from "./workspace-path-helpers.js";
|
|
@@ -2,10 +2,10 @@ 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
4
|
import { ConfigSchema, init_schema } from "./schema.js";
|
|
5
|
-
import { init_paths, resolveConfigPath } from "./paths.js";
|
|
6
5
|
import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
|
|
7
|
-
import {
|
|
6
|
+
import { init_paths, resolveConfigPath } from "./paths.js";
|
|
8
7
|
import { init_resolution, setActivePlatformDiscovery } from "../platform/resolution.js";
|
|
8
|
+
import { assertChannelPluginConfigs, init_validate_channel_configs } from "./validate-channel-configs.js";
|
|
9
9
|
import { dirname } from "path";
|
|
10
10
|
import { existsSync, mkdirSync, promises, readFileSync } from "fs";
|
|
11
11
|
import { config } from "dotenv";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
-
import { init_paths, resolveModelsJsonPath } from "./paths.js";
|
|
3
2
|
import { init_write_file_atomic, writeTextAtomicSync } from "../infra/write-file-atomic.js";
|
|
3
|
+
import { init_paths, resolveModelsJsonPath } from "./paths.js";
|
|
4
4
|
import { existsSync, readFileSync } from "fs";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
//#region src/config/models-json.ts
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { ENDPOINT_CONTACT_LIST_OUTPUT_SCHEMA, ENDPOINT_CONTACT_OUTPUT_SCHEMA, ENDPOINT_FILE_OUTPUT_SCHEMA, ENDPOINT_TEXT_OUTPUT_SCHEMA, canonicalJson } from "../../packages/endpoint-tools-protocol/src/index.js";
|
|
2
|
+
import { BROWSER_CONTROL_ENDPOINT_INPUT_SCHEMA, BROWSER_CONTROL_ENDPOINT_OUTPUT_SCHEMA } from "../../packages/browser-control-contract/src/index.js";
|
|
2
3
|
import Ajv2020 from "ajv/dist/2020.js";
|
|
3
4
|
//#region src/endpoint-tools/policy.ts
|
|
4
5
|
var EndpointToolPolicyError = class extends Error {};
|
|
5
|
-
function contract(policyId, outputSchema, resultKinds, permissions, legacyPolicyIds = []) {
|
|
6
|
+
function contract(policyId, outputSchema, resultKinds, permissions, legacyPolicyIds = [], inputSchema) {
|
|
6
7
|
return {
|
|
7
8
|
policyId,
|
|
8
9
|
legacyPolicyIds,
|
|
10
|
+
inputSchema,
|
|
9
11
|
outputSchema,
|
|
10
12
|
resultKinds,
|
|
11
13
|
permissions
|
|
@@ -31,7 +33,8 @@ const POLICY_BY_TOOL = {
|
|
|
31
33
|
"mobile.notification.show": contract("user.foreground-write", ENDPOINT_TEXT_OUTPUT_SCHEMA, ["text"], ["notifications"]),
|
|
32
34
|
"mobile.device.get_info": contract("public.background-read", ENDPOINT_TEXT_OUTPUT_SCHEMA, ["text"], []),
|
|
33
35
|
"mobile.clipboard.write": contract("user.foreground-write", ENDPOINT_TEXT_OUTPUT_SCHEMA, ["text"], ["clipboard-write"]),
|
|
34
|
-
"mobile.app.open_url": contract("user.foreground-write", ENDPOINT_TEXT_OUTPUT_SCHEMA, ["text"], ["open-external-url"])
|
|
36
|
+
"mobile.app.open_url": contract("user.foreground-write", ENDPOINT_TEXT_OUTPUT_SCHEMA, ["text"], ["open-external-url"]),
|
|
37
|
+
"browser.control": contract("browser.control", BROWSER_CONTROL_ENDPOINT_OUTPUT_SCHEMA, ["json"], ["browser-control"], [], BROWSER_CONTROL_ENDPOINT_INPUT_SCHEMA)
|
|
35
38
|
};
|
|
36
39
|
var EndpointToolPolicy = class {
|
|
37
40
|
ajv = new Ajv2020({
|
|
@@ -43,7 +46,7 @@ var EndpointToolPolicy = class {
|
|
|
43
46
|
const contract = POLICY_BY_TOOL[descriptor.name];
|
|
44
47
|
if (!contract) throw new EndpointToolPolicyError(`Tool ${descriptor.name} has no trusted server policy`);
|
|
45
48
|
if (descriptor.policyId !== contract.policyId && !contract.legacyPolicyIds.includes(descriptor.policyId)) throw new EndpointToolPolicyError(`Tool ${descriptor.name} does not match its trusted server policy`);
|
|
46
|
-
if (canonicalJson(descriptor.outputSchema) !== canonicalJson(contract.outputSchema) || canonicalJson(descriptor.resultKinds) !== canonicalJson(contract.resultKinds) || canonicalJson([...descriptor.requiredPermissions].sort()) !== canonicalJson([...contract.permissions].sort())) throw new EndpointToolPolicyError(`Tool ${descriptor.name} does not match its trusted server contract`);
|
|
49
|
+
if (contract.inputSchema && canonicalJson(descriptor.inputSchema) !== canonicalJson(contract.inputSchema) || canonicalJson(descriptor.outputSchema) !== canonicalJson(contract.outputSchema) || canonicalJson(descriptor.resultKinds) !== canonicalJson(contract.resultKinds) || canonicalJson([...descriptor.requiredPermissions].sort()) !== canonicalJson([...contract.permissions].sort())) throw new EndpointToolPolicyError(`Tool ${descriptor.name} does not match its trusted server contract`);
|
|
47
50
|
this.validatePolicyFields(descriptor);
|
|
48
51
|
try {
|
|
49
52
|
this.ajv.compile(descriptor.outputSchema);
|
|
@@ -79,6 +82,10 @@ var EndpointToolPolicy = class {
|
|
|
79
82
|
if (descriptor.effect === "read") throw new EndpointToolPolicyError(`Mutating tool ${descriptor.name} cannot declare a read effect`);
|
|
80
83
|
if (descriptor.confirmation !== "always" || !descriptor.requiresForeground || descriptor.sensitivity !== "personal" || descriptor.requiredPermissions.length === 0) throw new EndpointToolPolicyError(`Mutating tool ${descriptor.name} violates its trusted policy`);
|
|
81
84
|
return;
|
|
85
|
+
case "browser.control":
|
|
86
|
+
this.assertFields(descriptor, "write", "never", false, "personal");
|
|
87
|
+
if (descriptor.requiredPermissions.length !== 1 || descriptor.requiredPermissions[0] !== "browser-control" || descriptor.timeoutMs !== 12e4 || descriptor.maxConcurrency !== 4 || descriptor.supportsCancellation !== true || descriptor.idempotent !== false) throw new EndpointToolPolicyError(`Browser tool ${descriptor.name} violates its trusted policy`);
|
|
88
|
+
return;
|
|
82
89
|
default: throw new EndpointToolPolicyError(`Unknown endpoint policy: ${descriptor.policyId}`);
|
|
83
90
|
}
|
|
84
91
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
|
-
import { init_paths, resolveExtensionsDir, resolveExtensionsLockPath } from "../config/paths.js";
|
|
4
3
|
import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
|
|
4
|
+
import { init_paths, resolveExtensionsDir, resolveExtensionsLockPath } from "../config/paths.js";
|
|
5
5
|
import { dirname, join } from "path";
|
|
6
6
|
import { existsSync } from "fs";
|
|
7
7
|
import { mkdir, readFile } from "fs/promises";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
|
|
2
|
-
import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
|
|
3
2
|
import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
|
|
3
|
+
import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
|
|
4
4
|
import { AGENT_PROFILE_MARKDOWN_SYSTEM_FILES, REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET } from "../agent/context/workspace.js";
|
|
5
5
|
import { isPathUnderWorkspace, resolveWorkspaceSafePath } from "./workspace-editor-path.js";
|
|
6
6
|
import { seedAgentProfileMarkdownFiles } from "../agent/context/workspace-seed.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { init_paths_state, resolveStateDir } from "../config/paths-state.js";
|
|
2
2
|
import { init_agent_scope, resolveAgentProfileDir } from "../agent/agent-scope.js";
|
|
3
|
-
import { extractProfileAgentId } from "../config/agent-profile.js";
|
|
4
3
|
import { init_paths, resolveConfigPath, resolveSkillsDir } from "../config/paths.js";
|
|
4
|
+
import { extractProfileAgentId } from "../config/agent-profile.js";
|
|
5
5
|
import { isBareProfileMarkdownFileName, resolveProfileMarkdownPathIfBareName } from "../agent/tools/tool-paths.js";
|
|
6
6
|
import { isPathUnderWorkspace, resolveWorkspaceSafePath } from "./workspace-editor-path.js";
|
|
7
7
|
import { basename, isAbsolute, resolve } from "node:path";
|
|
@@ -5,6 +5,7 @@ import { resolveAllowedBrowserOrigins, resolveGatewayServiceListenPort } from ".
|
|
|
5
5
|
import { resolveGatewayEffectiveHost } from "../../config/gateway-bind.js";
|
|
6
6
|
import { loadTunnelState } from "../../tunnel/tunnel-state.js";
|
|
7
7
|
import { resolveReverseProxyPublicUrl } from "../public-url.js";
|
|
8
|
+
import { BROWSER_EXTENSION_ID } from "../../browser/extension-identity.js";
|
|
8
9
|
import { maxSessionInputRequestBodyBytes } from "../chat-limits.js";
|
|
9
10
|
import { isLoopbackIpAddress, isTrustedProxyAddress } from "../client-ip.js";
|
|
10
11
|
import { buildGatewayConsoleCspHeader } from "../security/csp.js";
|
|
@@ -65,7 +66,11 @@ function createHonoApp(config) {
|
|
|
65
66
|
return [];
|
|
66
67
|
}
|
|
67
68
|
};
|
|
68
|
-
const resolveAllBrowserOrigins = () => [
|
|
69
|
+
const resolveAllBrowserOrigins = () => [
|
|
70
|
+
...resolveBrowserOrigins(),
|
|
71
|
+
`chrome-extension://${BROWSER_EXTENSION_ID}`,
|
|
72
|
+
...resolvePairedBrowserExtensionOrigins()
|
|
73
|
+
];
|
|
69
74
|
/**
|
|
70
75
|
* TCP source for the in-flight request, normalized for trusted-proxy checks.
|
|
71
76
|
* Returns undefined when the runtime doesn't expose conninfo (tests, mocks).
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ContextPlanningConfigSchema, KnowledgeMemoryConfigSchema, UserModelConfigSchema, init_config } from "../../../user-context/config.js";
|
|
2
2
|
import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveDefaultAgentId } from "../../../agent/agent-scope.js";
|
|
3
3
|
import { resolveModelsJsonPath } from "../../../config/paths.js";
|
|
4
|
-
import { buildChannelCatalogForConfig, buildChannelCatalogFromSnapshot, getChannelSetupStatus, init_channel_catalog_service } from "../../../channels/catalog/channel-catalog-service.js";
|
|
5
4
|
import { init_models_json, loadModelsJson } from "../../../config/models-json.js";
|
|
6
5
|
import { CredentialResolver, init_credentials } from "../../../auth/credentials.js";
|
|
6
|
+
import { buildChannelCatalogForConfig, buildChannelCatalogFromSnapshot, getChannelSetupStatus, init_channel_catalog_service } from "../../../channels/catalog/channel-catalog-service.js";
|
|
7
7
|
import { getProviderRegistry, init_plugin_registry } from "../../../providers/plugin-registry.js";
|
|
8
8
|
import { getAllProviders, init_providers, isProviderConfigured } from "../../../providers/index.js";
|
|
9
9
|
import { normalizeConfiguredMcpServers } from "../../../config/mcp-config-normalize.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { deleteBrowserTabBinding, getBrowserTabBinding, setBrowserTabBinding } from "../../../storage/sqlite/browser-tab-binding-repository.js";
|
|
2
2
|
import { browserTabBindingRequestSchema } from "../../../../packages/gateway-contract/src/browser-tab-binding.js";
|
|
3
3
|
import { getDevice } from "../../../storage/sqlite/device-access-repository.js";
|
|
4
|
+
import "../../../../packages/browser-control-contract/src/index.js";
|
|
4
5
|
import { decideBrowserApproval, listBrowserApprovals } from "../../../browser/policy/approval-store.js";
|
|
5
6
|
import { createBrowserDriver } from "../../../browser/drivers/create-driver.js";
|
|
6
7
|
import { checkBrowserReadiness } from "../../../browser/readiness.js";
|
|
@@ -9,34 +10,19 @@ import { getGatewayPrincipal } from "../../security/gateway-principal.js";
|
|
|
9
10
|
import { getConnInfo } from "@hono/node-server/conninfo";
|
|
10
11
|
//#region src/gateway/hono/routes/browser.ts
|
|
11
12
|
/** Browser Control status, approvals, and driver diagnostics. */
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
let running = snapshot.active;
|
|
17
|
-
let socketConnected = false;
|
|
18
|
-
let connected = false;
|
|
19
|
-
let protocolVersion = null;
|
|
20
|
-
let expectedProtocolVersion = null;
|
|
21
|
-
let extensionVersion = null;
|
|
22
|
-
try {
|
|
23
|
-
const payload = await (await fetch(EXTENSION_ENDPOINT, { signal: AbortSignal.timeout(2e3) })).json();
|
|
24
|
-
running ||= payload.ok === true;
|
|
25
|
-
socketConnected = payload.socketConnected ?? payload.connected === true;
|
|
26
|
-
connected = payload.connected === true;
|
|
27
|
-
protocolVersion = typeof payload.protocolVersion === "number" ? payload.protocolVersion : null;
|
|
28
|
-
expectedProtocolVersion = typeof payload.expectedProtocolVersion === "number" ? payload.expectedProtocolVersion : null;
|
|
29
|
-
extensionVersion = typeof payload.extensionVersion === "string" ? payload.extensionVersion : null;
|
|
30
|
-
} catch {}
|
|
13
|
+
async function extensionStatus(service) {
|
|
14
|
+
const endpoint = service.endpointTools.registry.list().filter((item) => item.kind === "browser" && item.tools.some((tool) => tool.descriptor.name === "browser.control")).sort((left, right) => right.lastHeartbeatAt - left.lastHeartbeatAt)[0];
|
|
15
|
+
const connected = Boolean(endpoint);
|
|
16
|
+
const extensionVersion = endpoint?.appVersion ?? null;
|
|
31
17
|
const { browserExtDoctor } = await import("../../../browser/providers/browser-ext-install.js");
|
|
32
18
|
const doctor = await browserExtDoctor({ runtimeExtensionVersion: extensionVersion ?? void 0 });
|
|
33
19
|
return {
|
|
34
|
-
running,
|
|
35
|
-
socketConnected,
|
|
20
|
+
running: true,
|
|
21
|
+
socketConnected: connected,
|
|
36
22
|
connected,
|
|
37
23
|
driverKind: "extension",
|
|
38
|
-
protocolVersion,
|
|
39
|
-
expectedProtocolVersion,
|
|
24
|
+
protocolVersion: connected ? 4 : null,
|
|
25
|
+
expectedProtocolVersion: 4,
|
|
40
26
|
extensionVersion,
|
|
41
27
|
artifacts: {
|
|
42
28
|
installed: doctor.installed,
|
|
@@ -45,10 +31,12 @@ async function extensionStatus() {
|
|
|
45
31
|
xopcVersion: doctor.xopcVersion,
|
|
46
32
|
installedVersion: doctor.installedVersion,
|
|
47
33
|
needsRefresh: doctor.needsRefresh,
|
|
48
|
-
needsChromeReload: doctor.needsChromeReload
|
|
34
|
+
needsChromeReload: doctor.needsChromeReload,
|
|
35
|
+
nativeHost: doctor.nativeHost
|
|
49
36
|
},
|
|
50
|
-
bridgeHeld:
|
|
51
|
-
refCount:
|
|
37
|
+
bridgeHeld: false,
|
|
38
|
+
refCount: connected ? 1 : 0,
|
|
39
|
+
transport: "gateway-realtime"
|
|
52
40
|
};
|
|
53
41
|
}
|
|
54
42
|
function isLocalOwnerRequest(c, service) {
|
|
@@ -156,7 +144,7 @@ function registerBrowserRoutes(authenticated, deps) {
|
|
|
156
144
|
});
|
|
157
145
|
authenticated.get("/api/browser/extension-status", async (c) => {
|
|
158
146
|
try {
|
|
159
|
-
return c.json(await extensionStatus());
|
|
147
|
+
return c.json(await extensionStatus(service));
|
|
160
148
|
} catch (error) {
|
|
161
149
|
return c.json({
|
|
162
150
|
running: false,
|
|
@@ -177,7 +165,7 @@ function registerBrowserRoutes(authenticated, deps) {
|
|
|
177
165
|
}
|
|
178
166
|
});
|
|
179
167
|
const readiness = await checkBrowserReadiness(service.currentConfig);
|
|
180
|
-
const driverStatus = config.driver.kind === "extension" ? await extensionStatus().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;
|
|
168
|
+
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;
|
|
181
169
|
const extensionConnected = config.driver.kind === "extension" ? driverStatus.connected === true : true;
|
|
182
170
|
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;
|
|
183
171
|
return c.json({
|
|
@@ -204,7 +192,7 @@ function registerBrowserRoutes(authenticated, deps) {
|
|
|
204
192
|
const startedAt = Date.now();
|
|
205
193
|
let driver;
|
|
206
194
|
try {
|
|
207
|
-
driver = await createBrowserDriver(service.currentConfig.browser);
|
|
195
|
+
driver = await createBrowserDriver(service.currentConfig.browser, service.endpointTools);
|
|
208
196
|
await driver.connect();
|
|
209
197
|
return c.json({
|
|
210
198
|
ok: true,
|
|
@@ -229,12 +217,14 @@ function registerBrowserRoutes(authenticated, deps) {
|
|
|
229
217
|
}, 403);
|
|
230
218
|
const body = await c.req.json().catch(() => ({}));
|
|
231
219
|
try {
|
|
232
|
-
const { browserExtDoctor, ensureBrowserExtensionArtifacts } = await import("../../../browser/providers/browser-ext-install.js");
|
|
220
|
+
const { browserExtDoctor, ensureBrowserExtensionArtifacts, installBrowserNativeMessagingHost } = await import("../../../browser/providers/browser-ext-install.js");
|
|
233
221
|
const result = await ensureBrowserExtensionArtifacts({ force: body.force === true });
|
|
222
|
+
const nativeHost = await installBrowserNativeMessagingHost({ configPath: service.getHealth().configPath });
|
|
234
223
|
return c.json({
|
|
235
224
|
ok: true,
|
|
236
225
|
payload: {
|
|
237
226
|
...result,
|
|
227
|
+
nativeHost,
|
|
238
228
|
doctor: await browserExtDoctor()
|
|
239
229
|
}
|
|
240
230
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { resolveModelsJsonPath } from "../../../config/paths.js";
|
|
2
1
|
import { init_resolve_config_value, testApiKeyResolution } from "../../../config/resolve-config-value.js";
|
|
2
|
+
import { resolveModelsJsonPath } from "../../../config/paths.js";
|
|
3
3
|
import { init_models_json, loadModelsJson, saveModelsJson, validateModelsConfig } from "../../../config/models-json.js";
|
|
4
4
|
import { getModelCatalogStore, init_model_catalog_store } from "../../../providers/model-catalog-store.js";
|
|
5
5
|
import { getModelRegistry } from "../../../providers/model-registry.js";
|
|
@@ -15,6 +15,11 @@ function isLoopbackHost(hostname) {
|
|
|
15
15
|
function parseOriginHost(originRaw) {
|
|
16
16
|
const trimmed = (originRaw ?? "").trim();
|
|
17
17
|
if (!trimmed || trimmed === "null") return null;
|
|
18
|
+
if (isChromeExtensionOrigin(trimmed)) return {
|
|
19
|
+
origin: trimmed.toLowerCase(),
|
|
20
|
+
host: "",
|
|
21
|
+
hostname: ""
|
|
22
|
+
};
|
|
18
23
|
try {
|
|
19
24
|
const url = new URL(trimmed);
|
|
20
25
|
return {
|
|
@@ -41,8 +41,6 @@ export interface GatewayConfigCoordinatorOptions {
|
|
|
41
41
|
getChannelManager: () => ChannelManager;
|
|
42
42
|
getHeartbeatService: () => HeartbeatService | null;
|
|
43
43
|
getExtensionLoader: () => ExtensionLoader | null;
|
|
44
|
-
/** Re-evaluate browser-extension server attachment after agent defaults change. */
|
|
45
|
-
reconcileBrowserExtensionServer: () => Promise<void>;
|
|
46
44
|
/** Sync deterministic user-model maintenance automations after config changes. */
|
|
47
45
|
reconcileMemoryMaintenanceAutomations: () => Promise<void>;
|
|
48
46
|
/** Latest channel status snapshot for the `channels.status` event. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
-
import { loadConfig, saveConfig } from "../../config/loader.js";
|
|
4
3
|
import { getModelRegistry } from "../../providers/model-registry.js";
|
|
4
|
+
import { loadConfig, saveConfig } from "../../config/loader.js";
|
|
5
5
|
import { init_providers } from "../../providers/index.js";
|
|
6
6
|
import { disposeAllSessionMcpRuntimes } from "../../agent/mcp/bundle-mcp-runtime.js";
|
|
7
7
|
import { reloadImageGenerationProviders } from "../../agent/image/generation/provider-registry.js";
|
|
@@ -223,7 +223,6 @@ var GatewayConfigCoordinator = class {
|
|
|
223
223
|
log.debug("Reloading agent defaults...");
|
|
224
224
|
this.opts.setConfig(newConfig);
|
|
225
225
|
this.opts.getAgentService().applyAgentDefaultsFromConfig(newConfig);
|
|
226
|
-
this.opts.reconcileBrowserExtensionServer();
|
|
227
226
|
this.opts.reconcileMemoryMaintenanceAutomations().catch((err) => {
|
|
228
227
|
const em = err instanceof Error ? err.message : String(err);
|
|
229
228
|
log.warn({
|
|
@@ -350,7 +349,6 @@ var GatewayConfigCoordinator = class {
|
|
|
350
349
|
this.opts.setConfig(reloaded);
|
|
351
350
|
if (sanitizeTunnelConfig(reloaded)) await saveConfig(reloaded, this.opts.configPath);
|
|
352
351
|
this.opts.getAgentService().applyAgentDefaultsFromConfig(reloaded);
|
|
353
|
-
await this.opts.reconcileBrowserExtensionServer();
|
|
354
352
|
await this.opts.reconcileMemoryMaintenanceAutomations().catch((err) => {
|
|
355
353
|
const em = err instanceof Error ? err.message : String(err);
|
|
356
354
|
log.warn({
|
|
@@ -39,10 +39,6 @@ export declare class GatewayService {
|
|
|
39
39
|
private notesService;
|
|
40
40
|
private extensionLoader;
|
|
41
41
|
private extensionMetadataSnapshot;
|
|
42
|
-
private browserExtensionProvider;
|
|
43
|
-
private browserExtensionRelease;
|
|
44
|
-
/** `${host}:${port}` when the gateway holds the extension bridge listener. */
|
|
45
|
-
private browserExtensionBindKey;
|
|
46
42
|
private heartbeatService;
|
|
47
43
|
private sessionIndex;
|
|
48
44
|
private running;
|
|
@@ -198,13 +194,6 @@ export declare class GatewayService {
|
|
|
198
194
|
*/
|
|
199
195
|
onHttpListening(): Promise<void>;
|
|
200
196
|
stop(): Promise<void>;
|
|
201
|
-
/** Start the browser extension WebSocket server when its driver is active. */
|
|
202
|
-
private startBrowserExtensionServerIfNeeded;
|
|
203
|
-
/**
|
|
204
|
-
* Start/stop/rebind the Chrome extension bridge.
|
|
205
|
-
* PATCH saves update config in memory without re-running gateway startup, so this must run on save too.
|
|
206
|
-
*/
|
|
207
|
-
reconcileBrowserExtensionServer(): Promise<void>;
|
|
208
197
|
/**
|
|
209
198
|
* Start processing outbound messages and send through channels
|
|
210
199
|
*/
|
|
@@ -12,16 +12,16 @@ import { getSessionConfig } from "../storage/sqlite/config-repository.js";
|
|
|
12
12
|
import "../storage/sqlite/index.js";
|
|
13
13
|
import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
|
|
14
14
|
import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agent/agent-scope.js";
|
|
15
|
-
import { buildSessionKey, init_session_key, sanitizeSegment } from "../routing/session-key.js";
|
|
16
|
-
import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
|
|
17
|
-
import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
|
|
18
15
|
import { init_paths, resolveConfigPath, resolveExtensionsDir } from "../config/paths.js";
|
|
16
|
+
import { prewarmModelRegistry } from "../providers/model-registry.js";
|
|
19
17
|
import { areExtensionsGloballyDisabled } from "../extensions/discover-extensions.js";
|
|
20
18
|
import { buildExtensionMetadataSnapshot } from "../extensions/extension-metadata-snapshot.js";
|
|
21
19
|
import { buildChannelCatalogForConfig, buildChannelCatalogFromSnapshot, init_channel_catalog_service } from "../channels/catalog/channel-catalog-service.js";
|
|
22
20
|
import { loadConfig, saveConfig } from "../config/loader.js";
|
|
23
|
-
import {
|
|
21
|
+
import { buildSessionKey, init_session_key, sanitizeSegment } from "../routing/session-key.js";
|
|
22
|
+
import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
|
|
24
23
|
import { init_providers, providers_exports } from "../providers/index.js";
|
|
24
|
+
import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
|
|
25
25
|
import { TaskRepository } from "../tasks/task-repository.js";
|
|
26
26
|
import { TaskConversationRepository } from "../tasks/task-conversation-repository.js";
|
|
27
27
|
import { getEmbeddedExecutionSession } from "../agent/embedded/execution-context.js";
|
|
@@ -152,10 +152,6 @@ var GatewayService = class {
|
|
|
152
152
|
notesService;
|
|
153
153
|
extensionLoader = null;
|
|
154
154
|
extensionMetadataSnapshot = null;
|
|
155
|
-
browserExtensionProvider = null;
|
|
156
|
-
browserExtensionRelease = null;
|
|
157
|
-
/** `${host}:${port}` when the gateway holds the extension bridge listener. */
|
|
158
|
-
browserExtensionBindKey = null;
|
|
159
155
|
heartbeatService = null;
|
|
160
156
|
sessionIndex;
|
|
161
157
|
running = false;
|
|
@@ -249,6 +245,7 @@ var GatewayService = class {
|
|
|
249
245
|
get browserAutomations() {
|
|
250
246
|
if (!this.browserAutomationService) this.browserAutomationService = createRuntimeBrowserAutomationService({
|
|
251
247
|
getConfig: () => this.config,
|
|
248
|
+
endpointTools: this.endpointTools,
|
|
252
249
|
emit: (type, payload) => this.emit(type, payload)
|
|
253
250
|
});
|
|
254
251
|
return this.browserAutomationService;
|
|
@@ -520,7 +517,6 @@ var GatewayService = class {
|
|
|
520
517
|
getChannelManager: () => this.channelManager,
|
|
521
518
|
getHeartbeatService: () => this.heartbeatService,
|
|
522
519
|
getExtensionLoader: () => this.extensionLoader,
|
|
523
|
-
reconcileBrowserExtensionServer: () => this.reconcileBrowserExtensionServer(),
|
|
524
520
|
reconcileMemoryMaintenanceAutomations: () => this.reconcileMemoryMaintenanceAutomations(),
|
|
525
521
|
getChannelsStatus: () => this.getChannelsStatus(),
|
|
526
522
|
emit: (type, payload) => this.emit(type, payload)
|
|
@@ -1099,7 +1095,6 @@ var GatewayService = class {
|
|
|
1099
1095
|
workspaceId: this.currentWorkspacePath
|
|
1100
1096
|
}) });
|
|
1101
1097
|
import("../browser/providers/browser-ext-install.js").then(({ ensureBrowserExtensionOnStartup }) => ensureBrowserExtensionOnStartup(this.config)).catch((err) => log.warn({ err }, "Browser extension artifact ensure failed"));
|
|
1102
|
-
await trace.measure("browser-extension.start", () => this.startBrowserExtensionServerIfNeeded());
|
|
1103
1098
|
this.agentService.start().catch((err) => {
|
|
1104
1099
|
log.error({ err }, "Agent service error");
|
|
1105
1100
|
});
|
|
@@ -1260,12 +1255,6 @@ var GatewayService = class {
|
|
|
1260
1255
|
this.connectedKnowledgeCoordinator?.stop();
|
|
1261
1256
|
this.connectedKnowledgeCoordinator = null;
|
|
1262
1257
|
await this.browserAutomationService?.shutdown();
|
|
1263
|
-
if (this.browserExtensionRelease) {
|
|
1264
|
-
await this.browserExtensionRelease();
|
|
1265
|
-
this.browserExtensionRelease = null;
|
|
1266
|
-
}
|
|
1267
|
-
this.browserExtensionProvider = null;
|
|
1268
|
-
this.browserExtensionBindKey = null;
|
|
1269
1258
|
registerClarificationChannelRuntime(null);
|
|
1270
1259
|
this.connectionRecovery.stop();
|
|
1271
1260
|
this.agentRunner.disposeClarifications();
|
|
@@ -1288,73 +1277,6 @@ var GatewayService = class {
|
|
|
1288
1277
|
closeXopcDatabase();
|
|
1289
1278
|
log.debug("Gateway service stopped");
|
|
1290
1279
|
}
|
|
1291
|
-
/** Start the browser extension WebSocket server when its driver is active. */
|
|
1292
|
-
async startBrowserExtensionServerIfNeeded() {
|
|
1293
|
-
await this.reconcileBrowserExtensionServer();
|
|
1294
|
-
}
|
|
1295
|
-
/**
|
|
1296
|
-
* Start/stop/rebind the Chrome extension bridge.
|
|
1297
|
-
* PATCH saves update config in memory without re-running gateway startup, so this must run on save too.
|
|
1298
|
-
*/
|
|
1299
|
-
async reconcileBrowserExtensionServer() {
|
|
1300
|
-
const driver = this.config.browser.driver;
|
|
1301
|
-
const bridgeConfig = this.config.browser.enabled && driver.kind === "extension" ? {
|
|
1302
|
-
host: "127.0.0.1",
|
|
1303
|
-
port: 19820,
|
|
1304
|
-
connectionTimeout: this.config.browser.limits.actionTimeoutMs,
|
|
1305
|
-
commandTimeout: this.config.browser.limits.actionTimeoutMs
|
|
1306
|
-
} : null;
|
|
1307
|
-
if (!bridgeConfig) {
|
|
1308
|
-
if (this.browserExtensionRelease) {
|
|
1309
|
-
await this.browserExtensionRelease();
|
|
1310
|
-
this.browserExtensionRelease = null;
|
|
1311
|
-
this.browserExtensionProvider = null;
|
|
1312
|
-
this.browserExtensionBindKey = null;
|
|
1313
|
-
log.debug("Browser extension WebSocket server stopped because its driver is inactive");
|
|
1314
|
-
}
|
|
1315
|
-
return;
|
|
1316
|
-
}
|
|
1317
|
-
const { port, host, connectionTimeout, commandTimeout } = bridgeConfig;
|
|
1318
|
-
const bindKey = `${host}:${port}`;
|
|
1319
|
-
if (this.browserExtensionRelease && this.browserExtensionBindKey === bindKey) return;
|
|
1320
|
-
if (this.browserExtensionRelease) {
|
|
1321
|
-
await this.browserExtensionRelease();
|
|
1322
|
-
this.browserExtensionRelease = null;
|
|
1323
|
-
this.browserExtensionProvider = null;
|
|
1324
|
-
this.browserExtensionBindKey = null;
|
|
1325
|
-
}
|
|
1326
|
-
try {
|
|
1327
|
-
const { acquireExtensionBrowserServer } = await import("../browser/providers/extension-ws-acquire.js");
|
|
1328
|
-
const { provider, release } = await acquireExtensionBrowserServer({
|
|
1329
|
-
port,
|
|
1330
|
-
host,
|
|
1331
|
-
connectionTimeout,
|
|
1332
|
-
commandTimeout
|
|
1333
|
-
});
|
|
1334
|
-
this.browserExtensionProvider = provider;
|
|
1335
|
-
this.browserExtensionRelease = release;
|
|
1336
|
-
this.browserExtensionBindKey = bindKey;
|
|
1337
|
-
log.info({
|
|
1338
|
-
port,
|
|
1339
|
-
host
|
|
1340
|
-
}, "Browser extension WS server started");
|
|
1341
|
-
} catch (err) {
|
|
1342
|
-
if ((err && typeof err === "object" && "code" in err ? err.code : void 0) === "EADDRINUSE") {
|
|
1343
|
-
log.warn({
|
|
1344
|
-
err,
|
|
1345
|
-
phase: "browser_extension_ws",
|
|
1346
|
-
bindPort: port,
|
|
1347
|
-
bindHost: host,
|
|
1348
|
-
hint: "Another process holds the browser extension bridge port 19820. Stop it before starting xopc."
|
|
1349
|
-
}, `Browser extension WS server port is already in use: ${host}:${port}`);
|
|
1350
|
-
return;
|
|
1351
|
-
}
|
|
1352
|
-
log.error({
|
|
1353
|
-
err,
|
|
1354
|
-
phase: "browser_extension_ws"
|
|
1355
|
-
}, `Failed to start browser extension WS server: ${err instanceof Error ? err.message : String(err)}`);
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
1280
|
/**
|
|
1359
1281
|
* Start processing outbound messages and send through channels
|
|
1360
1282
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { init_sync_provider_auth, resolveProviderApiKeyForAgentSync } from "../../auth/sync-provider-auth.js";
|
|
2
1
|
import { getApiKeyFromEnv, init_env_keys } from "../env-keys.js";
|
|
2
|
+
import { init_sync_provider_auth, resolveProviderApiKeyForAgentSync } from "../../auth/sync-provider-auth.js";
|
|
3
3
|
import { getDefaultAuthProfileStore } from "./auth-profile-store.js";
|
|
4
4
|
//#region src/providers/auth-runtime/resolve-auth.ts
|
|
5
5
|
init_env_keys();
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { __esmMin, __exportAll } from "../../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
|
|
3
|
-
import { getModelOAuthProviderIds, init_registry } from "../auth/oauth/registry.js";
|
|
4
|
-
import { hasProviderAuthOnDiskSync, init_sync_provider_auth } from "../auth/sync-provider-auth.js";
|
|
5
3
|
import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "./env-keys.js";
|
|
6
4
|
import { init_model_ref, splitProviderModelRef } from "./model-ref.js";
|
|
7
5
|
import { ModelRegistry, getModelRegistry, init_model_registry, prewarmModelRegistry, resetModelRegistry } from "./model-registry.js";
|
|
6
|
+
import { getModelOAuthProviderIds, init_registry } from "../auth/oauth/registry.js";
|
|
8
7
|
import { CredentialResolver, hasCredentials, init_credentials } from "../auth/credentials.js";
|
|
8
|
+
import { hasProviderAuthOnDiskSync, init_sync_provider_auth } from "../auth/sync-provider-auth.js";
|
|
9
9
|
import { EXTENSION_PROVIDER_BASE_URL, init_constants } from "./constants.js";
|
|
10
10
|
import { applyOfficialModelMetadataCorrections, getSupplementalModels, init_model_supplements } from "./model-supplements.js";
|
|
11
11
|
import { getProviderRegistry, init_plugin_registry } from "./plugin-registry.js";
|