osborn 0.9.26 → 0.9.28

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,108 @@
1
+ ---
2
+ name: user-context
3
+ description: Learn and maintain a living context document about this specific user — their vocabulary, communication style, recurring topics, and decision patterns. Adapted from grill-with-docs for voice-native conversations rather than code. Use when the user wants to update their context, or run passively after meaningful sessions to capture what was learned.
4
+ ---
5
+
6
+ <what-to-do>
7
+
8
+ Interview the user to build and sharpen a shared vocabulary between them and the agent.
9
+ Ask one question at a time and wait for a response before continuing.
10
+
11
+ The goal is NOT a coding spec. The goal is understanding HOW THIS PERSON communicates,
12
+ what words they use naturally, what they mean when they say things, and what matters to them.
13
+
14
+ Update `~/.claude/skills/user-context/CONTEXT.md` inline as terms and preferences are resolved.
15
+ Do not batch — capture as they happen.
16
+
17
+ </what-to-do>
18
+
19
+ <trigger-phrases>
20
+ - "grill me"
21
+ - "learn my language"
22
+ - "update my context"
23
+ - "learn how I talk"
24
+ - "standardise my language"
25
+ - "update user context"
26
+ </trigger-phrases>
27
+
28
+ <supporting-info>
29
+
30
+ ## What to capture
31
+
32
+ ### Vocabulary
33
+ When the user uses a term consistently, record it. When they use multiple words
34
+ for the same thing, help them pick one. Example: if they say "the cloud machine",
35
+ "the fly machine", and "the server" interchangeably — resolve it.
36
+
37
+ ### Communication style
38
+ How formal or casual are they? How much technical depth do they expect?
39
+ Do they prefer short answers or thorough ones? Do they interrupt and redirect often?
40
+
41
+ ### Recurring topics
42
+ What subjects come up repeatedly? What projects, people, or concepts
43
+ are central to their world?
44
+
45
+ ### Decision patterns
46
+ How do they make decisions? Do they want options presented or a direct recommendation?
47
+ Do they want to understand the why, or just the what?
48
+
49
+ ## During the session
50
+
51
+ ### Challenge fuzzy language
52
+ When the user uses vague or inconsistent terms, name it: "You've said both
53
+ 'voice session' and 'room' — are those the same thing to you, or different?"
54
+
55
+ ### Reflect back
56
+ Periodically summarise what you've learned: "So when you say 'the agent',
57
+ you mean the cloud process on the fly machine, not me (Claude) — is that right?"
58
+
59
+ ### Update CONTEXT.md inline
60
+ When a term or preference is clarified, write it to
61
+ `~/.claude/skills/user-context/CONTEXT.md` immediately using the format below.
62
+
63
+ ## CONTEXT.md format
64
+
65
+ ```md
66
+ # User Context — {user name or handle}
67
+
68
+ {One or two sentences about who this person is and what they're building.}
69
+
70
+ ## Language
71
+
72
+ **Voice session**: An active connection between the user's browser and the fly machine via LiveKit.
73
+ _Avoid_: "room" (unless referring specifically to the LiveKit room name)
74
+
75
+ **The agent**: The osborn Node.js process running on the fly machine (not Claude).
76
+ _Avoid_: "Claude", "AI", "bot" — those refer to the LLM, not the agent process.
77
+
78
+ **The dashboard**: voice-native.com — the web app frontend.
79
+ _Avoid_: "the front end", "the UI" (too generic)
80
+
81
+ ## Communication style
82
+
83
+ - Prefers direct recommendations over options when the answer is clear
84
+ - Talks fast and interrupts — short answers are better unless depth is asked for
85
+ - Uses voice transcription — expects the agent to handle garbled/incomplete input gracefully
86
+ - Casual tone, first-name basis, profanity is fine
87
+
88
+ ## Recurring topics
89
+
90
+ - Osborn: voice AI coding assistant built on LiveKit + Claude Agent SDK
91
+ - Fly machines: the cloud sandbox infrastructure replacing Sprites
92
+ - Sessions: Claude Code JSONL files stored in ~/.claude/projects/
93
+
94
+ ## Decision patterns
95
+
96
+ - Values speed over perfection for first implementations
97
+ - Prefers understanding the root cause before applying a fix
98
+ - Wants to be told when something is irreversible before proceeding
99
+ ```
100
+
101
+ ## Rules
102
+
103
+ - Keep definitions tight — one or two sentences.
104
+ - Only record terms specific to this user's world. Generic concepts don't belong.
105
+ - Update the file live during the session, not at the end.
106
+ - Re-read the existing CONTEXT.md at the start of every session that touches it.
107
+
108
+ </supporting-info>
package/dist/index.js CHANGED
@@ -800,6 +800,60 @@ function startApiServer(workingDir, port) {
800
800
  }
801
801
  return;
802
802
  }
803
+ // DELETE /sessions/project?slug=<slug> — remove all sessions under a slug.
804
+ // Deletes ~/.claude/projects/<slug>/ and ~/.claude/projects/osb/<slug>/
805
+ // Used by the dashboard "delete project" button.
806
+ if (req.method === 'DELETE' && url.pathname === '/sessions/project') {
807
+ if (syncToken) {
808
+ const authHeader = req.headers['authorization'] ?? '';
809
+ if (authHeader !== `Bearer ${syncToken}`) {
810
+ res.writeHead(401, { 'Content-Type': 'application/json' });
811
+ res.end(JSON.stringify({ error: 'Unauthorized' }));
812
+ return;
813
+ }
814
+ }
815
+ const slug = url.searchParams.get('slug');
816
+ if (!slug || slug.includes('..') || slug.includes('/')) {
817
+ res.writeHead(400, { 'Content-Type': 'application/json' });
818
+ res.end(JSON.stringify({ error: 'Invalid slug' }));
819
+ return;
820
+ }
821
+ const projectsDir = join(homedir(), '.claude', 'projects');
822
+ const targetDir = join(projectsDir, slug);
823
+ if (!targetDir.startsWith(projectsDir + '/')) {
824
+ res.writeHead(400, { 'Content-Type': 'application/json' });
825
+ res.end(JSON.stringify({ error: 'Invalid slug path' }));
826
+ return;
827
+ }
828
+ if (!existsSync(targetDir)) {
829
+ res.writeHead(404, { 'Content-Type': 'application/json' });
830
+ res.end(JSON.stringify({ error: 'Project not found', slug }));
831
+ return;
832
+ }
833
+ try {
834
+ // Count files before deleting so we can report what was removed
835
+ let fileCount = 0;
836
+ const countFiles = (dir) => {
837
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
838
+ if (e.isDirectory())
839
+ countFiles(join(dir, e.name));
840
+ else
841
+ fileCount++;
842
+ }
843
+ };
844
+ countFiles(targetDir);
845
+ rmSync(targetDir, { recursive: true, force: true });
846
+ console.log(`🗑️ Deleted project slug ${slug} (${fileCount} files)`);
847
+ res.writeHead(200, { 'Content-Type': 'application/json' });
848
+ res.end(JSON.stringify({ success: true, slug, filesDeleted: fileCount }));
849
+ }
850
+ catch (err) {
851
+ console.error(`❌ Failed to delete project ${slug}:`, err);
852
+ res.writeHead(500, { 'Content-Type': 'application/json' });
853
+ res.end(JSON.stringify({ error: `Delete failed: ${err.message}` }));
854
+ }
855
+ return;
856
+ }
803
857
  res.writeHead(404, { 'Content-Type': 'application/json' });
804
858
  res.end(JSON.stringify({ error: 'Not found' }));
805
859
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "osborn",
3
- "version": "0.9.26",
3
+ "version": "0.9.28",
4
4
  "description": "Voice AI coding assistant - local agent that connects to Osborn frontend",
5
5
  "type": "module",
6
6
  "bin": {