@canonmsg/claude-code-plugin 0.19.6 → 0.21.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.
@@ -1,59 +0,0 @@
1
- /**
2
- * Startup recovery for inbound messages missed while the host was offline.
3
- *
4
- * The host persists a `lastInboundMessageId` cursor per conversation. On
5
- * startup we paginate `getMessagesPage` (newest-first pages, older pages via
6
- * its `before` message-id parameter) until the cursor is found or a hard
7
- * per-conversation bound is hit, then replay everything after the cursor.
8
- *
9
- * This module is intentionally identical in packages/claude-code-plugin and
10
- * packages/codex-plugin — keep both copies in sync (future consolidation
11
- * candidate).
12
- */
13
- export const STARTUP_RECOVERY_PAGE_SIZE = 25;
14
- export const STARTUP_RECOVERY_MAX_MESSAGES = 500;
15
- export async function collectMissedInboundMessages(input) {
16
- const maxMessages = input.maxMessages ?? STARTUP_RECOVERY_MAX_MESSAGES;
17
- const newestPage = await input.fetchPage();
18
- const collected = [...newestPage.messages];
19
- const seenIds = new Set(collected.map((message) => message.id));
20
- const hasCursor = (messages) => input.cursor != null && messages.some((message) => message.id === input.cursor);
21
- let cursorFound = hasCursor(collected);
22
- if (input.cursor != null) {
23
- while (!cursorFound && collected.length < maxMessages) {
24
- // Pages are newest-first, so the last collected message is the oldest.
25
- const before = collected[collected.length - 1]?.id;
26
- if (!before)
27
- break;
28
- const page = await input.fetchPage(before);
29
- const fresh = page.messages.filter((message) => !seenIds.has(message.id));
30
- // No pagination progress (history exhausted, or the server ignored the
31
- // `before` cursor because that message was hard-deleted) — stop here.
32
- if (fresh.length === 0)
33
- break;
34
- for (const message of fresh)
35
- seenIds.add(message.id);
36
- collected.push(...fresh);
37
- cursorFound = hasCursor(fresh);
38
- }
39
- }
40
- const ascending = [...collected].sort((a, b) => String(a.createdAt ?? '').localeCompare(String(b.createdAt ?? '')));
41
- const inboundOnly = (messages) => messages.filter((message) => message.senderId !== input.agentId);
42
- let mode;
43
- let missed;
44
- if (cursorFound) {
45
- const cursorIndex = ascending.findIndex((message) => message.id === input.cursor);
46
- mode = 'after-cursor';
47
- missed = inboundOnly(ascending.slice(cursorIndex + 1));
48
- }
49
- else if (input.cursor != null && collected.length >= maxMessages) {
50
- mode = 'truncated-window';
51
- missed = inboundOnly(ascending.slice(-maxMessages));
52
- }
53
- else {
54
- mode = 'latest-only';
55
- missed = inboundOnly(ascending).slice(-1);
56
- }
57
- // Safe: `missed` only holds elements of pages returned by `fetchPage`.
58
- return { mode, messages: missed, newestPage };
59
- }
@@ -1,16 +0,0 @@
1
- export interface StreamingBufferOptions {
2
- throttleMs: number;
3
- getText: () => string;
4
- setText: (text: string) => void;
5
- getTimer: () => ReturnType<typeof setTimeout> | null;
6
- setTimer: (timer: ReturnType<typeof setTimeout> | null) => void;
7
- onWrite: (text: string) => void;
8
- schedule?: typeof setTimeout;
9
- cancel?: typeof clearTimeout;
10
- }
11
- export declare function createStreamingBuffer(options: StreamingBufferOptions): {
12
- append(delta: string): void;
13
- flush: () => void;
14
- clear(): void;
15
- replace(text: string): void;
16
- };
@@ -1,52 +0,0 @@
1
- export function createStreamingBuffer(options) {
2
- const schedule = options.schedule ?? setTimeout;
3
- const cancel = options.cancel ?? clearTimeout;
4
- const flush = () => {
5
- const timer = options.getTimer();
6
- if (timer) {
7
- cancel(timer);
8
- options.setTimer(null);
9
- }
10
- const text = options.getText();
11
- if (text) {
12
- options.onWrite(text);
13
- }
14
- };
15
- return {
16
- append(delta) {
17
- if (!delta)
18
- return;
19
- options.setText(`${options.getText()}${delta}`);
20
- if (options.getTimer())
21
- return;
22
- const timer = schedule(() => {
23
- options.setTimer(null);
24
- const text = options.getText();
25
- if (text) {
26
- options.onWrite(text);
27
- }
28
- }, options.throttleMs);
29
- options.setTimer(timer);
30
- },
31
- flush,
32
- clear() {
33
- const timer = options.getTimer();
34
- if (timer) {
35
- cancel(timer);
36
- options.setTimer(null);
37
- }
38
- options.setText('');
39
- },
40
- replace(text) {
41
- const timer = options.getTimer();
42
- if (timer) {
43
- cancel(timer);
44
- options.setTimer(null);
45
- }
46
- options.setText(text);
47
- if (text) {
48
- options.onWrite(text);
49
- }
50
- },
51
- };
52
- }