@rubytech/create-maxy-code 0.1.443 → 0.1.444
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/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +1 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js +40 -24
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts +7 -7
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js +7 -7
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js.map +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +8 -4
- package/payload/platform/plugins/docs/references/admin-session.md +2 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +4 -0
- package/payload/platform/plugins/docs/references/cross-account-authority.md +3 -3
- package/payload/platform/plugins/outlook/references/auth.md +8 -0
- package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +3 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-attachment-suffix.test.d.ts +2 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-attachment-suffix.test.d.ts.map +1 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-attachment-suffix.test.js +44 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-attachment-suffix.test.js.map +1 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/format.d.ts +7 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/format.d.ts.map +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/format.js +27 -0
- package/payload/platform/plugins/whatsapp/mcp/dist/format.js.map +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +6 -19
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +3 -1
- package/payload/platform/plugins/work/mcp/dist/tools/work-create.d.ts.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/work-create.js +10 -7
- package/payload/platform/plugins/work/mcp/dist/tools/work-create.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +1 -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 +99 -8
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +0 -13
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.d.ts +8 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.js +11 -0
- package/payload/platform/services/claude-session-manager/dist/jsonl-path.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/passive-admin-assignment.d.ts +20 -0
- package/payload/platform/services/claude-session-manager/dist/passive-admin-assignment.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/passive-admin-assignment.js +66 -0
- package/payload/platform/services/claude-session-manager/dist/passive-admin-assignment.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/passive-spawn-tools-tail.d.ts +19 -0
- package/payload/platform/services/claude-session-manager/dist/passive-spawn-tools-tail.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/passive-spawn-tools-tail.js +50 -0
- package/payload/platform/services/claude-session-manager/dist/passive-spawn-tools-tail.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +14 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/server/public/assets/{chat-DhD-NES_.js → chat-Dq-X-ia8.js} +1 -1
- package/payload/server/public/assets/{operator-zcIfeB14.js → operator-88m0DMl2.js} +1 -1
- package/payload/server/public/assets/page-BRfxFXyi.js +32 -0
- package/payload/server/public/assets/{public-C0ehZCdE.js → public-BX2MjsFY.js} +1 -1
- package/payload/server/public/chat.html +2 -2
- package/payload/server/public/operator.html +2 -2
- package/payload/server/public/public.html +2 -2
- package/payload/server/server.js +65 -13
- package/payload/server/public/assets/page-6fCnIb45.js +0 -32
|
@@ -67,13 +67,13 @@ export declare function setManagingAdmin(accountsDir: string, accountId: string,
|
|
|
67
67
|
* if its account.json happens to carry the field. Filesystem-only; a dir with no
|
|
68
68
|
* account.json, or an unparseable one, is excluded (corruption discipline).
|
|
69
69
|
*
|
|
70
|
-
* Enumeration
|
|
71
|
-
* prefilter
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
70
|
+
* Enumeration decides membership solely by a parseable account.json — no UUID_RE
|
|
71
|
+
* prefilter — so the guard sees every account that carries the pointer. Drives
|
|
72
|
+
* the admin-remove reconciliation guard (Task 1501): removing an admin this
|
|
73
|
+
* returns non-empty for would orphan those accounts, so the removal is refused.
|
|
74
|
+
* (Passive intake no longer depends on this pointer being present — an absent or
|
|
75
|
+
* dangling managing admin falls back to the primary admin, Task 1630 — but the
|
|
76
|
+
* removal guard still runs so a reassign stays the operator's explicit choice.) */
|
|
77
77
|
export declare function findClientAccountsManagedBy(accountsDir: string, adminUserId: string): string[];
|
|
78
78
|
export type ReassignResult = {
|
|
79
79
|
ok: true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-lifecycle.d.ts","sourceRoot":"","sources":["../../src/tools/account-lifecycle.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8CAA8C,CAAC;AAI9E;;;;;;kEAMkE;AAClE,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG5D;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;oCAEoC;AACpC,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,EAAE,CAoBzE;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAEvE;AAED;;+DAE+D;AAC/D,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAE3E;AAED,MAAM,WAAW,qBAAqB;IACpC,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;8EAM8E;AAC9E,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAOtG;AAED;;;;;+DAK+D;AAC/D,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU7E;AAED;;;;0EAI0E;AAC1E,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,CAO7F;AAED;;;;mEAImE;AACnE,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAanE;AAED;;;;sEAIsE;AACtE,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAKlG;AAED;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"account-lifecycle.d.ts","sourceRoot":"","sources":["../../src/tools/account-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -142,13 +142,13 @@ export function setManagingAdmin(accountsDir, accountId, adminUserId) {
|
|
|
142
142
|
* if its account.json happens to carry the field. Filesystem-only; a dir with no
|
|
143
143
|
* account.json, or an unparseable one, is excluded (corruption discipline).
|
|
144
144
|
*
|
|
145
|
-
* Enumeration
|
|
146
|
-
* prefilter
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
145
|
+
* Enumeration decides membership solely by a parseable account.json — no UUID_RE
|
|
146
|
+
* prefilter — so the guard sees every account that carries the pointer. Drives
|
|
147
|
+
* the admin-remove reconciliation guard (Task 1501): removing an admin this
|
|
148
|
+
* returns non-empty for would orphan those accounts, so the removal is refused.
|
|
149
|
+
* (Passive intake no longer depends on this pointer being present — an absent or
|
|
150
|
+
* dangling managing admin falls back to the primary admin, Task 1630 — but the
|
|
151
|
+
* removal guard still runs so a reassign stays the operator's explicit choice.) */
|
|
152
152
|
export function findClientAccountsManagedBy(accountsDir, adminUserId) {
|
|
153
153
|
let names;
|
|
154
154
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-lifecycle.js","sourceRoot":"","sources":["../../src/tools/account-lifecycle.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"account-lifecycle.js","sourceRoot":"","sources":["../../src/tools/account-lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-architecture
|
|
3
3
|
description: Use when grounding any documented-surface claim about what Maxy ships — plugins, skills, specialists, install/deploy flows, internals. This is the install catalogue, not evidence of what is enabled on the current account. For install state on this account, call `capabilities-here`; for documented surface, cite the `Source:` URL inline.
|
|
4
|
-
content-hash: sha256:
|
|
4
|
+
content-hash: sha256:a6ec9b14c5c480f4b583a6df46bacf861b99e2493ba3a68c7ca0d3ca96173cab
|
|
5
5
|
brand: maxy-code
|
|
6
6
|
product-name: Maxy
|
|
7
7
|
---
|
|
@@ -530,13 +530,13 @@ By default the admin assistant is scoped the same way — it acts on the house a
|
|
|
530
530
|
|
|
531
531
|
The operator wants this for two surfaces: the account graph and the account filesystem. Each is a separate adoption; a coverage ledger tracks them and a background check confirms neither silently regresses.
|
|
532
532
|
|
|
533
|
-
## Creating a sub-account
|
|
533
|
+
## Creating a sub-account can name a managing admin
|
|
534
534
|
|
|
535
|
-
|
|
535
|
+
A client sub-account may have a responsible house admin, but one is optional. `account_create` takes the `userId` of a current house admin as the managing admin — the admin agent asks the operator which house admin manages the client (the choices come from `admin-list`) — and records it as `managingAdminUserId` on the sub-account; a supplied `userId` that is not a live house admin is refused. Omit it for a client run by its owner rather than a house team member. A WhatsApp requirement that comes in for that sub-account is filed as a task assigned to its managing admin; when the sub-account has no managing admin (or its recorded one is no longer a live house admin), the task is assigned to the install's primary admin (the first house admin) instead, so it always lands with a named owner rather than unassigned.
|
|
536
536
|
|
|
537
537
|
## Reassigning and removing a managing admin
|
|
538
538
|
|
|
539
|
-
To hand a client to a different team member — or to
|
|
539
|
+
To hand a client to a different team member — or to record a managing admin on an unmanaged account, or repair one whose admin was removed — use `account_reassign_admin` with the client's `accountId` and the new admin's `userId`. It refuses a target that is not a client sub-account or a `userId` that is not a current house admin. Removing a house admin is guarded so it cannot silently orphan anyone: `admin-remove` refuses to remove an admin who is still the managing admin of one or more client sub-accounts and names those accounts. Reassign each with `account_reassign_admin`, then remove the admin.
|
|
540
540
|
|
|
541
541
|
## Memory (graph)
|
|
542
542
|
|
|
@@ -2761,8 +2761,12 @@ either is a regression.
|
|
|
2761
2761
|
|
|
2762
2762
|
**`/chat` header always shows the account name.** The admin/operator `HeaderMenu` centre always renders the active account's name alongside the brand logo, on every chat surface, regardless of the active conversation — `headerTitle = businessName || brand.productName`. There is no per-conversation header title: the active conversation's label stays in the sidebar and the Conversations flyout (each resolves its own per-session title independently), never in the header. The account name is `LocalBusiness.name`, resolved by `fetchAccountName(accountId)` in `neo4j-store.ts` with **no theme gate** — unlike `fetchBranding` (which returns null unless a colour/logo property is also set, and stays the source for actual theming). The house account is seeded with `LocalBusiness.name = <brand productName>` (`seed-neo4j.sh`, coalesced ON MATCH so a re-seed backfills a name-less node and never clobbers a name the business-profile recorder set later), so the sub-account picker's house row shows the product name (e.g. "SiteDesk"), not the raw accountId UUID. When a name is absent the resolver emits `[branding] account-name-fallback accountId=<id8>… reason=no-name`, and the picker falls back to the accountId; the seed + backfill is the name source. The lite variant header is unchanged.
|
|
2763
2763
|
|
|
2764
|
+
**`/chat` sub-account switch starts a fresh conversation.** Switching sub-accounts from the header picker while on the chat page presents an empty greeting with no active session — no footer id, no highlighted conversation. The next message starts a **new** conversation for the switched-to account rather than reopening that account's previous one, and the previous conversation is left untouched and still resumable from the Conversations list. A normal visit to the chat page that did not switch accounts still reopens the account's most recent conversation as before. The full mechanism (the `clearSignal` first send and the `op=post-switch-pointer`/`op=send-target-resolve` diagnostics) lives in `.docs/admin-webchat-native-channel.md`.
|
|
2765
|
+
|
|
2764
2766
|
**`/chat` Claude-desktop transcript presentation.** The admin webchat keeps the shared `Transcript` shell (stream, follow-tail) but injects a /chat-only item renderer via the component's optional `renderItems` prop: `renderChatTimeline` in `app/chat/transcript-render.tsx`. Presentation: operator turns render as a right-aligned grey bubble showing the message text and, beneath it, a subtle always-visible time-of-day stamp (no label); delivered agent replies render as plain prose with the same time-of-day stamp beneath (the reply-document filename line stays, as prose); the stamp is HH:MM from the turn's `ts` (locale-formatted, right-aligned inside the operator bubble, left-aligned under agent prose), and a turn whose `ts` is null/unparseable shows no stamp, never an empty line — so only delivered operator and agent-reply turns are stamped, while tool runs, the collapsed "Thinking" block, and the agent-error banner stay time-free; a maximal consecutive run of `tool-call`/`tool-result` turns renders as one collapsed grey one-liner ("Used N tools ›") whose expansion shows every call and result payload — a lone call still gets the one-liner, and prose or a directive row ends a run. The WhatsApp/operator reader (`/whatsapp`, `OperatorConversations`) omits the prop and keeps the default `renderTimeline`, so its bubble/DM chrome is unchanged — except that since the attachment-render extraction the default renderer draws inbound `operator-inbound` uploads and `agent-file` deliveries inline (image thumbnail / pdf.js preview / voice-note player / download chip) via the attachment renderer shared with `/chat`, extracted to `app/chat/attachment-render.tsx` to break the cycle with `transcript-render.tsx`; `renderChatTimeline` is untouched. Both presentations are test-pinned (`app/whatsapp/__tests__/Transcript-*.test.tsx`, `app/chat/__tests__/transcript-render.test.tsx`, `app/chat/__tests__/pdf-preview.test.tsx`). **Day-divider:** both renderers insert a centered `.day-divider` row between two consecutive timeline items on different local calendar days (label `Today`/`Yesterday`, else `Sat 14 Jun 2026`), so a thread spanning midnight is never an ambiguous run of HH:MM; the first dated item gets a leading divider, a null/unparseable `ts` marks no boundary, dividers are computed over the filtered `visibleItems`, and in `/chat` a day crossover flushes any open tool/think run first so a collapsed run never spans it. Per-bubble HH:MM stamps are unchanged. Shared helpers `dayKey`/`dayLabel`/`itemTs`/`DayDivider` live in `app/whatsapp/Transcript.tsx`.
|
|
2765
2767
|
|
|
2768
|
+
**One delivered bubble per turn when the agent replied.** On the admin `/chat`, a turn that used the reply tool shows exactly one delivered bubble — the reply. A trailing sign-off or recap the agent writes after the reply is treated as narration and is not shown as a second bubble (it collapses like any mid-turn prose). Only a turn that ends **without** using the reply tool has its final text promoted to a delivered bubble, so a genuine no-reply answer is never lost. The tradeoff, accepted by the operator: a turn that acknowledges on the reply tool and then writes the real answer as trailing text will not show that trailing answer — the agent is steered to put the answer on the reply tool so this stays rare.
|
|
2769
|
+
|
|
2766
2770
|
**WhatsApp reader is read/write (WhatsApp-Web surface).** A WhatsApp store conversation in the operator Conversations reader (`OperatorConversations`) and the admin root channel viewer (`app/page.tsx`) no longer opens the plain read-only DM chrome — it opens `app/whatsapp/WhatsappWebConversation.tsx`, a WhatsApp-Web-styled surface: a conversation header, the delivered-only store transcript reskinned green/white under a `.wa-web` root class, and a reply composer (`app/whatsapp/ReplyComposer.tsx`). The operator can type text, insert emoji (a codepoint-data picker — no OS input, so the `check-no-emoji-in-jsx` gate stays green), record a voice note (MediaRecorder → the existing audio send path), attach a file **from device storage** (a modal browsing the DATA_ROOT tree via `GET /api/admin/files`, sent by reference — the OS file dialog is no longer the reader's picker), reply to a specific message (a per-bubble affordance that quotes the original in the composer and threads natively on WhatsApp), and search the loaded transcript (a header control that filters to matching turns and highlights the match). The header carries only that Search control — the former Video / Phone / menu icons are gone, because no call or presence data exists behind them. Sent files honour the webchat allowlist (`SUPPORTED_MIME_SET` / 50 MB / 5 files); a device-file reference is authorised server-side (`authorizeReplyFileRef`) against the send's own account (the conversation owner) **or** the session's pinned account (`getAccountIdForSession` — the exact scope the DeviceFilePicker used to offer it), so a house/managing-admin session can attach a managed-client file the picker listed. Because a reply sends bytes OUT to an external WhatsApp recipient, any other account, a `public` partition, and any install-wide / non-account path are refused fail-closed; the cross-account admission's authority is the session's pinned account, never the caller-supplied body `accountId` (the own-account admission matches the body `accountId`, which the route already trusts via `isValidAccountId` and the existing-conversation guard). A scope refusal returns a distinct HTTP 403 reason (`file-ref-cross-account` / `file-ref-public` / `file-ref-foreign`) and copy, never "device file not found" (reserved for a genuine resolve/stat miss). Per-ref `[wa-manual-send] op=reply-file-ref … via=own|session|deny reason=<…> ok=<bool>` logs the decision before any send; `via=deny ok=true` is the exfiltration signature that must never appear. **Send is reply-only and DM-only:** `POST /api/whatsapp-reader/reply` (`requireAdminSession`) refuses any target with no existing stored conversation (`reason=no-existing-conversation`, HTTP 403) — a cold first-contact send bans the account, so the composer is never a cold-contact path, enforced server-side — and refuses `@g.us` groups (`reason=group-send-blocked`), matching the agent's observe-only group invariant; a group thread shows a read-only note in place of the composer. The endpoint is the sole store writer for a manual send: right after each send resolves it appends the record itself, stamped `origin:'operator-manual'` (attributed "You", distinct from an assistant reply), because the Baileys echo that normally persists the store is gated on message text (`manager.ts:906`) and would leave an uncaptioned media send delivered-but-invisible. The record's `messageId` matches the echo's derivation so the async text echo's own persist dedups to a no-op; the send is confirmed by re-read (`op=recorded present=<bool>`). A sent send does not spawn an assistant turn (echo dispatch stays suppressed). Attachments deliver as WhatsApp media/documents and render **inline** in the store reader (image thumbnail / pdf preview / audio player / download chip), because the manual-send path records the message with the servable `attachmentId`. The `.wa-web` skin is scoped to WhatsApp store threads only, so `/chat`, the admin agent session view, and the public visitor webchat are unchanged; the visitor webchat gains no send capability. The in-bubble delivered-tick is cosmetic (no read-receipt data is stored); inbound bubbles keep their sender name so group threads stay attributable, and both directions carry a WhatsApp callout tail (`.wa-web`-scoped only). Non-WhatsApp reader rows (Telegram/webchat session JSONLs) keep the plain read-only `Transcript`. Observability rides `[wa-manual-send]` lines correlated by a per-request `sendId`. **Composer sizing matches the webchat composer:** the reply textarea auto-grows to fit multi-line content (measured from `scrollHeight`, clamped to a one-row minimum and a `viewport/3` maximum, scrollable past the cap with the scrollbar hidden), and a top-border grab handle drags (pointer) or nudges (ArrowUp/ArrowDown, keyboard-focusable) to an explicit height in the same clamp; a manual drag pins the height and overrides auto-grow until the field is cleared, which releases it back to auto-grow. A completed manual resize logs `[operator-ui] op=wa-composer-resize mode=drag|key h=<px>`; a bare click on the handle (no drag) logs nothing.
|
|
2767
2771
|
|
|
2768
2772
|
**`/chat` live activity line.** While a turn is in flight the transcript tail shows one ephemeral `ChatActivity` line (mounted only while `busy`, admin/operator only). It tracks real activity, not a timer: while a `Task` subagent runs it shows that subagent's headline (`agentType · description`, prefixed `N agents ·` when ≥2 are concurrent), sourced from `agent-<hex>.meta.json` via named `activity` SSE events the admin reader pushes from the session's `subagents/` dir; with no subagent active it shows a neutral word that advances only on a real turn arrival. The line carries a turn-elapsed clock and flips to a `stalled` state once nothing has been written for 5 minutes (`now − lastEmitAt`), so the operator can tell a wedge from progress without SSH. It is never added to the persisted timeline. Detail and the `[webchat-activity]` observability live in [`admin-webchat-native-channel.md`](../../../.docs/admin-webchat-native-channel.md).
|
|
@@ -99,6 +99,8 @@ The metadata pane surfaces two distinct identifier values. The three-id model wa
|
|
|
99
99
|
|
|
100
100
|
**The footer reads model/effort/turn-count from one shared JSONL resolver.** The `/chat` footer's model / effort / turn-count are the manager `GET /:sessionId/meta` enrichment, read from the session's JSONL tail. That read resolves the JSONL by the **same all-slug scan** the transcript uses — `findExistingJsonlForSessionId`, covering top-level and `archive/` under every project slug — not the single house-cwd slug. Previously the enrichment gated on the `spawnCwd` slug, so a sub-account session rc-spawned in a different cwd (its JSONL under a different slug) reported `model:null turns:0` while its transcript rendered; the transcript already scanned all slugs. `findSessionProjectDir` (the transcript resolver) delegates to the same function, so the two are one resolver — a session findable on disk is never reported `model:null`. The standing line is `[session-meta] op=enrich session=<id8> resolver=scan jsonl=<found|absent> model=… effort=… turns=…`.
|
|
101
101
|
|
|
102
|
+
The same all-slug scan runs on the **row-absent branch** too. The manager's fs-watcher is armed to only the boot/house account's project dir, so a sub-account session (its JSONL under a different slug) has no watcher row and `resolveRow` returns nothing. Rather than 404 — which gives the footer no payload at all, blanking model/effort/thinking — `/meta` scans for the JSONL first and, when found, returns an enriched 200 built rowless (`pid:null`, `role:null`, `status:ended`, `activity:idle`; model/turns/tokens from the tail, effort from settings). Only a session id with no JSONL anywhere still 404s. The row-absent line carries a `row=absent` token to distinguish it: `resolver=scan row=absent jsonl=found …` for the enriched 200, `resolver=none row=absent jsonl=absent …` for the genuine 404. So a session the transcript can render can never blank its footer on account of a missing watcher row.
|
|
103
|
+
|
|
102
104
|
| Operator label | What it is | Manager wire field | Log key |
|
|
103
105
|
|---|---|---|---|
|
|
104
106
|
| `sessionId` | Claude's session. Two phases: bridge suffix (`session_xxx`, the URL segment in `claude.ai/code/<session_xxx>`, set when claude prints the `/remote-control` URL) and JSONL basename UUID (claude's intrinsic id on disk, bound when the first turn flushes the JSONL). Both phases coexist on a live row after URL capture; the manager wire emits the bridge form when set, falling back to the JSONL basename in the pre-URL-capture window. The resolver routes either phase to the same row, so callers never need to choose. | `sessionId` (collapsed from the earlier three-field surface `sessionId` + `claudeSessionId` + `bridgeSessionId`) | `sessionId=` |
|
|
@@ -73,8 +73,12 @@ either is a regression.
|
|
|
73
73
|
|
|
74
74
|
**`/chat` header always shows the account name.** The admin/operator `HeaderMenu` centre always renders the active account's name alongside the brand logo, on every chat surface, regardless of the active conversation — `headerTitle = businessName || brand.productName`. There is no per-conversation header title: the active conversation's label stays in the sidebar and the Conversations flyout (each resolves its own per-session title independently), never in the header. The account name is `LocalBusiness.name`, resolved by `fetchAccountName(accountId)` in `neo4j-store.ts` with **no theme gate** — unlike `fetchBranding` (which returns null unless a colour/logo property is also set, and stays the source for actual theming). The house account is seeded with `LocalBusiness.name = <brand productName>` (`seed-neo4j.sh`, coalesced ON MATCH so a re-seed backfills a name-less node and never clobbers a name the business-profile recorder set later), so the sub-account picker's house row shows the product name (e.g. "SiteDesk"), not the raw accountId UUID. When a name is absent the resolver emits `[branding] account-name-fallback accountId=<id8>… reason=no-name`, and the picker falls back to the accountId; the seed + backfill is the name source. The lite variant header is unchanged.
|
|
75
75
|
|
|
76
|
+
**`/chat` sub-account switch starts a fresh conversation.** Switching sub-accounts from the header picker while on the chat page presents an empty greeting with no active session — no footer id, no highlighted conversation. The next message starts a **new** conversation for the switched-to account rather than reopening that account's previous one, and the previous conversation is left untouched and still resumable from the Conversations list. A normal visit to the chat page that did not switch accounts still reopens the account's most recent conversation as before. The full mechanism (the `clearSignal` first send and the `op=post-switch-pointer`/`op=send-target-resolve` diagnostics) lives in `.docs/admin-webchat-native-channel.md`.
|
|
77
|
+
|
|
76
78
|
**`/chat` Claude-desktop transcript presentation.** The admin webchat keeps the shared `Transcript` shell (stream, follow-tail) but injects a /chat-only item renderer via the component's optional `renderItems` prop: `renderChatTimeline` in `app/chat/transcript-render.tsx`. Presentation: operator turns render as a right-aligned grey bubble showing the message text and, beneath it, a subtle always-visible time-of-day stamp (no label); delivered agent replies render as plain prose with the same time-of-day stamp beneath (the reply-document filename line stays, as prose); the stamp is HH:MM from the turn's `ts` (locale-formatted, right-aligned inside the operator bubble, left-aligned under agent prose), and a turn whose `ts` is null/unparseable shows no stamp, never an empty line — so only delivered operator and agent-reply turns are stamped, while tool runs, the collapsed "Thinking" block, and the agent-error banner stay time-free; a maximal consecutive run of `tool-call`/`tool-result` turns renders as one collapsed grey one-liner ("Used N tools ›") whose expansion shows every call and result payload — a lone call still gets the one-liner, and prose or a directive row ends a run. The WhatsApp/operator reader (`/whatsapp`, `OperatorConversations`) omits the prop and keeps the default `renderTimeline`, so its bubble/DM chrome is unchanged — except that since the attachment-render extraction the default renderer draws inbound `operator-inbound` uploads and `agent-file` deliveries inline (image thumbnail / pdf.js preview / voice-note player / download chip) via the attachment renderer shared with `/chat`, extracted to `app/chat/attachment-render.tsx` to break the cycle with `transcript-render.tsx`; `renderChatTimeline` is untouched. Both presentations are test-pinned (`app/whatsapp/__tests__/Transcript-*.test.tsx`, `app/chat/__tests__/transcript-render.test.tsx`, `app/chat/__tests__/pdf-preview.test.tsx`). **Day-divider:** both renderers insert a centered `.day-divider` row between two consecutive timeline items on different local calendar days (label `Today`/`Yesterday`, else `Sat 14 Jun 2026`), so a thread spanning midnight is never an ambiguous run of HH:MM; the first dated item gets a leading divider, a null/unparseable `ts` marks no boundary, dividers are computed over the filtered `visibleItems`, and in `/chat` a day crossover flushes any open tool/think run first so a collapsed run never spans it. Per-bubble HH:MM stamps are unchanged. Shared helpers `dayKey`/`dayLabel`/`itemTs`/`DayDivider` live in `app/whatsapp/Transcript.tsx`.
|
|
77
79
|
|
|
80
|
+
**One delivered bubble per turn when the agent replied.** On the admin `/chat`, a turn that used the reply tool shows exactly one delivered bubble — the reply. A trailing sign-off or recap the agent writes after the reply is treated as narration and is not shown as a second bubble (it collapses like any mid-turn prose). Only a turn that ends **without** using the reply tool has its final text promoted to a delivered bubble, so a genuine no-reply answer is never lost. The tradeoff, accepted by the operator: a turn that acknowledges on the reply tool and then writes the real answer as trailing text will not show that trailing answer — the agent is steered to put the answer on the reply tool so this stays rare.
|
|
81
|
+
|
|
78
82
|
**WhatsApp reader is read/write (WhatsApp-Web surface).** A WhatsApp store conversation in the operator Conversations reader (`OperatorConversations`) and the admin root channel viewer (`app/page.tsx`) no longer opens the plain read-only DM chrome — it opens `app/whatsapp/WhatsappWebConversation.tsx`, a WhatsApp-Web-styled surface: a conversation header, the delivered-only store transcript reskinned green/white under a `.wa-web` root class, and a reply composer (`app/whatsapp/ReplyComposer.tsx`). The operator can type text, insert emoji (a codepoint-data picker — no OS input, so the `check-no-emoji-in-jsx` gate stays green), record a voice note (MediaRecorder → the existing audio send path), attach a file **from device storage** (a modal browsing the DATA_ROOT tree via `GET /api/admin/files`, sent by reference — the OS file dialog is no longer the reader's picker), reply to a specific message (a per-bubble affordance that quotes the original in the composer and threads natively on WhatsApp), and search the loaded transcript (a header control that filters to matching turns and highlights the match). The header carries only that Search control — the former Video / Phone / menu icons are gone, because no call or presence data exists behind them. Sent files honour the webchat allowlist (`SUPPORTED_MIME_SET` / 50 MB / 5 files); a device-file reference is authorised server-side (`authorizeReplyFileRef`) against the send's own account (the conversation owner) **or** the session's pinned account (`getAccountIdForSession` — the exact scope the DeviceFilePicker used to offer it), so a house/managing-admin session can attach a managed-client file the picker listed. Because a reply sends bytes OUT to an external WhatsApp recipient, any other account, a `public` partition, and any install-wide / non-account path are refused fail-closed; the cross-account admission's authority is the session's pinned account, never the caller-supplied body `accountId` (the own-account admission matches the body `accountId`, which the route already trusts via `isValidAccountId` and the existing-conversation guard). A scope refusal returns a distinct HTTP 403 reason (`file-ref-cross-account` / `file-ref-public` / `file-ref-foreign`) and copy, never "device file not found" (reserved for a genuine resolve/stat miss). Per-ref `[wa-manual-send] op=reply-file-ref … via=own|session|deny reason=<…> ok=<bool>` logs the decision before any send; `via=deny ok=true` is the exfiltration signature that must never appear. **Send is reply-only and DM-only:** `POST /api/whatsapp-reader/reply` (`requireAdminSession`) refuses any target with no existing stored conversation (`reason=no-existing-conversation`, HTTP 403) — a cold first-contact send bans the account, so the composer is never a cold-contact path, enforced server-side — and refuses `@g.us` groups (`reason=group-send-blocked`), matching the agent's observe-only group invariant; a group thread shows a read-only note in place of the composer. The endpoint is the sole store writer for a manual send: right after each send resolves it appends the record itself, stamped `origin:'operator-manual'` (attributed "You", distinct from an assistant reply), because the Baileys echo that normally persists the store is gated on message text (`manager.ts:906`) and would leave an uncaptioned media send delivered-but-invisible. The record's `messageId` matches the echo's derivation so the async text echo's own persist dedups to a no-op; the send is confirmed by re-read (`op=recorded present=<bool>`). A sent send does not spawn an assistant turn (echo dispatch stays suppressed). Attachments deliver as WhatsApp media/documents and render **inline** in the store reader (image thumbnail / pdf preview / audio player / download chip), because the manual-send path records the message with the servable `attachmentId`. The `.wa-web` skin is scoped to WhatsApp store threads only, so `/chat`, the admin agent session view, and the public visitor webchat are unchanged; the visitor webchat gains no send capability. The in-bubble delivered-tick is cosmetic (no read-receipt data is stored); inbound bubbles keep their sender name so group threads stay attributable, and both directions carry a WhatsApp callout tail (`.wa-web`-scoped only). Non-WhatsApp reader rows (Telegram/webchat session JSONLs) keep the plain read-only `Transcript`. Observability rides `[wa-manual-send]` lines correlated by a per-request `sendId`. **Composer sizing matches the webchat composer:** the reply textarea auto-grows to fit multi-line content (measured from `scrollHeight`, clamped to a one-row minimum and a `viewport/3` maximum, scrollable past the cap with the scrollbar hidden), and a top-border grab handle drags (pointer) or nudges (ArrowUp/ArrowDown, keyboard-focusable) to an explicit height in the same clamp; a manual drag pins the height and overrides auto-grow until the field is cleared, which releases it back to auto-grow. A completed manual resize logs `[operator-ui] op=wa-composer-resize mode=drag|key h=<px>`; a bare click on the handle (no drag) logs nothing.
|
|
79
83
|
|
|
80
84
|
**`/chat` live activity line.** While a turn is in flight the transcript tail shows one ephemeral `ChatActivity` line (mounted only while `busy`, admin/operator only). It tracks real activity, not a timer: while a `Task` subagent runs it shows that subagent's headline (`agentType · description`, prefixed `N agents ·` when ≥2 are concurrent), sourced from `agent-<hex>.meta.json` via named `activity` SSE events the admin reader pushes from the session's `subagents/` dir; with no subagent active it shows a neutral word that advances only on a real turn arrival. The line carries a turn-elapsed clock and flips to a `stalled` state once nothing has been written for 5 minutes (`now − lastEmitAt`), so the operator can tell a wedge from progress without SSH. It is never added to the persisted timeline. Detail and the `[webchat-activity]` observability live in [`admin-webchat-native-channel.md`](../../../.docs/admin-webchat-native-channel.md).
|
|
@@ -6,13 +6,13 @@ By default the admin assistant is scoped the same way — it acts on the house a
|
|
|
6
6
|
|
|
7
7
|
The operator wants this for two surfaces: the account graph and the account filesystem. Each is a separate adoption; a coverage ledger tracks them and a background check confirms neither silently regresses.
|
|
8
8
|
|
|
9
|
-
## Creating a sub-account
|
|
9
|
+
## Creating a sub-account can name a managing admin
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
A client sub-account may have a responsible house admin, but one is optional. `account_create` takes the `userId` of a current house admin as the managing admin — the admin agent asks the operator which house admin manages the client (the choices come from `admin-list`) — and records it as `managingAdminUserId` on the sub-account; a supplied `userId` that is not a live house admin is refused. Omit it for a client run by its owner rather than a house team member. A WhatsApp requirement that comes in for that sub-account is filed as a task assigned to its managing admin; when the sub-account has no managing admin (or its recorded one is no longer a live house admin), the task is assigned to the install's primary admin (the first house admin) instead, so it always lands with a named owner rather than unassigned.
|
|
12
12
|
|
|
13
13
|
## Reassigning and removing a managing admin
|
|
14
14
|
|
|
15
|
-
To hand a client to a different team member — or to
|
|
15
|
+
To hand a client to a different team member — or to record a managing admin on an unmanaged account, or repair one whose admin was removed — use `account_reassign_admin` with the client's `accountId` and the new admin's `userId`. It refuses a target that is not a client sub-account or a `userId` that is not a current house admin. Removing a house admin is guarded so it cannot silently orphan anyone: `admin-remove` refuses to remove an admin who is still the managing admin of one or more client sub-accounts and names those accounts. Reassign each with `account_reassign_admin`, then remove the admin.
|
|
16
16
|
|
|
17
17
|
## Memory (graph)
|
|
18
18
|
|
|
@@ -81,6 +81,14 @@ operator plugin
|
|
|
81
81
|
|
|
82
82
|
`poll` maps Microsoft's polling errors: `authorization_pending` → `pending` (wait `intervalSec`, poll again), `slow_down` → `pending` with a bumped interval, `expired_token` → `expired`, `access_denied` → `denied`.
|
|
83
83
|
|
|
84
|
+
### Re-registering an account that already consented
|
|
85
|
+
|
|
86
|
+
First-time registration completes cleanly. Re-registering a mailbox whose Microsoft account has **already granted this app access** on a prior registration does not: after the operator enters the user code, Microsoft's consent step redirects the browser to `http://localhost/?error=invalid_request&error_description=...response_type...`, a "site can't be reached" dead-end, and consent never finishes. Observed for personal accounts (outlook.com, hotmail.com, live.com), whose completion runs through the consumer stack (`login.live.com` `msaidpvalidate` → `post.srf`).
|
|
87
|
+
|
|
88
|
+
This is Microsoft's re-consent behaviour, not a plugin fault. Confirmed 2026-07-14: our `/devicecode` request is byte-identical to a run that succeeded days earlier (only the account's consent state differed); the `response_type` the error names is absent because the device-code grant has no such parameter; and the malformed redirect is built by Microsoft's `post.srf`, not by anything the plugin sends. Removing the app's `http://localhost` reply URL does not help (the redirect uses a request-supplied `redirect_uri`, not a registered one), and the Implicit-grant/ID-token toggle does not apply (device-code is a public-client flow, not Web/SPA).
|
|
89
|
+
|
|
90
|
+
The block is the **stale Microsoft-side grant**, which lives in the end user's own Microsoft account, so there is no server-side tool to clear it. The operator revokes the app at **https://account.microsoft.com/privacy/app-access** (remove the brand's app entry), then re-runs `outlook-account-register`; the next sign-in is treated as first-time and completes. The already-connected mailbox keeps working the whole time — only the re-registration is blocked. See `.tasks/backlog/1634-outlook-account-deregister-and-reconsent-guidance.md` for the follow-up on a server-side deregister tool and a register-time hint.
|
|
91
|
+
|
|
84
92
|
## Token store layout
|
|
85
93
|
|
|
86
94
|
One account can hold several mailboxes. Each mailbox owns its own `tokens.enc`
|
|
@@ -37,6 +37,8 @@ Subsequent tool calls use the persisted refresh token to mint access tokens tran
|
|
|
37
37
|
|
|
38
38
|
If the brand ships no vendor app yet, `outlook-account-register` reports that the client ID is not configured. There is no per-install workaround; the brand's vendor app has to exist first.
|
|
39
39
|
|
|
40
|
+
**Re-connecting a mailbox that already granted access.** First-time registration works cleanly. But if the target Microsoft account has *already* consented to this brand's app on a prior registration, starting a fresh `outlook-account-register` for it dead-ends: after the operator enters the code, Microsoft's consent step redirects the browser to a `http://localhost` "this site can't be reached" page instead of completing. This is Microsoft's re-consent behaviour for a personal account (outlook.com, hotmail.com, live.com), not a fault in this plugin; our device-code request is unchanged, and the connected mailbox keeps working throughout. The block is the stale Microsoft-side grant, and there is no server-side tool to clear it because that grant lives in the end user's own Microsoft account. To re-connect, the operator first revokes this app at **https://account.microsoft.com/privacy/app-access** (find the brand's app, remove it), then re-runs `outlook-account-register`; the next sign-in is treated as new and completes. Relay this to the operator whenever a re-registration stalls at a localhost page.
|
|
41
|
+
|
|
40
42
|
**Microsoft mail does not use IMAP or app passwords.** Microsoft retired Basic auth for Exchange Online and app passwords stopped working. Never route a Microsoft mailbox through the `email` plugin's IMAP path, and never suggest an app password. The device-code flow above is the only supported connection.
|
|
41
43
|
|
|
42
44
|
## Reading mail
|
|
@@ -85,6 +87,7 @@ All calendar writes need the `Calendars.ReadWrite` consent (see setup above). Ti
|
|
|
85
87
|
| `Microsoft Graph does not support on-premises Exchange` | Mailbox is on hybrid Exchange | Use the `email` plugin (IMAP) |
|
|
86
88
|
| `Outlook send scope not granted (missing Mail.Send)` | Mailbox registered under the old read-only consent | Re-run `outlook-account-register` and consent to the send scopes |
|
|
87
89
|
| `Outlook rate-limited without Retry-After hint` | Graph 429 with no backoff guidance | Retry later; if persistent, file a bug |
|
|
90
|
+
| Registration dead-ends at a `http://localhost` "site can't be reached" page | The account already granted this app access on a prior registration; Microsoft's re-consent path for a personal account breaks | Revoke this app at https://account.microsoft.com/privacy/app-access, then re-run `outlook-account-register` |
|
|
88
91
|
|
|
89
92
|
## Reference files
|
|
90
93
|
|
package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-attachment-suffix.test.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-attachment-suffix.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/format-attachment-suffix.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { attachmentSuffix } from "../format.js";
|
|
3
|
+
describe("attachmentSuffix", () => {
|
|
4
|
+
it("renders filename, mime, human-readable size, and the Read path", () => {
|
|
5
|
+
const s = attachmentSuffix({
|
|
6
|
+
filename: "CR2965 Priory Court Canopy.pdf",
|
|
7
|
+
mimeType: "application/pdf",
|
|
8
|
+
sizeBytes: 167936, // 164KB
|
|
9
|
+
path: "/data/accounts/x/uploads/y/y.pdf",
|
|
10
|
+
});
|
|
11
|
+
expect(s).toContain("CR2965 Priory Court Canopy.pdf");
|
|
12
|
+
expect(s).toContain("application/pdf, 164KB");
|
|
13
|
+
expect(s).toContain("Read: /data/accounts/x/uploads/y/y.pdf");
|
|
14
|
+
});
|
|
15
|
+
it("renders MB for sizes at or above 1MB", () => {
|
|
16
|
+
const s = attachmentSuffix({
|
|
17
|
+
filename: "big.xlsx",
|
|
18
|
+
mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
19
|
+
sizeBytes: 1_092_236, // ~1.0MB
|
|
20
|
+
path: "/p",
|
|
21
|
+
});
|
|
22
|
+
expect(s).toContain("1.0MB");
|
|
23
|
+
});
|
|
24
|
+
it("omits the size annotation when sizeBytes is absent (no misleading 0)", () => {
|
|
25
|
+
const s = attachmentSuffix({ filename: "x.pdf", mimeType: "application/pdf", path: "/p" });
|
|
26
|
+
expect(s).toContain("(application/pdf)");
|
|
27
|
+
expect(s).not.toContain("undefined");
|
|
28
|
+
});
|
|
29
|
+
it("returns empty string for a null/no-path attachment (unchanged behaviour)", () => {
|
|
30
|
+
expect(attachmentSuffix(null)).toBe("");
|
|
31
|
+
expect(attachmentSuffix({ filename: "x" })).toBe(""); // no path
|
|
32
|
+
});
|
|
33
|
+
it("still appends the readable-text line when present (unchanged behaviour)", () => {
|
|
34
|
+
const s = attachmentSuffix({
|
|
35
|
+
filename: "doc.xlsx",
|
|
36
|
+
mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
37
|
+
sizeBytes: 320,
|
|
38
|
+
path: "/p/doc.xlsx",
|
|
39
|
+
readableTextPath: "/p/doc.extracted.txt",
|
|
40
|
+
});
|
|
41
|
+
expect(s).toContain("[readable text; Read: /p/doc.extracted.txt]");
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=format-attachment-suffix.test.js.map
|
package/payload/platform/plugins/whatsapp/mcp/dist/__tests__/format-attachment-suffix.test.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-attachment-suffix.test.js","sourceRoot":"","sources":["../../src/__tests__/format-attachment-suffix.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,CAAC,GAAG,gBAAgB,CAAC;YACzB,QAAQ,EAAE,gCAAgC;YAC1C,QAAQ,EAAE,iBAAiB;YAC3B,SAAS,EAAE,MAAM,EAAE,QAAQ;YAC3B,IAAI,EAAE,kCAAkC;SACzC,CAAC,CAAC;QACH,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;QACtD,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QAC9C,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,wCAAwC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,GAAG,gBAAgB,CAAC;YACzB,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,mEAAmE;YAC7E,SAAS,EAAE,SAAS,EAAE,SAAS;YAC/B,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QACH,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,CAAC,GAAG,gBAAgB,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3F,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QACzC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;QAClF,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,CAAC,gBAAgB,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,MAAM,CAAC,GAAG,gBAAgB,CAAC;YACzB,QAAQ,EAAE,UAAU;YACpB,QAAQ,EAAE,mEAAmE;YAC7E,SAAS,EAAE,GAAG;YACd,IAAI,EAAE,aAAa;YACnB,gBAAgB,EAAE,sBAAsB;SACzC,CAAC,CAAC;QACH,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,6CAA6C,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -4,4 +4,11 @@ export declare function buildLoginStartText(result: {
|
|
|
4
4
|
pairingCode?: string;
|
|
5
5
|
selfPhone?: string;
|
|
6
6
|
}): string;
|
|
7
|
+
export declare function attachmentSuffix(att: {
|
|
8
|
+
filename?: string;
|
|
9
|
+
mimeType?: string;
|
|
10
|
+
path?: string;
|
|
11
|
+
sizeBytes?: number;
|
|
12
|
+
readableTextPath?: string;
|
|
13
|
+
} | null | undefined): string;
|
|
7
14
|
//# sourceMappingURL=format.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAE3F,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CAkBT"}
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAE3F,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CAkBT;AAmBD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAOvK"}
|
|
@@ -18,4 +18,31 @@ export function buildLoginStartText(result) {
|
|
|
18
18
|
}
|
|
19
19
|
return response;
|
|
20
20
|
}
|
|
21
|
+
/** Task 1635 — human-readable byte size. Near-identical formatters already exist
|
|
22
|
+
* elsewhere (attachment-render.tsx, email/mcp's imap.ts, memory/mcp) but none
|
|
23
|
+
* live anywhere this MCP package can import from (a React component, or another
|
|
24
|
+
* plugin's private lib) — see Task 1638 for consolidating them into a shared
|
|
25
|
+
* location. This stays private to this package until then. */
|
|
26
|
+
function humanSize(bytes) {
|
|
27
|
+
if (bytes < 1024 * 1024)
|
|
28
|
+
return `${Math.round(bytes / 1024)}KB`;
|
|
29
|
+
return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
|
|
30
|
+
}
|
|
31
|
+
// Task 1606 — render a recall row's attachment as an indented suffix the agent
|
|
32
|
+
// can act on. `path` points at the house-stored bytes (an image renders when the
|
|
33
|
+
// agent Reads it); `readableTextPath`, when the platform has extracted text, is
|
|
34
|
+
// the plain-text sibling to Read instead of the binary. Empty string when the
|
|
35
|
+
// row has no attachment, so callers append unconditionally.
|
|
36
|
+
// Task 1635 — `sizeBytes`, when present, renders inline next to the mime type
|
|
37
|
+
// so an agent can confirm a non-trivial size without a filesystem check.
|
|
38
|
+
export function attachmentSuffix(att) {
|
|
39
|
+
if (!att || !att.path)
|
|
40
|
+
return "";
|
|
41
|
+
const mime = att.mimeType ?? "unknown";
|
|
42
|
+
const sizeSuffix = typeof att.sizeBytes === "number" ? `, ${humanSize(att.sizeBytes)}` : "";
|
|
43
|
+
let s = `\n [attachment: ${att.filename ?? "file"} (${mime}${sizeSuffix}); Read: ${att.path}]`;
|
|
44
|
+
if (att.readableTextPath)
|
|
45
|
+
s += `\n [readable text; Read: ${att.readableTextPath}]`;
|
|
46
|
+
return s;
|
|
47
|
+
}
|
|
21
48
|
//# sourceMappingURL=format.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAE3F,MAAM,UAAU,mBAAmB,CAAC,MAInC;IACC,IAAI,QAAQ,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;IACpC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,QAAQ,GAAG;YACT,0BAA0B,MAAM,CAAC,WAAW,EAAE;YAC9C,EAAE;YACF,uDAAuD;YACvD,8DAA8D;YAC9D,yCAAyC;YACzC,uBAAuB,MAAM,CAAC,WAAW,EAAE;YAC3C,EAAE;YACF,uDAAuD;SACxD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,QAAQ,IAAI,mBAAmB,MAAM,CAAC,SAAS,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAE3F,MAAM,UAAU,mBAAmB,CAAC,MAInC;IACC,IAAI,QAAQ,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;IACpC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,QAAQ,GAAG;YACT,0BAA0B,MAAM,CAAC,WAAW,EAAE;YAC9C,EAAE;YACF,uDAAuD;YACvD,8DAA8D;YAC9D,yCAAyC;YACzC,uBAAuB,MAAM,CAAC,WAAW,EAAE;YAC3C,EAAE;YACF,uDAAuD;SACxD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,QAAQ,IAAI,mBAAmB,MAAM,CAAC,SAAS,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;+DAI+D;AAC/D,SAAS,SAAS,CAAC,KAAa;IAC9B,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC;IAChE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED,+EAA+E;AAC/E,iFAAiF;AACjF,gFAAgF;AAChF,8EAA8E;AAC9E,4DAA4D;AAC5D,8EAA8E;AAC9E,yEAAyE;AACzE,MAAM,UAAU,gBAAgB,CAAC,GAA8H;IAC7J,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,IAAI,SAAS,CAAC;IACvC,MAAM,UAAU,GAAG,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5F,IAAI,CAAC,GAAG,sBAAsB,GAAG,CAAC,QAAQ,IAAI,MAAM,KAAK,IAAI,GAAG,UAAU,YAAY,GAAG,CAAC,IAAI,GAAG,CAAC;IAClG,IAAI,GAAG,CAAC,gBAAgB;QAAE,CAAC,IAAI,+BAA+B,GAAG,CAAC,gBAAgB,GAAG,CAAC;IACtF,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -10,7 +10,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
10
10
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
import { callApi as rawCallApi } from "./call-api.js";
|
|
13
|
-
import { buildLoginStartText } from "./format.js";
|
|
13
|
+
import { buildLoginStartText, attachmentSuffix } from "./format.js";
|
|
14
14
|
import { resolveReadAccountId } from "./resolve-read-account.js";
|
|
15
15
|
import { callerScopeHeaders } from "./caller-scope-headers.js";
|
|
16
16
|
import { requirePortEnv } from "../../../../lib/require-port-env/dist/index.js";
|
|
@@ -50,19 +50,6 @@ function textResult(text, isError = false) {
|
|
|
50
50
|
...(isError ? { isError: true } : {}),
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
// Task 1606 — render a recall row's attachment as an indented suffix the agent
|
|
54
|
-
// can act on. `path` points at the house-stored bytes (an image renders when the
|
|
55
|
-
// agent Reads it); `readableTextPath`, when the platform has extracted text, is
|
|
56
|
-
// the plain-text sibling to Read instead of the binary. Empty string when the
|
|
57
|
-
// row has no attachment, so callers append unconditionally.
|
|
58
|
-
function attachmentSuffix(att) {
|
|
59
|
-
if (!att || !att.path)
|
|
60
|
-
return "";
|
|
61
|
-
let s = `\n [attachment: ${att.filename ?? "file"} (${att.mimeType ?? "unknown"}); Read: ${att.path}]`;
|
|
62
|
-
if (att.readableTextPath)
|
|
63
|
-
s += `\n [readable text; Read: ${att.readableTextPath}]`;
|
|
64
|
-
return s;
|
|
65
|
-
}
|
|
66
53
|
// ─── whatsapp-login-start ──────────────────────────────────────────────
|
|
67
54
|
lifelineTool(server, "whatsapp-login-start", 'Start WhatsApp pairing. Requires the operator\'s WhatsApp phone number (E.164). Returns an 8-character pairing code the operator types into WhatsApp → Linked Devices → Link a Device → "Link with phone number instead." No QR image — this surface is an async chat where a rotating QR cannot be scanned in time.', {
|
|
68
55
|
phone: z.string().describe("WhatsApp phone number in E.164 (e.g. +441234567890) — the number being linked"),
|
|
@@ -70,7 +57,7 @@ lifelineTool(server, "whatsapp-login-start", 'Start WhatsApp pairing. Requires t
|
|
|
70
57
|
force: z.boolean().optional().describe("Force re-link even if already connected"),
|
|
71
58
|
}, async ({ phone, accountId, force }) => {
|
|
72
59
|
try {
|
|
73
|
-
const result = await callApi("whatsapp-login-start", "/api/whatsapp/login/start", "POST", { phone, accountId, force });
|
|
60
|
+
const result = await callApi("whatsapp-login-start", "/api/whatsapp/login/start", "POST", { phone, accountId, force }, callerScopeHeaders(process.env));
|
|
74
61
|
if (result.error)
|
|
75
62
|
return textResult(`Login start failed: ${result.error}`, true);
|
|
76
63
|
return textResult(buildLoginStartText(result));
|
|
@@ -85,7 +72,7 @@ lifelineTool(server, "whatsapp-login-wait", "Wait for the operator to enter the
|
|
|
85
72
|
timeoutMs: z.number().optional().describe("Max wait time in ms (default: 60000)"),
|
|
86
73
|
}, async ({ accountId, timeoutMs }) => {
|
|
87
74
|
try {
|
|
88
|
-
const result = await callApi("whatsapp-login-wait", "/api/whatsapp/login/wait", "POST", { accountId, timeoutMs });
|
|
75
|
+
const result = await callApi("whatsapp-login-wait", "/api/whatsapp/login/wait", "POST", { accountId, timeoutMs }, callerScopeHeaders(process.env));
|
|
89
76
|
if (result.error)
|
|
90
77
|
return textResult(`Login wait failed: ${result.error}`, true);
|
|
91
78
|
let response = result.message;
|
|
@@ -101,7 +88,7 @@ lifelineTool(server, "whatsapp-login-wait", "Wait for the operator to enter the
|
|
|
101
88
|
// ─── whatsapp-status ───────────────────────────────────────────────────
|
|
102
89
|
lifelineTool(server, "whatsapp-status", "Get WhatsApp connection status for all linked accounts. Shows connected/disconnected state, linked phone number, and reconnection attempts.", {}, async () => {
|
|
103
90
|
try {
|
|
104
|
-
const result = await callApi("whatsapp-status", "/api/whatsapp/status", "GET");
|
|
91
|
+
const result = await callApi("whatsapp-status", "/api/whatsapp/status", "GET", undefined, callerScopeHeaders(process.env));
|
|
105
92
|
if (result.error)
|
|
106
93
|
return textResult(`Status check failed: ${result.error}`, true);
|
|
107
94
|
const accounts = result.accounts ?? [];
|
|
@@ -169,7 +156,7 @@ lifelineTool(server, "whatsapp-disconnect", "Disconnect a WhatsApp account. Clos
|
|
|
169
156
|
accountId: z.string().optional().describe('Account ID to disconnect (default: "default")'),
|
|
170
157
|
}, async ({ accountId }) => {
|
|
171
158
|
try {
|
|
172
|
-
const result = await callApi("whatsapp-disconnect", "/api/whatsapp/disconnect", "POST", { accountId });
|
|
159
|
+
const result = await callApi("whatsapp-disconnect", "/api/whatsapp/disconnect", "POST", { accountId }, callerScopeHeaders(process.env));
|
|
173
160
|
if (result.error)
|
|
174
161
|
return textResult(`Disconnect failed: ${result.error}`, true);
|
|
175
162
|
return textResult(`WhatsApp account "${result.accountId}" disconnected.`);
|
|
@@ -232,7 +219,7 @@ lifelineTool(server, "whatsapp-config", [
|
|
|
232
219
|
return textResult('Invalid JSON in "fields" parameter. Expected a JSON object, e.g. {"dmPolicy":"open","allowFrom":["*"]}', true);
|
|
233
220
|
}
|
|
234
221
|
}
|
|
235
|
-
const result = await callApi("whatsapp-config", "/api/whatsapp/config", "POST", { action, phone, managesAccount, mode, slug, fields: parsedFields, accountId });
|
|
222
|
+
const result = await callApi("whatsapp-config", "/api/whatsapp/config", "POST", { action, phone, managesAccount, mode, slug, fields: parsedFields, accountId }, callerScopeHeaders(process.env));
|
|
236
223
|
if (!result.ok)
|
|
237
224
|
return textResult(result.error ?? "Config operation failed.", true);
|
|
238
225
|
if (action === "list-admin-phones") {
|