@rubytech/create-maxy-code 0.1.282 → 0.1.284
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/config/brand.json +0 -1
- package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-search.test.js +3 -3
- package/payload/platform/plugins/admin/mcp/dist/__tests__/skill-search.test.js.map +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +4 -4
- package/payload/platform/plugins/business-assistant/skills/e-sign/SKILL.md +28 -4
- package/payload/platform/plugins/cloudflare/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/cloudflare/PLUGIN.md +5 -5
- package/payload/platform/plugins/cloudflare/references/api.md +78 -38
- package/payload/platform/plugins/cloudflare/references/d1-data-capture.md +27 -21
- package/payload/platform/plugins/cloudflare/references/dashboard-guide.md +3 -2
- package/payload/platform/plugins/cloudflare/references/hosting-sites.md +7 -5
- package/payload/platform/plugins/cloudflare/references/manual-setup.md +3 -2
- package/payload/platform/plugins/cloudflare/skills/cloudflare/SKILL.md +6 -6
- package/payload/platform/plugins/docs/references/telegram-guide.md +3 -3
- package/payload/platform/plugins/telegram/PLUGIN.md +7 -2
- package/payload/platform/plugins/telegram/mcp/dist/index.js +66 -11
- package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts +6 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js +20 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts +21 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js +52 -0
- package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js.map +1 -0
- package/payload/platform/plugins/telegram/mcp/dist/tools/message.d.ts.map +1 -1
- package/payload/platform/plugins/telegram/mcp/dist/tools/message.js +5 -2
- package/payload/platform/plugins/telegram/mcp/dist/tools/message.js.map +1 -1
- package/payload/platform/plugins/telegram/references/setup-guide.md +10 -7
- package/payload/platform/plugins/telegram/skills/configure/SKILL.md +79 -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 +17 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/server/public/assets/AdminShell-8Y7-maNi.js +1 -0
- package/payload/server/public/assets/{admin-0_VxffD5.js → admin-DyuZ4NT5.js} +1 -1
- package/payload/server/public/assets/{browser-Cxjkhtsk.js → browser-XrVAUQdG.js} +1 -1
- package/payload/server/public/assets/{data-BOgwOWnw.js → data-tcu3MXmK.js} +1 -1
- package/payload/server/public/assets/{graph-BqD2GjQd.js → graph-I4GyC2MW.js} +1 -1
- package/payload/server/public/browser.html +2 -2
- package/payload/server/public/data.html +2 -2
- package/payload/server/public/graph.html +2 -2
- package/payload/server/public/index.html +2 -2
- package/payload/server/server.js +827 -531
- package/payload/server/public/assets/AdminShell-FO766lOW.js +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Deploying a site to Cloudflare Pages
|
|
2
2
|
|
|
3
|
-
How to put a static or Next.js site on Cloudflare Pages via `wrangler`, the way `realagent.pages.dev` is deployed. This covers the build → deploy → verify loop and the Next.js specifics. Auth is
|
|
3
|
+
How to put a static or Next.js site on Cloudflare Pages via `wrangler`, the way `realagent.pages.dev` is deployed. This covers the build → deploy → verify loop and the Next.js specifics. Auth is the reused per-scope token per `api.md`; if the site also captures form data, read `d1-data-capture.md` for the dual Pages-Edit **and** D1-Edit scope.
|
|
4
4
|
|
|
5
5
|
This is distinct from `references/serving-published-sites.md`, which serves a platform-published site at a custom domain through the brand's **cloudflared tunnel**. This reference is about **Cloudflare Pages** — Cloudflare hosts the build, not the install device.
|
|
6
6
|
|
|
@@ -31,19 +31,21 @@ compatibility_flags = ["nodejs_compat"] # required for next-on-pages and most F
|
|
|
31
31
|
|
|
32
32
|
If the site captures form data, add the `[[d1_databases]]` binding from `d1-data-capture.md` here.
|
|
33
33
|
|
|
34
|
-
## 3.
|
|
34
|
+
## 3. Load the reused deploy token
|
|
35
35
|
|
|
36
|
-
A Pages deploy needs **Account · Cloudflare Pages · Edit**. If the site has Pages Functions hitting D1, the token also needs **Account · D1 · Edit** (the single most common breakage — see `d1-data-capture.md`).
|
|
36
|
+
A Pages deploy needs **Account · Cloudflare Pages · Edit**. If the site has Pages Functions hitting D1, the token also needs **Account · D1 · Edit** (the single most common breakage — see `d1-data-capture.md`). Load the stable per-scope token — minting it once only if absent — per `api.md` § Provisioning and reusing a stable per-scope token:
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
39
|
set -a; . "${SECRETS_DIR}/cloudflare.env"; set +a
|
|
40
|
-
|
|
40
|
+
: "${CLOUDFLARE_API_TOKEN:?credentials not loaded}"; : "${CLOUDFLARE_ACCOUNT_ID:?account id not loaded}"
|
|
41
|
+
# PAGES_D1 = the reused per-scope token (Pages Edit, + D1 Edit if the site uses D1),
|
|
42
|
+
# loaded from cloudflare.env and minted once if absent — see api.md § Provisioning and reusing.
|
|
41
43
|
```
|
|
42
44
|
|
|
43
45
|
## 4. Deploy
|
|
44
46
|
|
|
45
47
|
```bash
|
|
46
|
-
CLOUDFLARE_API_TOKEN="${
|
|
48
|
+
CLOUDFLARE_API_TOKEN="${PAGES_D1}" wrangler pages deploy <output-dir> \
|
|
47
49
|
--project-name <project> --branch=main
|
|
48
50
|
```
|
|
49
51
|
|
|
@@ -295,8 +295,9 @@ rather than failing.
|
|
|
295
295
|
|
|
296
296
|
**Access policy — API or dashboard.** `cloudflared` CLI has no
|
|
297
297
|
Access-application create subcommand, so author the policy either via
|
|
298
|
-
the Cloudflare API with
|
|
299
|
-
`references/api.md` § Access) or by hand in
|
|
298
|
+
the Cloudflare API with the reused Access-scoped token (`<brand>-access`,
|
|
299
|
+
minted once if absent — see `references/api.md` § Access) or by hand in
|
|
300
|
+
the dashboard. After the
|
|
300
301
|
ingress is in place, the dashboard path is:
|
|
301
302
|
|
|
302
303
|
```
|
|
@@ -14,7 +14,7 @@ This is the entry point for every Cloudflare task on the install. Pick the opera
|
|
|
14
14
|
| Stand up / diagnose / reset a tunnel so a hostname is reachable | `references/manual-setup.md` | external `curl -I https://<hostname>` → `200` |
|
|
15
15
|
| Switch accounts, edit an apex CNAME by hand, or other dashboard-only clicks | `references/dashboard-guide.md` | the click-path completed in the operator's browser |
|
|
16
16
|
| Tear down corrupt tunnel state and start clean | `references/reset-guide.md` | a fresh `manual-setup.md` run reaches `200` |
|
|
17
|
-
| Call the Cloudflare API (DNS, zones, tunnels, Access, token
|
|
17
|
+
| Call the Cloudflare API (DNS, zones, tunnels, Access, token list/reuse/revoke) | `references/api.md` | the API call returns success and the change is observable |
|
|
18
18
|
| Deploy a static / Next.js site to Cloudflare Pages | `references/hosting-sites.md` | the deployed URL serves the new build |
|
|
19
19
|
| Capture form/waitlist submissions into a database | `references/d1-data-capture.md` | a test POST appears in `SELECT … WHERE swept = 0` |
|
|
20
20
|
| Diagnose / enable Web Analytics on a site (0 visitors, no data) | `references/web-analytics.md` | beacon present in live HTML (`curl -s https://<host>/ \| grep cloudflareinsights`) |
|
|
@@ -22,9 +22,9 @@ This is the entry point for every Cloudflare task on the install. Pick the opera
|
|
|
22
22
|
## Two auth paths, by operation class
|
|
23
23
|
|
|
24
24
|
- **Tunnel auth is OAuth.** `cloudflared tunnel login` writes `cert.pem`; the operator clicks the linkified OAuth URL in their own browser. This is the only path for tunnel create/route/run. See `references/manual-setup.md`.
|
|
25
|
-
- **API auth is the master token.** The operator provisions one fully-scoped master token once (an **advanced**, operator-guided dashboard step — the agent does not automate it) and stores it at the account-scoped secrets file. The agent reads the master only to **
|
|
25
|
+
- **API auth is the master token.** The operator provisions one fully-scoped master token once (an **advanced**, operator-guided dashboard step — the agent does not automate it) and stores it at the account-scoped secrets file. The agent reads the master only to **provision one stable narrow token per scope** — `<brand>-pages-d1`, `<brand>-dns`, `<brand>-access` — loading it from the secrets file, minting it once if absent (no expiry), persisting it, and reusing it for every later operation in that scope. A standing **reconcile** pass revokes strays. See `references/api.md` for the storage convention, the provisioning-and-reuse flow, the reconcile pass, and the binding redaction discipline.
|
|
26
26
|
|
|
27
|
-
Neither the master token nor any
|
|
27
|
+
Neither the master token nor any per-scope token is ever written into a project tree, committed, or echoed into chat — the per-scope tokens persist only in the account-scoped secrets file, never in a deployable project tree.
|
|
28
28
|
|
|
29
29
|
## Outcome contracts — what "done" means
|
|
30
30
|
|
|
@@ -55,7 +55,7 @@ After the service is up, the agent runs `curl -I https://<admin-hostname>` and p
|
|
|
55
55
|
|
|
56
56
|
## Apex hostnames
|
|
57
57
|
|
|
58
|
-
The `cloudflared` CLI cannot route apex records (e.g. `maxy.chat`) — standard DNS forbids a CNAME at the zone apex. There are now two ways to create the apex record: the operator edits the apex CNAME in the dashboard (`references/dashboard-guide.md` § "Edit an apex CNAME"), or the agent creates it via the Cloudflare API with
|
|
58
|
+
The `cloudflared` CLI cannot route apex records (e.g. `maxy.chat`) — standard DNS forbids a CNAME at the zone apex. There are now two ways to create the apex record: the operator edits the apex CNAME in the dashboard (`references/dashboard-guide.md` § "Edit an apex CNAME"), or the agent creates it via the Cloudflare API with the reused DNS-scoped token (`<brand>-dns`, minted once if absent — `references/api.md` § DNS records). Either reaches the same flattened-CNAME result; pick the dashboard path when the operator prefers to click, the API path when an end-to-end agent run is wanted.
|
|
59
59
|
|
|
60
60
|
## Reset
|
|
61
61
|
|
|
@@ -66,10 +66,10 @@ When local Cloudflare state is corrupt or the operator wants to start from a kno
|
|
|
66
66
|
When the operator's request touches Cloudflare, the agent's permitted actions are:
|
|
67
67
|
|
|
68
68
|
- Invoke `cloudflared` via Bash, following `references/manual-setup.md`.
|
|
69
|
-
- Invoke `wrangler` and the Cloudflare API via Bash, following `references/api.md`, `references/hosting-sites.md`, and `references/d1-data-capture.md`, using
|
|
69
|
+
- Invoke `wrangler` and the Cloudflare API via Bash, following `references/api.md`, `references/hosting-sites.md`, and `references/d1-data-capture.md`, using the reused per-scope narrow token (minted once if absent, then reused).
|
|
70
70
|
- Write `config.yml` and `alias-domains.json` per the runbook.
|
|
71
71
|
- Install and start the brand's cloudflared user service.
|
|
72
72
|
- Quote `references/manual-setup.md`, `references/reset-guide.md`, or `references/dashboard-guide.md` verbatim when a dashboard click-path is the right tool.
|
|
73
73
|
- Verify reachability via `curl -I https://<hostname>` and surface the response.
|
|
74
74
|
|
|
75
|
-
The agent does not drive the dashboard via Playwright or Chrome DevTools, and does not browser-automate master-token creation. It does not synthesise `cloudflared` flag combinations from web search or training — every command comes from the runbook. It never writes a token to disk in a project tree, commits one, or prints one into chat. When a step fails, the agent reports the exact output, names the recovery step from `references/reset-guide.md`, and stops. Improvisation — "let me try a different flag"
|
|
75
|
+
The agent does not drive the dashboard via Playwright or Chrome DevTools, and does not browser-automate master-token creation. It does not synthesise `cloudflared` flag combinations from web search or training — every command comes from the runbook. **Cloudflare API calls are made with `curl` + `jq` only — never a Python or node script.** It never writes a token to disk in a project tree, commits one, or prints one into chat. When a step fails, the agent reports the exact output, names the recovery step from `references/reset-guide.md`, and stops. Improvisation — "let me try a different flag", "let me drive the dashboard myself", or "let me write a quick Python script for this API call" — is the behaviour this rule exists to prevent.
|
|
@@ -19,13 +19,13 @@ The Telegram plugin connects {{productName}} to a Telegram bot. Once set up, you
|
|
|
19
19
|
|
|
20
20
|
### Step 2: Connect the plugin
|
|
21
21
|
|
|
22
|
-
Tell {{productName}}: "Set up Telegram" or "Configure the Telegram bot."
|
|
22
|
+
Tell {{productName}}: "Set up Telegram" or "Configure the Telegram bot." Setup runs entirely in the admin chat — there is no settings page.
|
|
23
23
|
|
|
24
|
-
{{productName}}
|
|
24
|
+
{{productName}} asks for your bot token, then asks whether this is an **admin bot** (only your numeric Telegram IDs may message it) or a **public bot** (customer-facing, with a DM policy). It verifies the token, registers the bot's webhook on your brand's edge, stores the token under your brand's config (never in a shared system directory), and — for a public bot — sets the agent that will answer. The bot is now connected.
|
|
25
25
|
|
|
26
26
|
### Step 3: Start the bot
|
|
27
27
|
|
|
28
|
-
In Telegram, open your bot and send `/start
|
|
28
|
+
In Telegram, open your bot and send `/start`, then a message. {{productName}} receives it and replies in the same chat. Admin-bot messages from your registered IDs reach the admin agent; public-bot messages reach the public agent you selected.
|
|
29
29
|
|
|
30
30
|
## Sending Messages via {{productName}}
|
|
31
31
|
|
|
@@ -44,10 +44,15 @@ Walks users through connecting Telegram bots. Covers bot creation, token configu
|
|
|
44
44
|
- Multi-bot support — separate admin and public bots with different access policies
|
|
45
45
|
- Admin routing — restrict a bot to admin-only access via numeric user ID bindings
|
|
46
46
|
|
|
47
|
+
## Setup
|
|
48
|
+
|
|
49
|
+
Connecting a Telegram bot runs through the `telegram:configure` skill (`skills/configure/SKILL.md`) — the brand-aware, PTY-only setup flow. It is the maxy `telegram:configure`; on `-code` brands the upstream `claude-plugins-official/telegram` plugin is not installed, so there is no shadowing (Task 727). The skill stores the BotFather token under the brand install, registers the webhook on the `/api/telegram/` edge path, sets access policy, and selects the responding agent.
|
|
50
|
+
|
|
47
51
|
## References
|
|
48
52
|
|
|
49
53
|
| Task | When to use | Reference |
|
|
50
54
|
|------|-------------|-----------|
|
|
51
|
-
| Guided setup | User wants help connecting Telegram | `
|
|
55
|
+
| Guided setup | User wants help connecting Telegram | `skills/configure/SKILL.md` |
|
|
56
|
+
| BotFather / user-ID / admin-vs-public detail | Operator needs the underlying detail | `references/setup-guide.md` |
|
|
52
57
|
|
|
53
|
-
Load the
|
|
58
|
+
Load the skill and follow its instructions.
|
|
@@ -7,6 +7,7 @@ import { z } from "zod";
|
|
|
7
7
|
import { message } from "./tools/message.js";
|
|
8
8
|
import { messageHistory } from "./tools/message-history.js";
|
|
9
9
|
import { setWebhook, getWebhookInfo } from "./lib/telegram.js";
|
|
10
|
+
import { persistTelegramConfig, CANONICAL_TELEGRAM_PREFIX } from "./lib/account-write.js";
|
|
10
11
|
const server = new McpServer({
|
|
11
12
|
name: "maxy-messaging",
|
|
12
13
|
version: "0.1.0",
|
|
@@ -103,23 +104,26 @@ eagerTool(server, "message-history", "Query conversation history from the messag
|
|
|
103
104
|
import { homedir } from "node:os";
|
|
104
105
|
import { resolve, join } from "node:path";
|
|
105
106
|
import { existsSync, readFileSync } from "node:fs";
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
// The brand config-dir name (e.g. ".siteoffice-code"), read from brand.json.
|
|
108
|
+
// Falls back to ".maxy". Used for both the webhook-secret path and the
|
|
109
|
+
// op=token-write brand= log field.
|
|
110
|
+
function configDirName() {
|
|
110
111
|
const platformRoot = process.env.PLATFORM_ROOT;
|
|
111
112
|
if (platformRoot) {
|
|
112
113
|
const brandPath = join(platformRoot, "config", "brand.json");
|
|
113
114
|
if (existsSync(brandPath)) {
|
|
114
115
|
try {
|
|
115
|
-
|
|
116
|
-
if (brand.configDir)
|
|
117
|
-
configDirName = brand.configDir;
|
|
116
|
+
return JSON.parse(readFileSync(brandPath, "utf-8")).configDir ?? ".maxy";
|
|
118
117
|
}
|
|
119
118
|
catch { /* fall back to .maxy */ }
|
|
120
119
|
}
|
|
121
120
|
}
|
|
122
|
-
|
|
121
|
+
return ".maxy";
|
|
122
|
+
}
|
|
123
|
+
// Derive the webhook secret file path (mirrors paths.ts logic).
|
|
124
|
+
// Restricted to known filenames — prevents path traversal.
|
|
125
|
+
function resolveSecretFilePath(botType) {
|
|
126
|
+
const maxyDir = resolve(homedir(), configDirName());
|
|
123
127
|
const filename = botType === "admin"
|
|
124
128
|
? ".telegram-admin-webhook-secret"
|
|
125
129
|
: ".telegram-webhook-secret";
|
|
@@ -127,10 +131,36 @@ function resolveSecretFilePath(botType) {
|
|
|
127
131
|
}
|
|
128
132
|
eagerTool(server, "telegram-webhook-register", "Register or re-register a Telegram bot webhook. Generates a cryptographic secret, persists it to disk, and passes it to the Telegram Bot API. Call this after obtaining a bot token from BotFather.", {
|
|
129
133
|
botToken: z.string().describe("Telegram bot token from BotFather"),
|
|
130
|
-
webhookUrl: z.string().url().describe("Full webhook URL
|
|
131
|
-
botType: z.enum(["public", "admin"]).describe("Bot type — determines which secret file
|
|
132
|
-
|
|
134
|
+
webhookUrl: z.string().url().describe("Full webhook URL; path MUST be under /api/telegram/ (the maxy edge-admitted path), with ?bot=public or ?bot=admin"),
|
|
135
|
+
botType: z.enum(["public", "admin"]).describe("Bot type — determines which secret file + which account.json token field"),
|
|
136
|
+
adminUsers: z.array(z.number()).optional().describe("Admin numeric user IDs (admin bot only)"),
|
|
137
|
+
dmPolicy: z.enum(["open", "allowlist", "disabled"]).optional().describe("DM policy (public bot only)"),
|
|
138
|
+
allowFrom: z.array(z.number()).optional().describe("Allowlisted numeric user IDs (public bot, allowlist policy)"),
|
|
139
|
+
}, async ({ botToken, webhookUrl, botType, adminUsers, dmPolicy, allowFrom }) => {
|
|
133
140
|
const secretFilePath = resolveSecretFilePath(botType);
|
|
141
|
+
// Assert the webhook path is the one canonical maxy edge-admitted path
|
|
142
|
+
// before touching Telegram. A /channels/telegram URL (the official plugin's
|
|
143
|
+
// path) is rejected at the maxy edge, so registering it would silently fail
|
|
144
|
+
// on the first inbound — fail loudly here instead.
|
|
145
|
+
const webhookPath = (() => {
|
|
146
|
+
try {
|
|
147
|
+
return new URL(webhookUrl).pathname;
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return webhookUrl;
|
|
151
|
+
}
|
|
152
|
+
})();
|
|
153
|
+
const admitted = webhookPath.startsWith(CANONICAL_TELEGRAM_PREFIX);
|
|
154
|
+
console.error(`[telegram-setup] op=webhook-register path=${webhookPath} admitted=${admitted}`);
|
|
155
|
+
if (!admitted) {
|
|
156
|
+
return {
|
|
157
|
+
content: [{
|
|
158
|
+
type: "text",
|
|
159
|
+
text: `Webhook path "${webhookPath}" is not under ${CANONICAL_TELEGRAM_PREFIX} — the maxy edge will reject it. Use a URL whose path starts with ${CANONICAL_TELEGRAM_PREFIX}`,
|
|
160
|
+
}],
|
|
161
|
+
isError: true,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
134
164
|
try {
|
|
135
165
|
// Verify the token is valid by calling getMe
|
|
136
166
|
const meRes = await fetch(`https://api.telegram.org/bot${botToken}/getMe`);
|
|
@@ -160,6 +190,31 @@ eagerTool(server, "telegram-webhook-register", "Register or re-register a Telegr
|
|
|
160
190
|
isError: true,
|
|
161
191
|
};
|
|
162
192
|
}
|
|
193
|
+
// Persist the bot token + access policy into account.json's telegram
|
|
194
|
+
// block — the per-account, brand-isolated store the inbound receiver and
|
|
195
|
+
// the message tool both read. Assert the resolved dir is under the brand
|
|
196
|
+
// install (never ~/.claude) before claiming success.
|
|
197
|
+
const platformRoot = process.env.PLATFORM_ROOT;
|
|
198
|
+
const accountId = process.env.ACCOUNT_ID;
|
|
199
|
+
if (!platformRoot || !accountId) {
|
|
200
|
+
console.error(`[telegram-setup] op=token-write-rejected reason=no-account-env`);
|
|
201
|
+
return {
|
|
202
|
+
content: [{ type: "text", text: `PLATFORM_ROOT/ACCOUNT_ID not in MCP env — cannot persist the bot token to account.json` }],
|
|
203
|
+
isError: true,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
// persistTelegramConfig asserts the resolved dir is under the brand
|
|
207
|
+
// install BEFORE writing (non-brand-path is rejected, not written), so a
|
|
208
|
+
// failure here means nothing was persisted.
|
|
209
|
+
const persisted = persistTelegramConfig(platformRoot, accountId, { botType, botToken, adminUsers, dmPolicy, allowFrom });
|
|
210
|
+
if (!persisted.ok) {
|
|
211
|
+
console.error(`[telegram-setup] op=token-write-rejected reason=${persisted.error}${persisted.dir ? ` dir=${persisted.dir}` : ""}`);
|
|
212
|
+
const text = persisted.error === "non-brand-path"
|
|
213
|
+
? `Refusing to write token outside the brand install: ${persisted.dir}`
|
|
214
|
+
: `Token persist failed: ${persisted.error}`;
|
|
215
|
+
return { content: [{ type: "text", text }], isError: true };
|
|
216
|
+
}
|
|
217
|
+
console.error(`[telegram-setup] op=token-write dir=${persisted.dir} brand=${configDirName()}`);
|
|
163
218
|
// Verify registration — guarded because getWebhookInfo can fail
|
|
164
219
|
// independently of a successful registration (e.g., transient API error).
|
|
165
220
|
let verifyInfo = "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8CAA8C,CAAC;AAC7E,aAAa,CAAC,UAAU,CAAC,CAAC;AAE1B,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Resolve the Telegram bot token from the per-account account.json telegram
|
|
2
|
+
* block. Brand-isolated: account.json lives under the install's data/accounts,
|
|
3
|
+
* never ~/.claude. Prefers adminBotToken (the admin agent's outbound bot),
|
|
4
|
+
* falling back to publicBotToken. Returns null when neither is present. */
|
|
5
|
+
export declare function resolveBotToken(platformRoot: string, accountId: string): string | null;
|
|
6
|
+
//# sourceMappingURL=account-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-token.d.ts","sourceRoot":"","sources":["../../src/lib/account-token.ts"],"names":[],"mappings":"AAGA;;;4EAG4E;AAC5E,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYtF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { resolve, join } from "node:path";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
/** Resolve the Telegram bot token from the per-account account.json telegram
|
|
4
|
+
* block. Brand-isolated: account.json lives under the install's data/accounts,
|
|
5
|
+
* never ~/.claude. Prefers adminBotToken (the admin agent's outbound bot),
|
|
6
|
+
* falling back to publicBotToken. Returns null when neither is present. */
|
|
7
|
+
export function resolveBotToken(platformRoot, accountId) {
|
|
8
|
+
const accountsDir = resolve(platformRoot, "..", "data", "accounts");
|
|
9
|
+
const configPath = join(accountsDir, accountId, "account.json");
|
|
10
|
+
if (!existsSync(configPath))
|
|
11
|
+
return null;
|
|
12
|
+
try {
|
|
13
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
14
|
+
return config.telegram?.adminBotToken ?? config.telegram?.publicBotToken ?? null;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=account-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-token.js","sourceRoot":"","sources":["../../src/lib/account-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD;;;4EAG4E;AAC5E,MAAM,UAAU,eAAe,CAAC,YAAoB,EAAE,SAAiB;IACrE,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IACpE,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IAChE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAE1D,CAAC;QACF,OAAO,MAAM,CAAC,QAAQ,EAAE,aAAa,IAAI,MAAM,CAAC,QAAQ,EAAE,cAAc,IAAI,IAAI,CAAC;IACnF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** The single canonical maxy Telegram webhook path. Duplicated (intentionally)
|
|
2
|
+
* with platform/ui/server/public-host-gate.ts PUBLIC_ALLOWED_PREFIXES — a unit
|
|
3
|
+
* test asserts they agree. The official plugin's /channels/telegram is NOT this. */
|
|
4
|
+
export declare const CANONICAL_TELEGRAM_PREFIX = "/api/telegram/";
|
|
5
|
+
export interface PersistInput {
|
|
6
|
+
botType: "admin" | "public";
|
|
7
|
+
botToken: string;
|
|
8
|
+
adminUsers?: number[];
|
|
9
|
+
dmPolicy?: "open" | "allowlist" | "disabled";
|
|
10
|
+
allowFrom?: number[];
|
|
11
|
+
}
|
|
12
|
+
/** Persist the bot token + access policy into account.json's telegram block.
|
|
13
|
+
* Brand-isolated: account.json lives under the install's data/accounts. Returns
|
|
14
|
+
* the resolved account.json directory so the caller can log + assert it is under
|
|
15
|
+
* the brand install (never ~/.claude). */
|
|
16
|
+
export declare function persistTelegramConfig(platformRoot: string, accountId: string, input: PersistInput): {
|
|
17
|
+
ok: boolean;
|
|
18
|
+
dir?: string;
|
|
19
|
+
error?: string;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=account-write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-write.d.ts","sourceRoot":"","sources":["../../src/lib/account-write.ts"],"names":[],"mappings":"AAGA;;qFAEqF;AACrF,eAAO,MAAM,yBAAyB,mBAAmB,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;IAC7C,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;2CAG2C;AAC3C,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,YAAY,GAClB;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAmC/C"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { resolve, join, relative, isAbsolute } from "node:path";
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
/** The single canonical maxy Telegram webhook path. Duplicated (intentionally)
|
|
4
|
+
* with platform/ui/server/public-host-gate.ts PUBLIC_ALLOWED_PREFIXES — a unit
|
|
5
|
+
* test asserts they agree. The official plugin's /channels/telegram is NOT this. */
|
|
6
|
+
export const CANONICAL_TELEGRAM_PREFIX = "/api/telegram/";
|
|
7
|
+
/** Persist the bot token + access policy into account.json's telegram block.
|
|
8
|
+
* Brand-isolated: account.json lives under the install's data/accounts. Returns
|
|
9
|
+
* the resolved account.json directory so the caller can log + assert it is under
|
|
10
|
+
* the brand install (never ~/.claude). */
|
|
11
|
+
export function persistTelegramConfig(platformRoot, accountId, input) {
|
|
12
|
+
const accountsDir = resolve(platformRoot, "..", "data", "accounts");
|
|
13
|
+
const dir = join(accountsDir, accountId);
|
|
14
|
+
const configPath = join(dir, "account.json");
|
|
15
|
+
// Assert the resolved dir is under the brand install BEFORE any write — a
|
|
16
|
+
// traversal in accountId (e.g. "../../.claude") must never let a token land
|
|
17
|
+
// outside ~/.<brand>/. `relative` is separator-aware; a non-brand path yields
|
|
18
|
+
// a result that escapes ("..") or is absolute.
|
|
19
|
+
const brandRoot = resolve(platformRoot, "..");
|
|
20
|
+
const rel = relative(brandRoot, resolve(dir));
|
|
21
|
+
const underBrand = rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
|
|
22
|
+
if (!underBrand) {
|
|
23
|
+
return { ok: false, error: "non-brand-path", dir };
|
|
24
|
+
}
|
|
25
|
+
if (!existsSync(configPath)) {
|
|
26
|
+
return { ok: false, error: `account.json not found at ${configPath}` };
|
|
27
|
+
}
|
|
28
|
+
let config;
|
|
29
|
+
try {
|
|
30
|
+
config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
return { ok: false, error: `account.json parse failed: ${e.message}` };
|
|
34
|
+
}
|
|
35
|
+
const telegram = config.telegram ?? {};
|
|
36
|
+
if (input.botType === "admin") {
|
|
37
|
+
telegram.adminBotToken = input.botToken;
|
|
38
|
+
if (input.adminUsers)
|
|
39
|
+
telegram.adminUsers = input.adminUsers;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
telegram.publicBotToken = input.botToken;
|
|
43
|
+
if (input.dmPolicy)
|
|
44
|
+
telegram.dmPolicy = input.dmPolicy;
|
|
45
|
+
if (input.allowFrom)
|
|
46
|
+
telegram.allowFrom = input.allowFrom;
|
|
47
|
+
}
|
|
48
|
+
config.telegram = telegram;
|
|
49
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
50
|
+
return { ok: true, dir };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=account-write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-write.js","sourceRoot":"","sources":["../../src/lib/account-write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAElE;;qFAEqF;AACrF,MAAM,CAAC,MAAM,yBAAyB,GAAG,gBAAgB,CAAC;AAU1D;;;2CAG2C;AAC3C,MAAM,UAAU,qBAAqB,CACnC,YAAoB,EACpB,SAAiB,EACjB,KAAmB;IAEnB,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IACpE,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC7C,0EAA0E;IAC1E,4EAA4E;IAC5E,8EAA8E;IAC9E,+CAA+C;IAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7E,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC;IACrD,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,6BAA6B,UAAU,EAAE,EAAE,CAAC;IACzE,CAAC;IACD,IAAI,MAA+B,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IACzD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,8BAA+B,CAAW,CAAC,OAAO,EAAE,EAAE,CAAC;IACpF,CAAC;IACD,MAAM,QAAQ,GAAI,MAAM,CAAC,QAAoC,IAAI,EAAE,CAAC;IACpE,IAAI,KAAK,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;QAC9B,QAAQ,CAAC,aAAa,GAAG,KAAK,CAAC,QAAQ,CAAC;QACxC,IAAI,KAAK,CAAC,UAAU;YAAE,QAAQ,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;IAC/D,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,cAAc,GAAG,KAAK,CAAC,QAAQ,CAAC;QACzC,IAAI,KAAK,CAAC,QAAQ;YAAE,QAAQ,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QACvD,IAAI,KAAK,CAAC,SAAS;YAAE,QAAQ,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;IAC5D,CAAC;IACD,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AAC3B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../src/tools/message.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../src/tools/message.ts"],"names":[],"mappings":"AAGA,UAAU,aAAa;IACrB,OAAO,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,CAAC;IAC/C,cAAc,CAAC,EAAE,KAAK,CACpB,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAC7D,CAAC;CACH;AAED,UAAU,aAAa;IACrB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAwC3E"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { sendMessage } from "../lib/telegram.js";
|
|
2
|
+
import { resolveBotToken } from "../lib/account-token.js";
|
|
2
3
|
export async function message(params) {
|
|
3
|
-
const
|
|
4
|
+
const platformRoot = process.env.PLATFORM_ROOT;
|
|
5
|
+
const accountId = process.env.ACCOUNT_ID;
|
|
6
|
+
const botToken = platformRoot && accountId ? resolveBotToken(platformRoot, accountId) : null;
|
|
4
7
|
if (!botToken) {
|
|
5
8
|
return {
|
|
6
9
|
sent: false,
|
|
7
10
|
channel: params.channel,
|
|
8
|
-
error: "
|
|
11
|
+
error: "No Telegram bot token in account.json telegram block — run telegram:configure first",
|
|
9
12
|
};
|
|
10
13
|
}
|
|
11
14
|
let replyMarkup;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/tools/message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA+B,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/tools/message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA+B,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAmB1D,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,MAAqB;IACjD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;IACzC,MAAM,QAAQ,GACZ,YAAY,IAAI,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9E,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;YACL,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,KAAK,EACH,qFAAqF;SACxF,CAAC;IACJ,CAAC;IAED,IAAI,WAA+C,CAAC;IACpD,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;QAC1B,WAAW,GAAG;YACZ,eAAe,EAAE,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACjD,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBAChB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,aAAa,EAAE,GAAG,CAAC,YAAY;gBAC/B,GAAG,EAAE,GAAG,CAAC,GAAG;aACb,CAAC,CAAC,CACJ;SACF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE;QACzC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,WAAW;KACZ,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,EAAE;QACf,OAAO,EAAE,UAAU;QACnB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC;AACJ,CAAC"}
|
|
@@ -10,13 +10,16 @@
|
|
|
10
10
|
|
|
11
11
|
## Connecting the Bot
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
Setup happens entirely in the admin chat — there is no settings page to click through.
|
|
14
|
+
|
|
15
|
+
1. Tell the admin agent: "I want to connect a Telegram bot." The agent runs the `telegram:configure` skill.
|
|
16
|
+
2. Paste the bot token from BotFather when the agent asks.
|
|
17
|
+
3. Tell the agent whether this is an **admin bot** or a **public bot** (see below).
|
|
18
|
+
4. For an admin bot, give the agent the numeric Telegram user IDs that should have admin access. For a public bot, choose a DM policy (who can message it) and, for a whitelist, the allowed numeric IDs.
|
|
19
|
+
5. The agent verifies the token, registers the webhook on the brand's edge path, stores the token under the brand install, and — for a public bot — sets the agent that will respond.
|
|
20
|
+
6. The agent confirms the bot is connected. Message the bot; the reply comes back from the agent.
|
|
21
|
+
|
|
22
|
+
The token is stored in your account config under the brand install (never in a shared `~/.claude` directory), and the webhook is registered on the `/api/telegram/` path the brand's edge admits.
|
|
20
23
|
|
|
21
24
|
## Admin Bot vs Public Bot
|
|
22
25
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: configure
|
|
3
|
+
description: Guide the user through connecting a Telegram bot entirely via the admin chat — store the BotFather token under the brand install, register the webhook on the maxy edge-admitted path, set access policy, and select the agent. Complete PTY setup, no UI clicks.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Configure Telegram
|
|
7
|
+
|
|
8
|
+
Invoked from `specialists:personal-assistant`. This is the maxy `telegram:configure` skill. On `-code` brands the upstream `claude-plugins-official/telegram` plugin is not installed, so this is the only `telegram:configure` — it is brand-aware and PTY-only.
|
|
9
|
+
|
|
10
|
+
## When to activate
|
|
11
|
+
|
|
12
|
+
User says anything about connecting, linking, or setting up Telegram, BotFather, or a Telegram bot.
|
|
13
|
+
|
|
14
|
+
## What a correct setup looks like
|
|
15
|
+
|
|
16
|
+
A finished Telegram setup has all of these, and the skill is not done until each is true:
|
|
17
|
+
|
|
18
|
+
- The bot token from BotFather is stored in `account.json`'s `telegram` block (under the brand install, never `~/.claude/`). The `telegram-webhook-register` tool writes it there and logs `[telegram-setup] op=token-write dir=… brand=…`.
|
|
19
|
+
- The webhook is registered against a URL whose path is `/api/telegram/` (the only path the maxy edge admits). The register tool refuses any other path and logs `op=webhook-register path=… admitted=false` when it does.
|
|
20
|
+
- Access policy is set: admin bots carry the operator's numeric Telegram user IDs (`adminUsers`); public bots carry a DM policy (and an allowlist when the policy is `allowlist`).
|
|
21
|
+
- For a public bot, `account.json` `defaultAgent` names an existing public agent. Without it, public inbound is dropped with `op=reject reason=no-default-agent`.
|
|
22
|
+
|
|
23
|
+
## Flow
|
|
24
|
+
|
|
25
|
+
### Step 1 — Get the bot token
|
|
26
|
+
|
|
27
|
+
Follow `references/setup-guide.md` "Creating a Bot": the operator creates the bot via @BotFather and gives you the token (e.g. `123456:ABC-DEF…`). Confirm you have it before continuing.
|
|
28
|
+
|
|
29
|
+
### Step 2 — Decide admin or public
|
|
30
|
+
|
|
31
|
+
Ask which role this bot serves (see `references/setup-guide.md` "Admin Bot vs Public Bot"):
|
|
32
|
+
|
|
33
|
+
- **Admin bot** — only the operator's numeric Telegram user IDs may message it; everything else is denied. Collect those IDs (`references/setup-guide.md` "Finding Your Telegram User ID").
|
|
34
|
+
- **Public bot** — customer-facing; choose a DM policy (`open`, `allowlist`, or `disabled`) and, for `allowlist`, the allowed numeric IDs.
|
|
35
|
+
|
|
36
|
+
### Step 3 — Build the webhook URL
|
|
37
|
+
|
|
38
|
+
The path MUST be `/api/telegram/` with `?bot=admin` or `?bot=public`. Use the account's domain for the host — the admin domain for an admin bot, the public domain for a public bot (read them from `brand-settings` / the account config). Example: `https://<admin-domain>/api/telegram/?bot=admin`.
|
|
39
|
+
|
|
40
|
+
The register tool aborts on any other path, so do not invent `/channels/telegram` or similar.
|
|
41
|
+
|
|
42
|
+
### Step 4 — Register (stores token + policy + webhook + secret in one call)
|
|
43
|
+
|
|
44
|
+
Call `telegram-webhook-register` with:
|
|
45
|
+
- `botToken` — the BotFather token
|
|
46
|
+
- `webhookUrl` — the URL from Step 3
|
|
47
|
+
- `botType` — `admin` or `public`
|
|
48
|
+
- admin bot: `adminUsers` — the numeric IDs from Step 2
|
|
49
|
+
- public bot: `dmPolicy` and, for `allowlist`, `allowFrom`
|
|
50
|
+
|
|
51
|
+
On success the tool has: verified the token, set the webhook with a generated secret (written to the brand configDir), persisted the token + policy into `account.json`'s `telegram` block, and logged `op=token-write` + `op=webhook-register admitted=true`. If it returns an error, read it back to the operator verbatim — the common ones are a wrong path (`admitted=false`) or a token write blocked outside the brand install (`op=token-write-rejected`).
|
|
52
|
+
|
|
53
|
+
### Step 5 — Select the agent (public bot)
|
|
54
|
+
|
|
55
|
+
Public inbound routes to the account's `defaultAgent`. Set it and confirm:
|
|
56
|
+
|
|
57
|
+
1. `account-manage` to list available public agents.
|
|
58
|
+
2. `account-update` with `field: "defaultAgent"`, `value: "<slug>"`.
|
|
59
|
+
3. Re-read by calling `account-manage` (or `account-update` reports the change) and confirm `defaultAgent` is the chosen slug. The post-condition is a non-empty `defaultAgent`, not the intent to set it.
|
|
60
|
+
|
|
61
|
+
An admin bot does not need `defaultAgent` — admin inbound routes to the admin agent.
|
|
62
|
+
|
|
63
|
+
### Step 6 — Confirm
|
|
64
|
+
|
|
65
|
+
Tell the operator the bot is connected, which role it has, and that messaging the bot now reaches the agent and a reply returns. For a public bot, name the agent that will respond.
|
|
66
|
+
|
|
67
|
+
## Failure modes (state these loudly, do not paper over)
|
|
68
|
+
|
|
69
|
+
- **Wrong webhook path** — register returns an error and logs `op=webhook-register admitted=false`. Fix the URL to use `/api/telegram/`.
|
|
70
|
+
- **Token write outside the brand** — `op=token-write-rejected reason=non-brand-path`. The MCP env is misconfigured; do not retry blindly — report it.
|
|
71
|
+
- **`defaultAgent` unset on a public bot** — inbound is dropped with `[telegram-inbound] op=reject reason=no-default-agent`. Complete Step 5.
|
|
72
|
+
- **Bad secret on inbound** — `[telegram-inbound] op=reject reason=bad-secret` means the registered secret and the stored secret diverged; re-run register.
|
|
73
|
+
|
|
74
|
+
## Language
|
|
75
|
+
|
|
76
|
+
Use plain English:
|
|
77
|
+
- "bot token" not "Bot API credential"
|
|
78
|
+
- "your numeric Telegram ID" not "user_id integer"
|
|
79
|
+
- "the bot is connected" not "webhook registered with secret_token"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAS3B,OAAO,EAgBL,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAA;AAoBzB,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,iBAAiB,CAAA;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAgFtD,eAAO,MAAM,kBAAkB,QAA2B,CAAA;AAS1D,eAAO,MAAM,4BAA4B,QAAS,CAAA;AAIlD,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC7E;;qEAEiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,WAAW,CAAA;IAC/B,eAAe,EAAE,aAAa,CAAA;IAC9B;kFAC8E;IAC9E,cAAc,EAAE,cAAc,CAAA;IAC9B;;gFAE4E;IAC5E,cAAc,EAAE,cAAc,CAAA;IAC9B;;gFAE4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AA+MD;;;kEAGkE;AAClE,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG;IAC3B,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD;;;+CAG2C;IAC3C,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAChD,CAAA;AAmBD,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAS3B,OAAO,EAgBL,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAA;AAoBzB,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,iBAAiB,CAAA;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAgFtD,eAAO,MAAM,kBAAkB,QAA2B,CAAA;AAS1D,eAAO,MAAM,4BAA4B,QAAS,CAAA;AAIlD,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC7E;;qEAEiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,WAAW,CAAA;IAC/B,eAAe,EAAE,aAAa,CAAA;IAC9B;kFAC8E;IAC9E,cAAc,EAAE,cAAc,CAAA;IAC9B;;gFAE4E;IAC5E,cAAc,EAAE,cAAc,CAAA;IAC9B;;gFAE4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AA+MD;;;kEAGkE;AAClE,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG;IAC3B,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD;;;+CAG2C;IAC3C,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAChD,CAAA;AAmBD,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAo4DpD"}
|
|
@@ -1551,6 +1551,23 @@ export function buildHttpApp(deps) {
|
|
|
1551
1551
|
if (mainPid !== null && defaultProcessSignals.isAlive(mainPid))
|
|
1552
1552
|
seen.set(row.sessionId, mainPid);
|
|
1553
1553
|
}
|
|
1554
|
+
// Task 731 — a live, non-detached row whose owned PTY tracker has been
|
|
1555
|
+
// released (or was registered under a placeholder sessionId, never the
|
|
1556
|
+
// real one) is counted by the master-reconcile `liveSessions` census yet
|
|
1557
|
+
// missed by both arms above: it is not an owned PTY and not a detached
|
|
1558
|
+
// survivor. Adopt it on PID-file process truth — `row.pid` is claude's own
|
|
1559
|
+
// live pid for a `state==='live'` row — gated on `isAlive` so a stale PID
|
|
1560
|
+
// file (dead process) never reports a false-green dot. Detached rows are
|
|
1561
|
+
// excluded here on purpose: their liveness is the scope MainPID (resolved
|
|
1562
|
+
// above) and their `row.pid` may be a stale manager-side pid.
|
|
1563
|
+
for (const row of deps.watcher.all()) {
|
|
1564
|
+
if (row.state !== 'live' || row.status === 'detached' || seen.has(row.sessionId) || row.pid === null)
|
|
1565
|
+
continue;
|
|
1566
|
+
if (defaultProcessSignals.isAlive(row.pid)) {
|
|
1567
|
+
seen.set(row.sessionId, row.pid);
|
|
1568
|
+
deps.logger(`[live-sessions] op=adopt-orphan-live sessionId=${row.sessionId.slice(0, 8)} pid=${row.pid} via=reconcile`);
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1554
1571
|
const sessions = [...seen.entries()].map(([sessionId, pid]) => ({ sessionId, pid }));
|
|
1555
1572
|
return c.json({ sessions });
|
|
1556
1573
|
});
|