@juspay/shooter 1.24.2 → 1.25.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 (163) hide show
  1. package/.claude/hooks/notifier.cjs +32 -4
  2. package/build/client/_app/immutable/assets/{4.D4EDSN4H.css → 4.ChO_hlLs.css} +1 -1
  3. package/build/client/_app/immutable/assets/4.ChO_hlLs.css.br +0 -0
  4. package/build/client/_app/immutable/assets/4.ChO_hlLs.css.gz +0 -0
  5. package/build/client/_app/immutable/chunks/{BBuzUXZ9.js → BstJSK2K.js} +1 -1
  6. package/build/client/_app/immutable/chunks/BstJSK2K.js.br +0 -0
  7. package/build/client/_app/immutable/chunks/BstJSK2K.js.gz +0 -0
  8. package/build/client/_app/immutable/chunks/{Dqmsaccg.js → DINqYbXU.js} +1 -1
  9. package/build/client/_app/immutable/chunks/DINqYbXU.js.br +0 -0
  10. package/build/client/_app/immutable/chunks/DINqYbXU.js.gz +0 -0
  11. package/build/client/_app/immutable/chunks/ssAhjWfF.js +3 -0
  12. package/build/client/_app/immutable/chunks/ssAhjWfF.js.br +0 -0
  13. package/build/client/_app/immutable/chunks/ssAhjWfF.js.gz +0 -0
  14. package/build/client/_app/immutable/entry/{app.Bu4nq_bk.js → app.BPK9s2o5.js} +2 -2
  15. package/build/client/_app/immutable/entry/app.BPK9s2o5.js.br +0 -0
  16. package/build/client/_app/immutable/entry/app.BPK9s2o5.js.gz +0 -0
  17. package/build/client/_app/immutable/entry/start.DFPHuGE3.js +1 -0
  18. package/build/client/_app/immutable/entry/start.DFPHuGE3.js.br +2 -0
  19. package/build/client/_app/immutable/entry/start.DFPHuGE3.js.gz +0 -0
  20. package/build/client/_app/immutable/nodes/{0.CnSSjKHX.js → 0.BEbzRcwm.js} +1 -1
  21. package/build/client/_app/immutable/nodes/0.BEbzRcwm.js.br +0 -0
  22. package/build/client/_app/immutable/nodes/0.BEbzRcwm.js.gz +0 -0
  23. package/build/client/_app/immutable/nodes/{1.D_5wZINa.js → 1.C_V0SOr9.js} +1 -1
  24. package/build/client/_app/immutable/nodes/1.C_V0SOr9.js.br +0 -0
  25. package/build/client/_app/immutable/nodes/1.C_V0SOr9.js.gz +0 -0
  26. package/build/client/_app/immutable/nodes/{10.C_B2eMms.js → 10.6V-37_Rl.js} +1 -1
  27. package/build/client/_app/immutable/nodes/10.6V-37_Rl.js.br +0 -0
  28. package/build/client/_app/immutable/nodes/10.6V-37_Rl.js.gz +0 -0
  29. package/build/client/_app/immutable/nodes/{11.DUKnn5ja.js → 11.Lzf-KC6L.js} +1 -1
  30. package/build/client/_app/immutable/nodes/11.Lzf-KC6L.js.br +0 -0
  31. package/build/client/_app/immutable/nodes/11.Lzf-KC6L.js.gz +0 -0
  32. package/build/client/_app/immutable/nodes/{2.C37CZKYv.js → 2.Cl2dMP2L.js} +1 -1
  33. package/build/client/_app/immutable/nodes/2.Cl2dMP2L.js.br +0 -0
  34. package/build/client/_app/immutable/nodes/2.Cl2dMP2L.js.gz +0 -0
  35. package/build/client/_app/immutable/nodes/{3.C48G514u.js → 3.CuX2eSna.js} +1 -1
  36. package/build/client/_app/immutable/nodes/3.CuX2eSna.js.br +0 -0
  37. package/build/client/_app/immutable/nodes/3.CuX2eSna.js.gz +0 -0
  38. package/build/client/_app/immutable/nodes/4.2DvqoOaB.js +17 -0
  39. package/build/client/_app/immutable/nodes/4.2DvqoOaB.js.br +0 -0
  40. package/build/client/_app/immutable/nodes/4.2DvqoOaB.js.gz +0 -0
  41. package/build/client/_app/immutable/nodes/{6.DGlutNk6.js → 6.C7e6zQyP.js} +1 -1
  42. package/build/client/_app/immutable/nodes/6.C7e6zQyP.js.br +0 -0
  43. package/build/client/_app/immutable/nodes/6.C7e6zQyP.js.gz +0 -0
  44. package/build/client/_app/immutable/nodes/{7.BXAYsEHF.js → 7.1ygvNTnO.js} +1 -1
  45. package/build/client/_app/immutable/nodes/7.1ygvNTnO.js.br +0 -0
  46. package/build/client/_app/immutable/nodes/7.1ygvNTnO.js.gz +0 -0
  47. package/build/client/_app/immutable/nodes/{8.D-SxCq24.js → 8.CBVmgOk0.js} +1 -1
  48. package/build/client/_app/immutable/nodes/8.CBVmgOk0.js.br +0 -0
  49. package/build/client/_app/immutable/nodes/8.CBVmgOk0.js.gz +0 -0
  50. package/build/client/_app/immutable/nodes/{9.Bek2YR4U.js → 9.B-_ZFZhj.js} +1 -1
  51. package/build/client/_app/immutable/nodes/9.B-_ZFZhj.js.br +0 -0
  52. package/build/client/_app/immutable/nodes/9.B-_ZFZhj.js.gz +0 -0
  53. package/build/client/_app/version.json +1 -1
  54. package/build/client/_app/version.json.br +0 -0
  55. package/build/client/_app/version.json.gz +0 -0
  56. package/build/server/chunks/{0-ByOnI9Md.js → 0-BHU07xt9.js} +2 -2
  57. package/build/server/chunks/{0-ByOnI9Md.js.map → 0-BHU07xt9.js.map} +1 -1
  58. package/build/server/chunks/{1-DcJwehLu.js → 1-OVOd8GUH.js} +2 -2
  59. package/build/server/chunks/{1-DcJwehLu.js.map → 1-OVOd8GUH.js.map} +1 -1
  60. package/build/server/chunks/{10-B5bdfDfK.js → 10-CRHtvb_u.js} +2 -2
  61. package/build/server/chunks/{10-B5bdfDfK.js.map → 10-CRHtvb_u.js.map} +1 -1
  62. package/build/server/chunks/{11-DOJ9j7KC.js → 11-CdSex9j1.js} +2 -2
  63. package/build/server/chunks/{11-DOJ9j7KC.js.map → 11-CdSex9j1.js.map} +1 -1
  64. package/build/server/chunks/{2-BY0LGSMl.js → 2-bb78aIZ6.js} +2 -2
  65. package/build/server/chunks/{2-BY0LGSMl.js.map → 2-bb78aIZ6.js.map} +1 -1
  66. package/build/server/chunks/{3-DEa6RtDT.js → 3-CsTC6Lrn.js} +2 -2
  67. package/build/server/chunks/{3-DEa6RtDT.js.map → 3-CsTC6Lrn.js.map} +1 -1
  68. package/build/server/chunks/{4-w2W_T8ax.js → 4-DTTu8_Gr.js} +4 -4
  69. package/build/server/chunks/{4-w2W_T8ax.js.map → 4-DTTu8_Gr.js.map} +1 -1
  70. package/build/server/chunks/{6-DoTu6ygH.js → 6-BUgQGB_4.js} +2 -2
  71. package/build/server/chunks/{6-DoTu6ygH.js.map → 6-BUgQGB_4.js.map} +1 -1
  72. package/build/server/chunks/{7-CYQ9V6d4.js → 7-CsQZnkcG.js} +2 -2
  73. package/build/server/chunks/{7-CYQ9V6d4.js.map → 7-CsQZnkcG.js.map} +1 -1
  74. package/build/server/chunks/{8-DMwmCD5X.js → 8-DcIuPdyW.js} +2 -2
  75. package/build/server/chunks/{8-DMwmCD5X.js.map → 8-DcIuPdyW.js.map} +1 -1
  76. package/build/server/chunks/{9-CNmPa2Jo.js → 9-D8bkM1uj.js} +2 -2
  77. package/build/server/chunks/{9-CNmPa2Jo.js.map → 9-D8bkM1uj.js.map} +1 -1
  78. package/build/server/chunks/{_page.svelte-DDE2nChH.js → _page.svelte-BBbaKwNz.js} +101 -27
  79. package/build/server/chunks/_page.svelte-BBbaKwNz.js.map +1 -0
  80. package/build/server/chunks/{_server.ts-DfscXcFe.js → _server.ts-B7BLxK5u.js} +233 -186
  81. package/build/server/chunks/_server.ts-B7BLxK5u.js.map +1 -0
  82. package/build/server/chunks/{_server.ts-EJVmhLtg.js → _server.ts-BSS8cO80.js} +15 -3
  83. package/build/server/chunks/_server.ts-BSS8cO80.js.map +1 -0
  84. package/build/server/chunks/_server.ts-DNTxPoxO.js +115 -0
  85. package/build/server/chunks/_server.ts-DNTxPoxO.js.map +1 -0
  86. package/build/server/chunks/{_server.ts-D9_hkPQ6.js → _server.ts-DUb7fbuW.js} +17 -3
  87. package/build/server/chunks/_server.ts-DUb7fbuW.js.map +1 -0
  88. package/build/server/chunks/{_server.ts-v7TaT83B.js → _server.ts-FdKi8RwL.js} +7 -3
  89. package/build/server/chunks/_server.ts-FdKi8RwL.js.map +1 -0
  90. package/build/server/chunks/device-format-DTgEz4Yr.js +29 -0
  91. package/build/server/chunks/device-format-DTgEz4Yr.js.map +1 -0
  92. package/build/server/chunks/device-token-store-Ct7aTeR8.js +259 -0
  93. package/build/server/chunks/device-token-store-Ct7aTeR8.js.map +1 -0
  94. package/build/server/chunks/{library-apns-D8RPINlv.js → library-apns-DMlL1BAg.js} +158 -26
  95. package/build/server/chunks/library-apns-DMlL1BAg.js.map +1 -0
  96. package/build/server/index.js +1 -1
  97. package/build/server/index.js.map +1 -1
  98. package/build/server/manifest.js +17 -17
  99. package/build/server/manifest.js.map +1 -1
  100. package/package.json +2 -2
  101. package/server.ts +15 -1
  102. package/src/app.d.ts +4 -0
  103. package/src/lib/modules/server/apn/apns-classify.ts +103 -0
  104. package/src/lib/modules/server/apn/library-apns.ts +151 -35
  105. package/src/lib/modules/server/apn/notify-fanout.ts +40 -0
  106. package/src/lib/modules/server/fcm/fcm-classify.ts +61 -0
  107. package/src/lib/modules/server/fcm/fcm-service.ts +128 -29
  108. package/src/lib/modules/server/push/device-format.ts +42 -0
  109. package/src/lib/modules/server/push/device-token-store.ts +354 -0
  110. package/src/lib/types/apn.ts +4 -0
  111. package/src/lib/types/device.ts +156 -0
  112. package/src/lib/types/index.ts +1 -0
  113. package/src/routes/api/debug/+server.ts +13 -1
  114. package/src/routes/api/device-token/+server.ts +122 -37
  115. package/src/routes/api/health/+server.ts +16 -2
  116. package/src/routes/api/notify/+server.ts +175 -168
  117. package/src/routes/api/qr-config/+server.ts +9 -2
  118. package/src/routes/config/+page.svelte +182 -44
  119. package/build/client/_app/immutable/assets/4.D4EDSN4H.css.br +0 -0
  120. package/build/client/_app/immutable/assets/4.D4EDSN4H.css.gz +0 -0
  121. package/build/client/_app/immutable/chunks/BBuzUXZ9.js.br +0 -0
  122. package/build/client/_app/immutable/chunks/BBuzUXZ9.js.gz +0 -0
  123. package/build/client/_app/immutable/chunks/BPIV28L3.js +0 -3
  124. package/build/client/_app/immutable/chunks/BPIV28L3.js.br +0 -0
  125. package/build/client/_app/immutable/chunks/BPIV28L3.js.gz +0 -0
  126. package/build/client/_app/immutable/chunks/Dqmsaccg.js.br +0 -0
  127. package/build/client/_app/immutable/chunks/Dqmsaccg.js.gz +0 -0
  128. package/build/client/_app/immutable/entry/app.Bu4nq_bk.js.br +0 -0
  129. package/build/client/_app/immutable/entry/app.Bu4nq_bk.js.gz +0 -0
  130. package/build/client/_app/immutable/entry/start.CbpzR6Gp.js +0 -1
  131. package/build/client/_app/immutable/entry/start.CbpzR6Gp.js.br +0 -2
  132. package/build/client/_app/immutable/entry/start.CbpzR6Gp.js.gz +0 -0
  133. package/build/client/_app/immutable/nodes/0.CnSSjKHX.js.br +0 -0
  134. package/build/client/_app/immutable/nodes/0.CnSSjKHX.js.gz +0 -0
  135. package/build/client/_app/immutable/nodes/1.D_5wZINa.js.br +0 -0
  136. package/build/client/_app/immutable/nodes/1.D_5wZINa.js.gz +0 -0
  137. package/build/client/_app/immutable/nodes/10.C_B2eMms.js.br +0 -0
  138. package/build/client/_app/immutable/nodes/10.C_B2eMms.js.gz +0 -0
  139. package/build/client/_app/immutable/nodes/11.DUKnn5ja.js.br +0 -0
  140. package/build/client/_app/immutable/nodes/11.DUKnn5ja.js.gz +0 -0
  141. package/build/client/_app/immutable/nodes/2.C37CZKYv.js.br +0 -0
  142. package/build/client/_app/immutable/nodes/2.C37CZKYv.js.gz +0 -0
  143. package/build/client/_app/immutable/nodes/3.C48G514u.js.br +0 -0
  144. package/build/client/_app/immutable/nodes/3.C48G514u.js.gz +0 -0
  145. package/build/client/_app/immutable/nodes/4.C9fv_m2R.js +0 -16
  146. package/build/client/_app/immutable/nodes/4.C9fv_m2R.js.br +0 -0
  147. package/build/client/_app/immutable/nodes/4.C9fv_m2R.js.gz +0 -0
  148. package/build/client/_app/immutable/nodes/6.DGlutNk6.js.br +0 -0
  149. package/build/client/_app/immutable/nodes/6.DGlutNk6.js.gz +0 -0
  150. package/build/client/_app/immutable/nodes/7.BXAYsEHF.js.br +0 -0
  151. package/build/client/_app/immutable/nodes/7.BXAYsEHF.js.gz +0 -0
  152. package/build/client/_app/immutable/nodes/8.D-SxCq24.js.br +0 -0
  153. package/build/client/_app/immutable/nodes/8.D-SxCq24.js.gz +0 -0
  154. package/build/client/_app/immutable/nodes/9.Bek2YR4U.js.br +0 -0
  155. package/build/client/_app/immutable/nodes/9.Bek2YR4U.js.gz +0 -0
  156. package/build/server/chunks/_page.svelte-DDE2nChH.js.map +0 -1
  157. package/build/server/chunks/_server.ts-D2RS8TFd.js +0 -72
  158. package/build/server/chunks/_server.ts-D2RS8TFd.js.map +0 -1
  159. package/build/server/chunks/_server.ts-D9_hkPQ6.js.map +0 -1
  160. package/build/server/chunks/_server.ts-DfscXcFe.js.map +0 -1
  161. package/build/server/chunks/_server.ts-EJVmhLtg.js.map +0 -1
  162. package/build/server/chunks/_server.ts-v7TaT83B.js.map +0 -1
  163. package/build/server/chunks/library-apns-D8RPINlv.js.map +0 -1
@@ -1,11 +1,10 @@
1
1
  import { b as private_env } from './shared-server-DaWdgxVh.js';
2
- import { existsSync, readFileSync } from 'fs';
3
- import { homedir } from 'os';
4
- import { join } from 'path';
5
- import { L as LibraryAPNsService } from './library-apns-D8RPINlv.js';
2
+ import { L as LibraryAPNsService } from './library-apns-DMlL1BAg.js';
6
3
  import { c as createPendingRequest } from './pending-requests-8rWjrF6d.js';
7
4
  import { v as validateAuth } from './auth-DuunT7Cg.js';
8
5
  import admin from 'firebase-admin';
6
+ import { m as maskToken } from './device-format-DTgEz4Yr.js';
7
+ import { d as deviceTokenStore } from './device-token-store-Ct7aTeR8.js';
9
8
  import { t as toErrorMessage } from './error-DDXB3duW.js';
10
9
  import { b as broadcastEvent } from './guest-registry-Dxvd7p-g.js';
11
10
  import './super-session-handler-DPyxFgmz.js';
@@ -14,34 +13,15 @@ import 'child_process';
14
13
  import 'jsonwebtoken';
15
14
  import 'util';
16
15
  import 'better-sqlite3';
16
+ import 'fs';
17
+ import 'path';
17
18
  import './shooter-home-4f_HkdGI.js';
19
+ import 'os';
18
20
  import 'crypto';
19
21
  import './registry-D4J_CuzW.js';
20
22
  import './qwen-reader-DGfUbKaJ.js';
21
23
  import './coordinator-DMU_ADXf.js';
22
24
 
23
- const normalize = (value) => {
24
- const trimmed = value?.trim();
25
- return trimmed ? trimmed : void 0;
26
- };
27
- function readPersistedDeviceToken(platform) {
28
- const tokensFile = join(homedir(), ".shooter", "device-tokens.json");
29
- if (!existsSync(tokensFile)) {
30
- return void 0;
31
- }
32
- try {
33
- const parsed = JSON.parse(readFileSync(tokensFile, "utf-8"));
34
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
35
- const value = parsed[platform];
36
- return typeof value === "string" && value ? value : void 0;
37
- }
38
- } catch {
39
- }
40
- return void 0;
41
- }
42
- function resolveDeviceToken(requestToken, persistedToken, envToken) {
43
- return normalize(requestToken) ?? normalize(persistedToken) ?? normalize(envToken);
44
- }
45
25
  const MAX_HISTORY = 100;
46
26
  const history = [];
47
27
  function addNotification(record) {
@@ -53,42 +33,140 @@ function addNotification(record) {
53
33
  function getNotifications(limit = 50) {
54
34
  return history.slice(0, limit);
55
35
  }
36
+ function selectPlatforms(platformFilter) {
37
+ if (platformFilter === "ios") {
38
+ return { doAndroid: false, doIos: true };
39
+ }
40
+ if (platformFilter === "android") {
41
+ return { doAndroid: true, doIos: false };
42
+ }
43
+ return { doAndroid: true, doIos: true };
44
+ }
45
+ function summarizeNotifyDelivery(apns, fcm) {
46
+ const sent = apns.totalSent + fcm.successCount;
47
+ const failed = apns.totalFailed + fcm.failureCount;
48
+ const staleTokens = [...apns.staleTokens, ...fcm.staleTokens];
49
+ const succeededTokens = [
50
+ ...apns.results.filter((r) => r.success).map((r) => r.token),
51
+ ...fcm.results.filter((r) => r.success).map((r) => r.token)
52
+ ];
53
+ return { delivered: sent > 0, failed, sent, staleTokens, succeededTokens };
54
+ }
55
+ const PRUNABLE_FCM_CODES = /* @__PURE__ */ new Set([
56
+ "messaging/registration-token-not-registered"
57
+ ]);
58
+ function chunk(items, size) {
59
+ const out = [];
60
+ for (let i = 0; i < items.length; i += size) {
61
+ out.push(items.slice(i, i + size));
62
+ }
63
+ return out;
64
+ }
65
+ function classifyFcmError(code) {
66
+ return code && PRUNABLE_FCM_CODES.has(code) ? "prune" : "keep";
67
+ }
68
+ function summarizeFcmFanOut(outcomes) {
69
+ const results = [];
70
+ const staleTokens = [];
71
+ let successCount = 0;
72
+ let failureCount = 0;
73
+ for (const o of outcomes) {
74
+ if (o.success) {
75
+ successCount += 1;
76
+ } else {
77
+ failureCount += 1;
78
+ if (classifyFcmError(o.errorCode) === "prune") {
79
+ staleTokens.push(o.token);
80
+ }
81
+ }
82
+ results.push({
83
+ error: o.errorCode,
84
+ messageId: o.messageId,
85
+ success: o.success,
86
+ token: o.token
87
+ });
88
+ }
89
+ return { failureCount, results, staleTokens, successCount };
90
+ }
56
91
  let app = null;
92
+ const FCM_MULTICAST_CHUNK = 100;
57
93
  function isFCMConfigured() {
58
94
  return !!(process.env.FCM_PROJECT_ID && process.env.FCM_CLIENT_EMAIL && process.env.FCM_PRIVATE_KEY);
59
95
  }
60
- async function sendFCMNotification(deviceToken, payload) {
96
+ async function sendFCMNotificationMulti(tokens, payload) {
97
+ if (tokens.length === 0) {
98
+ return { failureCount: 0, results: [], staleTokens: [], successCount: 0 };
99
+ }
100
+ let fcmApp;
61
101
  try {
62
- const fcmApp = getApp();
63
- const message = {
64
- android: {
65
- priority: "high",
66
- // Ensures delivery even in Doze mode
67
- ttl: 3e5
68
- // 5 minutes TTL (matches pending request expiry)
69
- },
70
- data: {
71
- body: payload.body || payload.message || "",
72
- category: payload.category ?? (typeof payload.data?.category === "string" ? payload.data.category : ""),
73
- project: typeof payload.data?.project === "string" ? payload.data.project : "",
74
- requestId: typeof payload.data?.requestId === "string" ? payload.data.requestId : "",
75
- source: typeof payload.data?.source === "string" ? payload.data.source : "",
76
- subtitle: payload.subtitle ?? "",
77
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
78
- title: payload.title,
79
- toolInput: payload.data?.toolInput ? JSON.stringify(payload.data.toolInput) : "",
80
- toolName: typeof payload.data?.toolName === "string" ? payload.data.toolName : "",
81
- type: typeof payload.data?.type === "string" ? payload.data.type : ""
82
- },
83
- token: deviceToken
84
- };
85
- const messageId = await admin.messaging(fcmApp).send(message);
86
- return { messageId, success: true };
102
+ fcmApp = getApp();
87
103
  } catch (error) {
88
- const errorMessage = error instanceof Error ? error.message : String(error);
89
- console.error("[FCM] Send failed:", errorMessage);
90
- return { error: errorMessage, success: false };
104
+ const msg = error instanceof Error ? error.message : String(error);
105
+ console.error("[FCM] multi-send setup failed:", fcmErrorLabel(error));
106
+ return {
107
+ failureCount: tokens.length,
108
+ results: tokens.map((token) => ({ error: msg, messageId: null, success: false, token })),
109
+ staleTokens: [],
110
+ successCount: 0
111
+ };
91
112
  }
113
+ const base = buildDataMessage(payload);
114
+ const outcomes = [];
115
+ for (const group of chunk(tokens, FCM_MULTICAST_CHUNK)) {
116
+ try {
117
+ const batch = await admin.messaging(fcmApp).sendEachForMulticast({ ...base, tokens: [...group] });
118
+ batch.responses.forEach((resp, i) => {
119
+ const errorCode = resp.error?.code ?? null;
120
+ if (errorCode === "messaging/invalid-argument") {
121
+ console.error(`[FCM] invalid-argument for token ${maskToken(group[i])}: ${errorCode}`);
122
+ }
123
+ outcomes.push({
124
+ errorCode,
125
+ messageId: resp.messageId ?? null,
126
+ success: resp.success,
127
+ token: group[i]
128
+ });
129
+ });
130
+ } catch (error) {
131
+ console.error("[FCM] multicast chunk failed:", fcmErrorLabel(error));
132
+ for (const token of group) {
133
+ outcomes.push({ errorCode: null, messageId: null, success: false, token });
134
+ }
135
+ }
136
+ }
137
+ return summarizeFcmFanOut(outcomes);
138
+ }
139
+ function buildDataMessage(payload) {
140
+ return {
141
+ android: {
142
+ priority: "high",
143
+ // Ensures delivery even in Doze mode
144
+ ttl: 3e5
145
+ // 5 minutes TTL (matches pending request expiry)
146
+ },
147
+ data: {
148
+ body: payload.body || payload.message || "",
149
+ category: payload.category ?? (typeof payload.data?.category === "string" ? payload.data.category : ""),
150
+ project: typeof payload.data?.project === "string" ? payload.data.project : "",
151
+ requestId: typeof payload.data?.requestId === "string" ? payload.data.requestId : "",
152
+ source: typeof payload.data?.source === "string" ? payload.data.source : "",
153
+ subtitle: payload.subtitle ?? "",
154
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
155
+ title: payload.title,
156
+ toolInput: payload.data?.toolInput ? JSON.stringify(payload.data.toolInput) : "",
157
+ toolName: typeof payload.data?.toolName === "string" ? payload.data.toolName : "",
158
+ type: typeof payload.data?.type === "string" ? payload.data.type : ""
159
+ }
160
+ };
161
+ }
162
+ function fcmErrorLabel(error) {
163
+ if (error && typeof error === "object" && "code" in error) {
164
+ const code = error.code;
165
+ if (typeof code === "string" && code.length > 0) {
166
+ return code;
167
+ }
168
+ }
169
+ return error instanceof Error ? error.message : String(error);
92
170
  }
93
171
  function getApp() {
94
172
  if (!app) {
@@ -113,6 +191,57 @@ function getAPNsClient() {
113
191
  }
114
192
  return apnsSingleton;
115
193
  }
194
+ const EMPTY_APNS_RESULT = {
195
+ results: [],
196
+ staleTokens: [],
197
+ totalFailed: 0,
198
+ totalSent: 0
199
+ };
200
+ const EMPTY_FCM_RESULT = {
201
+ failureCount: 0,
202
+ results: [],
203
+ staleTokens: [],
204
+ successCount: 0
205
+ };
206
+ function resolveAndroidTokens() {
207
+ const rows = deviceTokenStore.listActive("android");
208
+ if (rows.length > 0) {
209
+ return rows.map((r) => r.token);
210
+ }
211
+ const seed = private_env.ANDROID_DEVICE_TOKEN?.trim();
212
+ return seed ? [seed] : [];
213
+ }
214
+ function resolveIosDevices(override) {
215
+ const appEnv = serverApnEnv();
216
+ if (override) {
217
+ return [syntheticSeedDevice(override, "ios", appEnv)];
218
+ }
219
+ const rows = deviceTokenStore.listActiveForEnv("ios", appEnv);
220
+ if (rows.length > 0) {
221
+ return rows;
222
+ }
223
+ const seed = private_env.DEVICE_TOKEN?.trim();
224
+ return seed ? [syntheticSeedDevice(seed, "ios", appEnv)] : [];
225
+ }
226
+ function serverApnEnv() {
227
+ return private_env.APNS_PRODUCTION === "true" ? "production" : "sandbox";
228
+ }
229
+ function syntheticSeedDevice(token, platform, appEnv) {
230
+ const nowIso = (/* @__PURE__ */ new Date()).toISOString();
231
+ return {
232
+ appEnv,
233
+ bundleId: null,
234
+ deviceId: null,
235
+ failureCount: 0,
236
+ friendlyName: null,
237
+ id: `seed-${platform}`,
238
+ isActive: true,
239
+ lastSeenAt: nowIso,
240
+ platform,
241
+ registeredAt: nowIso,
242
+ token
243
+ };
244
+ }
116
245
  const notificationCache = /* @__PURE__ */ new Map();
117
246
  const DEDUP_WINDOW = 1e4;
118
247
  function broadcastHookEvent(body) {
@@ -189,6 +318,9 @@ function buildNotificationRecord(id, title, message, status, data, error) {
189
318
  }
190
319
  function intelligentNotificationFilter(title, message, data, waitForResponse = false) {
191
320
  const source = data?.source || "unknown";
321
+ if (waitForResponse) {
322
+ return { reason: "Bidirectional request — never filtered", send: true };
323
+ }
192
324
  if (isDuplicateNotification(title, message, data, waitForResponse)) {
193
325
  return {
194
326
  reason: "Duplicate notification within 10-second window",
@@ -372,138 +504,53 @@ const POST = async ({ request }) => {
372
504
  ...subtitle ? { subtitle } : {},
373
505
  title
374
506
  };
375
- const platform = private_env.DEVICE_PLATFORM || "ios";
376
- if (platform === "android") {
377
- if (!isFCMConfigured()) {
378
- return json(
379
- {
380
- details: "Missing FCM_PROJECT_ID, FCM_CLIENT_EMAIL, or FCM_PRIVATE_KEY environment variables",
381
- error: "FCM not configured"
382
- },
383
- { status: 500 }
384
- );
385
- }
386
- const androidToken = resolveDeviceToken(
387
- requestDeviceToken,
388
- readPersistedDeviceToken("android"),
389
- private_env.ANDROID_DEVICE_TOKEN
390
- );
391
- if (!androidToken) {
392
- return json(
393
- {
394
- details: "No Android device token available — set ANDROID_DEVICE_TOKEN, pass deviceToken in the request body, or open the Android app so it can auto-register its FCM token.",
395
- error: "No device token configured"
396
- },
397
- { status: 500 }
398
- );
399
- }
400
- const fcmResult = await sendFCMNotification(androidToken, payload);
401
- if (fcmResult.success) {
402
- recordNotification(title, message, data);
403
- if (waitForResponse) {
404
- createPendingRequest(canonicalRequestId, {
405
- options,
406
- question: question ?? null,
407
- responseKind: responseKind ?? "hook",
408
- sessionId: data?.sessionId || "",
409
- toolInput: data?.toolInput || {},
410
- toolName: data?.toolName || ""
411
- });
412
- }
413
- addNotification(buildNotificationRecord(canonicalRequestId, title, message, "sent", data));
414
- return json({
415
- message: "Notification sent successfully",
416
- requestId: canonicalRequestId,
417
- result: { messageId: fcmResult.messageId },
418
- success: true,
419
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
420
- });
421
- } else {
422
- console.error(`[notify] FCM delivery failed: ${fcmResult.error}`);
423
- releaseNotification(title, message, data);
424
- addNotification(
425
- buildNotificationRecord(
426
- canonicalRequestId,
427
- title,
428
- message,
429
- "failed",
430
- data,
431
- fcmResult.error
432
- )
433
- );
434
- return json(
435
- {
436
- details: fcmResult.error,
437
- error: "Failed to send notification",
438
- requestId: canonicalRequestId,
439
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
440
- },
441
- { status: 500 }
442
- );
443
- }
507
+ const override = requestDeviceToken?.trim() || void 0;
508
+ const { doAndroid, doIos } = selectPlatforms(private_env.DEVICE_PLATFORM);
509
+ const iosDevices = doIos ? override ? resolveIosDevices(override) : resolveIosDevices() : [];
510
+ const androidTokens = doAndroid ? override ? [override] : resolveAndroidTokens() : [];
511
+ const collapseId = waitForResponse ? canonicalRequestId : void 0;
512
+ const [apnsResult, fcmResult] = await Promise.all([
513
+ iosDevices.length > 0 && apnsClient.isConfigured() ? apnsClient.sendToMany(iosDevices, payload, collapseId) : Promise.resolve(EMPTY_APNS_RESULT),
514
+ androidTokens.length > 0 && isFCMConfigured() ? sendFCMNotificationMulti(androidTokens, payload) : Promise.resolve(EMPTY_FCM_RESULT)
515
+ ]);
516
+ const summary = summarizeNotifyDelivery(apnsResult, fcmResult);
517
+ const pruned = !override && summary.staleTokens.length ? deviceTokenStore.pruneByTokens(summary.staleTokens) : 0;
518
+ if (summary.succeededTokens.length > 0) {
519
+ deviceTokenStore.touchLastSeen(summary.succeededTokens);
520
+ }
521
+ if (summary.delivered && summary.failed === 0) {
522
+ recordNotification(title, message, data);
444
523
  } else {
445
- if (!apnsClient.isConfigured()) {
446
- return json(
447
- {
448
- details: "Missing APNS_KEY, APNS_KEY_ID, or APNS_TEAM_ID environment variables",
449
- error: "APNs client not configured"
450
- },
451
- { status: 500 }
452
- );
453
- }
454
- const deviceToken = resolveDeviceToken(
455
- requestDeviceToken,
456
- readPersistedDeviceToken("ios"),
457
- private_env.DEVICE_TOKEN
458
- );
459
- if (!deviceToken) {
460
- return json(
461
- {
462
- details: "No iOS device token available — pass deviceToken in the request body, ensure ~/.shooter/device-tokens.json contains an ios token, or set DEVICE_TOKEN.",
463
- error: "No device token configured"
464
- },
465
- { status: 500 }
466
- );
467
- }
468
- try {
469
- const result = await apnsClient.sendNotification(deviceToken, payload);
470
- recordNotification(title, message, data);
471
- if (waitForResponse) {
472
- createPendingRequest(canonicalRequestId, {
473
- options,
474
- question: question ?? null,
475
- responseKind: responseKind ?? "hook",
476
- sessionId: data?.sessionId || "",
477
- toolInput: data?.toolInput || {},
478
- toolName: data?.toolName || ""
479
- });
480
- }
481
- addNotification(buildNotificationRecord(canonicalRequestId, title, message, "sent", data));
482
- return json({
483
- message: "Notification sent successfully",
484
- requestId: canonicalRequestId,
485
- result,
486
- success: true,
487
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
488
- });
489
- } catch (notificationError) {
490
- const notifErrMsg = toErrorMessage(notificationError);
491
- console.error(`[notify] APNs delivery failed: ${notifErrMsg}`);
492
- releaseNotification(title, message, data);
493
- addNotification(
494
- buildNotificationRecord(canonicalRequestId, title, message, "failed", data, notifErrMsg)
495
- );
496
- return json(
497
- {
498
- details: notifErrMsg,
499
- error: "Failed to send notification",
500
- requestId: canonicalRequestId,
501
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
502
- },
503
- { status: 500 }
504
- );
505
- }
524
+ releaseNotification(title, message, data);
506
525
  }
526
+ if (waitForResponse && summary.delivered) {
527
+ createPendingRequest(canonicalRequestId, {
528
+ options,
529
+ question: question ?? null,
530
+ responseKind: responseKind ?? "hook",
531
+ sessionId: data?.sessionId || "",
532
+ toolInput: data?.toolInput || {},
533
+ toolName: data?.toolName || ""
534
+ });
535
+ }
536
+ addNotification(
537
+ buildNotificationRecord(
538
+ canonicalRequestId,
539
+ title,
540
+ message,
541
+ summary.delivered ? "sent" : "failed",
542
+ data,
543
+ summary.delivered ? null : "No registered device accepted the notification"
544
+ )
545
+ );
546
+ return json({
547
+ failed: summary.failed,
548
+ pruned,
549
+ requestId: canonicalRequestId,
550
+ sent: summary.sent,
551
+ success: summary.delivered,
552
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
553
+ });
507
554
  } catch (error) {
508
555
  console.error("Notification error:", error);
509
556
  return json(
@@ -531,4 +578,4 @@ const GET = ({ request, url }) => {
531
578
  };
532
579
 
533
580
  export { GET, POST };
534
- //# sourceMappingURL=_server.ts-DfscXcFe.js.map
581
+ //# sourceMappingURL=_server.ts-B7BLxK5u.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_server.ts-B7BLxK5u.js","sources":["../../../.svelte-kit/adapter-node/entries/endpoints/api/notify/_server.ts.js"],"sourcesContent":["import { b as private_env } from \"../../../../chunks/shared-server.js\";\nimport { L as LibraryAPNsService } from \"../../../../chunks/library-apns.js\";\nimport { c as createPendingRequest } from \"../../../../chunks/pending-requests.js\";\nimport { v as validateAuth } from \"../../../../chunks/auth.js\";\nimport admin from \"firebase-admin\";\nimport { m as maskToken } from \"../../../../chunks/device-format.js\";\nimport { d as deviceTokenStore } from \"../../../../chunks/device-token-store.js\";\nimport { t as toErrorMessage } from \"../../../../chunks/error.js\";\nimport { b as broadcastEvent } from \"../../../../chunks/guest-registry.js\";\nimport \"../../../../chunks/super-session-handler.js\";\nimport { json } from \"@sveltejs/kit\";\nconst MAX_HISTORY = 100;\nconst history = [];\nfunction addNotification(record) {\n history.unshift(record);\n if (history.length > MAX_HISTORY) {\n history.length = MAX_HISTORY;\n }\n}\nfunction getNotifications(limit = 50) {\n return history.slice(0, limit);\n}\nfunction selectPlatforms(platformFilter) {\n if (platformFilter === \"ios\") {\n return { doAndroid: false, doIos: true };\n }\n if (platformFilter === \"android\") {\n return { doAndroid: true, doIos: false };\n }\n return { doAndroid: true, doIos: true };\n}\nfunction summarizeNotifyDelivery(apns, fcm) {\n const sent = apns.totalSent + fcm.successCount;\n const failed = apns.totalFailed + fcm.failureCount;\n const staleTokens = [...apns.staleTokens, ...fcm.staleTokens];\n const succeededTokens = [\n ...apns.results.filter((r) => r.success).map((r) => r.token),\n ...fcm.results.filter((r) => r.success).map((r) => r.token)\n ];\n return { delivered: sent > 0, failed, sent, staleTokens, succeededTokens };\n}\nconst PRUNABLE_FCM_CODES = /* @__PURE__ */ new Set([\n \"messaging/registration-token-not-registered\"\n]);\nfunction chunk(items, size) {\n const out = [];\n for (let i = 0; i < items.length; i += size) {\n out.push(items.slice(i, i + size));\n }\n return out;\n}\nfunction classifyFcmError(code) {\n return code && PRUNABLE_FCM_CODES.has(code) ? \"prune\" : \"keep\";\n}\nfunction summarizeFcmFanOut(outcomes) {\n const results = [];\n const staleTokens = [];\n let successCount = 0;\n let failureCount = 0;\n for (const o of outcomes) {\n if (o.success) {\n successCount += 1;\n } else {\n failureCount += 1;\n if (classifyFcmError(o.errorCode) === \"prune\") {\n staleTokens.push(o.token);\n }\n }\n results.push({\n error: o.errorCode,\n messageId: o.messageId,\n success: o.success,\n token: o.token\n });\n }\n return { failureCount, results, staleTokens, successCount };\n}\nlet app = null;\nconst FCM_MULTICAST_CHUNK = 100;\nfunction isFCMConfigured() {\n return !!(process.env.FCM_PROJECT_ID && process.env.FCM_CLIENT_EMAIL && process.env.FCM_PRIVATE_KEY);\n}\nasync function sendFCMNotificationMulti(tokens, payload) {\n if (tokens.length === 0) {\n return { failureCount: 0, results: [], staleTokens: [], successCount: 0 };\n }\n let fcmApp;\n try {\n fcmApp = getApp();\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(\"[FCM] multi-send setup failed:\", fcmErrorLabel(error));\n return {\n failureCount: tokens.length,\n results: tokens.map((token) => ({ error: msg, messageId: null, success: false, token })),\n staleTokens: [],\n successCount: 0\n };\n }\n const base = buildDataMessage(payload);\n const outcomes = [];\n for (const group of chunk(tokens, FCM_MULTICAST_CHUNK)) {\n try {\n const batch = await admin.messaging(fcmApp).sendEachForMulticast({ ...base, tokens: [...group] });\n batch.responses.forEach((resp, i) => {\n const errorCode = resp.error?.code ?? null;\n if (errorCode === \"messaging/invalid-argument\") {\n console.error(`[FCM] invalid-argument for token ${maskToken(group[i])}: ${errorCode}`);\n }\n outcomes.push({\n errorCode,\n messageId: resp.messageId ?? null,\n success: resp.success,\n token: group[i]\n });\n });\n } catch (error) {\n console.error(\"[FCM] multicast chunk failed:\", fcmErrorLabel(error));\n for (const token of group) {\n outcomes.push({ errorCode: null, messageId: null, success: false, token });\n }\n }\n }\n return summarizeFcmFanOut(outcomes);\n}\nfunction buildDataMessage(payload) {\n return {\n android: {\n priority: \"high\",\n // Ensures delivery even in Doze mode\n ttl: 3e5\n // 5 minutes TTL (matches pending request expiry)\n },\n data: {\n body: payload.body || payload.message || \"\",\n category: payload.category ?? (typeof payload.data?.category === \"string\" ? payload.data.category : \"\"),\n project: typeof payload.data?.project === \"string\" ? payload.data.project : \"\",\n requestId: typeof payload.data?.requestId === \"string\" ? payload.data.requestId : \"\",\n source: typeof payload.data?.source === \"string\" ? payload.data.source : \"\",\n subtitle: payload.subtitle ?? \"\",\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n title: payload.title,\n toolInput: payload.data?.toolInput ? JSON.stringify(payload.data.toolInput) : \"\",\n toolName: typeof payload.data?.toolName === \"string\" ? payload.data.toolName : \"\",\n type: typeof payload.data?.type === \"string\" ? payload.data.type : \"\"\n }\n };\n}\nfunction fcmErrorLabel(error) {\n if (error && typeof error === \"object\" && \"code\" in error) {\n const code = error.code;\n if (typeof code === \"string\" && code.length > 0) {\n return code;\n }\n }\n return error instanceof Error ? error.message : String(error);\n}\nfunction getApp() {\n if (!app) {\n const projectId = process.env.FCM_PROJECT_ID;\n const clientEmail = process.env.FCM_CLIENT_EMAIL;\n const privateKey = process.env.FCM_PRIVATE_KEY?.replace(/\\\\n/g, \"\\n\");\n if (!projectId || !clientEmail || !privateKey) {\n throw new Error(\n \"FCM not configured: missing FCM_PROJECT_ID, FCM_CLIENT_EMAIL, or FCM_PRIVATE_KEY\"\n );\n }\n app = admin.initializeApp({\n credential: admin.credential.cert({ clientEmail, privateKey, projectId })\n });\n }\n return app;\n}\nlet apnsSingleton = null;\nfunction getAPNsClient() {\n if (!apnsSingleton) {\n apnsSingleton = new LibraryAPNsService();\n }\n return apnsSingleton;\n}\nconst EMPTY_APNS_RESULT = {\n results: [],\n staleTokens: [],\n totalFailed: 0,\n totalSent: 0\n};\nconst EMPTY_FCM_RESULT = {\n failureCount: 0,\n results: [],\n staleTokens: [],\n successCount: 0\n};\nfunction resolveAndroidTokens() {\n const rows = deviceTokenStore.listActive(\"android\");\n if (rows.length > 0) {\n return rows.map((r) => r.token);\n }\n const seed = private_env.ANDROID_DEVICE_TOKEN?.trim();\n return seed ? [seed] : [];\n}\nfunction resolveIosDevices(override) {\n const appEnv = serverApnEnv();\n if (override) {\n return [syntheticSeedDevice(override, \"ios\", appEnv)];\n }\n const rows = deviceTokenStore.listActiveForEnv(\"ios\", appEnv);\n if (rows.length > 0) {\n return rows;\n }\n const seed = private_env.DEVICE_TOKEN?.trim();\n return seed ? [syntheticSeedDevice(seed, \"ios\", appEnv)] : [];\n}\nfunction serverApnEnv() {\n return private_env.APNS_PRODUCTION === \"true\" ? \"production\" : \"sandbox\";\n}\nfunction syntheticSeedDevice(token, platform, appEnv) {\n const nowIso = (/* @__PURE__ */ new Date()).toISOString();\n return {\n appEnv,\n bundleId: null,\n deviceId: null,\n failureCount: 0,\n friendlyName: null,\n id: `seed-${platform}`,\n isActive: true,\n lastSeenAt: nowIso,\n platform,\n registeredAt: nowIso,\n token\n };\n}\nconst notificationCache = /* @__PURE__ */ new Map();\nconst DEDUP_WINDOW = 1e4;\nfunction broadcastHookEvent(body) {\n const data = body.data ?? {};\n const eventType = typeof data.eventType === \"string\" ? data.eventType : typeof body.eventType === \"string\" ? body.eventType : \"\";\n const tool = typeof data.tool === \"string\" ? data.tool : \"\";\n const terminalId = typeof data.terminalId === \"string\" ? data.terminalId : void 0;\n const sessionId = typeof data.sessionId === \"string\" ? data.sessionId : void 0;\n switch (eventType) {\n case \"error\":\n broadcastEvent({\n error: typeof data.error === \"string\" ? data.error : typeof data.message === \"string\" ? data.message : \"Unknown error\",\n terminalId,\n tool,\n type: \"tool-failed\"\n });\n break;\n case \"idle_input\":\n case \"session.idle\":\n broadcastEvent({\n message: typeof data.message === \"string\" ? data.message : \"\",\n sessionId,\n terminalId,\n type: \"agent-idle\"\n });\n break;\n case \"permission\":\n case \"permission_notification\":\n if (data.requestId && data.toolName) {\n broadcastEvent({\n input: typeof data.toolInput === \"object\" && data.toolInput !== null ? data.toolInput : {},\n requestId: data.requestId,\n tool: data.toolName,\n type: \"permission-requested\"\n });\n }\n break;\n case \"question\":\n broadcastEvent({\n message: typeof data.message === \"string\" ? data.message : \"\",\n sessionId,\n terminalId,\n type: \"agent-question\"\n });\n break;\n case \"tool.after\":\n broadcastEvent({ success: true, terminalId, tool, type: \"tool-completed\" });\n break;\n case \"tool.before\":\n broadcastEvent({\n command: typeof data.command === \"string\" ? data.command : \"\",\n filePath: typeof data.filePath === \"string\" ? data.filePath : typeof data.files === \"string\" ? data.files : \"\",\n terminalId,\n tool,\n type: \"tool-started\"\n });\n break;\n }\n}\nfunction buildNotificationRecord(id, title, message, status, data, error) {\n return {\n category: data?.category ?? null,\n data: data ?? null,\n error: error ?? null,\n id,\n message,\n project: data?.project ?? null,\n source: data?.source ?? null,\n status,\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n title,\n tool: data?.tool ?? null\n };\n}\nfunction intelligentNotificationFilter(title, message, data, waitForResponse = false) {\n const source = data?.source || \"unknown\";\n if (waitForResponse) {\n return { reason: \"Bidirectional request — never filtered\", send: true };\n }\n if (isDuplicateNotification(title, message, data, waitForResponse)) {\n return {\n reason: \"Duplicate notification within 10-second window\",\n send: false\n };\n }\n if (source === \"smart-completion-detector\" || source === \"shooter-completion-detector\") {\n return {\n reason: \"Smart completion detector - completion or intervention needed\",\n send: true\n };\n }\n const spamPatterns = [\n /PreToolUse/i,\n // Any PreToolUse notifications\n /PostToolUse/i,\n // Any PostToolUse notifications\n /^(Read|Write|Edit|Bash)\\s+Starting\\s*\\|\\s*\\w+$/i,\n // Only basic tool starting patterns\n /^unknown\\s*\\|\\s*\\w+$/i\n // Only \"unknown | projectname\" exactly\n ];\n const isSpam = spamPatterns.some((pattern) => pattern.test(title) || pattern.test(message));\n if (isSpam) {\n return {\n reason: \"Filtered spam notification from old hook system\",\n send: false\n };\n }\n const importantPatterns = [\n /session complete/i,\n /intervention needed/i,\n /error/i,\n /failed/i,\n /blocked/i,\n /attention/i\n ];\n const isImportant = importantPatterns.some(\n (pattern) => pattern.test(title) || pattern.test(message)\n );\n if (isImportant) {\n return {\n reason: \"Important notification - completion or intervention\",\n send: true\n };\n }\n return {\n reason: \"General notification - allowing by default\",\n send: true\n };\n}\nfunction isDuplicateNotification(title, message, data, waitForResponse = false) {\n if (waitForResponse) {\n return false;\n }\n const dataRecord = data;\n const key = dataRecord?.dedupKey ? dataRecord.dedupKey : `${title}|${message}|${data?.category || \"unknown\"}`;\n const now = Date.now();\n if (notificationCache.has(key)) {\n const lastSent = notificationCache.get(key) ?? 0;\n if (now - lastSent < DEDUP_WINDOW) {\n return true;\n }\n }\n for (const [k, v] of notificationCache.entries()) {\n if (now - v > DEDUP_WINDOW) {\n notificationCache.delete(k);\n }\n }\n notificationCache.set(key, now);\n return false;\n}\nfunction notificationKey(title, message, data) {\n const dataRecord = data;\n return dataRecord?.dedupKey ?? `${title}|${message}|${data?.category || \"unknown\"}`;\n}\nfunction recordNotification(title, message, data) {\n notificationCache.set(notificationKey(title, message, data), Date.now());\n}\nfunction releaseNotification(title, message, data) {\n notificationCache.delete(notificationKey(title, message, data));\n}\nconst POST = async ({ request }) => {\n try {\n const apnsClient = getAPNsClient();\n const authError = validateAuth(request);\n if (authError) {\n return authError;\n }\n const rawBody = await request.json();\n if (!rawBody || typeof rawBody !== \"object\" || Array.isArray(rawBody)) {\n return json({ error: \"Request body must be a JSON object\" }, { status: 400 });\n }\n const body = rawBody;\n const data = body.data;\n const requestDeviceToken = body.deviceToken;\n const message = body.message;\n const title = body.title;\n const subtitle = typeof body.subtitle === \"string\" ? body.subtitle : void 0;\n const skipPush = typeof body.skipPush === \"boolean\" ? body.skipPush : false;\n const waitForResponse = typeof body.waitForResponse === \"boolean\" ? body.waitForResponse : false;\n const forcePush = typeof body.forcePush === \"boolean\" ? body.forcePush : false;\n const notificationCategory = typeof body.notificationCategory === \"string\" && body.notificationCategory.length > 0 ? body.notificationCategory : void 0;\n const question = typeof body.question === \"string\" ? body.question : void 0;\n const options = Array.isArray(body.options) && body.options.every((o) => o && typeof o === \"object\") ? body.options : void 0;\n const responseKindRaw = body.responseKind;\n const responseKind = responseKindRaw === \"hook\" || responseKindRaw === \"pty\" || responseKindRaw === \"info\" ? responseKindRaw : void 0;\n try {\n broadcastHookEvent(body);\n } catch {\n }\n if (!title || typeof title !== \"string\" || !message || typeof message !== \"string\") {\n return json({ error: \"Title and message are required and must be strings\" }, { status: 400 });\n }\n if (requestDeviceToken !== void 0 && typeof requestDeviceToken !== \"string\") {\n return json({ error: \"deviceToken must be a string\" }, { status: 400 });\n }\n const requestId = Math.random().toString(36).substring(2, 15);\n const dataRequestId = typeof data?.requestId === \"string\" ? data.requestId : void 0;\n const canonicalRequestId = dataRequestId || requestId;\n const shouldSendNotification = intelligentNotificationFilter(\n title,\n message,\n data,\n waitForResponse\n );\n if (!shouldSendNotification.send) {\n addNotification(\n buildNotificationRecord(\n canonicalRequestId,\n title,\n message,\n \"filtered\",\n data,\n shouldSendNotification.reason\n )\n );\n return json({\n message: \"Notification filtered (not sent)\",\n reason: shouldSendNotification.reason,\n success: true,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n if (skipPush && !forcePush) {\n if (waitForResponse) {\n createPendingRequest(canonicalRequestId, {\n options,\n question: question ?? null,\n responseKind: responseKind ?? \"hook\",\n sessionId: data?.sessionId || \"\",\n toolInput: data?.toolInput || {},\n toolName: data?.toolName || \"\"\n });\n }\n addNotification(buildNotificationRecord(canonicalRequestId, title, message, \"skipped\", data));\n return json({\n message: \"Push skipped (WebSocket clients connected)\",\n requestId: canonicalRequestId,\n success: true,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n const payload = {\n badge: 1,\n body: message,\n // notificationCategory wins when explicitly set so plan-mode /\n // elicitation flows can pick CLAUDE_PLAN_APPROVAL / CHOICE_2..4.\n // Falls back to CLAUDE_PERMISSION for the legacy bidirectional\n // permission flow when only waitForResponse is provided.\n category: notificationCategory ?? (waitForResponse ? \"CLAUDE_PERMISSION\" : void 0),\n data: {\n ...data,\n requestId: canonicalRequestId,\n source: \"modern-apns-api\",\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n waitForResponse: waitForResponse || false\n },\n message: null,\n sound: \"default\",\n ...subtitle ? { subtitle } : {},\n title\n };\n const override = requestDeviceToken?.trim() || void 0;\n const { doAndroid, doIos } = selectPlatforms(private_env.DEVICE_PLATFORM);\n const iosDevices = doIos ? override ? resolveIosDevices(override) : resolveIosDevices() : [];\n const androidTokens = doAndroid ? override ? [override] : resolveAndroidTokens() : [];\n const collapseId = waitForResponse ? canonicalRequestId : void 0;\n const [apnsResult, fcmResult] = await Promise.all([\n iosDevices.length > 0 && apnsClient.isConfigured() ? apnsClient.sendToMany(iosDevices, payload, collapseId) : Promise.resolve(EMPTY_APNS_RESULT),\n androidTokens.length > 0 && isFCMConfigured() ? sendFCMNotificationMulti(androidTokens, payload) : Promise.resolve(EMPTY_FCM_RESULT)\n ]);\n const summary = summarizeNotifyDelivery(apnsResult, fcmResult);\n const pruned = !override && summary.staleTokens.length ? deviceTokenStore.pruneByTokens(summary.staleTokens) : 0;\n if (summary.succeededTokens.length > 0) {\n deviceTokenStore.touchLastSeen(summary.succeededTokens);\n }\n if (summary.delivered && summary.failed === 0) {\n recordNotification(title, message, data);\n } else {\n releaseNotification(title, message, data);\n }\n if (waitForResponse && summary.delivered) {\n createPendingRequest(canonicalRequestId, {\n options,\n question: question ?? null,\n responseKind: responseKind ?? \"hook\",\n sessionId: data?.sessionId || \"\",\n toolInput: data?.toolInput || {},\n toolName: data?.toolName || \"\"\n });\n }\n addNotification(\n buildNotificationRecord(\n canonicalRequestId,\n title,\n message,\n summary.delivered ? \"sent\" : \"failed\",\n data,\n summary.delivered ? null : \"No registered device accepted the notification\"\n )\n );\n return json({\n failed: summary.failed,\n pruned,\n requestId: canonicalRequestId,\n sent: summary.sent,\n success: summary.delivered,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n } catch (error) {\n console.error(\"Notification error:\", error);\n return json(\n {\n details: toErrorMessage(error),\n error: \"Failed to send notification\",\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n },\n { status: 500 }\n );\n }\n};\nconst GET = ({ request, url }) => {\n const authError = validateAuth(request);\n if (authError) {\n return authError;\n }\n const limit = parseInt(url.searchParams.get(\"limit\") || \"50\");\n const notifications = getNotifications(limit);\n return json({\n count: notifications.length,\n notifications,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n};\nexport {\n GET,\n POST\n};\n"],"names":[],"mappings":"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"}
@@ -1,12 +1,18 @@
1
1
  import { b as private_env } from './shared-server-DaWdgxVh.js';
2
- import { L as LibraryAPNsService } from './library-apns-D8RPINlv.js';
2
+ import { L as LibraryAPNsService } from './library-apns-DMlL1BAg.js';
3
3
  import { v as validateAuth } from './auth-DuunT7Cg.js';
4
+ import { d as deviceTokenStore } from './device-token-store-Ct7aTeR8.js';
4
5
  import { j as json } from './index-lhTMmBNn.js';
5
6
  import 'child_process';
6
7
  import 'jsonwebtoken';
7
8
  import 'util';
8
9
  import './error-DDXB3duW.js';
9
10
  import 'crypto';
11
+ import 'better-sqlite3';
12
+ import 'fs';
13
+ import 'path';
14
+ import './shooter-home-4f_HkdGI.js';
15
+ import 'os';
10
16
 
11
17
  const GET = ({ request }) => {
12
18
  const authError = validateAuth(request);
@@ -14,7 +20,9 @@ const GET = ({ request }) => {
14
20
  return authError;
15
21
  }
16
22
  const apnsClient = new LibraryAPNsService();
17
- const deviceToken = private_env.DEVICE_TOKEN?.trim();
23
+ const apnsEnv = private_env.APNS_PRODUCTION === "true" ? "production" : "sandbox";
24
+ const iosDevices = deviceTokenStore.listActiveForEnv("ios", apnsEnv);
25
+ const deviceToken = iosDevices[0]?.token ?? private_env.DEVICE_TOKEN?.trim() ?? "";
18
26
  return json({
19
27
  apns: {
20
28
  configured: apnsClient.isConfigured(),
@@ -31,9 +39,13 @@ const GET = ({ request }) => {
31
39
  },
32
40
  environment: private_env.NODE_ENV || "development",
33
41
  hasApiKey: !!private_env.API_KEY,
42
+ registeredDevices: {
43
+ android: deviceTokenStore.listActive("android").length,
44
+ ios: iosDevices.length
45
+ },
34
46
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
35
47
  });
36
48
  };
37
49
 
38
50
  export { GET };
39
- //# sourceMappingURL=_server.ts-EJVmhLtg.js.map
51
+ //# sourceMappingURL=_server.ts-BSS8cO80.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_server.ts-BSS8cO80.js","sources":["../../../.svelte-kit/adapter-node/entries/endpoints/api/debug/_server.ts.js"],"sourcesContent":["import { b as private_env } from \"../../../../chunks/shared-server.js\";\nimport { L as LibraryAPNsService } from \"../../../../chunks/library-apns.js\";\nimport { v as validateAuth } from \"../../../../chunks/auth.js\";\nimport { d as deviceTokenStore } from \"../../../../chunks/device-token-store.js\";\nimport { json } from \"@sveltejs/kit\";\nconst GET = ({ request }) => {\n const authError = validateAuth(request);\n if (authError) {\n return authError;\n }\n const apnsClient = new LibraryAPNsService();\n const apnsEnv = private_env.APNS_PRODUCTION === \"true\" ? \"production\" : \"sandbox\";\n const iosDevices = deviceTokenStore.listActiveForEnv(\"ios\", apnsEnv);\n const deviceToken = iosDevices[0]?.token ?? private_env.DEVICE_TOKEN?.trim() ?? \"\";\n return json({\n apns: {\n configured: apnsClient.isConfigured(),\n environment: private_env.APNS_PRODUCTION === \"true\" ? \"production\" : \"sandbox\",\n hasBundleId: !!private_env.APNS_BUNDLE_ID,\n hasKey: !!private_env.APNS_KEY,\n hasKeyId: !!private_env.APNS_KEY_ID,\n hasTeamId: !!private_env.APNS_TEAM_ID\n },\n deviceToken: {\n exists: !!deviceToken,\n length: deviceToken ? deviceToken.length : 0,\n valid: deviceToken ? /^[a-f0-9]{64}$/i.test(deviceToken) : false\n },\n environment: private_env.NODE_ENV || \"development\",\n hasApiKey: !!private_env.API_KEY,\n registeredDevices: {\n android: deviceTokenStore.listActive(\"android\").length,\n ios: iosDevices.length\n },\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n};\nexport {\n GET\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAKK,MAAC,GAAG,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK;AAC7B,EAAE,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC;AACzC,EAAE,IAAI,SAAS,EAAE;AACjB,IAAI,OAAO,SAAS;AACpB,EAAE;AACF,EAAE,MAAM,UAAU,GAAG,IAAI,kBAAkB,EAAE;AAC7C,EAAE,MAAM,OAAO,GAAG,WAAW,CAAC,eAAe,KAAK,MAAM,GAAG,YAAY,GAAG,SAAS;AACnF,EAAE,MAAM,UAAU,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC;AACtE,EAAE,MAAM,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,WAAW,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE;AACpF,EAAE,OAAO,IAAI,CAAC;AACd,IAAI,IAAI,EAAE;AACV,MAAM,UAAU,EAAE,UAAU,CAAC,YAAY,EAAE;AAC3C,MAAM,WAAW,EAAE,WAAW,CAAC,eAAe,KAAK,MAAM,GAAG,YAAY,GAAG,SAAS;AACpF,MAAM,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,cAAc;AAC/C,MAAM,MAAM,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ;AACpC,MAAM,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,WAAW;AACzC,MAAM,SAAS,EAAE,CAAC,CAAC,WAAW,CAAC;AAC/B,KAAK;AACL,IAAI,WAAW,EAAE;AACjB,MAAM,MAAM,EAAE,CAAC,CAAC,WAAW;AAC3B,MAAM,MAAM,EAAE,WAAW,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC;AAClD,MAAM,KAAK,EAAE,WAAW,GAAG,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG;AACjE,KAAK;AACL,IAAI,WAAW,EAAE,WAAW,CAAC,QAAQ,IAAI,aAAa;AACtD,IAAI,SAAS,EAAE,CAAC,CAAC,WAAW,CAAC,OAAO;AACpC,IAAI,iBAAiB,EAAE;AACvB,MAAM,OAAO,EAAE,gBAAgB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,MAAM;AAC5D,MAAM,GAAG,EAAE,UAAU,CAAC;AACtB,KAAK;AACL,IAAI,SAAS,EAAE,iBAAiB,IAAI,IAAI,EAAE,EAAE,WAAW;AACvD,GAAG,CAAC;AACJ;;;;"}