@1presence/bridge 0.1.6 → 0.1.8

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/README.md CHANGED
@@ -35,18 +35,6 @@ rm ~/.1presence/auth.json
35
35
 
36
36
  The next run will prompt you to sign in again. If authentication fails (e.g. an expired token), the bridge clears credentials automatically and exits with an error.
37
37
 
38
- ## Environment
39
-
40
- | Variable | Default | Description |
41
- |---|---|---|
42
- | `BRIDGE_GATEWAY_URL` | `https://api.1presence.com` | Override for self-hosted or local dev |
43
-
44
- ## Local development
45
-
46
- ```bash
47
- BRIDGE_GATEWAY_URL=http://localhost:8080 npx @1presence/bridge
48
- ```
49
-
50
38
  ## Troubleshooting
51
39
 
52
40
  **`claude CLI not found`** — Install Claude Code from [claude.ai/code](https://claude.ai/code) and make sure the `claude` command is on your PATH.
package/dist/auth.js CHANGED
@@ -67,7 +67,7 @@ function openBrowser(url) {
67
67
  console.error('Could not open browser automatically. Please open this URL manually:\n' + url);
68
68
  });
69
69
  }
70
- function runBrowserAuthFlow(gatewayUrl) {
70
+ function runBrowserAuthFlow(gatewayUrl, pwaUrl) {
71
71
  return new Promise((resolve, reject) => {
72
72
  const server = (0, http_1.createServer)((req, res) => {
73
73
  // CORS headers so the PWA (https) can POST to http://localhost
@@ -114,8 +114,7 @@ function runBrowserAuthFlow(gatewayUrl) {
114
114
  });
115
115
  server.listen(0, '127.0.0.1', () => {
116
116
  const { port } = server.address();
117
- const base = gatewayUrl.replace(/^wss?:/, 'https:').replace(/\/$/, '');
118
- const authUrl = `${base}/cli-auth?port=${port}`;
117
+ const authUrl = `${pwaUrl.replace(/\/$/, '')}/cli-auth?port=${port}`;
119
118
  console.log('\nOpening browser for sign-in…');
120
119
  console.log(`If the browser doesn't open, visit:\n ${authUrl}\n`);
121
120
  openBrowser(authUrl);
@@ -127,12 +126,12 @@ function runBrowserAuthFlow(gatewayUrl) {
127
126
  });
128
127
  }
129
128
  // ─── Public API ───────────────────────────────────────────────────────────────
130
- async function getValidAuth(gatewayUrl) {
129
+ async function getValidAuth(gatewayUrl, pwaUrl) {
131
130
  const cached = loadCachedAuth();
132
131
  if (cached)
133
132
  return cached;
134
133
  console.log('Sign-in required.');
135
- const auth = await runBrowserAuthFlow(gatewayUrl);
134
+ const auth = await runBrowserAuthFlow(gatewayUrl, pwaUrl);
136
135
  saveCachedAuth(auth);
137
136
  return auth;
138
137
  }
package/dist/claude.js CHANGED
@@ -31,6 +31,8 @@ function spawnClaude(params) {
31
31
  active.set(conversationId, proc);
32
32
  let sessionIdExtracted = false;
33
33
  let messageCount = 0;
34
+ let costUsd = 0;
35
+ let usage = null;
34
36
  let buffer = '';
35
37
  proc.stdout.on('data', (chunk) => {
36
38
  buffer += chunk.toString('utf-8');
@@ -59,6 +61,14 @@ function spawnClaude(params) {
59
61
  // Count complete assistant turns
60
62
  if (type === 'assistant')
61
63
  messageCount++;
64
+ // Extract cost + usage from the final result event
65
+ if (type === 'result') {
66
+ if (typeof event['cost_usd'] === 'number')
67
+ costUsd = event['cost_usd'];
68
+ const u = event['usage'];
69
+ if (u)
70
+ usage = { input_tokens: u['input_tokens'] ?? 0, output_tokens: u['output_tokens'] ?? 0 };
71
+ }
62
72
  onEvent(event);
63
73
  }
64
74
  });
@@ -81,7 +91,7 @@ function spawnClaude(params) {
81
91
  onError(`claude exited with code ${code}`);
82
92
  }
83
93
  else {
84
- onDone(messageCount);
94
+ onDone(messageCount, costUsd, usage);
85
95
  }
86
96
  });
87
97
  proc.on('error', (err) => {
package/dist/index.js CHANGED
@@ -10,10 +10,13 @@ const os_1 = require("os");
10
10
  const path_1 = require("path");
11
11
  const auth_1 = require("./auth");
12
12
  const claude_1 = require("./claude");
13
+ const package_json_1 = require("../package.json");
13
14
  // ─── Config ───────────────────────────────────────────────────────────────────
14
15
  const GATEWAY_URL = process.env.BRIDGE_GATEWAY_URL ?? 'https://api.1presence.com';
15
16
  const GATEWAY_WS = GATEWAY_URL.replace(/^https?:/, 'wss:').replace(/\/$/, '') + '/bridge';
16
17
  const GATEWAY_HTTP = GATEWAY_URL.replace(/^wss?:/, 'https:').replace(/\/$/, '');
18
+ // PWA hosts the /cli-auth sign-in page; strip 'api.' subdomain to derive it from gateway URL
19
+ const PWA_URL = process.env.BRIDGE_PWA_URL ?? GATEWAY_HTTP.replace('://api.', '://');
17
20
  // ─── In-memory state ──────────────────────────────────────────────────────────
18
21
  let currentAuth = null;
19
22
  // ─── Vault file fetch ─────────────────────────────────────────────────────────
@@ -72,23 +75,38 @@ function connect(auth, retryDelay = 1000) {
72
75
  if (msg.type !== 'message' || !msg.conversationId || !msg.text)
73
76
  return;
74
77
  const { conversationId, text, sessionId } = msg;
78
+ const ts = new Date().toLocaleTimeString();
79
+ const preview = text.length > 80 ? text.slice(0, 80) + '…' : text;
80
+ console.log(`[${ts}] ▶ ${preview}`);
81
+ let responding = false;
75
82
  (0, claude_1.spawnClaude)({
76
83
  conversationId,
77
84
  presenceSessionId: sessionId ?? null,
78
85
  text,
79
86
  uid: auth.uid,
80
87
  onEvent: (event) => {
88
+ if (!responding && event['type'] === 'assistant') {
89
+ responding = true;
90
+ console.log(`[${new Date().toLocaleTimeString()}] ◐ responding…`);
91
+ }
81
92
  if (ws.readyState === ws_1.default.OPEN) {
82
93
  ws.send(JSON.stringify({ type: 'stream', conversationId, event }));
83
94
  }
84
95
  },
85
- onDone: (messageCount) => {
96
+ onDone: (messageCount, costUsd, usage) => {
97
+ const parts = [];
98
+ if (usage)
99
+ parts.push(`in:${usage.input_tokens} out:${usage.output_tokens}`);
100
+ if (costUsd > 0)
101
+ parts.push(`$${costUsd.toFixed(4)}`);
102
+ const suffix = parts.length ? ` (${parts.join(' ')})` : '';
103
+ console.log(`[${new Date().toLocaleTimeString()}] ✓ done${suffix}`);
86
104
  if (ws.readyState === ws_1.default.OPEN) {
87
- ws.send(JSON.stringify({ type: 'done', conversationId, messageCount, costUsd: 0 }));
105
+ ws.send(JSON.stringify({ type: 'done', conversationId, messageCount, costUsd }));
88
106
  }
89
107
  },
90
108
  onError: (message) => {
91
- console.error(`[bridge] conversation ${conversationId}: ${message}`);
109
+ console.error(`[${new Date().toLocaleTimeString()}] ${message}`);
92
110
  if (ws.readyState === ws_1.default.OPEN) {
93
111
  ws.send(JSON.stringify({ type: 'error', conversationId, message }));
94
112
  }
@@ -123,9 +141,9 @@ function connect(auth, retryDelay = 1000) {
123
141
  }
124
142
  // ─── Main ─────────────────────────────────────────────────────────────────────
125
143
  async function main() {
126
- console.log('1Presence Bridge\n');
144
+ console.log(`1Presence Bridge v${package_json_1.version}\n`);
127
145
  // Auth
128
- const auth = await (0, auth_1.getValidAuth)(GATEWAY_HTTP);
146
+ const auth = await (0, auth_1.getValidAuth)(GATEWAY_HTTP, PWA_URL);
129
147
  currentAuth = auth;
130
148
  // Write system prompt + MCP config
131
149
  process.stdout.write('Setting up…');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1presence/bridge",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Run 1Presence on your Mac and use your Claude.ai Pro subscription from any device",
5
5
  "bin": {
6
6
  "1presence-bridge": "dist/index.js"