@1presence/bridge 0.77.0 → 0.79.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.
Files changed (2) hide show
  1. package/dist/claude.js +45 -16
  2. package/package.json +1 -1
package/dist/claude.js CHANGED
@@ -117,6 +117,21 @@ function joinErrorDetail(...parts) {
117
117
  const SDK_STDERR_ERROR_RE = /\b(error|exception|fail(?:ed|ure)?|invalid|unauthor|forbidden|refus|denied|40[0-9]|429|5\d\d|overloaded|rate.?limit)\b/i;
118
118
  const REMOTE_MCP_SERVER_NAME = '1presence';
119
119
  const MCP_SESSION_EXPIRED_RE = /session not found or expired|Error POSTing to endpoint \(HTTP 404\)/i;
120
+ const MCP_TRANSPORT_DEAD_RE = /SSE (?:stream|error)|not connected|connection (?:closed|error|reset|refused|dropped)|dropped connection|socket hang up|ECONNRESET|ECONNREFUSED|ETIMEDOUT|EPIPE|fetch failed|terminated|transport (?:closed|error)|request timed out|-32001|\(HTTP 50\d\)/i;
121
+ const OUTBOUND_NETWORK_TOOLS = new Set([
122
+ 'mcp__1presence__web_fetch',
123
+ 'mcp__1presence__web_search',
124
+ ]);
125
+ export function shouldReconnectRemoteMcp(args) {
126
+ const { toolName, isError, text } = args;
127
+ if (MCP_SESSION_EXPIRED_RE.test(text))
128
+ return true;
129
+ if (!isError || !toolName.startsWith('mcp__1presence__'))
130
+ return false;
131
+ if (OUTBOUND_NETWORK_TOOLS.has(toolName))
132
+ return false;
133
+ return MCP_TRANSPORT_DEAD_RE.test(text);
134
+ }
120
135
  function toolResultText(content) {
121
136
  if (typeof content === 'string')
122
137
  return content;
@@ -361,22 +376,29 @@ export function spawnClaude(params) {
361
376
  process.stderr.write('\n');
362
377
  }
363
378
  }
364
- if ((verbose || debug) && type === 'user') {
379
+ if (type === 'user') {
365
380
  const msg = event['message'];
366
381
  const content = msg?.['content'];
367
382
  if (Array.isArray(content)) {
368
383
  for (const block of content) {
369
- if (block['type'] === 'tool_result') {
370
- const id = block['tool_use_id'] ?? '';
371
- const out = block['content'];
372
- if (debug) {
373
- const name = toolNames.get(id) ?? id ?? 'result';
374
- const errFlag = block['is_error'] ? ' [error]' : '';
375
- debugBlock(`result ← ${name}${errFlag}`, SECTION_COLORS.result, formatPayload(out));
376
- }
377
- else {
378
- process.stderr.write(paint(SECTION_COLORS.result, `[bridge:verbose] ─── output ${id} ───\n${formatPayload(out)}\n[bridge:verbose] ─── end output ───`) + '\n');
379
- }
384
+ if (block['type'] !== 'tool_result')
385
+ continue;
386
+ const id = block['tool_use_id'] ?? '';
387
+ const out = block['content'];
388
+ const name = toolNames.get(id) ?? id ?? 'result';
389
+ if (block['is_error'] && !verbose && !debug) {
390
+ const detail = toolResultText(out).replace(/\s+/g, ' ').trim();
391
+ const shown = detail.length > 400 ? `${detail.slice(0, 400)}…` : detail;
392
+ process.stderr.write(paint(SECTION_COLORS.result, `[bridge] tool error ← ${name}: ${shown || 'no detail'}`) + '\n');
393
+ }
394
+ if (!verbose && !debug)
395
+ continue;
396
+ if (debug) {
397
+ const errFlag = block['is_error'] ? ' [error]' : '';
398
+ debugBlock(`result ← ${name}${errFlag}`, SECTION_COLORS.result, formatPayload(out));
399
+ }
400
+ else {
401
+ process.stderr.write(paint(SECTION_COLORS.result, `[bridge:verbose] ─── output ${id} ───\n${formatPayload(out)}\n[bridge:verbose] ─── end output ───`) + '\n');
380
402
  }
381
403
  }
382
404
  }
@@ -453,7 +475,6 @@ export function spawnClaude(params) {
453
475
  mcpServers: mcpServers,
454
476
  strictMcpConfig: true,
455
477
  settingSources: [],
456
- allowedTools: ['mcp__1presence__*', 'mcp__local__read_session_file'],
457
478
  canUseTool,
458
479
  tools: [],
459
480
  cwd: BRIDGE_CWD,
@@ -478,7 +499,7 @@ export function spawnClaude(params) {
478
499
  return;
479
500
  mcpReconnecting = true;
480
501
  lastMcpReconnectAt = now;
481
- process.stderr.write(paint(SECTION_COLORS.result, '[bridge] remote MCP session expired — reconnecting and retrying') + '\n');
502
+ process.stderr.write(paint(SECTION_COLORS.result, '[bridge] remote MCP connection lost — reconnecting and retrying') + '\n');
482
503
  onNotice?.('Reconnecting to 1Presence tools…');
483
504
  void q.reconnectMcpServer(REMOTE_MCP_SERVER_NAME)
484
505
  .then(() => process.stderr.write(paint(SECTION_COLORS.result, '[bridge] remote MCP reconnected') + '\n'))
@@ -541,8 +562,16 @@ export function spawnClaude(params) {
541
562
  const content = um.message?.['content'];
542
563
  if (Array.isArray(content)) {
543
564
  for (const block of content) {
544
- if (block && typeof block === 'object' && block['type'] === 'tool_result'
545
- && MCP_SESSION_EXPIRED_RE.test(toolResultText(block['content']))) {
565
+ if (!block || typeof block !== 'object')
566
+ continue;
567
+ const b = block;
568
+ if (b['type'] !== 'tool_result')
569
+ continue;
570
+ if (shouldReconnectRemoteMcp({
571
+ toolName: toolNames.get(b['tool_use_id'] ?? '') ?? '',
572
+ isError: b['is_error'] === true,
573
+ text: toolResultText(b['content']),
574
+ })) {
546
575
  maybeReconnectRemoteMcp(q);
547
576
  break;
548
577
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1presence/bridge",
3
- "version": "0.77.0",
3
+ "version": "0.79.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",