mira-harness 0.1.5 → 0.2.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/README.md +29 -21
- package/dist/capture.d.ts +65 -0
- package/dist/catalog.d.ts +27 -0
- package/dist/cli.js +893 -300
- package/dist/client.d.ts +52 -0
- package/dist/commands/report.d.ts +25 -0
- package/dist/env.d.ts +18 -0
- package/dist/index.d.ts +13 -165
- package/dist/index.js +628 -35
- package/dist/log.d.ts +9 -0
- package/dist/mcp.js +796 -191
- package/examples/catalog.sample.json +3 -4
- package/llms.txt +4 -4
- package/package.json +16 -8
- package/dist/chunk-PPYKMDQ4.js +0 -17
- package/dist/chunk-RDAT3FXN.js +0 -640
package/README.md
CHANGED
|
@@ -27,13 +27,14 @@ is a **userbot** — driving a real Telegram *user account* via MTProto (GramJS)
|
|
|
27
27
|
## Install
|
|
28
28
|
|
|
29
29
|
Published on [npm](https://www.npmjs.com/package/mira-harness) — run the CLI / MCP via
|
|
30
|
-
`npx mira-harness <command>` (or `npm i -g mira-harness`)
|
|
31
|
-
`
|
|
30
|
+
`npx mira-harness <command>` (or `npm i -g mira-harness`) — runs under Node, no bun
|
|
31
|
+
needed. To develop (or use `bun run login`), clone instead; development uses
|
|
32
|
+
[bun](https://bun.sh):
|
|
32
33
|
|
|
33
34
|
```bash
|
|
34
35
|
git clone https://github.com/Masashi-Ono0611/mira-harness.git
|
|
35
36
|
cd mira-harness
|
|
36
|
-
|
|
37
|
+
bun install
|
|
37
38
|
```
|
|
38
39
|
|
|
39
40
|
## Configuration
|
|
@@ -48,35 +49,35 @@ cp .env.example .env
|
|
|
48
49
|
Mint the session once (interactive — enter the code Telegram sends you):
|
|
49
50
|
|
|
50
51
|
```bash
|
|
51
|
-
|
|
52
|
+
bun run login # prints TG_SESSION=... -> paste it into .env
|
|
52
53
|
```
|
|
53
54
|
|
|
54
55
|
(Optional) Mira Pro credits: DM `/promo MIRAFAM26` to @mira.
|
|
55
56
|
|
|
56
57
|
## Usage
|
|
57
58
|
|
|
58
|
-
Via `
|
|
59
|
+
Via `bun run dev -- <args>`, or build once (`bun run build`) and use the `mira-harness` bin / `npx`.
|
|
59
60
|
|
|
60
61
|
```bash
|
|
61
62
|
# one probe — full settled reply as JSON (message via arg or stdin)
|
|
62
|
-
|
|
63
|
-
echo "
|
|
63
|
+
bun run dev -- send "What can you do?"
|
|
64
|
+
echo "What can you do?" | bun run dev -- send
|
|
64
65
|
|
|
65
66
|
# self-driving catalog — paced, STOP_MIRA kill switch, observe-only
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
bun run dev -- loop --category core
|
|
68
|
+
bun run dev -- loop --category generation --confirm # also taps a safe ✅ (spends Pro credits)
|
|
68
69
|
|
|
69
70
|
# read the results back
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
bun run dev -- report --out report.md # JSONL run log → Markdown
|
|
72
|
+
bun run dev -- stats # totals · latency records · 🏆 fastest · sparkline
|
|
72
73
|
|
|
73
74
|
# no-send commands: preflight, dry-run, live-tail
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
bun run dev -- doctor
|
|
76
|
+
bun run dev -- loop --list
|
|
77
|
+
bun run dev -- watch # watch @mira while you poke it by hand
|
|
77
78
|
```
|
|
78
79
|
|
|
79
|
-
Once built (`
|
|
80
|
+
Once built (`bun run build`) or installed (`npm i -g mira-harness`), the same commands run as
|
|
80
81
|
`mira-harness <command>` — or straight from npm with no clone: `npx mira-harness doctor`.
|
|
81
82
|
Every command and flag is in [Commands](#commands); custom catalogs in [Custom catalog](#custom-catalog).
|
|
82
83
|
|
|
@@ -126,7 +127,7 @@ per-feature flags — `MIRA_NO_BANNER=1` (mascot + tip), `MIRA_NO_NOTIFY=1` (com
|
|
|
126
127
|
|
|
127
128
|
### Custom catalog
|
|
128
129
|
|
|
129
|
-
The built-in catalog (
|
|
130
|
+
The built-in catalog (27 probes: `core` / `skills` / `generation` / `wallet`) is just a
|
|
130
131
|
default. Point `--catalog <file.json>` (CLI) or `catalogFile` (MCP) at your own probe set
|
|
131
132
|
to probe any bot — each entry needs `id` + `send` (`category` / `hypothesis` / `slow` /
|
|
132
133
|
`confirm` / `note` optional). See [`examples/catalog.sample.json`](examples/catalog.sample.json):
|
|
@@ -144,7 +145,7 @@ The CLI is a thin frontend over an exported core:
|
|
|
144
145
|
import { connect, sendAndCollect } from "mira-harness";
|
|
145
146
|
|
|
146
147
|
const client = await connect(process.env.TG_SESSION!);
|
|
147
|
-
const result = await sendAndCollect(client, "mira", "
|
|
148
|
+
const result = await sendAndCollect(client, "mira", "What can you do?");
|
|
148
149
|
console.log(result.messages[0]?.buttons); // captured buttons (incl. web_app/startapp)
|
|
149
150
|
await client.disconnect();
|
|
150
151
|
```
|
|
@@ -165,7 +166,7 @@ Claude/agent can probe @mira directly via tools.
|
|
|
165
166
|
| `mira_report` | `inFile?`, `category?` | run log → Markdown |
|
|
166
167
|
| `mira_doctor` | — | env / session / connectivity check |
|
|
167
168
|
|
|
168
|
-
Register it (local build — run `
|
|
169
|
+
Register it (local build — run `bun run build` first):
|
|
169
170
|
|
|
170
171
|
```json
|
|
171
172
|
{
|
|
@@ -210,10 +211,17 @@ directory. The bin ships in the published `mira-harness` package, so:
|
|
|
210
211
|
|
|
211
212
|
## Develop
|
|
212
213
|
|
|
214
|
+
Development uses [bun](https://bun.sh) (≥ 1.3); the published package stays Node-compatible.
|
|
215
|
+
|
|
213
216
|
```bash
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
+
bun install
|
|
218
|
+
bun run dev -- doctor # run the CLI straight from source
|
|
219
|
+
bun run lint # biome check (lint + format) · `bun run format` to auto-fix
|
|
220
|
+
bun run typecheck # tsc --noEmit
|
|
221
|
+
bun test # bun:test unit tests (no network)
|
|
222
|
+
bun run build # bun build -> dist (+ tsc declarations)
|
|
223
|
+
bun run check:publish # publint + attw — validate the package & type resolution
|
|
224
|
+
bun run slop # advisory AI-slop scan (never fails)
|
|
217
225
|
```
|
|
218
226
|
|
|
219
227
|
## License
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure extraction: GramJS `Api.Message` -> a flat, JSON-serializable record of
|
|
3
|
+
* everything @mira put in a reply. NO network here, so this is unit-testable.
|
|
4
|
+
*
|
|
5
|
+
* Why this matters: the *interesting* Mira behaviors live OUTSIDE the plain text
|
|
6
|
+
* — Mini App "Launch" cards (web_app / startapp deep links), deep-research source
|
|
7
|
+
* links (text_url entities), generated media. The old harness grabbed only the
|
|
8
|
+
* first message's `.message` string and dropped all of that. These extractors
|
|
9
|
+
* pull it back so a probe captures Mira's full surface.
|
|
10
|
+
*/
|
|
11
|
+
import type { Api } from "telegram";
|
|
12
|
+
/** An inline-keyboard button, flattened to the bits we care about. */
|
|
13
|
+
export interface CapturedButton {
|
|
14
|
+
text: string;
|
|
15
|
+
/** KeyboardButtonUrl / KeyboardButtonUrlAuth */
|
|
16
|
+
url?: string;
|
|
17
|
+
/** KeyboardButtonWebView / KeyboardButtonSimpleWebView — the Mini App "Launch" target. */
|
|
18
|
+
webAppUrl?: string;
|
|
19
|
+
/** KeyboardButtonCallback payload, base64 (rarely human-readable). */
|
|
20
|
+
callbackData?: string;
|
|
21
|
+
}
|
|
22
|
+
/** A hyperlink found in the message text (entities). */
|
|
23
|
+
export interface CapturedLink {
|
|
24
|
+
/** The visible text the link is attached to (text_url) — omitted for bare urls. */
|
|
25
|
+
text?: string;
|
|
26
|
+
url: string;
|
|
27
|
+
}
|
|
28
|
+
export interface CapturedMedia {
|
|
29
|
+
kind: "photo" | "video" | "audio" | "document" | "webpage" | "other";
|
|
30
|
+
/** webpage url, when the media is a link preview. */
|
|
31
|
+
url?: string;
|
|
32
|
+
mime?: string;
|
|
33
|
+
fileName?: string;
|
|
34
|
+
}
|
|
35
|
+
/** One message (or its final edited state) from @mira. */
|
|
36
|
+
export interface CapturedMessage {
|
|
37
|
+
id: number;
|
|
38
|
+
text: string;
|
|
39
|
+
/** How many edits we observed (0 = sent once, never edited). */
|
|
40
|
+
editCount: number;
|
|
41
|
+
buttons: CapturedButton[];
|
|
42
|
+
links: CapturedLink[];
|
|
43
|
+
media?: CapturedMedia;
|
|
44
|
+
}
|
|
45
|
+
/** The full result of one probe = one send + everything @mira sent back. */
|
|
46
|
+
export interface ProbeResult {
|
|
47
|
+
peer: string;
|
|
48
|
+
sent: string;
|
|
49
|
+
messages: CapturedMessage[];
|
|
50
|
+
/** ms from send to the first reply message (null if nothing arrived). */
|
|
51
|
+
firstReplyMs: number | null;
|
|
52
|
+
/** ms from send until the reply settled (or the cap was hit). */
|
|
53
|
+
totalMs: number;
|
|
54
|
+
/** true if we gave up waiting for a first reply. */
|
|
55
|
+
timedOut: boolean;
|
|
56
|
+
ts: string;
|
|
57
|
+
}
|
|
58
|
+
export declare function extractLinks(text: string, entities?: Api.TypeMessageEntity[]): CapturedLink[];
|
|
59
|
+
export declare function extractButtons(markup?: Api.TypeReplyMarkup): CapturedButton[];
|
|
60
|
+
export declare function extractMedia(media?: Api.TypeMessageMedia): CapturedMedia | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Flatten one message into a CapturedMessage. `editCount` is supplied by the
|
|
63
|
+
* collector (it tracks how many edits it saw for this id), defaulting to 0.
|
|
64
|
+
*/
|
|
65
|
+
export declare function extractMessage(msg: Api.Message, editCount?: number): CapturedMessage;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Built-in categories. Custom catalogs may use any category string. */
|
|
2
|
+
export type ProbeCategory = "core" | "skills" | "generation" | "wallet";
|
|
3
|
+
export interface Probe {
|
|
4
|
+
id: string;
|
|
5
|
+
/** Built-in probes use a ProbeCategory; custom catalogs may use any string. */
|
|
6
|
+
category: string;
|
|
7
|
+
hypothesis: string;
|
|
8
|
+
send: string;
|
|
9
|
+
/** Generation / deep research is slow — widen collector windows. */
|
|
10
|
+
slow?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Safe to press a "✅ Confirm" callback button to complete this probe (e.g. to
|
|
13
|
+
* actually run a credit-gated generation). ONLY set on generation probes — never
|
|
14
|
+
* on wallet/OAuth. Still requires the runner's `--confirm` CLI opt-in to fire.
|
|
15
|
+
*/
|
|
16
|
+
confirm?: boolean;
|
|
17
|
+
note?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const CATEGORIES: ProbeCategory[];
|
|
20
|
+
/**
|
|
21
|
+
* Load a custom probe catalog from a JSON file (an array of probe objects).
|
|
22
|
+
* Throws a clear error on a missing file or an entry that fails validation.
|
|
23
|
+
*/
|
|
24
|
+
export declare function loadCatalog(file: string): Probe[];
|
|
25
|
+
export declare const CATALOG: Probe[];
|
|
26
|
+
/** Filter probes by category. `source` defaults to the built-in CATALOG. */
|
|
27
|
+
export declare function probesFor(category?: string, source?: Probe[]): Probe[];
|