mira-harness 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Masashi Ono
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,201 @@
1
+ # mira-harness
2
+
3
+ **Automated probe harness for the [@mira](https://t.me/mira) Telegram bot.**
4
+
5
+ Drive @mira from a Telegram *userbot* (GramJS), capture the **full** reply — buttons,
6
+ deep-link / `startapp` targets, source links, media, edits, latency — and run a
7
+ self-driving experiment catalog. No screenshots, no copy-paste.
8
+
9
+ > Built to let an AI agent (Claude) experiment on another AI (@mira) hands-free, and
10
+ > to keep a structured, reproducible record of how @mira actually behaves.
11
+
12
+ ## Why a userbot (not a bot)
13
+
14
+ @mira has **no public API**, and Telegram has a hard rule: **a bot cannot read
15
+ another bot's messages**. So a bot token can't talk to @mira. The only working path
16
+ is a **userbot** — driving a real Telegram *user account* via MTProto (GramJS).
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ git clone https://github.com/Masashi-Ono0611/mira-harness.git
22
+ cd mira-harness
23
+ npm install
24
+ ```
25
+
26
+ ## Configuration
27
+
28
+ Copy `.env.example` to `.env` and fill in your Telegram `api_id` / `api_hash` (it's gitignored):
29
+
30
+ ```bash
31
+ cp .env.example .env
32
+ ```
33
+
34
+ Mint the session once (interactive — enter the code Telegram sends you):
35
+
36
+ ```bash
37
+ npm run login # prints TG_SESSION=... -> paste it into .env
38
+ ```
39
+
40
+ (Optional) Mira Pro credits: DM `/promo MIRAFAM26` to @mira.
41
+
42
+ ## Usage
43
+
44
+ Via `npm run dev -- <args>`, or build once (`npm run build`) and use the `mira-harness` bin / `npx`.
45
+
46
+ ```bash
47
+ # one probe — prints the full settled reply as JSON
48
+ npm run dev -- send "STON_USDT_10"
49
+
50
+ # self-driving catalog (paced 15s, STOP_MIRA kill switch, observe-only)
51
+ npm run dev -- loop --category core
52
+ npm run dev -- loop --category skills --max 4
53
+
54
+ # also press a safe ✅ Confirm on generation probes (spends Pro credits)
55
+ npm run dev -- loop --category generation --confirm
56
+
57
+ # run in a group instead of the DM (needs TG_EXPERIMENT_CHAT)
58
+ npm run dev -- loop --peer experiment
59
+
60
+ # distill the run log into Markdown
61
+ npm run dev -- report
62
+ npm run dev -- report --out report.md
63
+
64
+ # preflight checks (env / session / connectivity) and list the catalog
65
+ npm run dev -- doctor
66
+ npm run dev -- catalog
67
+ npm run dev -- loop --list
68
+
69
+ # message via stdin; tune timing; quiet (no spinner); skip the run log
70
+ echo "STON_USDT_10" | npm run dev -- send
71
+ npm run dev -- send "ping" --settle 3000 --timeout 30000 --quiet --no-log
72
+
73
+ # live-tail @mira while you poke at it by hand; custom catalog; filtered report
74
+ npm run dev -- watch
75
+ npm run dev -- loop --catalog ./examples/catalog.sample.json
76
+ npm run dev -- report --category core
77
+ ```
78
+
79
+ After `npm run build` (or once published):
80
+
81
+ ```bash
82
+ npx mira-harness doctor
83
+ npx mira-harness send "STON_USDT_10"
84
+ npx mira-harness loop --category core
85
+ ```
86
+
87
+ ## Capture fidelity (the point)
88
+
89
+ @mira's interesting behavior lives **outside the plain text**. `send`/`loop` wait a
90
+ **settle window** (quiet period after the last activity, bounded by a hard cap, with
91
+ a "typing…" fallback for a slow bot — replies run 5–62s) and capture, per message:
92
+
93
+ - **multi-message** replies and **streamed edits** (final text + an `editCount`),
94
+ - **buttons** — inline `url` and **`web_app` / startapp** targets (Mini App "Launch" cards),
95
+ - **links** — `text_url` entities (deep-research source links),
96
+ - **media** — photo / video / audio / document / webpage (metadata; not downloaded).
97
+
98
+ `report` turns the JSONL run log into a per-probe Markdown table (gist / signals / latency).
99
+
100
+ ## Commands
101
+
102
+ | Command | What |
103
+ |---|---|
104
+ | `login` | One-time interactive login → prints `TG_SESSION` |
105
+ | `doctor` | Check `.env` / session / connectivity / @mira resolution (read-only) |
106
+ | `send [message...]` | One probe → full reply as JSON (message via arg or stdin). `--quiet --settle --timeout --no-log` |
107
+ | `loop` | Run the catalog paced. `--category --max --confirm --peer --gap --settle --timeout --list --catalog --quiet` |
108
+ | `catalog` | List the catalog (no sends). `--category --catalog --json` |
109
+ | `watch` | Live-tail @mira's messages (observe-only). `--peer` |
110
+ | `report` | Distill the run log into Markdown. `--in --out --category` |
111
+
112
+ Run `mira-harness --help` (or `<command> --help`) for full options.
113
+
114
+ ### Custom catalog
115
+
116
+ The built-in catalog (30 probes: `core` / `skills` / `generation` / `wallet`) is just a
117
+ default. Point `--catalog <file.json>` (CLI) or `catalogFile` (MCP) at your own probe set
118
+ to probe any bot — each entry needs `id` + `send` (`category` / `hypothesis` / `slow` /
119
+ `confirm` / `note` optional). See [`examples/catalog.sample.json`](examples/catalog.sample.json):
120
+
121
+ ```bash
122
+ mira-harness loop --catalog ./examples/catalog.sample.json
123
+ mira-harness catalog --catalog ./examples/catalog.sample.json --json
124
+ ```
125
+
126
+ ## Use as a library
127
+
128
+ The CLI is a thin frontend over an exported core:
129
+
130
+ ```ts
131
+ import { connect, sendAndCollect } from "mira-harness";
132
+
133
+ const client = await connect(process.env.TG_SESSION!);
134
+ const result = await sendAndCollect(client, "mira", "STON_USDT_10");
135
+ console.log(result.messages[0]?.buttons); // captured buttons (incl. web_app/startapp)
136
+ await client.disconnect();
137
+ ```
138
+
139
+ Exposed: `connect` · `sendAndCollect` · `clickAndCollect` · `extractMessage` · `CATALOG` /
140
+ `probesFor` · `appendRun` · `renderReport` · `tgEnv` (and their types).
141
+
142
+ ## MCP server
143
+
144
+ A third frontend over the same core: an MCP **stdio** server (`mira-harness-mcp`) so a
145
+ Claude/agent can probe @mira directly via tools.
146
+
147
+ | Tool | Args | What |
148
+ |---|---|---|
149
+ | `mira_send` | `message`, `settleMs?`, `timeoutMs?` | one probe → full reply (JSON) |
150
+ | `mira_loop` | `category?`, `max?`, `peer?`, `gapMs?`, `settleMs?`, `timeoutMs?`, `catalogFile?` | run the catalog, **observe-only** (never clicks / spends credits) |
151
+ | `mira_catalog` | `category?`, `catalogFile?` | list the catalog (no network) |
152
+ | `mira_report` | `inFile?`, `category?` | run log → Markdown |
153
+ | `mira_doctor` | — | env / session / connectivity check |
154
+
155
+ Register it (local build — run `npm run build` first):
156
+
157
+ ```json
158
+ {
159
+ "mcpServers": {
160
+ "mira-harness": {
161
+ "command": "node",
162
+ "args": ["/abs/path/to/mira-harness/dist/mcp.js"],
163
+ "env": {
164
+ "TG_API_ID": "...",
165
+ "TG_API_HASH": "...",
166
+ "TG_SESSION": "...",
167
+ "MIRA_PEER": "mira"
168
+ }
169
+ }
170
+ }
171
+ }
172
+ ```
173
+
174
+ Credentials come from the `env` block above or a `.env` in the server's working
175
+ directory. Once published (the bin ships in the `mira-harness` package):
176
+ `{ "command": "npx", "args": ["-y", "--package", "mira-harness", "mira-harness-mcp"] }`.
177
+
178
+ ## Safety
179
+
180
+ - **Allowlist** — sends only to `MIRA_PEER` (+ optional `TG_EXPERIMENT_CHAT`); anything else throws.
181
+ - **Kill switch** — `touch STOP_MIRA` blocks all sends (re-checked before a credit-gated confirm too).
182
+ - **Observe-only by default** — never clicks. `--confirm` presses only a one-shot **✅ Confirm**
183
+ on `confirm: true` (generation) probes; wallet / OAuth / transfer / "Always yes" are never pressed.
184
+ - **Rate** — human-like gap between probes (own-account ban risk).
185
+ - **Secrets** — `TG_SESSION` = full account access. `.env` only, never commit.
186
+
187
+ > Automating a personal account is a Telegram ToS gray area; a ban hits your real
188
+ > account. Low frequency + allowlist + kill switch mitigate it. To fully isolate, log
189
+ > in with a dedicated test account — no code changes needed.
190
+
191
+ ## Develop
192
+
193
+ ```bash
194
+ npm run typecheck # tsc --noEmit
195
+ npm test # unit tests for the pure extractors (no network)
196
+ npm run build # tsup -> dist/cli.js
197
+ ```
198
+
199
+ ## License
200
+
201
+ MIT