@1presence/bridge 0.83.0 → 0.85.0

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/claude.js CHANGED
@@ -127,16 +127,25 @@ const PERMISSION_TRANSPORT_DEAD_RE = /Tool permission request failed/i;
127
127
  export function isPermissionTransportFailure(text) {
128
128
  return PERMISSION_TRANSPORT_DEAD_RE.test(text);
129
129
  }
130
+ const MCP_TOOL_UNREGISTERED_RE = /No such tool available:\s*mcp__1presence__/i;
130
131
  export function shouldReconnectRemoteMcp(args) {
131
132
  const { toolName, isError, text } = args;
132
133
  if (MCP_SESSION_EXPIRED_RE.test(text))
133
134
  return true;
135
+ if (MCP_TOOL_UNREGISTERED_RE.test(text))
136
+ return true;
134
137
  if (!isError || !toolName.startsWith('mcp__1presence__'))
135
138
  return false;
136
139
  if (OUTBOUND_NETWORK_TOOLS.has(toolName))
137
140
  return false;
138
141
  return MCP_TRANSPORT_DEAD_RE.test(text);
139
142
  }
143
+ export function assessRemoteMcpSurface(init) {
144
+ const entry = (init.mcp_servers ?? []).find((s) => s?.name === REMOTE_MCP_SERVER_NAME);
145
+ const status = entry?.status ?? 'absent';
146
+ const toolCount = (init.tools ?? []).filter((t) => t.startsWith('mcp__1presence__')).length;
147
+ return { status, toolCount, usable: status === 'connected' && toolCount > 0 };
148
+ }
140
149
  function toolResultText(content) {
141
150
  if (typeof content === 'string')
142
151
  return content;
@@ -245,11 +254,6 @@ export function spawnClaude(params) {
245
254
  }
246
255
  else {
247
256
  process.stderr.write(`[bridge] session ${presenceSessionId}\n`);
248
- const prompt = text.replace(/\s+/g, ' ').trim();
249
- if (prompt) {
250
- const shown = prompt.length > 300 ? `${prompt.slice(0, 300)}…` : prompt;
251
- process.stderr.write(paint(SECTION_COLORS.user, `[bridge] ▸ ${shown}`) + '\n');
252
- }
253
257
  }
254
258
  void vaultFileOpen;
255
259
  void clientCapabilities;
@@ -551,6 +555,28 @@ export function spawnClaude(params) {
551
555
  const event = { type: 'system', subtype: 'init', model: init.model, apiKeySource: init.apiKeySource, claude_code_version: init.claude_code_version };
552
556
  if (handleEvent(event))
553
557
  onEvent(event);
558
+ const surface = assessRemoteMcpSurface(m);
559
+ process.stderr.write(paint(surface.usable ? SECTION_COLORS.system : SECTION_COLORS.error, `[bridge] mcp surface: ${REMOTE_MCP_SERVER_NAME}=${surface.status}, ${surface.toolCount} tool(s)`) + '\n');
560
+ if (!surface.usable) {
561
+ let detail = '';
562
+ try {
563
+ const statuses = await q.mcpServerStatus();
564
+ const remote = statuses.find((st) => st.name === REMOTE_MCP_SERVER_NAME);
565
+ if (remote?.error)
566
+ detail = ` — ${remote.error.replace(/\s+/g, ' ').trim().slice(0, 300)}`;
567
+ }
568
+ catch { }
569
+ process.stderr.write(paint(SECTION_COLORS.error, `[bridge] FATAL no 1Presence tools this turn (${surface.status}) — ending the turn rather than answering blind${detail}`) + '\n');
570
+ if (surface.status === 'needs-auth' && !detail) {
571
+ process.stderr.write(paint(SECTION_COLORS.error, '[bridge] ↳ the server asked for OAuth, which Local Mode does not use — this is NOT a stale local token, and restarting will not clear it. The gateway is rejecting this account\'s token on /mcp.') + '\n');
572
+ }
573
+ active.delete(conversationId);
574
+ clearTimeout(inputReleaseTimer);
575
+ input.release();
576
+ abort.abort();
577
+ onError('Local Mode could not reach your 1Presence tools, so nothing was read or changed. Please send that again.', usage, extractedModel);
578
+ return;
579
+ }
554
580
  }
555
581
  else if (subtype === 'api_retry') {
556
582
  const r = m;
package/dist/index.js CHANGED
@@ -169,7 +169,7 @@ function writeMcpConfig(auth) {
169
169
  mcpServers: {
170
170
  '1presence': {
171
171
  type: 'sse',
172
- url: `${GATEWAY_HTTP}/mcp`,
172
+ url: `${GATEWAY_HTTP}/mcp/bridge`,
173
173
  headers: { Authorization: `Bearer ${token}` },
174
174
  alwaysLoad: true,
175
175
  },
@@ -539,7 +539,7 @@ function connect(auth, retryDelay = 1000) {
539
539
  const now = new Date();
540
540
  const ts = `${now.toLocaleDateString(undefined, { day: '2-digit', month: 'short' })} ${now.toLocaleTimeString()}`;
541
541
  const hist = Array.isArray(history) ? history : [];
542
- console.log(`[${ts}] ▶ ${text}${hist.length ? ` (history: ${hist.length} turn${hist.length === 1 ? '' : 's'})` : ''}`);
542
+ console.log(paint(SECTION_COLORS.user, `[${ts}] ▶ ${text}${hist.length ? ` (history: ${hist.length} turn${hist.length === 1 ? '' : 's'})` : ''}`));
543
543
  startTurnTimer();
544
544
  handleMessage(conversationId, text, sessionId ?? null, hist, auth, vaultFileOpen, clientCapabilities, syncedFolders, agentSlug, model).catch((err) => {
545
545
  stopTurnTimer();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1presence/bridge",
3
- "version": "0.83.0",
3
+ "version": "0.85.0",
4
4
  "description": "Run 1Presence on your Mac and use your Claude.ai Pro subscription from any device",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",