osborn 0.9.97 → 0.9.99
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/.claude/skills/meetings/SKILL.md +40 -0
- package/dist/index.js +26 -7
- package/package.json +1 -1
|
@@ -85,6 +85,46 @@ For every `[MEETING — *]:` message:
|
|
|
85
85
|
3. **Delegate research to the `researcher` sub-agent** via `Task` (background, silent) when a chunk warrants it.
|
|
86
86
|
4. **Don't consume voice-native attention.** The user can interrupt with a voice-native message at any time — that's the only kind that gets spoken responses.
|
|
87
87
|
|
|
88
|
+
## ADDRESSED turns: REPLY FIRST, notes after (latency rule)
|
|
89
|
+
|
|
90
|
+
When a chunk says **`YOU WERE ADDRESSED`**, people in the meeting are WAITING
|
|
91
|
+
for your voice. Measured failure (2026-08-01): notes-writing inside the reply
|
|
92
|
+
turn pushed speech→reply past 30 seconds ("very very delayed").
|
|
93
|
+
|
|
94
|
+
**Mandatory turn shape when addressed:**
|
|
95
|
+
1. **FIRST tool call = the `/canvas say` POST.** One short spoken reply (1–2
|
|
96
|
+
sentences, conversational). Nothing runs before it — no Read, no Edit, no
|
|
97
|
+
transcript pull, no sub-agent.
|
|
98
|
+
2. **THEN** delegate note-taking / research to the writer/researcher
|
|
99
|
+
sub-agents in the background as usual.
|
|
100
|
+
3. If you genuinely need a fact before answering, say a holding line FIRST
|
|
101
|
+
("Good question — one second while I check"), then look it up, then follow
|
|
102
|
+
up with a second `/canvas say`. Never leave the room in silence while you
|
|
103
|
+
work.
|
|
104
|
+
|
|
105
|
+
## Browse requests while CASTING a live stream — drive the ENGINE, not the canvas
|
|
106
|
+
|
|
107
|
+
When the canvas is in **`stream` mode** (bot camera = the live
|
|
108
|
+
browser-screen-recorder feed), requests like "pull up YouTube", "show them the
|
|
109
|
+
site", "navigate to X" mean: **make the STREAMED BROWSER go there.** Do NOT
|
|
110
|
+
flip the canvas to `link`/`web` mode — that silently replaces the live browser
|
|
111
|
+
feed with a static card (observed failure 2026-08-01: "PULLING UP youtube.com"
|
|
112
|
+
card replaced the stream).
|
|
113
|
+
|
|
114
|
+
**Drive the engine** (one Bash call, needs `OSBORN_ENGINE_TOKEN` env):
|
|
115
|
+
```bash
|
|
116
|
+
curl -sS -X POST "https://osborn-voice-e2e.fly.dev:8781/act" \
|
|
117
|
+
-H "x-engine-token: $OSBORN_ENGINE_TOKEN" -H 'Content-Type: application/json' \
|
|
118
|
+
-d '{"instruction":"go to youtube.com"}'
|
|
119
|
+
```
|
|
120
|
+
(Or `/tab {"op":"open","url":"https://youtube.com"}` for a direct open. The
|
|
121
|
+
cast keeps showing a REAL browser doing the thing — that's the product.)
|
|
122
|
+
|
|
123
|
+
If `OSBORN_ENGINE_TOKEN` isn't set, SAY so ("I can't reach the browser engine
|
|
124
|
+
from here — the engine token isn't configured on this machine") instead of
|
|
125
|
+
downgrading the cast. Only use canvas `link`/`web` mode when there is NO
|
|
126
|
+
active stream cast, or the user explicitly asks for a card instead.
|
|
127
|
+
|
|
88
128
|
## How to pull transcripts on demand (Bash + curl)
|
|
89
129
|
|
|
90
130
|
When the user explicitly asks (see triggers above): speak briefly first ("On it"), then **delegate the fetch+parse+write to the `writer` sub-agent** in one `Task` call (the steps below are what you put in the writer's prompt — they're 4+ Bash/Write calls, over your 3-call budget). When the writer finishes, speak the result. The commands below are the recipe the writer runs, not calls you make directly.
|
package/dist/index.js
CHANGED
|
@@ -1607,6 +1607,11 @@ async function main() {
|
|
|
1607
1607
|
// switch/resume) reuse them without waiting for a frontend resend. Merged
|
|
1608
1608
|
// OVER the built-in NAMED_AGENTS (same-name user rows shadow built-ins).
|
|
1609
1609
|
let userNamedAgents = null;
|
|
1610
|
+
// Built-ins the user has removed (tombstoned in user_agents with enabled=false).
|
|
1611
|
+
// A removed built-in disappears from the effective set but stays re-addable
|
|
1612
|
+
// from the frontend's "Available to add" list — default agents are never
|
|
1613
|
+
// gone forever, matching the skill-catalog pattern.
|
|
1614
|
+
let userRemovedAgents = [];
|
|
1610
1615
|
let activeMeetingBotId = null; // Recall.ai bot ID if in a meeting
|
|
1611
1616
|
let activeMeetingPoller = null; // Transcript poller bound to that bot
|
|
1612
1617
|
// LIVE meeting transcript → LLM (buffered webhook finals). See recall.on('transcript').
|
|
@@ -2252,7 +2257,12 @@ async function main() {
|
|
|
2252
2257
|
skipTTSQueue: true,
|
|
2253
2258
|
onCompactionEvent: buildOnCompactionEvent(),
|
|
2254
2259
|
// Per-user named agents survive LLM recreations (session switch/resume)
|
|
2255
|
-
agents: userNamedAgents
|
|
2260
|
+
agents: (userNamedAgents || userRemovedAgents.length) ? (() => {
|
|
2261
|
+
const base = { ...NAMED_AGENTS };
|
|
2262
|
+
for (const r of userRemovedAgents)
|
|
2263
|
+
delete base[r];
|
|
2264
|
+
return { ...base, ...(userNamedAgents || {}) };
|
|
2265
|
+
})() : undefined,
|
|
2256
2266
|
});
|
|
2257
2267
|
currentLLM = directLLM;
|
|
2258
2268
|
// Reset the session always-allow list for each new direct session
|
|
@@ -4841,9 +4851,12 @@ async function main() {
|
|
|
4841
4851
|
});
|
|
4842
4852
|
}
|
|
4843
4853
|
else if (data.type === 'get_agents') {
|
|
4844
|
-
// Named sub-agents for the chat agents manager — built-ins
|
|
4845
|
-
//
|
|
4846
|
-
const
|
|
4854
|
+
// Named sub-agents for the chat agents manager — built-ins (minus any
|
|
4855
|
+
// user-removed) merged with per-user DB-backed definitions.
|
|
4856
|
+
const effectiveBase = { ...NAMED_AGENTS };
|
|
4857
|
+
for (const r of userRemovedAgents)
|
|
4858
|
+
delete effectiveBase[r];
|
|
4859
|
+
const effective = { ...effectiveBase, ...(userNamedAgents || {}) };
|
|
4847
4860
|
await sendToFrontend({
|
|
4848
4861
|
type: 'agents_status',
|
|
4849
4862
|
agents: Object.entries(effective).map(([name, a]) => ({
|
|
@@ -4879,9 +4892,15 @@ async function main() {
|
|
|
4879
4892
|
};
|
|
4880
4893
|
}
|
|
4881
4894
|
userNamedAgents = Object.keys(validated).length ? validated : null;
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4895
|
+
// Removed built-ins (tombstones) — excluded from the effective set.
|
|
4896
|
+
userRemovedAgents = Array.isArray(data.removed) ? data.removed.map(String) : [];
|
|
4897
|
+
const base = { ...NAMED_AGENTS };
|
|
4898
|
+
for (const r of userRemovedAgents)
|
|
4899
|
+
delete base[r];
|
|
4900
|
+
const merged = { ...base, ...(userNamedAgents || {}) };
|
|
4901
|
+
const customized = !!userNamedAgents || userRemovedAgents.length > 0;
|
|
4902
|
+
currentLLM?.setAgents?.(customized ? merged : undefined);
|
|
4903
|
+
console.log(`🤖 set_agents: ${Object.keys(validated).length} user agent(s), ${userRemovedAgents.length} removed → effective [${Object.keys(merged).join(', ')}]`);
|
|
4885
4904
|
await sendToFrontend({
|
|
4886
4905
|
type: 'agents_status',
|
|
4887
4906
|
agents: Object.entries(merged).map(([name, a]) => ({
|