bridgerator 1.1.5 → 1.1.6

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.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "bridgerator",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "bridgerator",
9
- "version": "1.1.5",
9
+ "version": "1.1.6",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@modelcontextprotocol/sdk": "^1.29.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bridgerator",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "description": "Connect ChatGPT to your Windows PC: files, search and terminal through an outbound-only bridge with folder limits. No inbound ports, no admin rights.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/bridge.mjs CHANGED
@@ -9,7 +9,7 @@ import { createRequire } from 'node:module';
9
9
  import WebSocket from 'ws';
10
10
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
11
11
  import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
12
- import { createPolicy, debrand, debrandResult, TERMINAL_TOOLS, ALWAYS_HIDDEN } from './policy.mjs';
12
+ import { createPolicy, debrand, debrandResult, ourUi, engineUi, TERMINAL_TOOLS, ALWAYS_HIDDEN } from './policy.mjs';
13
13
  import { showNotice } from './notice.mjs';
14
14
  import { usage } from './telemetry.mjs';
15
15
  import { createGate, askOnPc, CONFIRM_TOOL_DEFS } from './confirm.mjs';
@@ -152,7 +152,7 @@ export async function startDesktopCommander(cfg, log = console.log, { ask: askAr
152
152
  // Snapshots + Undo (on by default) in %LOCALAPPDATA%\Bridgerator\snapshots (given by the CLI).
153
153
  const snapCfg = () => ({ ...SNAP_DEFAULTS, ...(cfg.snapshots || {}) });
154
154
  const snapshots = cfg.snapshotsDir ? createSnapshots(cfg.snapshotsDir, { limits: snapCfg, log }) : null;
155
- const visible = [...tools.filter(listed).map(debrand), ...CONFIRM_TOOL_DEFS, SETUP_TOOL_DEF, ...(cfg.configFile ? [SETTINGS_TOOL_DEF] : []), ...(cfg.configDir ? QUEUE_TOOL_DEFS : []), ...(snapshots ? [UNDO_TOOL_DEF] : []), ...extra.defs.filter(policy.visible)].map(shorten);
155
+ const visible = [...tools.filter(listed).map(debrand), ...CONFIRM_TOOL_DEFS, SETUP_TOOL_DEF, ...(cfg.configFile ? [SETTINGS_TOOL_DEF] : []), ...(cfg.configDir ? QUEUE_TOOL_DEFS : []), ...(snapshots ? [UNDO_TOOL_DEF] : []), ...extra.defs.filter(policy.visible)].map(shorten).map(ourUi);
156
156
  const virtual = new Set(CONFIRM_TOOL_DEFS.map((t) => t.name));
157
157
  // namePending: a computer name given on this PC not yet accepted by the relay — kept in config.json too,
158
158
  // so a restart before the next link does not lose it; cleared by nameSent() (welcome / live mode message).
@@ -197,7 +197,7 @@ export async function startDesktopCommander(cfg, log = console.log, { ask: askAr
197
197
  return gate.accept(s ? { enabled: s.enabled } : {});
198
198
  };
199
199
  // MCP Apps widgets (file preview, config view) — served to ChatGPT through the relay as-is.
200
- const resources = ((await client.listResources().catch(() => ({ resources: [] }))).resources || []).map(debrand);
200
+ const resources = ourUi(((await client.listResources().catch(() => ({ resources: [] }))).resources || []).map(debrand));
201
201
  const resourceUris = new Set(resources.map((r) => r.uri));
202
202
  log(`[bridgerator] engine up: ${visible.length} tools; allowed=${JSON.stringify(cfg.allowedDirectories || [])} excluded=${JSON.stringify(cfg.deniedDirectories || [])} read-only=${JSON.stringify(cfg.readOnlyDirectories || [])} confirm=${gate.mode()}`);
203
203
  if (!(cfg.allowedDirectories || []).length) log('[bridgerator] folders: all (no list), except the always-blocked ones');
@@ -492,8 +492,9 @@ export async function startDesktopCommander(cfg, log = console.log, { ask: askAr
492
492
  return { ...rest, confirm: { enabled: confirm.enabled, ...confirm.ask, timeoutSeconds: confirm.timeoutSec }, telemetryEnabled: telemetry };
493
493
  };
494
494
  async function readResource(uri) {
495
- if (!resourceUris.has(uri)) return { error: 'unknown resource' };
496
- try { return { result: debrand(await client.readResource({ uri })) }; } catch (e) { return { error: String(e?.message || e) }; }
495
+ // The old ui://desktop-commander/… still works: ChatGPT and the relay's offline list may have cached it.
496
+ if (!resourceUris.has(ourUi(String(uri)))) return { error: 'unknown resource' };
497
+ try { return { result: ourUi(debrand(await client.readResource({ uri: engineUi(uri) }))) }; } catch (e) { return { error: String(e?.message || e) }; }
497
498
  }
498
499
  // Requests of the Bridgerator window (tray helper). Made by the person at the PC: no extra prompt.
499
500
  // Theme for our pop-ups = the window's theme (Settings → Appearance); sound / style from Notifications.
package/src/policy.mjs CHANGED
@@ -274,6 +274,11 @@ export function createPolicy(cfg = {}) {
274
274
  // The bundled engine's own name and links are not shown to the user: tool titles/descriptions and
275
275
  // widget HTML say Bridgerator. Tool RESULTS are never rewritten (they are the user's own data).
276
276
  const BRAND = [[/"DC: \.\.\." or /g, ''], [/Desktop ?Commander/g, 'Bridgerator'], [/https?:\/\/(www\.)?desktopcommander\.app[^\s"'\)<]*/g, 'https://bridgerator.recondeck.com']];
277
+ // The engine's widget URIs and their in-page state key carry its name: ChatGPT sees them in tool _meta and resources.
278
+ // Shown as ui://bridgerator/…, mapped back when a resource is read (owner 26.10: "как будто наш код").
279
+ const UI_ENGINE = 'ui://desktop-commander/', UI_OURS = 'ui://bridgerator/';
280
+ export const ourUi = (v) => JSON.parse(JSON.stringify(v).replaceAll(UI_ENGINE, UI_OURS).replaceAll('desktop-commander:widget-state', 'bridgerator:widget-state'));
281
+ export const engineUi = (uri) => String(uri).replace(UI_OURS, UI_ENGINE);
277
282
  export function debrand(v) {
278
283
  if (typeof v === 'string') return BRAND.reduce((s, [re, to]) => s.replace(re, to), v);
279
284
  if (Array.isArray(v)) return v.map(debrand);