@agent-native/core 0.109.2 → 0.109.3
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +8 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/create.ts +18 -12
- package/corpus/core/src/client/require-session.tsx +19 -3
- package/corpus/core/src/client/use-action.ts +145 -2
- package/corpus/core/src/client/use-session.ts +79 -48
- package/corpus/core/src/db/client.ts +13 -7
- package/corpus/core/src/db/create-get-db.ts +20 -13
- package/corpus/core/src/db/request-telemetry.ts +154 -0
- package/corpus/core/src/integrations/index.ts +1 -0
- package/corpus/core/src/integrations/plugin.ts +9 -3
- package/corpus/core/src/integrations/remote-push-delivery-job.ts +48 -0
- package/corpus/core/src/integrations/remote-push-delivery.ts +370 -0
- package/corpus/core/src/integrations/remote-push-store.ts +275 -26
- package/corpus/core/src/server/better-auth-instance.ts +11 -3
- package/corpus/core/src/server/core-routes-plugin.ts +36 -14
- package/corpus/core/src/server/framework-request-handler.ts +11 -1
- package/corpus/core/src/server/http-response-telemetry.ts +233 -31
- package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +19 -0
- package/corpus/templates/clips/actions/finalize-recording.ts +3 -1
- package/corpus/templates/clips/actions/set-mobile-capture-state.ts +4 -1
- package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -6
- package/corpus/templates/clips/changelog/2026-07-18-new-recording-is-now-emphasized-as-the-primary-action-in-the.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-18-recordings-now-remain-safely-recoverable-until-the-stored-me.md +6 -0
- package/corpus/templates/tasks/AGENTS.md +3 -0
- package/corpus/templates/tasks/actions/render-task-list-inline.ts +202 -0
- package/corpus/templates/tasks/changelog/2026-07-18-task-lists-can-now-appear-as-interactive-widgets-inline-in-c.md +6 -0
- package/corpus/templates/tasks/docs/features/f8-chat.mdx +2 -0
- package/corpus/templates/tasks/server/plugins/agent-chat.ts +2 -0
- package/dist/cli/create.d.ts +10 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +17 -13
- package/dist/cli/create.js.map +1 -1
- package/dist/client/require-session.d.ts.map +1 -1
- package/dist/client/require-session.js +6 -3
- package/dist/client/require-session.js.map +1 -1
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +117 -1
- package/dist/client/use-action.js.map +1 -1
- package/dist/client/use-session.d.ts.map +1 -1
- package/dist/client/use-session.js +72 -50
- package/dist/client/use-session.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +7 -1
- package/dist/db/client.js.map +1 -1
- package/dist/db/create-get-db.d.ts +3 -6
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +9 -2
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/db/request-telemetry.d.ts +23 -0
- package/dist/db/request-telemetry.d.ts.map +1 -0
- package/dist/db/request-telemetry.js +95 -0
- package/dist/db/request-telemetry.js.map +1 -0
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/index.d.ts +1 -0
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +1 -0
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +8 -3
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/remote-push-delivery-job.d.ts +4 -0
- package/dist/integrations/remote-push-delivery-job.d.ts.map +1 -0
- package/dist/integrations/remote-push-delivery-job.js +44 -0
- package/dist/integrations/remote-push-delivery-job.js.map +1 -0
- package/dist/integrations/remote-push-delivery.d.ts +11 -0
- package/dist/integrations/remote-push-delivery.d.ts.map +1 -0
- package/dist/integrations/remote-push-delivery.js +265 -0
- package/dist/integrations/remote-push-delivery.js.map +1 -0
- package/dist/integrations/remote-push-store.d.ts +33 -0
- package/dist/integrations/remote-push-store.d.ts.map +1 -1
- package/dist/integrations/remote-push-store.js +195 -26
- package/dist/integrations/remote-push-store.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/better-auth-instance.js +7 -3
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +8 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +23 -8
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +9 -1
- package/dist/server/framework-request-handler.js.map +1 -1
- package/dist/server/http-response-telemetry.d.ts +3 -2
- package/dist/server/http-response-telemetry.d.ts.map +1 -1
- package/dist/server/http-response-telemetry.js +160 -27
- package/dist/server/http-response-telemetry.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +19 -0
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +19 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-push-delivery-job.d.ts","sourceRoot":"","sources":["../../src/integrations/remote-push-delivery-job.ts"],"names":[],"mappings":"AAQA,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAY3D;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CASjD;AAED,wBAAgB,yBAAyB,IAAI,IAAI,CAUhD"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { deliverPendingRemotePushNotifications } from "./remote-push-delivery.js";
|
|
2
|
+
const DELIVERY_INTERVAL_MS = 60_000;
|
|
3
|
+
let retryInterval = null;
|
|
4
|
+
let initialTimer = null;
|
|
5
|
+
let running = false;
|
|
6
|
+
export async function runRemotePushDelivery() {
|
|
7
|
+
if (running)
|
|
8
|
+
return;
|
|
9
|
+
running = true;
|
|
10
|
+
try {
|
|
11
|
+
await deliverPendingRemotePushNotifications();
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
console.error("[integrations] Remote push delivery failed", {
|
|
15
|
+
error: error instanceof Error ? error.name : "UnknownError",
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
running = false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function startRemotePushDeliveryJob() {
|
|
23
|
+
if (retryInterval)
|
|
24
|
+
return;
|
|
25
|
+
initialTimer = setTimeout(() => void runRemotePushDelivery(), 10_000);
|
|
26
|
+
unrefTimer(initialTimer);
|
|
27
|
+
retryInterval = setInterval(() => void runRemotePushDelivery(), DELIVERY_INTERVAL_MS);
|
|
28
|
+
unrefTimer(retryInterval);
|
|
29
|
+
}
|
|
30
|
+
export function stopRemotePushDeliveryJob() {
|
|
31
|
+
if (initialTimer) {
|
|
32
|
+
clearTimeout(initialTimer);
|
|
33
|
+
initialTimer = null;
|
|
34
|
+
}
|
|
35
|
+
if (retryInterval) {
|
|
36
|
+
clearInterval(retryInterval);
|
|
37
|
+
retryInterval = null;
|
|
38
|
+
}
|
|
39
|
+
running = false;
|
|
40
|
+
}
|
|
41
|
+
function unrefTimer(timer) {
|
|
42
|
+
timer.unref?.();
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=remote-push-delivery-job.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-push-delivery-job.js","sourceRoot":"","sources":["../../src/integrations/remote-push-delivery-job.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qCAAqC,EAAE,MAAM,2BAA2B,CAAC;AAElF,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAEpC,IAAI,aAAa,GAA0C,IAAI,CAAC;AAChE,IAAI,YAAY,GAAyC,IAAI,CAAC;AAC9D,IAAI,OAAO,GAAG,KAAK,CAAC;AAEpB,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,IAAI,OAAO;QAAE,OAAO;IACpB,OAAO,GAAG,IAAI,CAAC;IACf,IAAI,CAAC;QACH,MAAM,qCAAqC,EAAE,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE;YAC1D,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc;SAC5D,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,OAAO,GAAG,KAAK,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,IAAI,aAAa;QAAE,OAAO;IAC1B,YAAY,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,qBAAqB,EAAE,EAAE,MAAM,CAAC,CAAC;IACtE,UAAU,CAAC,YAAY,CAAC,CAAC;IACzB,aAAa,GAAG,WAAW,CACzB,GAAG,EAAE,CAAC,KAAK,qBAAqB,EAAE,EAClC,oBAAoB,CACrB,CAAC;IACF,UAAU,CAAC,aAAa,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,IAAI,YAAY,EAAE,CAAC;QACjB,YAAY,CAAC,YAAY,CAAC,CAAC;QAC3B,YAAY,GAAG,IAAI,CAAC;IACtB,CAAC;IACD,IAAI,aAAa,EAAE,CAAC;QAClB,aAAa,CAAC,aAAa,CAAC,CAAC;QAC7B,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;IACD,OAAO,GAAG,KAAK,CAAC;AAClB,CAAC;AAED,SAAS,UAAU,CAAC,KAAqC;IACtD,KAA2C,CAAC,KAAK,EAAE,EAAE,CAAC;AACzD,CAAC","sourcesContent":["import { deliverPendingRemotePushNotifications } from \"./remote-push-delivery.js\";\n\nconst DELIVERY_INTERVAL_MS = 60_000;\n\nlet retryInterval: ReturnType<typeof setInterval> | null = null;\nlet initialTimer: ReturnType<typeof setTimeout> | null = null;\nlet running = false;\n\nexport async function runRemotePushDelivery(): Promise<void> {\n if (running) return;\n running = true;\n try {\n await deliverPendingRemotePushNotifications();\n } catch (error) {\n console.error(\"[integrations] Remote push delivery failed\", {\n error: error instanceof Error ? error.name : \"UnknownError\",\n });\n } finally {\n running = false;\n }\n}\n\nexport function startRemotePushDeliveryJob(): void {\n if (retryInterval) return;\n initialTimer = setTimeout(() => void runRemotePushDelivery(), 10_000);\n unrefTimer(initialTimer);\n retryInterval = setInterval(\n () => void runRemotePushDelivery(),\n DELIVERY_INTERVAL_MS,\n );\n unrefTimer(retryInterval);\n}\n\nexport function stopRemotePushDeliveryJob(): void {\n if (initialTimer) {\n clearTimeout(initialTimer);\n initialTimer = null;\n }\n if (retryInterval) {\n clearInterval(retryInterval);\n retryInterval = null;\n }\n running = false;\n}\n\nfunction unrefTimer(timer: ReturnType<typeof setInterval>): void {\n (timer as unknown as { unref?: () => void }).unref?.();\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare function deliverPendingRemotePushNotifications(options?: {
|
|
2
|
+
fetchImpl?: typeof fetch;
|
|
3
|
+
now?: () => number;
|
|
4
|
+
limit?: number;
|
|
5
|
+
}): Promise<{
|
|
6
|
+
sent: number;
|
|
7
|
+
delivered: number;
|
|
8
|
+
retried: number;
|
|
9
|
+
failed: number;
|
|
10
|
+
}>;
|
|
11
|
+
//# sourceMappingURL=remote-push-delivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-push-delivery.d.ts","sourceRoot":"","sources":["../../src/integrations/remote-push-delivery.ts"],"names":[],"mappings":"AAmCA,wBAAsB,qCAAqC,CAAC,OAAO,CAAC,EAAE;IACpE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAgED"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { claimNextRemotePushDelivery, deactivateRemotePushRegistration, failRemotePushDelivery, markRemotePushDelivered, markRemotePushTicketAccepted, retryRemotePushDelivery, } from "./remote-push-store.js";
|
|
2
|
+
const EXPO_PUSH_SEND_URL = "https://exp.host/--/api/v2/push/send";
|
|
3
|
+
const EXPO_PUSH_RECEIPTS_URL = "https://exp.host/--/api/v2/push/getReceipts";
|
|
4
|
+
const REQUEST_TIMEOUT_MS = 10_000;
|
|
5
|
+
const RECEIPT_CHECK_DELAY_MS = 15 * 60_000;
|
|
6
|
+
const MAX_DELIVERY_ATTEMPTS = 12;
|
|
7
|
+
const DEFAULT_DELIVERY_LIMIT = 100;
|
|
8
|
+
export async function deliverPendingRemotePushNotifications(options) {
|
|
9
|
+
const fetchImpl = options?.fetchImpl ?? fetch;
|
|
10
|
+
const now = options?.now ?? Date.now;
|
|
11
|
+
const limit = Math.max(1, Math.min(options?.limit ?? DEFAULT_DELIVERY_LIMIT, 100));
|
|
12
|
+
const summary = { sent: 0, delivered: 0, retried: 0, failed: 0 };
|
|
13
|
+
const claimedDeliveries = [];
|
|
14
|
+
for (let processed = 0; processed < limit; processed++) {
|
|
15
|
+
const delivery = await claimNextRemotePushDelivery({ now: now() });
|
|
16
|
+
if (!delivery)
|
|
17
|
+
break;
|
|
18
|
+
if (delivery.attempts > MAX_DELIVERY_ATTEMPTS) {
|
|
19
|
+
await failRemotePushDelivery({
|
|
20
|
+
id: delivery.id,
|
|
21
|
+
phase: delivery.phase,
|
|
22
|
+
errorCode: "attempts_exhausted",
|
|
23
|
+
});
|
|
24
|
+
summary.failed++;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
claimedDeliveries.push(delivery);
|
|
28
|
+
}
|
|
29
|
+
const sendDeliveries = claimedDeliveries.filter((delivery) => delivery.phase === "send");
|
|
30
|
+
if (sendDeliveries.length > 0) {
|
|
31
|
+
let outcomes;
|
|
32
|
+
try {
|
|
33
|
+
outcomes = await sendExpoPushNotifications(sendDeliveries, fetchImpl);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
const errorCode = classifyTransportError(error);
|
|
37
|
+
outcomes = sendDeliveries.map(() => ({ kind: "retry", errorCode }));
|
|
38
|
+
}
|
|
39
|
+
for (let index = 0; index < sendDeliveries.length; index++) {
|
|
40
|
+
await applyDeliveryOutcome(sendDeliveries[index], outcomes[index], summary, now);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
for (const delivery of claimedDeliveries) {
|
|
44
|
+
if (delivery.phase !== "receipt")
|
|
45
|
+
continue;
|
|
46
|
+
let outcome;
|
|
47
|
+
try {
|
|
48
|
+
outcome = await readExpoPushReceipt(delivery, fetchImpl);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
outcome = {
|
|
52
|
+
kind: "retry",
|
|
53
|
+
errorCode: classifyTransportError(error),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
await applyDeliveryOutcome(delivery, outcome, summary, now);
|
|
57
|
+
}
|
|
58
|
+
return summary;
|
|
59
|
+
}
|
|
60
|
+
async function applyDeliveryOutcome(delivery, outcome, summary, now) {
|
|
61
|
+
if (outcome.kind === "ticket") {
|
|
62
|
+
await markRemotePushTicketAccepted({
|
|
63
|
+
id: delivery.id,
|
|
64
|
+
providerTicketId: outcome.ticketId,
|
|
65
|
+
checkAfter: now() + RECEIPT_CHECK_DELAY_MS,
|
|
66
|
+
});
|
|
67
|
+
summary.sent++;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (outcome.kind === "delivered") {
|
|
71
|
+
await markRemotePushDelivered(delivery.id);
|
|
72
|
+
summary.delivered++;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (outcome.kind === "failed") {
|
|
76
|
+
await failRemotePushDelivery({
|
|
77
|
+
id: delivery.id,
|
|
78
|
+
phase: delivery.phase,
|
|
79
|
+
errorCode: outcome.errorCode,
|
|
80
|
+
});
|
|
81
|
+
if (outcome.deactivate) {
|
|
82
|
+
await deactivateRemotePushRegistration(delivery.registrationId);
|
|
83
|
+
}
|
|
84
|
+
summary.failed++;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
await retryRemotePushDelivery({
|
|
88
|
+
id: delivery.id,
|
|
89
|
+
phase: delivery.phase,
|
|
90
|
+
retryAt: now() + retryDelayMs(delivery.attempts),
|
|
91
|
+
errorCode: outcome.errorCode,
|
|
92
|
+
resend: outcome.resend,
|
|
93
|
+
});
|
|
94
|
+
summary.retried++;
|
|
95
|
+
}
|
|
96
|
+
async function sendExpoPushNotifications(deliveries, fetchImpl) {
|
|
97
|
+
const outcomes = new Map();
|
|
98
|
+
const supportedDeliveries = deliveries.filter((delivery) => {
|
|
99
|
+
const supported = delivery.provider === "expo" && isExpoPushToken(delivery.token);
|
|
100
|
+
if (!supported) {
|
|
101
|
+
outcomes.set(delivery.id, {
|
|
102
|
+
kind: "failed",
|
|
103
|
+
errorCode: "unsupported_push_registration",
|
|
104
|
+
deactivate: true,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return supported;
|
|
108
|
+
});
|
|
109
|
+
if (supportedDeliveries.length === 0) {
|
|
110
|
+
return deliveries.map((delivery) => outcomes.get(delivery.id));
|
|
111
|
+
}
|
|
112
|
+
const messages = supportedDeliveries.map(buildExpoMessage);
|
|
113
|
+
const response = await fetchWithTimeout(fetchImpl, EXPO_PUSH_SEND_URL, expoRequestInit(messages.length === 1 ? messages[0] : messages));
|
|
114
|
+
const body = await readExpoResponse(response);
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
const outcome = responseFailure(response.status, body);
|
|
117
|
+
for (const delivery of supportedDeliveries) {
|
|
118
|
+
outcomes.set(delivery.id, outcome);
|
|
119
|
+
}
|
|
120
|
+
return deliveries.map((delivery) => outcomes.get(delivery.id));
|
|
121
|
+
}
|
|
122
|
+
const tickets = Array.isArray(body.data)
|
|
123
|
+
? body.data
|
|
124
|
+
: body.data && isExpoResult(body.data)
|
|
125
|
+
? [body.data]
|
|
126
|
+
: [];
|
|
127
|
+
if (tickets.length !== supportedDeliveries.length ||
|
|
128
|
+
tickets.some((ticket) => !isExpoResult(ticket))) {
|
|
129
|
+
for (const delivery of supportedDeliveries) {
|
|
130
|
+
outcomes.set(delivery.id, {
|
|
131
|
+
kind: "retry",
|
|
132
|
+
errorCode: "invalid_push_ticket",
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return deliveries.map((delivery) => outcomes.get(delivery.id));
|
|
136
|
+
}
|
|
137
|
+
for (let index = 0; index < supportedDeliveries.length; index++) {
|
|
138
|
+
const delivery = supportedDeliveries[index];
|
|
139
|
+
const ticket = tickets[index];
|
|
140
|
+
outcomes.set(delivery.id, ticket.status === "ok" && typeof ticket.id === "string"
|
|
141
|
+
? { kind: "ticket", ticketId: ticket.id }
|
|
142
|
+
: expoResultFailure(ticket, false));
|
|
143
|
+
}
|
|
144
|
+
return deliveries.map((delivery) => outcomes.get(delivery.id));
|
|
145
|
+
}
|
|
146
|
+
async function readExpoPushReceipt(delivery, fetchImpl) {
|
|
147
|
+
if (!delivery.providerTicketId) {
|
|
148
|
+
return { kind: "retry", errorCode: "missing_push_ticket", resend: true };
|
|
149
|
+
}
|
|
150
|
+
const response = await fetchWithTimeout(fetchImpl, EXPO_PUSH_RECEIPTS_URL, expoRequestInit({ ids: [delivery.providerTicketId] }));
|
|
151
|
+
const body = await readExpoResponse(response);
|
|
152
|
+
if (!response.ok)
|
|
153
|
+
return responseFailure(response.status, body);
|
|
154
|
+
const receipts = body.data;
|
|
155
|
+
if (!receipts || Array.isArray(receipts) || isExpoResult(receipts)) {
|
|
156
|
+
return { kind: "retry", errorCode: "push_receipt_unavailable" };
|
|
157
|
+
}
|
|
158
|
+
const receipt = receipts[delivery.providerTicketId];
|
|
159
|
+
if (!receipt) {
|
|
160
|
+
return { kind: "retry", errorCode: "push_receipt_unavailable" };
|
|
161
|
+
}
|
|
162
|
+
if (receipt.status === "ok")
|
|
163
|
+
return { kind: "delivered" };
|
|
164
|
+
return expoResultFailure(receipt, true);
|
|
165
|
+
}
|
|
166
|
+
function buildExpoMessage(delivery) {
|
|
167
|
+
const payload = readRecord(delivery.payload);
|
|
168
|
+
const title = boundedString(payload?.title, 120) ?? "Agent Native update";
|
|
169
|
+
const body = boundedString(payload?.body, 300);
|
|
170
|
+
const data = compactData(payload);
|
|
171
|
+
return {
|
|
172
|
+
to: delivery.token,
|
|
173
|
+
title,
|
|
174
|
+
...(body ? { body } : {}),
|
|
175
|
+
sound: "default",
|
|
176
|
+
priority: "high",
|
|
177
|
+
data: {
|
|
178
|
+
url: "agentnative://sessions",
|
|
179
|
+
...data,
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function compactData(payload) {
|
|
184
|
+
if (!payload)
|
|
185
|
+
return {};
|
|
186
|
+
const data = {};
|
|
187
|
+
for (const key of ["commandId", "hostId", "kind", "status"]) {
|
|
188
|
+
const value = boundedString(payload[key], 200);
|
|
189
|
+
if (value)
|
|
190
|
+
data[key] = value;
|
|
191
|
+
}
|
|
192
|
+
if (typeof payload.updatedAt === "number" &&
|
|
193
|
+
Number.isFinite(payload.updatedAt)) {
|
|
194
|
+
data.updatedAt = payload.updatedAt;
|
|
195
|
+
}
|
|
196
|
+
return data;
|
|
197
|
+
}
|
|
198
|
+
function expoRequestInit(body) {
|
|
199
|
+
const headers = {
|
|
200
|
+
Accept: "application/json",
|
|
201
|
+
"Content-Type": "application/json",
|
|
202
|
+
};
|
|
203
|
+
const accessToken = process.env.EXPO_ACCESS_TOKEN?.trim();
|
|
204
|
+
if (accessToken)
|
|
205
|
+
headers.Authorization = `Bearer ${accessToken}`;
|
|
206
|
+
return { method: "POST", headers, body: JSON.stringify(body) };
|
|
207
|
+
}
|
|
208
|
+
async function fetchWithTimeout(fetchImpl, url, init) {
|
|
209
|
+
const controller = new AbortController();
|
|
210
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
211
|
+
try {
|
|
212
|
+
return await fetchImpl(url, { ...init, signal: controller.signal });
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
clearTimeout(timeout);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async function readExpoResponse(response) {
|
|
219
|
+
const body = await response.json().catch(() => null);
|
|
220
|
+
return (readRecord(body) ?? {});
|
|
221
|
+
}
|
|
222
|
+
function responseFailure(status, body) {
|
|
223
|
+
const code = boundedString(body.errors?.[0]?.code, 120);
|
|
224
|
+
if (status === 429 || status >= 500) {
|
|
225
|
+
return { kind: "retry", errorCode: code ?? `expo_http_${status}` };
|
|
226
|
+
}
|
|
227
|
+
return { kind: "failed", errorCode: code ?? `expo_http_${status}` };
|
|
228
|
+
}
|
|
229
|
+
function expoResultFailure(result, fromReceipt) {
|
|
230
|
+
const code = boundedString(result.details?.error, 120) ?? "expo_push_error";
|
|
231
|
+
if (code === "DeviceNotRegistered") {
|
|
232
|
+
return { kind: "failed", errorCode: code, deactivate: true };
|
|
233
|
+
}
|
|
234
|
+
if (code === "MessageRateExceeded") {
|
|
235
|
+
return { kind: "retry", errorCode: code, resend: fromReceipt };
|
|
236
|
+
}
|
|
237
|
+
return { kind: "failed", errorCode: code };
|
|
238
|
+
}
|
|
239
|
+
function retryDelayMs(attempt) {
|
|
240
|
+
return Math.min(60 * 60_000, 5_000 * 2 ** Math.max(0, attempt - 1));
|
|
241
|
+
}
|
|
242
|
+
function classifyTransportError(error) {
|
|
243
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
244
|
+
return "expo_request_timeout";
|
|
245
|
+
}
|
|
246
|
+
return "expo_transport_error";
|
|
247
|
+
}
|
|
248
|
+
function isExpoPushToken(value) {
|
|
249
|
+
return /^(Expo(nent)?PushToken)\[[A-Za-z0-9_-]+\]$/.test(value);
|
|
250
|
+
}
|
|
251
|
+
function isExpoResult(value) {
|
|
252
|
+
return value !== null && typeof value === "object" && "status" in value;
|
|
253
|
+
}
|
|
254
|
+
function readRecord(value) {
|
|
255
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
256
|
+
? value
|
|
257
|
+
: null;
|
|
258
|
+
}
|
|
259
|
+
function boundedString(value, maxLength) {
|
|
260
|
+
if (typeof value !== "string")
|
|
261
|
+
return null;
|
|
262
|
+
const trimmed = value.trim();
|
|
263
|
+
return trimmed ? trimmed.slice(0, maxLength) : null;
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=remote-push-delivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-push-delivery.js","sourceRoot":"","sources":["../../src/integrations/remote-push-delivery.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n claimNextRemotePushDelivery,\n deactivateRemotePushRegistration,\n failRemotePushDelivery,\n markRemotePushDelivered,\n markRemotePushTicketAccepted,\n retryRemotePushDelivery,\n type ClaimedRemotePushDelivery,\n} from \"./remote-push-store.js\";\n\nconst EXPO_PUSH_SEND_URL = \"https://exp.host/--/api/v2/push/send\";\nconst EXPO_PUSH_RECEIPTS_URL = \"https://exp.host/--/api/v2/push/getReceipts\";\nconst REQUEST_TIMEOUT_MS = 10_000;\nconst RECEIPT_CHECK_DELAY_MS = 15 * 60_000;\nconst MAX_DELIVERY_ATTEMPTS = 12;\nconst DEFAULT_DELIVERY_LIMIT = 100;\n\ntype ExpoResult = {\n status?: unknown;\n id?: unknown;\n message?: unknown;\n details?: { error?: unknown };\n};\n\ntype ExpoPushResponse = {\n data?: ExpoResult | ExpoResult[] | Record<string, ExpoResult>;\n errors?: Array<{ code?: unknown; message?: unknown }>;\n};\n\ntype DeliveryOutcome =\n | { kind: \"ticket\"; ticketId: string }\n | { kind: \"delivered\" }\n | { kind: \"retry\"; errorCode: string; resend?: boolean }\n | { kind: \"failed\"; errorCode: string; deactivate?: boolean };\n\nexport async function deliverPendingRemotePushNotifications(options?: {\n fetchImpl?: typeof fetch;\n now?: () => number;\n limit?: number;\n}): Promise<{\n sent: number;\n delivered: number;\n retried: number;\n failed: number;\n}> {\n const fetchImpl = options?.fetchImpl ?? fetch;\n const now = options?.now ?? Date.now;\n const limit = Math.max(\n 1,\n Math.min(options?.limit ?? DEFAULT_DELIVERY_LIMIT, 100),\n );\n const summary = { sent: 0, delivered: 0, retried: 0, failed: 0 };\n const claimedDeliveries: ClaimedRemotePushDelivery[] = [];\n\n for (let processed = 0; processed < limit; processed++) {\n const delivery = await claimNextRemotePushDelivery({ now: now() });\n if (!delivery) break;\n\n if (delivery.attempts > MAX_DELIVERY_ATTEMPTS) {\n await failRemotePushDelivery({\n id: delivery.id,\n phase: delivery.phase,\n errorCode: \"attempts_exhausted\",\n });\n summary.failed++;\n continue;\n }\n\n claimedDeliveries.push(delivery);\n }\n\n const sendDeliveries = claimedDeliveries.filter(\n (delivery) => delivery.phase === \"send\",\n );\n if (sendDeliveries.length > 0) {\n let outcomes: DeliveryOutcome[];\n try {\n outcomes = await sendExpoPushNotifications(sendDeliveries, fetchImpl);\n } catch (error) {\n const errorCode = classifyTransportError(error);\n outcomes = sendDeliveries.map(() => ({ kind: \"retry\", errorCode }));\n }\n for (let index = 0; index < sendDeliveries.length; index++) {\n await applyDeliveryOutcome(\n sendDeliveries[index]!,\n outcomes[index]!,\n summary,\n now,\n );\n }\n }\n\n for (const delivery of claimedDeliveries) {\n if (delivery.phase !== \"receipt\") continue;\n let outcome: DeliveryOutcome;\n try {\n outcome = await readExpoPushReceipt(delivery, fetchImpl);\n } catch (error) {\n outcome = {\n kind: \"retry\",\n errorCode: classifyTransportError(error),\n };\n }\n\n await applyDeliveryOutcome(delivery, outcome, summary, now);\n }\n\n return summary;\n}\n\nasync function applyDeliveryOutcome(\n delivery: ClaimedRemotePushDelivery,\n outcome: DeliveryOutcome,\n summary: {\n sent: number;\n delivered: number;\n retried: number;\n failed: number;\n },\n now: () => number,\n): Promise<void> {\n if (outcome.kind === \"ticket\") {\n await markRemotePushTicketAccepted({\n id: delivery.id,\n providerTicketId: outcome.ticketId,\n checkAfter: now() + RECEIPT_CHECK_DELAY_MS,\n });\n summary.sent++;\n return;\n }\n if (outcome.kind === \"delivered\") {\n await markRemotePushDelivered(delivery.id);\n summary.delivered++;\n return;\n }\n if (outcome.kind === \"failed\") {\n await failRemotePushDelivery({\n id: delivery.id,\n phase: delivery.phase,\n errorCode: outcome.errorCode,\n });\n if (outcome.deactivate) {\n await deactivateRemotePushRegistration(delivery.registrationId);\n }\n summary.failed++;\n return;\n }\n\n await retryRemotePushDelivery({\n id: delivery.id,\n phase: delivery.phase,\n retryAt: now() + retryDelayMs(delivery.attempts),\n errorCode: outcome.errorCode,\n resend: outcome.resend,\n });\n summary.retried++;\n}\n\nasync function sendExpoPushNotifications(\n deliveries: ClaimedRemotePushDelivery[],\n fetchImpl: typeof fetch,\n): Promise<DeliveryOutcome[]> {\n const outcomes = new Map<string, DeliveryOutcome>();\n const supportedDeliveries = deliveries.filter((delivery) => {\n const supported =\n delivery.provider === \"expo\" && isExpoPushToken(delivery.token);\n if (!supported) {\n outcomes.set(delivery.id, {\n kind: \"failed\",\n errorCode: \"unsupported_push_registration\",\n deactivate: true,\n });\n }\n return supported;\n });\n if (supportedDeliveries.length === 0) {\n return deliveries.map((delivery) => outcomes.get(delivery.id)!);\n }\n\n const messages = supportedDeliveries.map(buildExpoMessage);\n const response = await fetchWithTimeout(\n fetchImpl,\n EXPO_PUSH_SEND_URL,\n expoRequestInit(messages.length === 1 ? messages[0] : messages),\n );\n const body = await readExpoResponse(response);\n if (!response.ok) {\n const outcome = responseFailure(response.status, body);\n for (const delivery of supportedDeliveries) {\n outcomes.set(delivery.id, outcome);\n }\n return deliveries.map((delivery) => outcomes.get(delivery.id)!);\n }\n\n const tickets = Array.isArray(body.data)\n ? body.data\n : body.data && isExpoResult(body.data)\n ? [body.data]\n : [];\n if (\n tickets.length !== supportedDeliveries.length ||\n tickets.some((ticket) => !isExpoResult(ticket))\n ) {\n for (const delivery of supportedDeliveries) {\n outcomes.set(delivery.id, {\n kind: \"retry\",\n errorCode: \"invalid_push_ticket\",\n });\n }\n return deliveries.map((delivery) => outcomes.get(delivery.id)!);\n }\n\n for (let index = 0; index < supportedDeliveries.length; index++) {\n const delivery = supportedDeliveries[index]!;\n const ticket = tickets[index]!;\n outcomes.set(\n delivery.id,\n ticket.status === \"ok\" && typeof ticket.id === \"string\"\n ? { kind: \"ticket\", ticketId: ticket.id }\n : expoResultFailure(ticket, false),\n );\n }\n return deliveries.map((delivery) => outcomes.get(delivery.id)!);\n}\n\nasync function readExpoPushReceipt(\n delivery: ClaimedRemotePushDelivery,\n fetchImpl: typeof fetch,\n): Promise<DeliveryOutcome> {\n if (!delivery.providerTicketId) {\n return { kind: \"retry\", errorCode: \"missing_push_ticket\", resend: true };\n }\n const response = await fetchWithTimeout(\n fetchImpl,\n EXPO_PUSH_RECEIPTS_URL,\n expoRequestInit({ ids: [delivery.providerTicketId] }),\n );\n const body = await readExpoResponse(response);\n if (!response.ok) return responseFailure(response.status, body);\n\n const receipts = body.data;\n if (!receipts || Array.isArray(receipts) || isExpoResult(receipts)) {\n return { kind: \"retry\", errorCode: \"push_receipt_unavailable\" };\n }\n const receipt = receipts[delivery.providerTicketId];\n if (!receipt) {\n return { kind: \"retry\", errorCode: \"push_receipt_unavailable\" };\n }\n if (receipt.status === \"ok\") return { kind: \"delivered\" };\n return expoResultFailure(receipt, true);\n}\n\nfunction buildExpoMessage(delivery: ClaimedRemotePushDelivery) {\n const payload = readRecord(delivery.payload);\n const title = boundedString(payload?.title, 120) ?? \"Agent Native update\";\n const body = boundedString(payload?.body, 300);\n const data = compactData(payload);\n return {\n to: delivery.token,\n title,\n ...(body ? { body } : {}),\n sound: \"default\",\n priority: \"high\",\n data: {\n url: \"agentnative://sessions\",\n ...data,\n },\n };\n}\n\nfunction compactData(payload: Record<string, unknown> | null) {\n if (!payload) return {};\n const data: Record<string, string | number> = {};\n for (const key of [\"commandId\", \"hostId\", \"kind\", \"status\"] as const) {\n const value = boundedString(payload[key], 200);\n if (value) data[key] = value;\n }\n if (\n typeof payload.updatedAt === \"number\" &&\n Number.isFinite(payload.updatedAt)\n ) {\n data.updatedAt = payload.updatedAt;\n }\n return data;\n}\n\nfunction expoRequestInit(body: unknown): RequestInit {\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n };\n const accessToken = process.env.EXPO_ACCESS_TOKEN?.trim();\n if (accessToken) headers.Authorization = `Bearer ${accessToken}`;\n return { method: \"POST\", headers, body: JSON.stringify(body) };\n}\n\nasync function fetchWithTimeout(\n fetchImpl: typeof fetch,\n url: string,\n init: RequestInit,\n): Promise<Response> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n return await fetchImpl(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timeout);\n }\n}\n\nasync function readExpoResponse(response: Response): Promise<ExpoPushResponse> {\n const body = await response.json().catch(() => null);\n return (readRecord(body) ?? {}) as ExpoPushResponse;\n}\n\nfunction responseFailure(\n status: number,\n body: ExpoPushResponse,\n): DeliveryOutcome {\n const code = boundedString(body.errors?.[0]?.code, 120);\n if (status === 429 || status >= 500) {\n return { kind: \"retry\", errorCode: code ?? `expo_http_${status}` };\n }\n return { kind: \"failed\", errorCode: code ?? `expo_http_${status}` };\n}\n\nfunction expoResultFailure(\n result: ExpoResult,\n fromReceipt: boolean,\n): DeliveryOutcome {\n const code = boundedString(result.details?.error, 120) ?? \"expo_push_error\";\n if (code === \"DeviceNotRegistered\") {\n return { kind: \"failed\", errorCode: code, deactivate: true };\n }\n if (code === \"MessageRateExceeded\") {\n return { kind: \"retry\", errorCode: code, resend: fromReceipt };\n }\n return { kind: \"failed\", errorCode: code };\n}\n\nfunction retryDelayMs(attempt: number): number {\n return Math.min(60 * 60_000, 5_000 * 2 ** Math.max(0, attempt - 1));\n}\n\nfunction classifyTransportError(error: unknown): string {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n return \"expo_request_timeout\";\n }\n return \"expo_transport_error\";\n}\n\nfunction isExpoPushToken(value: string): boolean {\n return /^(Expo(nent)?PushToken)\\[[A-Za-z0-9_-]+\\]$/.test(value);\n}\n\nfunction isExpoResult(value: unknown): value is ExpoResult {\n return value !== null && typeof value === \"object\" && \"status\" in value;\n}\n\nfunction readRecord(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction boundedString(value: unknown, maxLength: number): string | null {\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, maxLength) : null;\n}\n"]}
|
|
@@ -34,4 +34,37 @@ export declare function listRemotePushNotificationsForOwner(input: {
|
|
|
34
34
|
status?: RemotePushNotification["status"];
|
|
35
35
|
limit?: number;
|
|
36
36
|
}): Promise<RemotePushNotification[]>;
|
|
37
|
+
export interface ClaimedRemotePushDelivery {
|
|
38
|
+
id: string;
|
|
39
|
+
registrationId: string;
|
|
40
|
+
provider: string;
|
|
41
|
+
token: string;
|
|
42
|
+
payload: unknown;
|
|
43
|
+
phase: "send" | "receipt";
|
|
44
|
+
providerTicketId: string | null;
|
|
45
|
+
attempts: number;
|
|
46
|
+
}
|
|
47
|
+
export declare function claimNextRemotePushDelivery(input?: {
|
|
48
|
+
now?: number;
|
|
49
|
+
staleAfterMs?: number;
|
|
50
|
+
}): Promise<ClaimedRemotePushDelivery | null>;
|
|
51
|
+
export declare function markRemotePushTicketAccepted(input: {
|
|
52
|
+
id: string;
|
|
53
|
+
providerTicketId: string;
|
|
54
|
+
checkAfter: number;
|
|
55
|
+
}): Promise<boolean>;
|
|
56
|
+
export declare function markRemotePushDelivered(id: string): Promise<boolean>;
|
|
57
|
+
export declare function retryRemotePushDelivery(input: {
|
|
58
|
+
id: string;
|
|
59
|
+
phase: "send" | "receipt";
|
|
60
|
+
retryAt: number;
|
|
61
|
+
errorCode: string;
|
|
62
|
+
resend?: boolean;
|
|
63
|
+
}): Promise<boolean>;
|
|
64
|
+
export declare function failRemotePushDelivery(input: {
|
|
65
|
+
id: string;
|
|
66
|
+
phase: "send" | "receipt";
|
|
67
|
+
errorCode: string;
|
|
68
|
+
}): Promise<boolean>;
|
|
69
|
+
export declare function deactivateRemotePushRegistration(registrationId: string): Promise<boolean>;
|
|
37
70
|
//# sourceMappingURL=remote-push-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remote-push-store.d.ts","sourceRoot":"","sources":["../../src/integrations/remote-push-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"remote-push-store.d.ts","sourceRoot":"","sources":["../../src/integrations/remote-push-store.ts"],"names":[],"mappings":"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"}
|