@rubytech/create-maxy-code 0.1.276 → 0.1.277
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/package.json +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +3 -3
- package/payload/platform/plugins/docs/references/admin-identity-gate.md +44 -7
- package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
- package/payload/platform/scripts/check-no-esm-require.mjs +3 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +5 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +52 -10
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +8 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.d.ts +8 -0
- package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.js +13 -0
- package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/wa-channel-store.d.ts +29 -0
- package/payload/platform/services/claude-session-manager/dist/wa-channel-store.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/wa-channel-store.js +124 -0
- package/payload/platform/services/claude-session-manager/dist/wa-channel-store.js.map +1 -0
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +23 -0
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js +26 -0
- package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.js +41 -14
- package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
- package/payload/server/{chunk-W4EM7RK4.js → chunk-QHD5TKLQ.js} +2 -0
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/server.js +411 -172
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// Persistent per-session WhatsApp native-channel binding. One admin session is
|
|
2
|
+
// shared by the operator's WhatsApp thread and their claude.ai/code view (same
|
|
3
|
+
// sessionId/slug); both resume through the manager's `/rc-spawn`, but only the
|
|
4
|
+
// gateway path carries `waChannel`. Persisting the binding here lets every
|
|
5
|
+
// resume path re-apply the channel argv so `mcp__whatsapp-channel__reply` is
|
|
6
|
+
// present on every live PTY for the session — the agent never silently falls
|
|
7
|
+
// back to `whatsapp-send` (Task 683).
|
|
8
|
+
//
|
|
9
|
+
// Lifecycle mirrors UserTitleStore:
|
|
10
|
+
// - Boot reads `<accountDir>/wa-channel-bindings.json` into the in-memory Map.
|
|
11
|
+
// - `set(sessionId, binding)` write-throughs and atomically persists; called
|
|
12
|
+
// on every gateway `/rc-spawn` so gatewayUrl/serverPath stay current.
|
|
13
|
+
// - `get(sessionId)` reads the in-memory map for the resume read-back.
|
|
14
|
+
// - `remove(sessionId)` on session purge / delete cascade.
|
|
15
|
+
// - Corruption / missing file / permission errors at boot are logged and
|
|
16
|
+
// treated as an empty map; the manager NEVER refuses to start.
|
|
17
|
+
//
|
|
18
|
+
// File format (UTF-8 JSON):
|
|
19
|
+
// { "<sessionId>": { "senderId": "...", "gatewayUrl": "...", "serverPath": "...", "boundAt": "ISO-8601" } }
|
|
20
|
+
import { existsSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
21
|
+
function isValidBinding(v) {
|
|
22
|
+
if (!v || typeof v !== 'object')
|
|
23
|
+
return false;
|
|
24
|
+
const o = v;
|
|
25
|
+
return (typeof o.senderId === 'string' && o.senderId.length > 0 &&
|
|
26
|
+
typeof o.gatewayUrl === 'string' && o.gatewayUrl.length > 0 &&
|
|
27
|
+
typeof o.serverPath === 'string' && o.serverPath.length > 0);
|
|
28
|
+
}
|
|
29
|
+
export class WaChannelStore {
|
|
30
|
+
bySessionId = new Map();
|
|
31
|
+
filePath;
|
|
32
|
+
logger;
|
|
33
|
+
constructor(filePath, logger) {
|
|
34
|
+
this.filePath = filePath;
|
|
35
|
+
this.logger = logger;
|
|
36
|
+
}
|
|
37
|
+
/** Read the persisted file into the in-memory map. Boot-resilient: any
|
|
38
|
+
* failure (missing file, malformed JSON, permission denied) is logged and
|
|
39
|
+
* the store starts empty. Never throws. */
|
|
40
|
+
loadFromDisk() {
|
|
41
|
+
if (!existsSync(this.filePath)) {
|
|
42
|
+
this.logger(`[claude-session-manager] wa-channel-store-load empty reason=file-missing path=${this.filePath}`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
let raw;
|
|
46
|
+
try {
|
|
47
|
+
raw = readFileSync(this.filePath, 'utf-8');
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
51
|
+
this.logger(`[claude-session-manager] wa-channel-store-load failed reason=read-error detail=${detail.slice(0, 200)} — starting empty`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
let parsed;
|
|
55
|
+
try {
|
|
56
|
+
parsed = JSON.parse(raw);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
60
|
+
this.logger(`[claude-session-manager] wa-channel-store-load failed reason=malformed-json detail=${detail.slice(0, 200)} — starting empty`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
64
|
+
this.logger(`[claude-session-manager] wa-channel-store-load failed reason=not-an-object — starting empty`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
let loaded = 0;
|
|
68
|
+
for (const [sessionId, value] of Object.entries(parsed)) {
|
|
69
|
+
if (typeof sessionId !== 'string' || sessionId.length === 0)
|
|
70
|
+
continue;
|
|
71
|
+
if (!isValidBinding(value))
|
|
72
|
+
continue;
|
|
73
|
+
// `value` is now narrowed to WaChannelBinding (the three required strings);
|
|
74
|
+
// boundAt is optional on disk, so read it off the raw record.
|
|
75
|
+
const rawBoundAt = value.boundAt;
|
|
76
|
+
const boundAt = typeof rawBoundAt === 'string' && rawBoundAt.length > 0 ? rawBoundAt : new Date(0).toISOString();
|
|
77
|
+
this.bySessionId.set(sessionId, {
|
|
78
|
+
senderId: value.senderId,
|
|
79
|
+
gatewayUrl: value.gatewayUrl,
|
|
80
|
+
serverPath: value.serverPath,
|
|
81
|
+
boundAt,
|
|
82
|
+
});
|
|
83
|
+
loaded += 1;
|
|
84
|
+
}
|
|
85
|
+
this.logger(`[claude-session-manager] wa-channel-store-load ok entries=${loaded} path=${this.filePath}`);
|
|
86
|
+
}
|
|
87
|
+
get(sessionId) {
|
|
88
|
+
return this.bySessionId.get(sessionId);
|
|
89
|
+
}
|
|
90
|
+
/** Write-through `binding` for `sessionId`; refreshes boundAt each call. */
|
|
91
|
+
set(sessionId, binding) {
|
|
92
|
+
const entry = { ...binding, boundAt: new Date().toISOString() };
|
|
93
|
+
this.bySessionId.set(sessionId, entry);
|
|
94
|
+
this.persistAtomic();
|
|
95
|
+
return entry;
|
|
96
|
+
}
|
|
97
|
+
/** Remove the entry for `sessionId` if present. Returns true when removed. */
|
|
98
|
+
remove(sessionId) {
|
|
99
|
+
const had = this.bySessionId.delete(sessionId);
|
|
100
|
+
if (had)
|
|
101
|
+
this.persistAtomic();
|
|
102
|
+
return had;
|
|
103
|
+
}
|
|
104
|
+
/** Current in-memory snapshot — diagnostic only. */
|
|
105
|
+
size() {
|
|
106
|
+
return this.bySessionId.size;
|
|
107
|
+
}
|
|
108
|
+
persistAtomic() {
|
|
109
|
+
const obj = {};
|
|
110
|
+
for (const [sessionId, entry] of this.bySessionId)
|
|
111
|
+
obj[sessionId] = entry;
|
|
112
|
+
const tmp = `${this.filePath}.tmp`;
|
|
113
|
+
try {
|
|
114
|
+
writeFileSync(tmp, JSON.stringify(obj, null, 2), 'utf-8');
|
|
115
|
+
renameSync(tmp, this.filePath);
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
119
|
+
this.logger(`[claude-session-manager] wa-channel-store-persist failed detail=${detail.slice(0, 200)}`);
|
|
120
|
+
// No rethrow — reads still serve from the in-memory map until next boot.
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=wa-channel-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wa-channel-store.js","sourceRoot":"","sources":["../src/wa-channel-store.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,+EAA+E;AAC/E,+EAA+E;AAC/E,2EAA2E;AAC3E,6EAA6E;AAC7E,6EAA6E;AAC7E,sCAAsC;AACtC,EAAE;AACF,oCAAoC;AACpC,iFAAiF;AACjF,+EAA+E;AAC/E,0EAA0E;AAC1E,yEAAyE;AACzE,6DAA6D;AAC7D,2EAA2E;AAC3E,mEAAmE;AACnE,EAAE;AACF,4BAA4B;AAC5B,8GAA8G;AAE9G,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAc7E,SAAS,cAAc,CAAC,CAAU;IAChC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC7C,MAAM,CAAC,GAAG,CAA4B,CAAA;IACtC,OAAO,CACL,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QACvD,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QAC3D,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAC5D,CAAA;AACH,CAAC;AAED,MAAM,OAAO,cAAc;IACR,WAAW,GAAG,IAAI,GAAG,EAA0B,CAAA;IAC/C,QAAQ,CAAQ;IAChB,MAAM,CAAQ;IAE/B,YAAY,QAAgB,EAAE,MAAc;QAC1C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;IAED;;gDAE4C;IAC5C,YAAY;QACV,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,iFAAiF,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;YAC7G,OAAM;QACR,CAAC;QACD,IAAI,GAAW,CAAA;QACf,IAAI,CAAC;YACH,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QAC5C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC/D,IAAI,CAAC,MAAM,CAAC,kFAAkF,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,mBAAmB,CAAC,CAAA;YACtI,OAAM;QACR,CAAC;QACD,IAAI,MAAe,CAAA;QACnB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC/D,IAAI,CAAC,MAAM,CAAC,sFAAsF,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,mBAAmB,CAAC,CAAA;YAC1I,OAAM;QACR,CAAC;QACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,IAAI,CAAC,MAAM,CAAC,6FAA6F,CAAC,CAAA;YAC1G,OAAM;QACR,CAAC;QACD,IAAI,MAAM,GAAG,CAAC,CAAA;QACd,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAiC,CAAC,EAAE,CAAC;YACnF,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAQ;YACrE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC;gBAAE,SAAQ;YACpC,4EAA4E;YAC5E,8DAA8D;YAC9D,MAAM,UAAU,GAAI,KAA+B,CAAC,OAAO,CAAA;YAC3D,MAAM,OAAO,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;YAChH,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE;gBAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,OAAO;aACR,CAAC,CAAA;YACF,MAAM,IAAI,CAAC,CAAA;QACb,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,6DAA6D,MAAM,SAAS,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC1G,CAAC;IAED,GAAG,CAAC,SAAiB;QACnB,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACxC,CAAC;IAED,4EAA4E;IAC5E,GAAG,CAAC,SAAiB,EAAE,OAAyB;QAC9C,MAAM,KAAK,GAAmB,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAA;QAC/E,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QACtC,IAAI,CAAC,aAAa,EAAE,CAAA;QACpB,OAAO,KAAK,CAAA;IACd,CAAC;IAED,8EAA8E;IAC9E,MAAM,CAAC,SAAiB;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAC9C,IAAI,GAAG;YAAE,IAAI,CAAC,aAAa,EAAE,CAAA;QAC7B,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,oDAAoD;IACpD,IAAI;QACF,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAA;IAC9B,CAAC;IAEO,aAAa;QACnB,MAAM,GAAG,GAAmC,EAAE,CAAA;QAC9C,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW;YAAE,GAAG,CAAC,SAAS,CAAC,GAAG,KAAK,CAAA;QACzE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,QAAQ,MAAM,CAAA;QAClC,IAAI,CAAC;YACH,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;YACzD,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAChC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC/D,IAAI,CAAC,MAAM,CAAC,mEAAmE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;YACtG,yEAAyE;QAC3E,CAAC;IACH,CAAC;CACF"}
|
|
@@ -41,4 +41,27 @@ export declare function buildReplyPostBody(mySenderId: string, text: string): {
|
|
|
41
41
|
senderId: string;
|
|
42
42
|
text: string;
|
|
43
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* Build the body for POST /wa-channel/received — the receipt ack the channel
|
|
46
|
+
* server sends after it has emitted a drained inbound to the agent. It confirms
|
|
47
|
+
* the dev-channel side received the message so the gateway can mark it delivered
|
|
48
|
+
* (op=channel-received) instead of timing out as drain-undelivered. The senderId
|
|
49
|
+
* is the server's fixed sender, never model-supplied.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildReceivedPostBody(mySenderId: string, waMessageId: string): {
|
|
52
|
+
senderId: string;
|
|
53
|
+
waMessageId: string;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Retry an idempotent POST until it is accepted or the attempt cap is reached.
|
|
57
|
+
* `attempt` returns whether the POST was accepted; the helper returns on the
|
|
58
|
+
* first acceptance, otherwise sleeps `delayMs` and retries, up to `attempts`
|
|
59
|
+
* total. `sleep` is injected so tests run without real timers. Pure of the MCP
|
|
60
|
+
* SDK, like the other helpers here.
|
|
61
|
+
*/
|
|
62
|
+
export declare function postWithRetry(attempt: () => Promise<boolean>, opts: {
|
|
63
|
+
attempts: number;
|
|
64
|
+
delayMs: number;
|
|
65
|
+
sleep: (ms: number) => Promise<void>;
|
|
66
|
+
}): Promise<boolean>;
|
|
44
67
|
//# sourceMappingURL=notification.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../src/notification.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAA;IACZ,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,cAAc;;;;;EAOzD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAElF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAEvG"}
|
|
1
|
+
{"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../src/notification.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAA;IACZ,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,cAAc;;;;;EAOzD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAElF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAEvG;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAE3C;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAC/B,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,GAChF,OAAO,CAAC,OAAO,CAAC,CAMlB"}
|
|
@@ -37,4 +37,30 @@ export function acceptsSender(mySenderId, p) {
|
|
|
37
37
|
export function buildReplyPostBody(mySenderId, text) {
|
|
38
38
|
return { senderId: mySenderId, text };
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Build the body for POST /wa-channel/received — the receipt ack the channel
|
|
42
|
+
* server sends after it has emitted a drained inbound to the agent. It confirms
|
|
43
|
+
* the dev-channel side received the message so the gateway can mark it delivered
|
|
44
|
+
* (op=channel-received) instead of timing out as drain-undelivered. The senderId
|
|
45
|
+
* is the server's fixed sender, never model-supplied.
|
|
46
|
+
*/
|
|
47
|
+
export function buildReceivedPostBody(mySenderId, waMessageId) {
|
|
48
|
+
return { senderId: mySenderId, waMessageId };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Retry an idempotent POST until it is accepted or the attempt cap is reached.
|
|
52
|
+
* `attempt` returns whether the POST was accepted; the helper returns on the
|
|
53
|
+
* first acceptance, otherwise sleeps `delayMs` and retries, up to `attempts`
|
|
54
|
+
* total. `sleep` is injected so tests run without real timers. Pure of the MCP
|
|
55
|
+
* SDK, like the other helpers here.
|
|
56
|
+
*/
|
|
57
|
+
export async function postWithRetry(attempt, opts) {
|
|
58
|
+
for (let i = 0; i < opts.attempts; i++) {
|
|
59
|
+
if (await attempt())
|
|
60
|
+
return true;
|
|
61
|
+
if (i < opts.attempts - 1)
|
|
62
|
+
await opts.sleep(opts.delayMs);
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
40
66
|
//# sourceMappingURL=notification.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification.js","sourceRoot":"","sources":["../src/notification.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,yEAAyE;AACzE,yEAAyE;AAWzE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,wBAAwB,CAAC,CAAiB;IACxD,OAAO;QACL,MAAM,EAAE,8BAAuC;QAC/C,MAAM,EAAE;YACN,OAAO,EAAE,CAAC,CAAC,IAAI;SAChB;KACF,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,UAAkB,EAAE,CAAuB;IACvE,OAAO,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAA;AAClC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB,EAAE,IAAY;IACjE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;AACvC,CAAC"}
|
|
1
|
+
{"version":3,"file":"notification.js","sourceRoot":"","sources":["../src/notification.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,yEAAyE;AACzE,yEAAyE;AAWzE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,wBAAwB,CAAC,CAAiB;IACxD,OAAO;QACL,MAAM,EAAE,8BAAuC;QAC/C,MAAM,EAAE;YACN,OAAO,EAAE,CAAC,CAAC,IAAI;SAChB;KACF,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,UAAkB,EAAE,CAAuB;IACvE,OAAO,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAA;AAClC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB,EAAE,IAAY;IACjE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;AACvC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,UAAkB,EAClB,WAAmB;IAEnB,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,CAAA;AAC9C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAA+B,EAC/B,IAAiF;IAEjF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,IAAI,MAAM,OAAO,EAAE;YAAE,OAAO,IAAI,CAAA;QAChC,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC;YAAE,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC3D,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
13
13
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
14
14
|
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
15
|
-
import { acceptsSender, buildInboundNotification, buildReplyPostBody } from './notification.js';
|
|
15
|
+
import { acceptsSender, buildInboundNotification, buildReplyPostBody, buildReceivedPostBody, postWithRetry } from './notification.js';
|
|
16
16
|
function requireEnv(name) {
|
|
17
17
|
const v = process.env[name];
|
|
18
18
|
if (!v)
|
|
@@ -21,6 +21,11 @@ function requireEnv(name) {
|
|
|
21
21
|
}
|
|
22
22
|
const SENDER_ID = requireEnv('WA_CHANNEL_SENDER_ID');
|
|
23
23
|
const GATEWAY_URL = requireEnv('WA_CHANNEL_GATEWAY_URL').replace(/\/$/, '');
|
|
24
|
+
// Receipt-ack retry budget. 5 attempts × 2000ms = up to ~8s of sleeping,
|
|
25
|
+
// comfortably inside the gateway's 30s ack window (ACK_THRESHOLD_MS), so a
|
|
26
|
+
// recovered ack lands before the sweep would emit a false drain-undelivered.
|
|
27
|
+
const RECEIPT_ACK_ATTEMPTS = 5;
|
|
28
|
+
const RECEIPT_ACK_DELAY_MS = 2000;
|
|
24
29
|
// Co-visibility: the operator watches the same session in claude.ai/code,
|
|
25
30
|
// where the reply tool call shows but its text does not. Instruct the agent to
|
|
26
31
|
// also write its answer as normal assistant text so the operator can read it
|
|
@@ -73,6 +78,13 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
73
78
|
// disconnect mid-session, and the agent would lose the reply tool (falling back
|
|
74
79
|
// to the standard WhatsApp plugin and dropping the co-visibility mirror). The
|
|
75
80
|
// process still dies with the session because claude SIGTERMs its stdio child.
|
|
81
|
+
async function postReady() {
|
|
82
|
+
await fetch(`${GATEWAY_URL}/wa-channel/ready`, {
|
|
83
|
+
method: 'POST',
|
|
84
|
+
headers: { 'content-type': 'application/json' },
|
|
85
|
+
body: JSON.stringify({ senderId: SENDER_ID }),
|
|
86
|
+
}).catch(() => { });
|
|
87
|
+
}
|
|
76
88
|
async function subscribeInbound() {
|
|
77
89
|
const url = `${GATEWAY_URL}/wa-channel/inbound?senderId=${encodeURIComponent(SENDER_ID)}`;
|
|
78
90
|
for (;;) {
|
|
@@ -80,6 +92,10 @@ async function subscribeInbound() {
|
|
|
80
92
|
const res = await fetch(url, { headers: { accept: 'text/event-stream' } });
|
|
81
93
|
if (!res.ok || !res.body)
|
|
82
94
|
throw new Error(`subscribe failed: ${res.status}`);
|
|
95
|
+
// The SSE link is established. Only NOW announce readiness, so the gateway
|
|
96
|
+
// drains any cold-start queue ONTO this live subscription rather than into
|
|
97
|
+
// a stream the channel server is not yet consuming (the cold-start drop).
|
|
98
|
+
await postReady();
|
|
83
99
|
const reader = res.body.getReader();
|
|
84
100
|
const decoder = new TextDecoder();
|
|
85
101
|
let buffer = '';
|
|
@@ -107,6 +123,27 @@ async function subscribeInbound() {
|
|
|
107
123
|
if (!acceptsSender(SENDER_ID, payload))
|
|
108
124
|
continue;
|
|
109
125
|
await mcp.notification(buildInboundNotification(payload));
|
|
126
|
+
// Confirm receipt so the gateway marks this message delivered
|
|
127
|
+
// (op=channel-received) instead of timing out as drain-undelivered.
|
|
128
|
+
// Retry within the gateway's ack window so a transient gateway blip
|
|
129
|
+
// does not produce a false drain-undelivered; log only on final
|
|
130
|
+
// give-up so a genuine ack-transport failure stays legible.
|
|
131
|
+
const acked = await postWithRetry(async () => {
|
|
132
|
+
try {
|
|
133
|
+
const r = await fetch(`${GATEWAY_URL}/wa-channel/received`, {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
headers: { 'content-type': 'application/json' },
|
|
136
|
+
body: JSON.stringify(buildReceivedPostBody(SENDER_ID, payload.waMessageId)),
|
|
137
|
+
});
|
|
138
|
+
return r.ok;
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}, { attempts: RECEIPT_ACK_ATTEMPTS, delayMs: RECEIPT_ACK_DELAY_MS, sleep: (ms) => new Promise((r) => setTimeout(r, ms)) });
|
|
144
|
+
if (!acked) {
|
|
145
|
+
console.error(`[whatsapp-channel] op=receipt-ack-failed senderId=${SENDER_ID} waMessageId=${payload.waMessageId} attempts=${RECEIPT_ACK_ATTEMPTS}`);
|
|
146
|
+
}
|
|
110
147
|
}
|
|
111
148
|
}
|
|
112
149
|
console.error('[whatsapp-channel] inbound stream closed by gateway; reconnecting');
|
|
@@ -115,23 +152,13 @@ async function subscribeInbound() {
|
|
|
115
152
|
console.error(`[whatsapp-channel] inbound stream error: ${err instanceof Error ? err.message : String(err)}; reconnecting`);
|
|
116
153
|
}
|
|
117
154
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
118
|
-
// Re-announce readiness so any message queued during the gap drains onto
|
|
119
|
-
// the fresh subscription.
|
|
120
|
-
await fetch(`${GATEWAY_URL}/wa-channel/ready`, {
|
|
121
|
-
method: 'POST',
|
|
122
|
-
headers: { 'content-type': 'application/json' },
|
|
123
|
-
body: JSON.stringify({ senderId: SENDER_ID }),
|
|
124
|
-
}).catch(() => { });
|
|
125
155
|
}
|
|
126
156
|
}
|
|
127
157
|
async function main() {
|
|
128
158
|
await mcp.connect(new StdioServerTransport());
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
headers: { 'content-type': 'application/json' },
|
|
133
|
-
body: JSON.stringify({ senderId: SENDER_ID }),
|
|
134
|
-
}).catch(() => { });
|
|
159
|
+
// Readiness is announced inside subscribeInbound, after the SSE link is up —
|
|
160
|
+
// never before, or the gateway would drain into a stream this server is not
|
|
161
|
+
// yet consuming.
|
|
135
162
|
await subscribeInbound();
|
|
136
163
|
}
|
|
137
164
|
main().catch((err) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA,0EAA0E;AAC1E,0EAA0E;AAC1E,eAAe;AACf,8EAA8E;AAC9E,uDAAuD;AACvD,+EAA+E;AAC/E,kCAAkC;AAClC,EAAE;AACF,+EAA+E;AAC/E,0EAA0E;AAE1E,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAA;AAClG,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,kBAAkB,EAAuB,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -2700,6 +2700,7 @@ console.log(
|
|
|
2700
2700
|
var CHROMIUM_PROFILE_DIR = resolve(homedir(), configDirName, "chromium-profile");
|
|
2701
2701
|
var PLATFORM_ROOT = process.env.MAXY_PLATFORM_ROOT ?? resolve(process.cwd(), "..");
|
|
2702
2702
|
var USERS_FILE = resolve(MAXY_DIR, "users.json");
|
|
2703
|
+
var LID_MAP_FILE = resolve(MAXY_DIR, "whatsapp-lid-map.json");
|
|
2703
2704
|
var LOG_DIR = resolve(MAXY_DIR, "logs");
|
|
2704
2705
|
var BIN_DIR = resolve(MAXY_DIR, "bin");
|
|
2705
2706
|
var REMOTE_PASSWORD_FILE = resolve(MAXY_DIR, ".remote-password");
|
|
@@ -5604,6 +5605,7 @@ export {
|
|
|
5604
5605
|
CDP_PORT,
|
|
5605
5606
|
CHROMIUM_PROFILE_DIR,
|
|
5606
5607
|
USERS_FILE,
|
|
5608
|
+
LID_MAP_FILE,
|
|
5607
5609
|
LOG_DIR,
|
|
5608
5610
|
BIN_DIR,
|
|
5609
5611
|
INSTALL_OWNER_FILE,
|