osborn 0.9.81 → 0.9.82

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.
@@ -0,0 +1,32 @@
1
+ # Voice-E2E — browser testing with ears, a mouth, hands and a brain
2
+
3
+ ## SKILL IDENTITY
4
+ Name: voice-e2e
5
+ Version: 1 (packaged seed — the served copy at the URL below is source of truth)
6
+ Served from: https://www.voice-native.com/api/test-skill
7
+ Landing page: https://www.voice-native.com/test-skill
8
+
9
+ Agent-driven end-to-end testing for voice and web apps in a REAL browser:
10
+ speak into the page's mic (synthesized on the fly), hear and transcribe what
11
+ it plays back, click via a natural-language brain, improvise conversations,
12
+ and get video + audio replays per run. Works on any website.
13
+
14
+ ## UPDATE CHECK (notify-first, run before major test/research runs)
15
+ This packaged copy ships with every machine and may lag the served version.
16
+ Check, then NOTIFY the user before updating — never silently force:
17
+
18
+ ```bash
19
+ SERVED_V=$(curl -sf --max-time 10 https://www.voice-native.com/api/test-skill | grep -m1 '^Version:' | awk '{print $2}')
20
+ LOCAL_V=$(grep -m1 '^Version:' ~/.claude/skills/voice-e2e/SKILL.md 2>/dev/null | awk '{print $2}')
21
+ [ -n "$SERVED_V" ] && [ "$SERVED_V" != "$LOCAL_V" ] && echo "UPDATE AVAILABLE: voice-e2e v${LOCAL_V:-none} -> v$SERVED_V — tell the user what's new and ask before updating (curl -sS https://www.voice-native.com/api/test-skill -o ~/.claude/skills/voice-e2e/SKILL.md), then refresh the harness bundle per the served INSTALLATION."
22
+ ```
23
+
24
+ If the user approves (or has pre-approved auto-updates), update the skill
25
+ file AND re-run the served INSTALLATION step 2 (harness bundle refresh) so
26
+ the accompanying files stay in lockstep with the skill.
27
+
28
+ ## FIRST USE
29
+ Fetch the served copy and follow its INSTALLATION section — it materializes
30
+ the harness (~/voice-e2e-harness/), installs dependencies, and asks the user
31
+ for a GOOGLE_API_KEY (required, Gemini brain) plus optional OPENAI/DEEPGRAM
32
+ keys for the voice mouth and audible verification.
package/dist/index.js CHANGED
@@ -70,7 +70,7 @@ function loadSkillsList(agentDir) {
70
70
  // Extract description from first paragraph after heading
71
71
  const descMatch = content.match(/^#[^\n]+\n+([^\n#]+)/m);
72
72
  const description = descMatch ? descMatch[1].trim() : '';
73
- skills.push({ name, description });
73
+ skills.push({ name, description, folder: skillName });
74
74
  }
75
75
  }
76
76
  }
@@ -4558,6 +4558,33 @@ async function main() {
4558
4558
  }
4559
4559
  }
4560
4560
  }
4561
+ else if (data.type === 'skill_get') {
4562
+ const folder = (data.name || '').trim().toLowerCase().replace(/[^a-z0-9-]/g, '-');
4563
+ const p = join(sessionBaseDir, '.claude', 'skills', folder, 'SKILL.md');
4564
+ if (folder && existsSync(p)) {
4565
+ await sendToFrontend({ type: 'skill_content', name: folder, content: readFileSync(p, 'utf-8') });
4566
+ }
4567
+ else {
4568
+ await sendToFrontend({ type: 'skill_content', name: folder, error: 'skill not found' });
4569
+ }
4570
+ }
4571
+ else if (data.type === 'skill_remove') {
4572
+ const folder = (data.name || '').trim().toLowerCase().replace(/[^a-z0-9-]/g, '-');
4573
+ const dir = join(sessionBaseDir, '.claude', 'skills', folder);
4574
+ if (!folder || !existsSync(dir)) {
4575
+ await sendToFrontend({ type: 'skill_remove_result', success: false, error: 'skill not found' });
4576
+ }
4577
+ else {
4578
+ try {
4579
+ rmSync(dir, { recursive: true, force: true });
4580
+ console.log(`🗑️ Skill removed: ${folder}`);
4581
+ await sendToFrontend({ type: 'skill_remove_result', success: true, skills: loadSkillsList(sessionBaseDir) });
4582
+ }
4583
+ catch (err) {
4584
+ await sendToFrontend({ type: 'skill_remove_result', success: false, error: String(err) });
4585
+ }
4586
+ }
4587
+ }
4561
4588
  else if (data.type === 'join_meeting') {
4562
4589
  const meetingUrl = data.url;
4563
4590
  if (meetingUrl) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "osborn",
3
- "version": "0.9.81",
3
+ "version": "0.9.82",
4
4
  "description": "Voice AI coding assistant - local agent that connects to Osborn frontend",
5
5
  "type": "module",
6
6
  "bin": {