@delt/claude-alarm 0.9.0 → 0.9.1

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.
@@ -871,7 +871,7 @@
871
871
  <div class="token-overlay hidden" id="tokenOverlay">
872
872
  <div class="token-form">
873
873
  <h2>Authentication Required</h2>
874
- <p>Enter the hub token to connect. Find it by running: <code>claude-alarm token</code></p>
874
+ <p>Enter the hub token to connect. Run <code>claude-alarm token</code>, or open the login link printed by <code>claude-alarm hub start</code>.</p>
875
875
  <input type="text" id="tokenInput" placeholder="Paste token here..." autocomplete="off">
876
876
  <button id="tokenSubmit">Connect</button>
877
877
  <div class="token-error" id="tokenError">Connection failed. Check your token.</div>
@@ -1026,7 +1026,6 @@
1026
1026
  selectedSession: null,
1027
1027
  messages: {},
1028
1028
  notifications: [],
1029
- token: null,
1030
1029
  pendingImage: null,
1031
1030
  unread: {},
1032
1031
  waitingReply: {},
@@ -1291,25 +1290,28 @@
1291
1290
  initTheme();
1292
1291
 
1293
1292
  // --- Token handling ---
1294
- function getToken() {
1295
- const params = new URLSearchParams(location.search);
1296
- const urlToken = params.get('token');
1297
- if (urlToken) {
1298
- sessionStorage.setItem('claude-alarm-token', urlToken);
1299
- return urlToken;
1293
+ async function checkAuth() {
1294
+ try {
1295
+ return (await fetch('/api/status')).status !== 401;
1296
+ } catch {
1297
+ return true;
1300
1298
  }
1301
- return sessionStorage.getItem('claude-alarm-token');
1302
1299
  }
1303
1300
 
1304
1301
  function showTokenForm() { $('#tokenOverlay').classList.remove('hidden'); }
1305
1302
  function hideTokenForm() { $('#tokenOverlay').classList.add('hidden'); }
1306
1303
 
1307
- $('#tokenSubmit').addEventListener('click', () => {
1304
+ $('#tokenSubmit').addEventListener('click', async () => {
1308
1305
  const token = $('#tokenInput').value.trim();
1309
1306
  if (!token) return;
1310
- state.token = token;
1311
- sessionStorage.setItem('claude-alarm-token', token);
1307
+ const res = await fetch('/api/login', {
1308
+ method: 'POST',
1309
+ headers: { 'Content-Type': 'application/json' },
1310
+ body: JSON.stringify({ token }),
1311
+ }).catch(() => null);
1312
+ if (!res || !res.ok) { $('#tokenError').style.display = 'block'; return; }
1312
1313
  $('#tokenError').style.display = 'none';
1314
+ $('#tokenInput').value = '';
1313
1315
  hideTokenForm();
1314
1316
  connect();
1315
1317
  });
@@ -1320,25 +1322,23 @@
1320
1322
  // --- WebSocket ---
1321
1323
  function connect() {
1322
1324
  const proto = location.protocol === 'https:' ? 'wss' : 'ws';
1323
- const tokenQuery = state.token ? `?token=${encodeURIComponent(state.token)}` : '';
1324
- const ws = new WebSocket(`${proto}://${location.host}/ws/dashboard${tokenQuery}`);
1325
+ const ws = new WebSocket(`${proto}://${location.host}/ws/dashboard`);
1326
+ let opened = false;
1325
1327
 
1326
1328
  ws.onopen = () => {
1329
+ opened = true;
1327
1330
  state.ws = ws;
1328
1331
  hideTokenForm();
1329
1332
  $('#connDot').classList.add('connected');
1330
1333
  $('#connLabel').textContent = 'Connected';
1331
1334
  };
1332
- ws.onclose = () => {
1335
+ ws.onclose = async () => {
1333
1336
  state.ws = null;
1334
1337
  $('#connDot').classList.remove('connected');
1335
1338
  $('#connLabel').textContent = 'Disconnected';
1339
+ if (!opened && !(await checkAuth())) { showTokenForm(); return; }
1336
1340
  setTimeout(connect, 3000);
1337
1341
  };
1338
- ws.onerror = () => {
1339
- if (!state.token) { showTokenForm(); } else { $('#tokenError').style.display = 'block'; showTokenForm(); }
1340
- ws.close();
1341
- };
1342
1342
  ws.onmessage = (e) => { try { handleMessage(JSON.parse(e.data)); } catch {} };
1343
1343
  }
1344
1344
 
@@ -2128,16 +2128,14 @@
2128
2128
  $('#settingsToggle').addEventListener('click', async () => {
2129
2129
  // Load webhook data
2130
2130
  try {
2131
- const tokenQuery = state.token ? `?token=${encodeURIComponent(state.token)}` : '';
2132
- const res = await fetch(`/api/webhooks${tokenQuery}`);
2131
+ const res = await fetch(`/api/webhooks`);
2133
2132
  const data = await res.json();
2134
2133
  webhookData = data.webhooks || [];
2135
2134
  } catch { webhookData = []; }
2136
2135
  renderWebhooks();
2137
2136
  // Load telegram data
2138
2137
  try {
2139
- const tokenQuery = state.token ? `?token=${encodeURIComponent(state.token)}` : '';
2140
- const res = await fetch(`/api/telegram${tokenQuery}`);
2138
+ const res = await fetch(`/api/telegram`);
2141
2139
  const data = await res.json();
2142
2140
  const tg = data.telegram || {};
2143
2141
  if (!$('#tgBotToken').value || $('#tgBotToken').value.includes('...')) {
@@ -2172,8 +2170,7 @@
2172
2170
  $('#webhookSave').addEventListener('click', async () => {
2173
2171
  const valid = webhookData.filter(w => w.url.trim());
2174
2172
  try {
2175
- const tokenQuery = state.token ? `?token=${encodeURIComponent(state.token)}` : '';
2176
- await fetch(`/api/webhooks${tokenQuery}`, {
2173
+ await fetch(`/api/webhooks`, {
2177
2174
  method: 'POST',
2178
2175
  headers: { 'Content-Type': 'application/json' },
2179
2176
  body: JSON.stringify({ webhooks: valid }),
@@ -2248,8 +2245,7 @@
2248
2245
  $('#tgDetectStatus').textContent = 'Detecting...';
2249
2246
  $('#tgChatList').innerHTML = '';
2250
2247
  try {
2251
- const tokenQuery = state.token ? `?token=${encodeURIComponent(state.token)}` : '';
2252
- const res = await fetch(`/api/telegram/detect${tokenQuery}`, {
2248
+ const res = await fetch(`/api/telegram/detect`, {
2253
2249
  method: 'POST',
2254
2250
  headers: { 'Content-Type': 'application/json' },
2255
2251
  body: JSON.stringify({ botToken }),
@@ -2286,8 +2282,7 @@
2286
2282
  const chatId = $('#tgChatId').value.trim();
2287
2283
  if (!botToken || !chatId) { showTgStatus('Bot Token and Chat ID are required.', false); return; }
2288
2284
  try {
2289
- const tokenQuery = state.token ? `?token=${encodeURIComponent(state.token)}` : '';
2290
- const res = await fetch(`/api/telegram/test${tokenQuery}`, {
2285
+ const res = await fetch(`/api/telegram/test`, {
2291
2286
  method: 'POST',
2292
2287
  headers: { 'Content-Type': 'application/json' },
2293
2288
  body: JSON.stringify({ botToken, chatId }),
@@ -2306,8 +2301,7 @@
2306
2301
  if (!botToken || !chatId) { showTgStatus('Bot Token and Chat ID are required.', false); return; }
2307
2302
  if (botToken.includes('...')) { showTgStatus('Bot Token is masked. Please enter the full token.', false); return; }
2308
2303
  try {
2309
- const tokenQuery = state.token ? `?token=${encodeURIComponent(state.token)}` : '';
2310
- await fetch(`/api/telegram${tokenQuery}`, {
2304
+ await fetch(`/api/telegram`, {
2311
2305
  method: 'POST',
2312
2306
  headers: { 'Content-Type': 'application/json' },
2313
2307
  body: JSON.stringify({ telegram: { botToken, chatId, enabled } }),
@@ -2335,8 +2329,7 @@
2335
2329
  document.querySelector('.sessions-panel').classList.add('mobile-active');
2336
2330
  }
2337
2331
 
2338
- state.token = getToken();
2339
- connect();
2332
+ checkAuth().then((ok) => (ok ? connect() : showTokenForm()));
2340
2333
  })();
2341
2334
  </script>
2342
2335
  </body>