@mrrlin-dev/mcp 0.2.3 → 0.2.5

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.
@@ -0,0 +1,189 @@
1
+ ---
2
+ name: report-issue
3
+ description: Use when a Mrrlin user hits a problem and wants it reported to support. Reads the local Director bridge log, asks the user a few clarifying questions in their own language, packages an English report, and sends it to the shared support Telegram channel via a single POST.
4
+ ---
5
+
6
+ # Report a Mrrlin issue to support
7
+
8
+ You are helping a Mrrlin **user/customer** report a problem. Do all the plumbing
9
+ yourself and keep it invisible to them: read their local logs, ask only what you
10
+ genuinely cannot infer, then send one packaged report to the support Telegram
11
+ channel. The user should never see or touch the token, the log path, or the POST.
12
+
13
+ ## How this gets invoked
14
+
15
+ This prompt ships inside `@mrrlin-dev/mcp`. `mrrlin-mcp report-issue` prints this
16
+ file to stdout, so the same text drives all three surfaces:
17
+
18
+ - **Terminal (feed it to Codex):** `codex "$(mrrlin-mcp report-issue)"`
19
+ - **Codex slash command:** `mrrlin-mcp report-issue > ~/.codex/prompts/report-issue.md` once, then run `/report-issue`.
20
+ - **Skill:** it has skill frontmatter (`name` + `description`), so a skill-aware agent can activate it directly.
21
+
22
+ ## Service bot it talks to
23
+
24
+ The token below is **intentionally public** — `@mrrlinIssuesBot` is a throwaway
25
+ service bot dedicated to the Mrrlin support group. Anyone reading this file may
26
+ see it; that is by design. The bot can only post to the one chat hardcoded
27
+ below, so leaking the token costs at most some spam in that chat — rotate via
28
+ @BotFather if it ever happens.
29
+
30
+ - Bot: `@mrrlinIssuesBot` (id `8506614214`)
31
+ - Group: "Mrrlin", chat id `-5373779177`
32
+
33
+ ---
34
+
35
+ ## What to do
36
+
37
+ ### 1. Take the user's hint as the search key
38
+
39
+ When the operator invokes `/report-issue`, they typically include a hint along
40
+ with the command — a pasted error blurb, a quote of weird output, a one-line
41
+ description, or a `sessionId`/`spanId` they copied. **That hint is your primary
42
+ search key.** Do not blindly read the tail of the latest log.
43
+
44
+ Extract candidate signals from the hint:
45
+
46
+ - **Quoted substrings** — verbatim text from the failure (highest priority).
47
+ - **Error words** — "error", "failed", "timeout", "401", "500", "ENOENT", stack-trace fragments.
48
+ - **Identifiers** — `sessionId` (uuid-shaped) or `spanId` if pasted.
49
+ - **Time hints** — "just now", "5 minutes ago", "today around 14:00".
50
+
51
+ If the operator gave no hint at all, fall back to the tail (see below) — but
52
+ say so plainly when you confirm, so they know the report may have grabbed the
53
+ wrong incident.
54
+
55
+ ### 2. Find the relevant log window
56
+
57
+ Logs live at the first existing dir:
58
+
59
+ 1. `$CODEX_HOME/mrrlin/director-bridge/logs/` (only if `CODEX_HOME` is set)
60
+ 2. `~/.mrrlin/director-bridge/logs/`
61
+
62
+ Files are `bridge-YYYY-MM-DD.jsonl` (UTC dates). Sort newest-first. Each line:
63
+
64
+ ```json
65
+ {"ts":"...","dir":"in|out","spanId":"...","sessionId":"...","type":"turn|event|error|...","ms":123,"payload":{...}}
66
+ ```
67
+
68
+ Secrets are already redacted by the logger (tokens show as `[REDACTED]`), so the
69
+ log lines are safe to forward as-is.
70
+
71
+ **With a hint** — grep across the **3 most recent files** (today + last 2 days)
72
+ in this signal order, stopping at the first that matches:
73
+
74
+ 1. The literal quoted substring from the hint (case-insensitive).
75
+ 2. The `sessionId` or `spanId` from the hint.
76
+ 3. Error-word lines clustered near any time hint the user gave.
77
+
78
+ Pick the **most recent** matching cluster. The "relevant window" = the matching
79
+ line + ~10 lines before and ~30 lines after. If the matching line has a
80
+ `sessionId`, bound the window to that session.
81
+
82
+ **Without a hint** — read the last ~200 lines of the newest file. The window is
83
+ the last contiguous cluster of `type:"error"` lines (or, if none, the last few
84
+ `type:"turn"` lines).
85
+
86
+ From the relevant window extract:
87
+
88
+ - Every `type:"error"` line and any `dir:"out"` payload that looks like a failure (non-2xx HTTP, stack traces, "failed", "timeout").
89
+ - The last few `type:"turn"` lines before the failure (what the user was doing).
90
+ - The `sessionId` and `spanId`s tied to the failure.
91
+ - `ts` of the first and last lines in the window.
92
+
93
+ If the log dir doesn't exist, or the hint matches nothing in the last 3 days,
94
+ say so plainly and lean on the user's answers in step 3 — still send the report.
95
+
96
+ ### 3. Ask the user — in THEIR language — only what the log doesn't already tell you
97
+
98
+ Detect the language the user is writing in and ask in that language. Keep it
99
+ short, ask **once**, and **skip any question the hint + log already answered**:
100
+
101
+ - **What were you doing** when it broke? — skip if the hint or the preceding `type:"turn"` lines make this obvious.
102
+ - **What actually happened (the symptom)?** — skip if the hint is itself a verbatim error/output.
103
+ - **What did you expect to happen instead?** — ask only if the expected result is not obvious from the log or hint.
104
+
105
+ If the user gives short or partial answers, accept them and move on. Never block
106
+ the report on a perfect answer.
107
+
108
+ ### 4. Package the report (in ENGLISH)
109
+
110
+ Translate the user's answers to English. Build a plain-text report. Keep the whole
111
+ thing under **4096 characters** (Telegram's per-message limit) — trim the log
112
+ excerpt first if needed, keeping the error lines over the context lines.
113
+
114
+ ```
115
+ 🛠️ Mrrlin issue report
116
+ When (UTC): <iso timestamp of the report>
117
+ Mrrlin MCP: v<version if known> | OS: <platform> | Node: <version>
118
+
119
+ ▶ User hint (verbatim):
120
+ <the text the operator passed with /report-issue, untranslated; "(none)" if absent>
121
+
122
+ ▶ What the user was doing:
123
+ <their answer, in English>
124
+
125
+ ▶ Expected result:
126
+ <their answer, or "(obvious from context: ...)", or "(not provided)">
127
+
128
+ ▶ Actual result / symptom:
129
+ <their answer, in English>
130
+
131
+ ▶ Errors from bridge log (<filename>, matched by: <hint substring | sessionId | tail-fallback>):
132
+ <the extracted error lines, verbatim — already redacted>
133
+
134
+ ▶ Context:
135
+ session=<sessionId> spanIds=<...> window=<first ts>..<last ts>
136
+ ```
137
+
138
+ ### 5. Send it — a single POST to Telegram
139
+
140
+ This is **just one HTTP POST** to the Telegram Bot API `sendMessage` method.
141
+ Endpoint and shape:
142
+
143
+ ```
144
+ POST https://api.telegram.org/bot8506614214:AAGyhO1phWb7ah2aN6_gAX2Co7OXNN3zb0A/sendMessage
145
+ Content-Type: application/json
146
+ body: { "chat_id": "-5373779177", "text": "<the report>", "disable_web_page_preview": true }
147
+ ```
148
+
149
+ Do **not** set `parse_mode` — send the report as plain text so nothing needs
150
+ escaping. Because the report has newlines and quotes, build the JSON safely
151
+ (serialize it; don't hand-concatenate a string), write it to a temp file, and POST
152
+ the file so the shell can't mangle it:
153
+
154
+ ```bash
155
+ # Write the JSON payload with a proper serializer, then:
156
+ curl -sS -X POST \
157
+ "https://api.telegram.org/bot8506614214:AAGyhO1phWb7ah2aN6_gAX2Co7OXNN3zb0A/sendMessage" \
158
+ -H "Content-Type: application/json" \
159
+ --data-binary @/tmp/mrrlin-report.json
160
+ ```
161
+
162
+ Check the response: Telegram returns `{"ok":true,...}` on success. If it returns
163
+ `{"ok":false,"description":"..."}` or curl fails, show the user the error and offer
164
+ to retry once.
165
+
166
+ **Optional — full log as an attachment.** If the trimmed excerpt lost important
167
+ lines, also send the full log file as a document (separate call):
168
+
169
+ ```bash
170
+ curl -sS -X POST \
171
+ "https://api.telegram.org/bot8506614214:AAGyhO1phWb7ah2aN6_gAX2Co7OXNN3zb0A/sendDocument" \
172
+ -F "chat_id=-5373779177" \
173
+ -F "document=@<path-to-bridge-YYYY-MM-DD.jsonl>"
174
+ ```
175
+
176
+ ### 6. Confirm
177
+
178
+ Tell the user, in their language, that the report was sent (or that it failed and
179
+ why). Don't dump the raw report or the token back at them — just confirm.
180
+
181
+ ## Rules
182
+
183
+ - The operator's hint drives log search. Tail-only mode is the **fallback**, not the default.
184
+ - Always include the verbatim hint in the report (under "User hint"), so the channel reader can see what was originally pasted before any translation.
185
+ - Ask the user in their language; write the report in English. Skip any question the hint + log already answered.
186
+ - Hide the mechanics: never surface the token, the log path, or the curl command to the user.
187
+ - Forward log lines as-is — they're already secret-redacted. Do not paste anything that looks like a live token even if you see one.
188
+ - One report = one `sendMessage` POST. Keep it under 4096 chars; use `sendDocument` only for the optional full log.
189
+ - If anything is missing (no log match, vague answers), still send the best report you can rather than giving up — and say in the report which signal you actually matched on.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrrlin-dev/mcp",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mrrlin-mcp": "dist/bin.cjs"
@@ -10,7 +10,8 @@
10
10
  },
11
11
  "files": [
12
12
  "dist/bin.cjs",
13
- "dist/consensus/personas"
13
+ "dist/consensus/personas",
14
+ "dist/prompts"
14
15
  ],
15
16
  "devDependencies": {
16
17
  "@types/node": "^20.17.50",
@@ -20,10 +21,10 @@
20
21
  "esbuild": "^0.24.0",
21
22
  "tsx": "^4.22.3",
22
23
  "@mrrlin/client": "0.0.0",
23
- "@mrrlin/codex-client": "0.0.0",
24
24
  "@mrrlin/director-e2e": "0.0.0",
25
- "@mrrlin/tsconfig": "0.0.0",
25
+ "@mrrlin/codex-client": "0.0.0",
26
26
  "@mrrlin/schemas": "0.0.0",
27
+ "@mrrlin/tsconfig": "0.0.0",
27
28
  "@mrrlin/wiki": "0.0.0"
28
29
  },
29
30
  "dependencies": {
@@ -36,7 +37,7 @@
36
37
  },
37
38
  "scripts": {
38
39
  "build": "tsc -p tsconfig.json && pnpm run bundle && chmod +x dist/bin.cjs",
39
- "bundle": "esbuild src/bin.ts --bundle --platform=node --format=cjs --target=node20 --outfile=dist/bin.cjs --banner:js='#!/usr/bin/env node' && mkdir -p dist/consensus/personas && cp src/consensus/personas/*.md dist/consensus/personas/",
40
+ "bundle": "esbuild src/bin.ts --bundle --platform=node --format=cjs --target=node20 --outfile=dist/bin.cjs --banner:js='#!/usr/bin/env node' && mkdir -p dist/consensus/personas && cp src/consensus/personas/*.md dist/consensus/personas/ && mkdir -p dist/prompts && cp src/prompts/*.md dist/prompts/",
40
41
  "dev": "tsx watch src/bin.ts serve",
41
42
  "lint": "eslint .",
42
43
  "start": "node dist/bin.cjs serve",