4 Commits

Author SHA1 Message Date
Alejandro Gutiérrez
9ae378c2e3 fix(cli): v0.5.3 — add push delivery debug logging
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled
Release / Publish multi-arch images (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:49:49 +01:00
Alejandro Gutiérrez
7381738f0b fix(web): disable turbopack for prod build (payload CSS compat)
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:46:28 +01:00
Alejandro Gutiérrez
8c6b0c0e07 fix(cli): v0.5.2 — poll-based push delivery (1s interval)
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled
Release / Publish multi-arch images (push) Has been cancelled
Replace WS onPush→notification with timer-based buffer drain.
The old claude-intercom used 1s polling and worked reliably.
WS async callbacks may not flush stdio properly for MCP
notifications. Polling on a timer ensures consistent delivery.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:33:26 +01:00
Alejandro Gutiérrez
ec9626503c fix(web): force-dynamic on payload admin page (build CSS error)
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:16:21 +01:00
4 changed files with 60 additions and 47 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "claudemesh-cli", "name": "claudemesh-cli",
"version": "0.5.1", "version": "0.5.3",
"description": "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.", "description": "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
"keywords": [ "keywords": [
"claude-code", "claude-code",

View File

@@ -722,19 +722,23 @@ Your message mode is "${messageMode}".
// any mesh's broker connection becomes a <channel source="claudemesh"> // any mesh's broker connection becomes a <channel source="claudemesh">
// system reminder injected into Claude Code's context. // system reminder injected into Claude Code's context.
for (const client of allClients()) { for (const client of allClients()) {
client.onPush(async (msg) => { // Poll-based push: drain pushBuffer every 1s and emit channel notifications.
// In "off" mode, silently skip notification — messages are still // This is the proven approach from claude-intercom. The WS onPush handler
// buffered in pushBuffer and accessible via check_messages. // fires instantly but server.notification() may not flush stdio reliably
if (messageMode === "off") return; // from an async WS callback. Polling on a timer ensures consistent delivery.
if (messageMode !== "off") {
const pushPollTimer = setInterval(async () => {
const buffered = client.drainPushBuffer();
if (buffered.length > 0) {
process.stderr.write(`[claudemesh] poll: ${buffered.length} message(s) to push\n`);
}
for (const msg of buffered) {
const fromPubkey = msg.senderPubkey || ""; const fromPubkey = msg.senderPubkey || "";
// Resolve sender's display name from the cached peer list.
const fromName = fromPubkey const fromName = fromPubkey
? await resolvePeerName(client, fromPubkey) ? await resolvePeerName(client, fromPubkey)
: "unknown"; : "unknown";
if (messageMode === "inbox") { if (messageMode === "inbox") {
// Count-only notification, no content
try { try {
await server.notification({ await server.notification({
method: "notifications/claude/channel", method: "notifications/claude/channel",
@@ -744,10 +748,10 @@ Your message mode is "${messageMode}".
}, },
}); });
} catch { /* best effort */ } } catch { /* best effort */ }
return; continue;
} }
// push mode — full content notification // push mode — full content
const content = msg.plaintext ?? decryptFailedWarning(fromPubkey); const content = msg.plaintext ?? decryptFailedWarning(fromPubkey);
try { try {
await server.notification({ await server.notification({
@@ -766,10 +770,14 @@ Your message mode is "${messageMode}".
}, },
}, },
}); });
} catch { process.stderr.write(`[claudemesh] pushed: from=${fromName} content=${content.slice(0, 60)}\n`);
/* channel push is best-effort; check_messages is the fallback */ } catch (pushErr) {
process.stderr.write(`[claudemesh] push FAILED: ${pushErr}\n`);
}
}
}, 1_000);
pushPollTimer.unref();
} }
});
client.onStreamData(async (evt) => { client.onStreamData(async (evt) => {
try { try {

View File

@@ -25,6 +25,9 @@ ENV NEXT_PUBLIC_URL=$NEXT_PUBLIC_URL
ENV NEXT_PUBLIC_PRODUCT_NAME=$NEXT_PUBLIC_PRODUCT_NAME ENV NEXT_PUBLIC_PRODUCT_NAME=$NEXT_PUBLIC_PRODUCT_NAME
ENV NEXT_PUBLIC_DEFAULT_LOCALE=$NEXT_PUBLIC_DEFAULT_LOCALE ENV NEXT_PUBLIC_DEFAULT_LOCALE=$NEXT_PUBLIC_DEFAULT_LOCALE
# TURBOPACK=0 forces webpack for production build — Payload CMS's
# richtext-lexical CSS imports fail under Turbopack.
ENV TURBOPACK=0
RUN npx turbo run build --filter=web... RUN npx turbo run build --filter=web...
# Stage 2: runtime — standalone output only # Stage 2: runtime — standalone output only

View File

@@ -4,6 +4,8 @@ import { RootPage, generatePageMetadata } from "@payloadcms/next/views";
import { importMap } from "../importMap"; import { importMap } from "../importMap";
import config from "@payload-config"; import config from "@payload-config";
export const dynamic = "force-dynamic";
type Args = { params: Promise<{ segments: string[] }> }; type Args = { params: Promise<{ segments: string[] }> };
export const generateMetadata = ({ params }: Args) => export const generateMetadata = ({ params }: Args) =>