claude-relay 2.4.2 → 2.5.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 (75) hide show
  1. package/bin/cli.js +1 -2350
  2. package/package.json +7 -42
  3. package/LICENSE +0 -21
  4. package/README.md +0 -281
  5. package/lib/cli-sessions.js +0 -270
  6. package/lib/config.js +0 -222
  7. package/lib/daemon.js +0 -423
  8. package/lib/ipc.js +0 -112
  9. package/lib/pages.js +0 -714
  10. package/lib/project.js +0 -1224
  11. package/lib/public/app.js +0 -2157
  12. package/lib/public/apple-touch-icon.png +0 -0
  13. package/lib/public/css/base.css +0 -145
  14. package/lib/public/css/diff.css +0 -128
  15. package/lib/public/css/filebrowser.css +0 -1076
  16. package/lib/public/css/highlight.css +0 -144
  17. package/lib/public/css/input.css +0 -512
  18. package/lib/public/css/menus.css +0 -683
  19. package/lib/public/css/messages.css +0 -1159
  20. package/lib/public/css/overlays.css +0 -731
  21. package/lib/public/css/rewind.css +0 -529
  22. package/lib/public/css/sidebar.css +0 -794
  23. package/lib/public/favicon.svg +0 -26
  24. package/lib/public/icon-192.png +0 -0
  25. package/lib/public/icon-512.png +0 -0
  26. package/lib/public/icon-mono.svg +0 -19
  27. package/lib/public/index.html +0 -460
  28. package/lib/public/manifest.json +0 -27
  29. package/lib/public/modules/diff.js +0 -398
  30. package/lib/public/modules/events.js +0 -21
  31. package/lib/public/modules/filebrowser.js +0 -1375
  32. package/lib/public/modules/fileicons.js +0 -172
  33. package/lib/public/modules/icons.js +0 -54
  34. package/lib/public/modules/input.js +0 -578
  35. package/lib/public/modules/markdown.js +0 -149
  36. package/lib/public/modules/notifications.js +0 -643
  37. package/lib/public/modules/qrcode.js +0 -70
  38. package/lib/public/modules/rewind.js +0 -334
  39. package/lib/public/modules/sidebar.js +0 -628
  40. package/lib/public/modules/state.js +0 -3
  41. package/lib/public/modules/terminal.js +0 -658
  42. package/lib/public/modules/theme.js +0 -622
  43. package/lib/public/modules/tools.js +0 -1410
  44. package/lib/public/modules/utils.js +0 -56
  45. package/lib/public/style.css +0 -10
  46. package/lib/public/sw.js +0 -75
  47. package/lib/push.js +0 -125
  48. package/lib/sdk-bridge.js +0 -771
  49. package/lib/server.js +0 -577
  50. package/lib/sessions.js +0 -402
  51. package/lib/terminal-manager.js +0 -187
  52. package/lib/terminal.js +0 -24
  53. package/lib/themes/ayu-light.json +0 -9
  54. package/lib/themes/catppuccin-latte.json +0 -9
  55. package/lib/themes/catppuccin-mocha.json +0 -9
  56. package/lib/themes/claude-light.json +0 -9
  57. package/lib/themes/claude.json +0 -9
  58. package/lib/themes/dracula.json +0 -9
  59. package/lib/themes/everforest-light.json +0 -9
  60. package/lib/themes/everforest.json +0 -9
  61. package/lib/themes/github-light.json +0 -9
  62. package/lib/themes/gruvbox-dark.json +0 -9
  63. package/lib/themes/gruvbox-light.json +0 -9
  64. package/lib/themes/monokai.json +0 -9
  65. package/lib/themes/nord-light.json +0 -9
  66. package/lib/themes/nord.json +0 -9
  67. package/lib/themes/one-dark.json +0 -9
  68. package/lib/themes/one-light.json +0 -9
  69. package/lib/themes/rose-pine-dawn.json +0 -9
  70. package/lib/themes/rose-pine.json +0 -9
  71. package/lib/themes/solarized-dark.json +0 -9
  72. package/lib/themes/solarized-light.json +0 -9
  73. package/lib/themes/tokyo-night-light.json +0 -9
  74. package/lib/themes/tokyo-night.json +0 -9
  75. package/lib/updater.js +0 -96
@@ -1,56 +0,0 @@
1
- export function showToast(message, level, detail) {
2
- var el = document.createElement("div");
3
- el.className = "toast";
4
- if (level) el.classList.add("toast-" + level);
5
- el.textContent = message;
6
- if (detail) {
7
- var detailEl = document.createElement("div");
8
- detailEl.style.cssText = "font-size:11px;opacity:0.7;margin-top:4px;max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap";
9
- detailEl.textContent = detail.split("\n")[0];
10
- el.appendChild(detailEl);
11
- }
12
- document.body.appendChild(el);
13
- requestAnimationFrame(function () { el.classList.add("visible"); });
14
- var duration = level === "warn" ? 5000 : 1500;
15
- setTimeout(function () {
16
- el.classList.remove("visible");
17
- setTimeout(function () { el.remove(); }, 300);
18
- }, duration);
19
- }
20
-
21
- var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) ||
22
- (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
23
-
24
- export function copyToClipboard(text) {
25
- var p;
26
- if (isIOS) {
27
- // iOS Safari URL-encodes clipboard text that contains colons via the
28
- // Clipboard API. Use textarea + execCommand to copy raw text instead.
29
- var ta = document.createElement("textarea");
30
- ta.value = text;
31
- ta.style.cssText = "position:fixed;left:-9999px;opacity:0";
32
- document.body.appendChild(ta);
33
- ta.focus();
34
- ta.setSelectionRange(0, ta.value.length);
35
- document.execCommand("copy");
36
- document.body.removeChild(ta);
37
- p = Promise.resolve();
38
- } else if (navigator.clipboard && navigator.clipboard.writeText) {
39
- p = navigator.clipboard.writeText(text);
40
- } else {
41
- var ta2 = document.createElement("textarea");
42
- ta2.value = text;
43
- ta2.style.cssText = "position:fixed;left:-9999px;opacity:0";
44
- document.body.appendChild(ta2);
45
- ta2.focus();
46
- ta2.setSelectionRange(0, ta2.value.length);
47
- document.execCommand("copy");
48
- document.body.removeChild(ta2);
49
- p = Promise.resolve();
50
- }
51
- return p.then(function () { showToast("Copied to clipboard"); });
52
- }
53
-
54
- export function escapeHtml(s) {
55
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
56
- }
@@ -1,10 +0,0 @@
1
- @import url("css/base.css");
2
- @import url("css/sidebar.css");
3
- @import url("css/overlays.css");
4
- @import url("css/menus.css");
5
- @import url("css/messages.css");
6
- @import url("css/rewind.css");
7
- @import url("css/input.css");
8
- @import url("css/filebrowser.css");
9
- @import url("css/diff.css");
10
- @import url("css/highlight.css");
package/lib/public/sw.js DELETED
@@ -1,75 +0,0 @@
1
- self.addEventListener("install", function () {
2
- self.skipWaiting();
3
- });
4
-
5
- self.addEventListener("activate", function (event) {
6
- event.waitUntil(self.clients.claim());
7
- });
8
-
9
- self.addEventListener("push", function (event) {
10
- var data = {};
11
- try { data = event.data.json(); } catch (e) { return; }
12
-
13
- // Silent validation push, do not show notification
14
- if (data.type === "test") return;
15
-
16
- var options = {
17
- body: data.body || "",
18
- tag: data.tag || "claude-relay",
19
- data: data,
20
- };
21
-
22
- if (data.type === "permission_request") {
23
- options.requireInteraction = true;
24
- options.tag = "perm-" + data.requestId;
25
- } else if (data.type === "done") {
26
- options.tag = data.tag || "claude-done";
27
- } else if (data.type === "ask_user") {
28
- options.requireInteraction = true;
29
- options.tag = "claude-ask";
30
- } else if (data.type === "error") {
31
- options.requireInteraction = true;
32
- options.tag = "claude-error";
33
- }
34
-
35
- event.waitUntil(
36
- self.clients.matchAll({ type: "window", includeUncontrolled: true }).then(function (clientList) {
37
- // Always show permission requests, questions, and errors
38
- // Only suppress "done" notifications when app is in foreground
39
- if (data.type !== "permission_request" && data.type !== "ask_user" && data.type !== "error") {
40
- for (var i = 0; i < clientList.length; i++) {
41
- if (clientList[i].focused || clientList[i].visibilityState === "visible") return;
42
- }
43
- }
44
- return self.registration.showNotification(data.title || "Claude Relay", options);
45
- }).catch(function () {})
46
- );
47
- });
48
-
49
- self.addEventListener("notificationclick", function (event) {
50
- var data = event.notification.data || {};
51
- event.notification.close();
52
-
53
- // Build target URL from slug so we open the correct project
54
- var baseUrl = self.registration.scope || "/";
55
- var targetUrl = data.slug ? baseUrl + "p/" + data.slug + "/" : baseUrl;
56
-
57
- event.waitUntil(
58
- self.clients.matchAll({ type: "window", includeUncontrolled: true }).then(function (clientList) {
59
- // Prefer a client already on the correct project
60
- for (var i = 0; i < clientList.length; i++) {
61
- if (clientList[i].url.indexOf(targetUrl) !== -1) {
62
- return clientList[i].focus();
63
- }
64
- }
65
- // Fall back to any visible client
66
- for (var i = 0; i < clientList.length; i++) {
67
- if (clientList[i].visibilityState !== "hidden") {
68
- return clientList[i].focus();
69
- }
70
- }
71
- if (clientList.length > 0) return clientList[0].focus();
72
- return self.clients.openWindow(targetUrl);
73
- })
74
- );
75
- });
package/lib/push.js DELETED
@@ -1,125 +0,0 @@
1
- var webpush = require("web-push");
2
- var fs = require("fs");
3
- var path = require("path");
4
-
5
- function loadOrCreateVapidKeys() {
6
- var os = require("os");
7
- var dir = path.join(os.homedir(), ".claude-relay");
8
- var keyFile = path.join(dir, "vapid.json");
9
-
10
- try {
11
- var data = fs.readFileSync(keyFile, "utf8");
12
- return JSON.parse(data);
13
- } catch (e) {
14
- // Generate new keys
15
- }
16
-
17
- var keys = webpush.generateVAPIDKeys();
18
- fs.mkdirSync(dir, { recursive: true });
19
- fs.writeFileSync(keyFile, JSON.stringify(keys, null, 2));
20
- return keys;
21
- }
22
-
23
- function initPush() {
24
- var os = require("os");
25
- var keys = loadOrCreateVapidKeys();
26
-
27
- var vapidDetails = {
28
- subject: "mailto:push@claude-relay.dev",
29
- publicKey: keys.publicKey,
30
- privateKey: keys.privateKey,
31
- };
32
-
33
- var dir = path.join(os.homedir(), ".claude-relay");
34
- var subFile = path.join(dir, "push-subs.json");
35
- var subscriptions = new Map();
36
-
37
- // Load persisted subscriptions, but clear if VAPID key changed
38
- try {
39
- var saved = JSON.parse(fs.readFileSync(subFile, "utf8"));
40
- if (saved.vapidKey && saved.vapidKey !== keys.publicKey) {
41
- saved.subs = [];
42
- }
43
- var subs = saved.subs || saved;
44
- if (Array.isArray(subs)) {
45
- for (var i = 0; i < subs.length; i++) {
46
- if (subs[i] && subs[i].endpoint) subscriptions.set(subs[i].endpoint, subs[i]);
47
- }
48
- }
49
- } catch (e) {}
50
-
51
- function save() {
52
- try {
53
- fs.writeFileSync(subFile, JSON.stringify({
54
- vapidKey: keys.publicKey,
55
- subs: [...subscriptions.values()],
56
- }));
57
- } catch (e) {}
58
- }
59
-
60
- save();
61
-
62
- // Purge stale subscriptions on startup
63
- var startupEndpoints = Array.from(subscriptions.keys());
64
- for (var si = 0; si < startupEndpoints.length; si++) {
65
- (function (ep) {
66
- var sub = subscriptions.get(ep);
67
- webpush.sendNotification(sub, JSON.stringify({ type: "test" }), { TTL: 0, vapidDetails: vapidDetails })
68
- .then(function () {})
69
- .catch(function (err) {
70
- if (err.statusCode === 403 || err.statusCode === 410 || err.statusCode === 404) {
71
- subscriptions.delete(ep);
72
- save();
73
- }
74
- });
75
- })(startupEndpoints[si]);
76
- }
77
-
78
- function addSubscription(sub, replaceEndpoint) {
79
- if (!sub || !sub.endpoint) return;
80
- // Remove previous subscription from the same client if endpoint changed
81
- if (replaceEndpoint && replaceEndpoint !== sub.endpoint) {
82
- subscriptions.delete(replaceEndpoint);
83
- }
84
- // Store immediately, then validate async. Invalid subs get cleaned on first sendPush.
85
- subscriptions.set(sub.endpoint, sub);
86
- save();
87
- // Validate with a silent push (TTL 0 = don't actually deliver if device offline)
88
- webpush.sendNotification(sub, JSON.stringify({ type: "test" }), { TTL: 0, vapidDetails: vapidDetails })
89
- .then(function () {})
90
- .catch(function (err) {
91
- if (err.statusCode === 403 || err.statusCode === 410 || err.statusCode === 404) {
92
- subscriptions.delete(sub.endpoint);
93
- save();
94
- }
95
- });
96
- }
97
-
98
- function removeSubscription(endpoint) {
99
- subscriptions.delete(endpoint);
100
- save();
101
- }
102
-
103
- function sendPush(payload) {
104
- var json = JSON.stringify(payload);
105
- subscriptions.forEach(function (sub, endpoint) {
106
- webpush.sendNotification(sub, json, { vapidDetails: vapidDetails })
107
- .then(function () {})
108
- .catch(function (err) {
109
- if (err.statusCode === 410 || err.statusCode === 404 || err.statusCode === 403) {
110
- subscriptions.delete(endpoint);
111
- save();
112
- }
113
- });
114
- });
115
- }
116
-
117
- return {
118
- publicKey: keys.publicKey,
119
- addSubscription: addSubscription,
120
- removeSubscription: removeSubscription,
121
- sendPush: sendPush,
122
- };
123
- }
124
-
125
- module.exports = { initPush };