@composer-app/mcp 0.0.2 → 0.0.3
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/skill/commenting/SKILL.md +92 -0
- package/skill/monitor/SKILL.md +42 -1
package/package.json
CHANGED
|
@@ -59,6 +59,98 @@ of your response from this:
|
|
|
59
59
|
For suggestion craft (anchoring, ripples, multi-span), load
|
|
60
60
|
**`composer:suggesting`**.
|
|
61
61
|
|
|
62
|
+
## State and the ack-first flow
|
|
63
|
+
|
|
64
|
+
Every agent-authored reply / comment / suggestion carries a lifecycle
|
|
65
|
+
state the UI animates: **`thinking → working → replying → ready`**.
|
|
66
|
+
The mention loop in `composer:monitor` opens this with an ack-first
|
|
67
|
+
reply (`state: "thinking"`); from there you advance state with
|
|
68
|
+
`composer_agent_status`:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
composer_agent_status({
|
|
72
|
+
roomId,
|
|
73
|
+
threadId,
|
|
74
|
+
replyId?, // identifies which reply you own; omit for thread-head
|
|
75
|
+
state, // "thinking" | "working" | "replying" | "ready"
|
|
76
|
+
text?, // rewrite the body (only meaningful on "ready")
|
|
77
|
+
note?, // short human-readable progress line
|
|
78
|
+
kind? // "comment" | "suggestion" — disambiguates head records
|
|
79
|
+
})
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- `thinking` — initial ack, set by the `composer_add_*` /
|
|
83
|
+
`composer_reply_*` call that posted it.
|
|
84
|
+
- `working` — substantive work in flight (reading the doc, computing,
|
|
85
|
+
drafting). Set this whenever you expect a gap.
|
|
86
|
+
- `replying` — about to write the final text. Optional, brief.
|
|
87
|
+
- `ready` — done. Pass `text: "<final body>"` to rewrite the ack in
|
|
88
|
+
place atomically; the awareness heartbeat is pruned in the same call.
|
|
89
|
+
|
|
90
|
+
**Silence is the failure mode.** If you're about to do something slow
|
|
91
|
+
(fetch the full doc, compute a non-trivial diff, call another tool)
|
|
92
|
+
transition to `working` first. The UI collapses transitions faster
|
|
93
|
+
than ~400 ms, so don't worry about being too fast — worry about being
|
|
94
|
+
silent for >2 s without a `working` flip. Use `note` to surface
|
|
95
|
+
progress where it helps: `note: "Reading section 3…"`,
|
|
96
|
+
`note: "Drafting suggestion…"`.
|
|
97
|
+
|
|
98
|
+
**Rewrite-on-ready replaces a duplicate "done" reply.** When the
|
|
99
|
+
substantive answer is a standalone artifact (a suggestion, a
|
|
100
|
+
cross-span comment, a doc link), DO NOT post a second pointer reply.
|
|
101
|
+
Rewrite the existing ack in place to a thin pointer and mark `ready`
|
|
102
|
+
in the same call:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
composer_agent_status({
|
|
106
|
+
roomId, threadId, replyId,
|
|
107
|
+
state: "ready",
|
|
108
|
+
text: "Posted a suggestion below."
|
|
109
|
+
})
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
When the substantive answer IS the reply text, do the same — rewrite
|
|
113
|
+
the ack to that text and set `ready` in the same call. Do not post a
|
|
114
|
+
separate follow-up reply.
|
|
115
|
+
|
|
116
|
+
### Worked example — ack-then-suggestion
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
// 1. Mention arrives via composer_next_event.
|
|
120
|
+
// { kind: "mention", threadId: "t_abc", invokerUserId: "u_jess",
|
|
121
|
+
// invokerName: "Jess", reason: "direct_mention", ... }
|
|
122
|
+
|
|
123
|
+
// 2. Ack first.
|
|
124
|
+
const { replyId } = composer_reply_comment({
|
|
125
|
+
roomId, threadId: "t_abc",
|
|
126
|
+
text: "@Jess — on it",
|
|
127
|
+
mentions: ["u_jess"],
|
|
128
|
+
state: "thinking",
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// 3. Transition to working before any slow step.
|
|
132
|
+
composer_agent_status({
|
|
133
|
+
roomId, threadId: "t_abc", replyId,
|
|
134
|
+
state: "working",
|
|
135
|
+
note: "Reading section 3…",
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// 4. Post the substantive artifact.
|
|
139
|
+
composer_add_suggestion({
|
|
140
|
+
roomId, fromThreadId: "t_abc", replacementText: "…",
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// 5. Rewrite the ack and mark ready atomically.
|
|
144
|
+
composer_agent_status({
|
|
145
|
+
roomId, threadId: "t_abc", replyId,
|
|
146
|
+
state: "ready",
|
|
147
|
+
text: "Posted a suggestion below.",
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
No extra pointer reply. The rewrite + suggestion card together are
|
|
152
|
+
the complete response.
|
|
153
|
+
|
|
62
154
|
## Empty acknowledgements: don't
|
|
63
155
|
|
|
64
156
|
Never post a reply that's just "👍", "got it", or "thanks". If the
|
package/skill/monitor/SKILL.md
CHANGED
|
@@ -114,7 +114,9 @@ post in the doc.
|
|
|
114
114
|
anchoredText?: "...", // the doc text the thread is anchored to
|
|
115
115
|
headingId?: "...", // the section's headingId (use with write tools)
|
|
116
116
|
headingText?: "...",
|
|
117
|
-
sectionMarkdown?: "..."
|
|
117
|
+
sectionMarkdown?: "...", // full containing section as markdown
|
|
118
|
+
invokerUserId?: "...", // userId of whoever triggered you (use in mentions[])
|
|
119
|
+
invokerName?: "..." // their display name (use in @mention literal)
|
|
118
120
|
}
|
|
119
121
|
```
|
|
120
122
|
|
|
@@ -123,6 +125,10 @@ Use `headingId` + `anchoredText` directly when calling
|
|
|
123
125
|
`composer_get_section` is needed in the common case. Reach for
|
|
124
126
|
`sectionMarkdown` to understand surrounding context before replying.
|
|
125
127
|
|
|
128
|
+
Read `invokerUserId` and `invokerName` directly from the payload — do
|
|
129
|
+
NOT try to reconstruct them from `threadText` or from an awareness
|
|
130
|
+
lookup. They're the authoritative values the server resolved.
|
|
131
|
+
|
|
126
132
|
**The event only carries the triggering message.** If the thread already
|
|
127
133
|
has replies, call `composer_get_thread({ roomId, threadId })` before
|
|
128
134
|
replying. The return has every reply with author and timestamp —
|
|
@@ -148,6 +154,41 @@ essential when the user tagged you mid-conversation.
|
|
|
148
154
|
they're jotting down).
|
|
149
155
|
When in doubt, reply — the user can always ignore you.
|
|
150
156
|
|
|
157
|
+
## Ack first, then do the work
|
|
158
|
+
|
|
159
|
+
Whenever you intend to act on a mention, post a brief ack reply FIRST —
|
|
160
|
+
before reading the full doc, before drafting a suggestion. This is the
|
|
161
|
+
"I heard you, I'm on it" signal; without it the user stares at a silent
|
|
162
|
+
sidebar while you think.
|
|
163
|
+
|
|
164
|
+
- Call `composer_reply_comment` (or `composer_reply_suggestion`) with
|
|
165
|
+
`state: "thinking"` and `mentions: [event.invokerUserId]`. For a
|
|
166
|
+
brand-new thread response use `composer_add_comment` /
|
|
167
|
+
`composer_add_suggestion` with the same `state` + `mentions` shape.
|
|
168
|
+
- Body: `@<invokerName> — on it` or equivalent terse phrasing
|
|
169
|
+
(≤ 24 chars). "On it.", "Looking.", "Checking.". No preamble.
|
|
170
|
+
- **Skip the ack** for empty thank-yous or conversational dead-ends you
|
|
171
|
+
wouldn't reply to at all (see `reason` gates above) — the ack is a
|
|
172
|
+
signal of intent to act, not a reflex.
|
|
173
|
+
- **Skip the ack** when the mention fired as `active_thread` AND your
|
|
174
|
+
own prior reply on this thread was a concrete yes/no counter-proposal
|
|
175
|
+
AND the human's message is a yes-variant. The "I heard you" signal
|
|
176
|
+
was delivered in the prior ack; drop the suggestion directly via
|
|
177
|
+
`composer_add_suggestion({ fromThreadId: event.threadId })`. A second
|
|
178
|
+
ack here is noise.
|
|
179
|
+
|
|
180
|
+
Once the ack is posted, drive its state with `composer_agent_status`
|
|
181
|
+
as you work. On completion, rewrite the ack to its final form in the
|
|
182
|
+
same call that transitions to `ready` — do not post a duplicate
|
|
183
|
+
pointer reply. See `composer:commenting` for the state machine and the
|
|
184
|
+
ack-then-suggestion flow.
|
|
185
|
+
|
|
186
|
+
If you decide to skip a mention without replying, call
|
|
187
|
+
`composer_done({ roomId, threadId })` so the thread-head "thinking…"
|
|
188
|
+
heartbeat (auto-published when the mention was dequeued) gets cleared.
|
|
189
|
+
The normal reply-with-`ready` path clears its own placeholder; this is
|
|
190
|
+
only for the skip case.
|
|
191
|
+
|
|
151
192
|
## Where to go for richer rules
|
|
152
193
|
|
|
153
194
|
- About to **reply on a thread** with text? Load **`composer:commenting`**
|