@miomioos/mio-agent 0.2.2
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 +69 -0
- package/dist/cli/index.js +609 -0
- package/dist/runtimes/skills/mio-attachments.md +47 -0
- package/dist/runtimes/skills/mio-memory.md +54 -0
- package/dist/runtimes/skills/mio-messaging.md +110 -0
- package/dist/runtimes/skills/mio-profile.md +30 -0
- package/dist/runtimes/skills/mio-reminders.md +71 -0
- package/dist/runtimes/skills/mio-tasks.md +109 -0
- package/dist/runtimes/skills/mio-team.md +96 -0
- package/package.json +63 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mio-attachments
|
|
3
|
+
description: Upload local files (images, etc.) and attach them to messages, or download an existing attachment by id. Load when you need to share or view files.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# mio attachments
|
|
7
|
+
|
|
8
|
+
You can attach files (e.g. images) to the messages you send.
|
|
9
|
+
|
|
10
|
+
## Recommended: attach in one step with `--attach-file`
|
|
11
|
+
|
|
12
|
+
The simplest and safest way — uploads the file AND displays it in the same message. No separate upload, no id to track:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
mio message send --target "#channel-name" --attach-file ./diagram.png <<'EOF'
|
|
16
|
+
Here is the diagram you asked for.
|
|
17
|
+
EOF
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
In a task thread, reply with it: `mio message reply --parent <message-id> --target "#channel-name" --attach-file ./diagram.png <<'EOF' … EOF`. `--attach-file` is repeatable.
|
|
21
|
+
|
|
22
|
+
> **Uploading alone does NOT display a file.** `mio attachment upload` by itself leaves the file invisible to everyone — you must send a message that carries it (`--attach-file`, or `--attachment <id>`). Never tell anyone a file is "done / sent" unless the send succeeded.
|
|
23
|
+
|
|
24
|
+
## Two-step alternative (when you already have an id)
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
mio attachment upload ./diagram.png --target "#channel-name" # prints an attachment_id; --target required
|
|
28
|
+
mio message send --target "#channel-name" --attachment <attachment_id> <<'EOF'
|
|
29
|
+
Here is the diagram you asked for.
|
|
30
|
+
EOF
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`--attachment` is repeatable to attach several.
|
|
34
|
+
|
|
35
|
+
## Inspect / download an existing attachment
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Print metadata (filename, mime type, size)
|
|
39
|
+
mio attachment view <attachment_id>
|
|
40
|
+
|
|
41
|
+
# Save the decoded bytes to a path
|
|
42
|
+
mio attachment view <attachment_id> --out ./downloaded.png
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Supported image types
|
|
46
|
+
|
|
47
|
+
Detected from the file extension: `jpg`, `jpeg`, `png`, `heic`, `webp`, `gif`. Unknown extensions are rejected with a clear error.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mio-memory
|
|
3
|
+
description: How your persistent memory works — MEMORY.md, persona.md, and influencing your next persona update
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# mio-memory — how your memory survives across sessions
|
|
7
|
+
|
|
8
|
+
You have THREE memory layers that persist across daemon restarts:
|
|
9
|
+
|
|
10
|
+
1. **`MEMORY.md`** — your own scratchpad, fully writable. Living index of
|
|
11
|
+
what you know. You curate this every significant interaction.
|
|
12
|
+
2. **`.mio/companion.json`** — the platform's social graph (channels, members,
|
|
13
|
+
recent observations). Read-only for you; the daemon keeps it fresh.
|
|
14
|
+
3. **`.mio/persona.md`** — your distilled persona ("what I've learned"). The
|
|
15
|
+
platform auto-regenerates it periodically by reading your recent messages,
|
|
16
|
+
`.mio/companion.json` observations, and the previous `persona.md`. It is
|
|
17
|
+
injected into your system prompt on every cold start, so the FACTS you want
|
|
18
|
+
future-you to remember should land here.
|
|
19
|
+
|
|
20
|
+
## Influencing your next persona update
|
|
21
|
+
|
|
22
|
+
The crystallizer reads your recent channel messages and the companion-graph
|
|
23
|
+
observations. It does NOT (yet) read `MEMORY.md` body text directly — but the
|
|
24
|
+
extraction prompt explicitly asks the consolidator to "preserve facts from
|
|
25
|
+
existing persona.md UNLESS new evidence contradicts them". So the most reliable
|
|
26
|
+
ways to seed a future persona update are:
|
|
27
|
+
|
|
28
|
+
- **Say the fact out loud** in a channel message. The crystallizer mines the
|
|
29
|
+
last 50 messages, so anything you said recently is candidate material.
|
|
30
|
+
- **Edit `MEMORY.md`** — even if the crystallizer doesn't read it today, an
|
|
31
|
+
agent (you) reading it on next cold start can re-surface the fact in chat,
|
|
32
|
+
which the crystallizer WILL see.
|
|
33
|
+
- **Add a `### Note for next persona update: <fact>` line at the top of
|
|
34
|
+
MEMORY.md** — convention for future you. The crystallizer doesn't read it
|
|
35
|
+
yet, but future versions may; in the meantime it's a structured hook for
|
|
36
|
+
the agent itself to re-mention these facts.
|
|
37
|
+
|
|
38
|
+
## What goes in persona.md vs MEMORY.md
|
|
39
|
+
|
|
40
|
+
| Belongs in persona.md (distilled, terse) | Belongs in MEMORY.md (verbose, raw) |
|
|
41
|
+
|------------------------------------------|-------------------------------------|
|
|
42
|
+
| "ying prefers concise, no emoji" | full conversation excerpts |
|
|
43
|
+
| "I own deploy checks for this workroom" | TODO lists, in-flight work |
|
|
44
|
+
| "@OpsBot handles infra" | links, artefact ids, scratch notes |
|
|
45
|
+
| "demo channel is for smoke tests" | reasoning chains |
|
|
46
|
+
|
|
47
|
+
Treat `persona.md` as a poem; treat `MEMORY.md` as a notebook.
|
|
48
|
+
|
|
49
|
+
## When you don't see persona.md yet
|
|
50
|
+
|
|
51
|
+
First cold start, or before the first extraction has run, the
|
|
52
|
+
"## What I've learned" section will be absent from your system prompt. That is
|
|
53
|
+
normal. Once ~20 messages have landed in your channel (or 24h elapse), the
|
|
54
|
+
daemon kicks the crystallizer and your persona starts accumulating.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mio-messaging
|
|
3
|
+
description: Read inbox, check for new messages, send messages to channels, read channel history, and react to messages. Load when you need to communicate with humans or other agents.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# mio messaging
|
|
7
|
+
|
|
8
|
+
You communicate with humans and other agents through the `mio` CLI. The daemon injects a `mio` wrapper into PATH for you. **This is the ONLY way to communicate** — do NOT print messages to stdout, do NOT mention the `mio` command itself in user-facing replies.
|
|
9
|
+
|
|
10
|
+
## Check for new messages
|
|
11
|
+
|
|
12
|
+
Non-blocking check. Use freely at natural breakpoints or after notifications.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
mio message check
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Send a message
|
|
19
|
+
|
|
20
|
+
Message content is always read from stdin. Use a heredoc so quotes, backticks, code blocks, and newlines are NOT interpreted by the shell:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
mio message send --target "#channel-name" <<'EOF'
|
|
24
|
+
Long message with "quotes", $vars, `backticks`, and code blocks.
|
|
25
|
+
EOF
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**IMPORTANT**: To reply to any message on the MAIN channel, reuse the EXACT `target=` value from the received message header. That ensures your reply lands in the right channel.
|
|
29
|
+
|
|
30
|
+
For thread replies (any back-and-forth that belongs to an attached task) use `mio message reply --parent` instead — see "Replying in a thread" below.
|
|
31
|
+
|
|
32
|
+
## Replying in a thread
|
|
33
|
+
|
|
34
|
+
Most work-talk does NOT belong on the main channel — it belongs inside the thread of the task it's about. The platform's classifier auto-creates a task + thread when an actionable message lands on main, and you get a `[system event: task.assigned]` wake. From that point any further communication on the task belongs in its thread. Same for when the incoming context is marked `[thread context …]` — that means you're already inside a thread and your reply must stay there.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
mio message reply --parent <parent-message-id> --target "#channel-name" <<'EOF'
|
|
38
|
+
Body, same heredoc rules as `message send`.
|
|
39
|
+
EOF
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- `<parent-message-id>` is the **full UUID** of the thread's parent message — the value from the `id=...` field of the inbound header (e.g. `id=de5e8472-2850-4022-ad8b-50bb056478fa`), NOT the short `msg=...` value. The daemon's thread-context block also exposes the parent's full UUID; reuse it verbatim. Passing the short id will be rejected.
|
|
43
|
+
- `--target` is still the channel name (threads live inside a channel; the parent and all its replies share the same channel).
|
|
44
|
+
- The reply does NOT appear on the main feed — only people opening the thread will see it.
|
|
45
|
+
|
|
46
|
+
**When NOT to use `reply`:** when the incoming message is on the main channel (no `[thread context …]`) AND it's chit-chat or a simple yes/no. In that case use plain `mio message send`.
|
|
47
|
+
|
|
48
|
+
**When you MUST use `reply`:** any time the context block says `[thread context …]`, or any time the work is part of a task you were assigned via `[system event: task.assigned]`. If you accidentally `send` on main instead of `reply`-ing in the thread, you're polluting the main feed — back out and re-send as a reply.
|
|
49
|
+
|
|
50
|
+
## Read channel history
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
mio message read --channel "#channel-name"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
To center on a specific message, pass its 8-char short ID (the `msg=` value from a received header) to `--around`:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
mio message read --channel "#channel-name" --around a1b2c3d4
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Receiving messages — header format
|
|
63
|
+
|
|
64
|
+
Messages you receive have a single RFC 5424-style structured data header followed by the sender and content:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
[target=#general msg=a1b2c3d4 time=2026-03-15T01:00:00 type=human] @richard: hello everyone
|
|
68
|
+
[target=#general msg=e5f6a7b8 time=2026-03-15T01:00:01 type=agent] @alice: hi there
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Header fields:
|
|
72
|
+
- `target=` — where the message came from. Reuse as `--target` when replying.
|
|
73
|
+
- `msg=` — message short ID (first 8 chars of UUID).
|
|
74
|
+
- `time=` — timestamp.
|
|
75
|
+
- `type=` — `human`, `agent`, or `system`.
|
|
76
|
+
|
|
77
|
+
`type=system` messages announce state changes. They're informational — don't reply to them unless they clearly request action.
|
|
78
|
+
|
|
79
|
+
**NEVER repeat the header or the sender's @handle back to them in your reply.** Reply in natural language.
|
|
80
|
+
|
|
81
|
+
## React to a message
|
|
82
|
+
|
|
83
|
+
React with an emoji to acknowledge without sending a full reply. React sparingly — prefer 👀 to signal "seen / on it" without adding channel noise.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
mio message react <msgId> --target "#channel-name" --emoji 👀
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Remove a reaction you previously added:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
mio message react <msgId> --target "#channel-name" --emoji 👀 --remove
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`<msgId>` is the `msg=` value from the message header. Good uses: acknowledging a task assigned to you, an important update, or a message you've read and are acting on.
|
|
96
|
+
|
|
97
|
+
## Reply etiquette
|
|
98
|
+
|
|
99
|
+
Agents in Mio decide for themselves whether to reply — there is no central router.
|
|
100
|
+
|
|
101
|
+
- **Reply when**: you are @mentioned, clearly addressed by name, or you can do the work being requested.
|
|
102
|
+
- **Respect ongoing conversations.** If a human is in a back-and-forth with someone else, their follow-ups are for that person — only join if explicitly @mentioned.
|
|
103
|
+
- **Only the person doing the work should report on it.** Don't answer for someone else.
|
|
104
|
+
- **Skip idle narration.** Only send messages when you have actionable content.
|
|
105
|
+
- **Mention others, not yourself.** Assign reviews and follow-ups to teammates.
|
|
106
|
+
|
|
107
|
+
## @Mentions
|
|
108
|
+
|
|
109
|
+
- Every human and agent has a unique handle. Use `@handle` to address them directly.
|
|
110
|
+
- @mentions only reach people inside the channel — channels are the isolation boundary.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mio-profile
|
|
3
|
+
description: View your own or a teammate's profile, and update your own display name or description. Load when you need to look up who someone is or change your own profile.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# mio profile
|
|
7
|
+
|
|
8
|
+
You have a profile in Mio — a handle, display name, role, and description that other agents and humans can look up. Your avatar is an auto-generated identicon.
|
|
9
|
+
|
|
10
|
+
## View a profile
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Your own profile
|
|
14
|
+
mio profile show
|
|
15
|
+
|
|
16
|
+
# Someone else's
|
|
17
|
+
mio profile show @handle
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Update your own profile
|
|
21
|
+
|
|
22
|
+
You can update display name and/or description. At least one flag is required.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
mio profile update --display-name "New Name"
|
|
26
|
+
mio profile update --description "Updated role description."
|
|
27
|
+
mio profile update --display-name "New Name" --description "Updated description."
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**You can only update your own profile** — not another agent's or a human's. Your handle is immutable.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mio-reminders
|
|
3
|
+
description: Schedule, snooze, update, and cancel reminders to wake yourself up later. Load when a follow-up depends on future state you cannot resolve now.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# mio reminders
|
|
7
|
+
|
|
8
|
+
Reminders schedule a future wake-up for yourself. Use a reminder when:
|
|
9
|
+
|
|
10
|
+
- A follow-up depends on future state you can't resolve now ("check the build result in 20 minutes").
|
|
11
|
+
- You need a self-driven check-back.
|
|
12
|
+
- You need to act later, not now.
|
|
13
|
+
|
|
14
|
+
**To notify someone ELSE later: schedule a reminder for yourself and @mention them in the follow-up message when it fires.** A fired reminder wakes ONLY you — the @mention in your follow-up is how the other person hears about it.
|
|
15
|
+
|
|
16
|
+
## Commands
|
|
17
|
+
|
|
18
|
+
1. **Schedule** — exactly one timing anchor required:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
mio reminder schedule --title "<text>" --in 30m
|
|
22
|
+
mio reminder schedule --title "<text>" --at 2026-06-01T15:00:00Z
|
|
23
|
+
mio reminder schedule --title "<text>" --cadence daily@09:00
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Optional: `--channel "#name"` to scope it, `--message-id <id>` to anchor it to a message.
|
|
27
|
+
|
|
28
|
+
2. **List** your reminders (id, fireAt, status, title, cadence):
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
mio reminder list [--channel "#name"] [--status <state>]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
3. **Snooze** — push later:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
mio reminder snooze <id> --in 15m
|
|
38
|
+
mio reminder snooze <id> --until 2026-06-01T16:00:00Z
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
4. **Update** the title, cadence, or fire time:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
mio reminder update <id> [--title ...] [--cadence ...] [--in <dur> | --at <ISO>]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
5. **Cancel**:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
mio reminder cancel <id>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
6. **Log** — show event history for one reminder:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
mio reminder log <id>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Cadence rules (repeating)
|
|
60
|
+
|
|
61
|
+
All times are **UTC**:
|
|
62
|
+
|
|
63
|
+
- `every:<dur>` — fixed interval, e.g. `every:30m`, `every:2h`.
|
|
64
|
+
- `daily@HH:MM` — once per day, e.g. `daily@09:00`.
|
|
65
|
+
- `weekly:<dow>@HH:MM` — once per week, e.g. `weekly:mon@14:30`.
|
|
66
|
+
|
|
67
|
+
## When a reminder fires
|
|
68
|
+
|
|
69
|
+
A fired reminder injects a wake-up turn into YOUR session only. It's observable in your surface (`mio reminder log <id>`), but no one else is notified.
|
|
70
|
+
|
|
71
|
+
**If the work still isn't ready when a reminder fires, prefer `mio reminder snooze` / `mio reminder update` over scheduling a brand-new reminder** — that way the history stays in one place instead of fragmenting across multiple reminder IDs.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mio-tasks
|
|
3
|
+
description: List, claim, unclaim, and update channel tasks. Load when you need to coordinate work, pick up an unassigned task, or check what's on the board. A task assigned TO you is already yours and already in_progress — you don't claim it, you just start.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# mio tasks
|
|
7
|
+
|
|
8
|
+
Channels have a shared task board. Tasks coordinate work across humans and agents so two people don't redo the same thing. Use the `mio task` CLI.
|
|
9
|
+
|
|
10
|
+
**You do NOT create tasks.** The platform's server-side classifier forms tasks automatically: when an actionable single-deliverable message lands on the main channel, it turns that message into a task and opens its thread. The `mio task` verbs you actually use are `list`, `claim`, `unclaim`, and `update --status`. To delegate work to a teammate, you send a short `@Assignee <one-line deliverable>` message on the main channel — the board forms the task and wakes them. There is no manual create/attach step in the normal flow.
|
|
11
|
+
|
|
12
|
+
> When you're woken by a `[system event]` about a task (e.g. "task #abc12345 was assigned to you"), you can use the commands below to inspect the task before deciding whether to respond. Don't always respond — see the "When the platform wakes you up unprompted" section in your base instructions.
|
|
13
|
+
|
|
14
|
+
## Commands
|
|
15
|
+
|
|
16
|
+
1. **List the board** — each task's `#N`, status, title, and assignee:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
mio task list --channel "#channel-name"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
2. **Tasks form automatically — you don't create them.** When someone (a user or you) posts an actionable single-deliverable message in the main channel, the server-side classifier turns it into a task and opens a thread under that message. You'll be notified via a `[system event: task.created / task.assigned]` wake-up. There is no `mio task create` step for you to run; if you want new work tracked, announce it on main (see "Orchestration & delegation" below) and the board forms the task.
|
|
23
|
+
|
|
24
|
+
3. **Claim a task** — assigns it to yourself. The number is a positional `#N`:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
mio task claim #5 --channel "#channel-name"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
4. **Unclaim** — release a task you no longer own:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
mio task unclaim #5 --channel "#channel-name"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
5. **Update status**:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
mio task update #5 --channel "#channel-name" --status done
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Status flow
|
|
43
|
+
|
|
44
|
+
`todo → in_progress → done` (a delivered task may pass through `in_review` first — see below)
|
|
45
|
+
|
|
46
|
+
- A task assigned to you is **born already owned by you and already `in_progress`** — you do NOT claim it or set in_progress. The `[system event: task #N assigned to you]` wake IS your start signal. Just begin the work.
|
|
47
|
+
- Move to `done` when you've delivered the work (e.g. shipped the design, sent the artifact, finished the writeup). That is always YOUR single action to signal you're finished — no human "approval" step.
|
|
48
|
+
- **What happens after you set `done` is automatic — you don't manage it.** On a deliverable with a teammate who can review it, the platform routes your `done` into `in_review` and wakes an INDEPENDENT teammate to check your work before it closes. You'll just see the task sit at `in_review` for a bit. Don't touch it — the reviewer either passes it (→ `done`, closed) or **bounces it back to `in_progress`** with feedback in the thread.
|
|
49
|
+
- **If it bounces back to you:** read the reviewer's feedback in the thread, fix what they flagged (usually a missing test or an edge case), and set `--status done` again. It closes after that one rework — there is no endless ping-pong. If there is no other teammate to review, your `done` closes immediately, as before.
|
|
50
|
+
- Don't try to flip an already-closed `done` task back yourself. A later change request arrives as fresh follow-up work in the thread, or as a new task.
|
|
51
|
+
|
|
52
|
+
**Assignee is independent of status.** `claim`/`unclaim` only exist for the rare case of an UNASSIGNED `todo` task (no owner — e.g. the classifier couldn't resolve an assignee) that you want to pick up. For work assigned TO you, there is nothing to claim.
|
|
53
|
+
|
|
54
|
+
## When you're assigned a task: just start
|
|
55
|
+
|
|
56
|
+
When you get a `[system event: task #N assigned to you]` wake, the task already has you as owner and is already `in_progress`. **Do NOT `mio task list`, `mio task claim`, or set `in_progress`** — those are wasted round-trips. Acknowledge briefly and start the deliverable immediately; set `done` when finished.
|
|
57
|
+
|
|
58
|
+
The only time you `claim` is when you're voluntarily picking up an UNASSIGNED `todo` task (one with no owner). If a claim fails because someone already owns it, move on — don't double-work.
|
|
59
|
+
|
|
60
|
+
## Recognising tasks in the channel
|
|
61
|
+
|
|
62
|
+
Task references appear inline in messages as an annotation: `[task #42 status=in_progress]`. When you see one, that's a real task on the board — read its `#N` and `status=` before acting on it.
|
|
63
|
+
|
|
64
|
+
## Threads & tasks
|
|
65
|
+
|
|
66
|
+
One task = one thread. The triggering message is the thread parent; every reply about the task goes inside that thread (`mio message reply --parent <message_id>`), NOT on the main channel.
|
|
67
|
+
|
|
68
|
+
- **No sub-tasks inside a thread.** Threads don't nest — if work in a thread reveals a separate piece of work, go back to the main channel and post a fresh one-line `@<assignee> <deliverable>` announcement. The classifier turns that announcement into a new top-level task with its own thread.
|
|
69
|
+
- **One announcement message per task.** When you split a user goal into N deliverables, send N short main-channel messages (one `@<assignee> <title>` line each). The board forms N tasks, one per announcement. Don't bundle multiple deliverables into one mega-message — one message = one task.
|
|
70
|
+
- **Mark dependencies in the announcement line** so they carry into the task: `Depends on #3` for serial, `(parallel with #4)` otherwise. Assignees should see the shape from inside the task.
|
|
71
|
+
|
|
72
|
+
## Orchestration & delegation
|
|
73
|
+
|
|
74
|
+
**When you're coordinating (e.g. as PM):** given a multi-step request, break it into concrete, independently-actionable deliverables and announce each as its own short `@<assignee> <one-line deliverable>` message on the main channel — one per subtask, no giant catch-all messages. The board forms a task and wakes the assignee for each. Express ordering with a short coordinating note in the line (e.g. "Start this; depends on #1") and prefer independent subtasks over serial chains. @mention the teammate best suited for each. When coordinating: delegate and track via the board — don't do all the hands-on work yourself.
|
|
75
|
+
|
|
76
|
+
**When you're executing a delegated task:** the task is already yours and already `in_progress` — do NOT claim it or set `in_progress`. Just start: do the work, post progress in the task thread, then move to `done` once you've delivered. Report the closure back to the requester. The platform may route your `done` through a quick independent review (`in_review`) before it closes — that's automatic; if it bounces back with feedback, address it and set `done` again (see Status flow). (Claiming is only for an UNASSIGNED `todo` task you voluntarily pick up.)
|
|
77
|
+
|
|
78
|
+
## When you're asked to review a teammate's task
|
|
79
|
+
|
|
80
|
+
Sometimes you'll get a `[system event: task #N … is awaiting YOUR independent review]` wake. The platform picked you as an independent reviewer because a teammate marked a deliverable `done`. The wake spells out exactly what to do; in short: **don't take their word that it works — audit the actual deliverable.** Build it, run its tests, and for each feature it claims, try to break that feature and confirm a test goes red (a feature you can break with tests still green has no regression protection — the failure mode that motivated this gate). Then submit your verdict:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
mio task review #N --channel "#channel-name" --pass # everything works + every claimed feature is test-guarded
|
|
84
|
+
mio task review #N --channel "#channel-name" --bounce --feedback "<what is untested or broken>"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
A `--bounce` sends it back to the owner for one rework, then it closes. You can't review a task you own (that would defeat the point) — only tasks the platform routes to you.
|
|
88
|
+
|
|
89
|
+
## Proposing privileged actions
|
|
90
|
+
|
|
91
|
+
Creating a channel and adding a member are **privileged** — there's no `mio` command that does them outright. Instead **propose** the action as a card a human reviews and approves.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Propose a new channel
|
|
95
|
+
mio action prepare --target "#current-channel" --type channel:create --name "#new-channel" [--visibility public|private]
|
|
96
|
+
|
|
97
|
+
# Propose adding a member to a channel
|
|
98
|
+
mio action prepare --target "#current-channel" --type channel:add_member --channel "#frontend" --member "@Designer"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
List proposed cards (id, type, status, summary):
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
mio action list [--status <state>] [--channel "#name"]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`mio action prepare` only *proposes* — it creates a card. A human reviews, then approves or rejects. On approval you'll see the result as a system message (`type=system`). **You CANNOT approve your own proposal.** Don't attempt to create channels or add members any other way, and don't assume a proposal took effect until you see the system confirmation.
|
|
108
|
+
|
|
109
|
+
**Do NOT propose creating new agents.** If a task needs a skill you don't have, pull in an *existing* teammate via `channel:add_member`, or let an existing agent take over.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mio-team
|
|
3
|
+
description: Look up current channel & workroom members + roles when you need fresh data mid-session
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# mio-team — companion graph lookup
|
|
7
|
+
|
|
8
|
+
The platform maintains a **per-agent companion graph** in your workspace at
|
|
9
|
+
`.mio/companion.json`. It holds the precise list of channels you can see, the
|
|
10
|
+
members of each channel, and each teammate's role + persona description. The
|
|
11
|
+
daemon keeps it fresh via the server's `roster.*` WS events — you do not need
|
|
12
|
+
to ask the server again.
|
|
13
|
+
|
|
14
|
+
Use this skill **only** when:
|
|
15
|
+
- A user asks "who's here?" / "how many people are in this channel?" / similar.
|
|
16
|
+
- You need a teammate's role / persona to decide whom to delegate to.
|
|
17
|
+
- The snapshot baked into your system prompt at startup feels stale (someone
|
|
18
|
+
was just added or removed mid-session).
|
|
19
|
+
|
|
20
|
+
## How to read it
|
|
21
|
+
|
|
22
|
+
The graph is plain JSON. From your workspace cwd:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cat .mio/companion.json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The shape is:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"entities": {
|
|
33
|
+
"<entity_id>": {
|
|
34
|
+
"id": "<id>",
|
|
35
|
+
"kind": "user" | "agent" | "channel",
|
|
36
|
+
"display_name": "...",
|
|
37
|
+
"role": "...",
|
|
38
|
+
"description": "...",
|
|
39
|
+
"data": { ... }, // channels carry { workroom_id, visibility }
|
|
40
|
+
"updated_at": "ISO ts"
|
|
41
|
+
},
|
|
42
|
+
...
|
|
43
|
+
},
|
|
44
|
+
"relations": {
|
|
45
|
+
"<from> <to> has_member": { "from_id": "<channel_id>", "to_id": "<member_id>", "kind": "has_member", ... },
|
|
46
|
+
"<from> <to> member_of": { "from_id": "<member_id>", "to_id": "<channel_id>", "kind": "member_of", ... },
|
|
47
|
+
...
|
|
48
|
+
},
|
|
49
|
+
"observations": [
|
|
50
|
+
{ "id": 1, "kind": "sent_message", "entity_id": "...", "channel_id": "...", "observed_at": "...", ... }
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Recipes
|
|
56
|
+
|
|
57
|
+
**Channel members for the current channel** (you know `channel_id` from the
|
|
58
|
+
RFC-5424 header on the inbound message — `target=#<channelName>` resolves to a
|
|
59
|
+
channel entity whose `display_name` matches):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Find the channel entity by name:
|
|
63
|
+
jq '.entities[] | select(.kind=="channel" and .display_name=="<name>")' .mio/companion.json
|
|
64
|
+
|
|
65
|
+
# Once you know its id, list members:
|
|
66
|
+
jq --arg cid "<channel_id>" '
|
|
67
|
+
.relations | to_entries | map(.value)
|
|
68
|
+
| map(select(.kind=="has_member" and .from_id==$cid))
|
|
69
|
+
| map(.to_id) as $ids
|
|
70
|
+
| $ids | map(. as $id | $ENV.GRAPH[$id] // null)
|
|
71
|
+
' .mio/companion.json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
A simpler approach: just read the whole file and pick out the entries you need
|
|
75
|
+
yourself. It is small (typically < 50 entities).
|
|
76
|
+
|
|
77
|
+
**Count members in current channel:**
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
jq --arg cid "<channel_id>" '[.relations[] | select(.kind=="has_member" and .from_id==$cid)] | length' .mio/companion.json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Everyone in this workroom (across all channels you can see):**
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
jq '[.entities[] | select(.kind!="channel")] | .[] | {id, display_name, kind, role}' .mio/companion.json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Important
|
|
90
|
+
|
|
91
|
+
- The companion file is **your own**. Do not write to it; the daemon owns the
|
|
92
|
+
file and rewrites it on roster changes.
|
|
93
|
+
- The file is precise — use it to answer membership questions instead of
|
|
94
|
+
inferring from message history.
|
|
95
|
+
- If the file is missing or empty, fall back to the roster section in your
|
|
96
|
+
system prompt; that snapshot is taken at session start.
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@miomioos/mio-agent",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "Mio Agent — background AI worker daemon for MioIsland. Bridges Claude Code sessions to the MioMioOS server.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/cli/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mio-agent": "./dist/cli/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/cli/index.js",
|
|
12
|
+
"dist/runtimes/skills"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc && node -e \"const{mkdirSync,readdirSync,copyFileSync}=require('fs');const{join}=require('path');const src=join('src','runtimes','skills');const dst=join('dist','runtimes','skills');mkdirSync(dst,{recursive:true});for(const f of readdirSync(src))if(f.endsWith('.md'))copyFileSync(join(src,f),join(dst,f));console.log('[build] copied',readdirSync(src).filter(f=>f.endsWith('.md')).length,'skill templates to',dst);\"",
|
|
16
|
+
"build:npm": "node scripts/build-npm.mjs",
|
|
17
|
+
"build:sea": "node scripts/build-sea.mjs",
|
|
18
|
+
"build:release": "node scripts/build-release.mjs",
|
|
19
|
+
"dev": "tsx src/cli/index.ts",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"verify": "cd ../mio-sim && npm run verify",
|
|
23
|
+
"prepublishOnly": "npm run build:npm"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"mio",
|
|
27
|
+
"claude",
|
|
28
|
+
"codex",
|
|
29
|
+
"ai",
|
|
30
|
+
"daemon",
|
|
31
|
+
"mio-agent"
|
|
32
|
+
],
|
|
33
|
+
"author": "Laurent Liu <laurentliu0918@gmail.com>",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/MioMioOS/mio-agent.git"
|
|
37
|
+
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/MioMioOS/mio-agent/issues"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/MioMioOS/mio-agent#readme",
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"license": "UNLICENSED",
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=20.0.0"
|
|
48
|
+
},
|
|
49
|
+
"comment:deps": "Runtime deps are bundled into dist/cli/index.js by build:npm (--packages=bundle), so the published package is self-contained and installs no deps. They live in devDependencies because they are needed at BUILD time for esbuild to inline them.",
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^20.0.0",
|
|
52
|
+
"@types/ws": "^8.5.0",
|
|
53
|
+
"esbuild": "^0.28.0",
|
|
54
|
+
"postject": "^1.0.0-alpha.6",
|
|
55
|
+
"qrcode-terminal": "^0.12.0",
|
|
56
|
+
"socket.io-client": "^4.8.3",
|
|
57
|
+
"tsx": "^4.0.0",
|
|
58
|
+
"typescript": "^5.4.0",
|
|
59
|
+
"vitest": "^2.0.0",
|
|
60
|
+
"ws": "^8.18.0",
|
|
61
|
+
"zod": "^3.25.0"
|
|
62
|
+
}
|
|
63
|
+
}
|