osborn 0.8.34 → 0.9.0
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/Dockerfile.sandbox +2 -0
- package/dist/index.js +166 -7
- package/dist/meeting-output.html +32 -0
- package/package.json +2 -2
- package/.claude/settings.local.json +0 -9
- package/.claude/skills/browser-apply/SKILL.md +0 -114
- package/.claude/skills/markdown-to-pdf/SKILL.md +0 -29
- package/.claude/skills/pdf-to-markdown/SKILL.md +0 -28
- package/.claude/skills/playwright-browser/SKILL.md +0 -90
- package/.claude/skills/shadcn/SKILL.md +0 -232
- package/.claude/skills/shadcn/image.png +0 -0
- package/.claude/skills/youtube-transcript/SKILL.md +0 -24
- package/caresource-apply.js +0 -50
- package/caresource-apply.mjs +0 -34
- package/dist/conversation-brain.d.ts +0 -92
- package/dist/conversation-brain.js +0 -360
- package/dist/fast-llm.d.ts +0 -15
- package/dist/fast-llm.js +0 -81
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
# Skill: shadcn/ui Components
|
|
2
|
-
|
|
3
|
-
Add and configure shadcn/ui components in a Next.js or React project.
|
|
4
|
-
|
|
5
|
-
## When to use
|
|
6
|
-
When the user wants to add UI components (buttons, dialogs, cards, forms, tables, etc.) using shadcn/ui — the copy-paste component library built on Radix UI and Tailwind CSS.
|
|
7
|
-
|
|
8
|
-
## Setup (first time only)
|
|
9
|
-
|
|
10
|
-
Initialize shadcn in the project root (where package.json lives):
|
|
11
|
-
```bash
|
|
12
|
-
npx shadcn@latest init
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
This creates `components.json` and sets up `src/components/ui/`. Answer the prompts to match your project's style preferences.
|
|
16
|
-
|
|
17
|
-
## Add a component
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
npx shadcn@latest add <component-name>
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Add multiple components at once
|
|
24
|
-
```bash
|
|
25
|
-
npx shadcn@latest add button card dialog input form
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Commonly used components
|
|
29
|
-
|
|
30
|
-
| Component | Install name | Description |
|
|
31
|
-
|-----------|-------------|-------------|
|
|
32
|
-
| Button | `button` | Clickable button with variants |
|
|
33
|
-
| Card | `card` | Container with header/content/footer |
|
|
34
|
-
| Input | `input` | Text input field |
|
|
35
|
-
| Label | `label` | Form label |
|
|
36
|
-
| Textarea | `textarea` | Multi-line text input |
|
|
37
|
-
| Select | `select` | Dropdown select |
|
|
38
|
-
| Checkbox | `checkbox` | Checkbox with label |
|
|
39
|
-
| Switch | `switch` | Toggle switch |
|
|
40
|
-
| Dialog | `dialog` | Modal dialog |
|
|
41
|
-
| Sheet | `sheet` | Slide-in panel (drawer) |
|
|
42
|
-
| Popover | `popover` | Floating content panel |
|
|
43
|
-
| Tooltip | `tooltip` | Hover tooltip |
|
|
44
|
-
| Dropdown Menu | `dropdown-menu` | Contextual dropdown |
|
|
45
|
-
| Command | `command` | Command palette / search |
|
|
46
|
-
| Badge | `badge` | Small status indicator |
|
|
47
|
-
| Avatar | `avatar` | User avatar with fallback |
|
|
48
|
-
| Separator | `separator` | Visual divider |
|
|
49
|
-
| Table | `table` | Data table |
|
|
50
|
-
| Tabs | `tabs` | Tabbed interface |
|
|
51
|
-
| Accordion | `accordion` | Collapsible sections |
|
|
52
|
-
| Sonner | `sonner` | Toast notifications (preferred over toast) |
|
|
53
|
-
| Alert | `alert` | Inline alert message |
|
|
54
|
-
| Alert Dialog | `alert-dialog` | Confirmation dialog |
|
|
55
|
-
| Progress | `progress` | Progress bar |
|
|
56
|
-
| Skeleton | `skeleton` | Loading placeholder |
|
|
57
|
-
| Scroll Area | `scroll-area` | Custom scrollbar container |
|
|
58
|
-
| Calendar | `calendar` | Date picker calendar |
|
|
59
|
-
| Form | `form` | React Hook Form integration |
|
|
60
|
-
| Slider | `slider` | Range slider |
|
|
61
|
-
| Toggle | `toggle` | Toggle button |
|
|
62
|
-
| Navigation Menu | `navigation-menu` | Site navigation |
|
|
63
|
-
| Breadcrumb | `breadcrumb` | Page navigation breadcrumbs |
|
|
64
|
-
| Collapsible | `collapsible` | Expandable/collapsible section |
|
|
65
|
-
| Context Menu | `context-menu` | Right-click context menu |
|
|
66
|
-
| Menubar | `menubar` | Application menu bar |
|
|
67
|
-
| Resizable | `resizable` | Resizable panel groups |
|
|
68
|
-
|
|
69
|
-
## Import pattern
|
|
70
|
-
|
|
71
|
-
```tsx
|
|
72
|
-
import { Button } from "@/components/ui/button"
|
|
73
|
-
import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card"
|
|
74
|
-
import { Input } from "@/components/ui/input"
|
|
75
|
-
import { Label } from "@/components/ui/label"
|
|
76
|
-
import {
|
|
77
|
-
Dialog,
|
|
78
|
-
DialogContent,
|
|
79
|
-
DialogDescription,
|
|
80
|
-
DialogHeader,
|
|
81
|
-
DialogTitle,
|
|
82
|
-
DialogTrigger,
|
|
83
|
-
} from "@/components/ui/dialog"
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## Example — Button variants
|
|
87
|
-
|
|
88
|
-
```tsx
|
|
89
|
-
<Button>Default</Button>
|
|
90
|
-
<Button variant="destructive">Delete</Button>
|
|
91
|
-
<Button variant="outline">Cancel</Button>
|
|
92
|
-
<Button variant="ghost">Ghost</Button>
|
|
93
|
-
<Button variant="link">Link</Button>
|
|
94
|
-
<Button size="sm">Small</Button>
|
|
95
|
-
<Button size="lg">Large</Button>
|
|
96
|
-
<Button disabled>Disabled</Button>
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## Example — Card
|
|
100
|
-
|
|
101
|
-
```tsx
|
|
102
|
-
<Card>
|
|
103
|
-
<CardHeader>
|
|
104
|
-
<CardTitle>Card Title</CardTitle>
|
|
105
|
-
<CardDescription>Card description goes here</CardDescription>
|
|
106
|
-
</CardHeader>
|
|
107
|
-
<CardContent>
|
|
108
|
-
<p>Card content here</p>
|
|
109
|
-
</CardContent>
|
|
110
|
-
<CardFooter>
|
|
111
|
-
<Button>Action</Button>
|
|
112
|
-
</CardFooter>
|
|
113
|
-
</Card>
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
## Example — Form with validation (React Hook Form + Zod)
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
npx shadcn@latest add form input
|
|
120
|
-
npm install zod react-hook-form @hookform/resolvers
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
```tsx
|
|
124
|
-
import { useForm } from "react-hook-form"
|
|
125
|
-
import { zodResolver } from "@hookform/resolvers/zod"
|
|
126
|
-
import * as z from "zod"
|
|
127
|
-
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"
|
|
128
|
-
import { Input } from "@/components/ui/input"
|
|
129
|
-
import { Button } from "@/components/ui/button"
|
|
130
|
-
|
|
131
|
-
const formSchema = z.object({
|
|
132
|
-
email: z.string().email("Invalid email address"),
|
|
133
|
-
password: z.string().min(8, "Password must be at least 8 characters"),
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
export function LoginForm() {
|
|
137
|
-
const form = useForm<z.infer<typeof formSchema>>({
|
|
138
|
-
resolver: zodResolver(formSchema),
|
|
139
|
-
defaultValues: { email: "", password: "" },
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
function onSubmit(values: z.infer<typeof formSchema>) {
|
|
143
|
-
console.log(values)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return (
|
|
147
|
-
<Form {...form}>
|
|
148
|
-
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
|
149
|
-
<FormField
|
|
150
|
-
control={form.control}
|
|
151
|
-
name="email"
|
|
152
|
-
render={({ field }) => (
|
|
153
|
-
<FormItem>
|
|
154
|
-
<FormLabel>Email</FormLabel>
|
|
155
|
-
<FormControl>
|
|
156
|
-
<Input placeholder="you@example.com" {...field} />
|
|
157
|
-
</FormControl>
|
|
158
|
-
<FormMessage />
|
|
159
|
-
</FormItem>
|
|
160
|
-
)}
|
|
161
|
-
/>
|
|
162
|
-
<FormField
|
|
163
|
-
control={form.control}
|
|
164
|
-
name="password"
|
|
165
|
-
render={({ field }) => (
|
|
166
|
-
<FormItem>
|
|
167
|
-
<FormLabel>Password</FormLabel>
|
|
168
|
-
<FormControl>
|
|
169
|
-
<Input type="password" {...field} />
|
|
170
|
-
</FormControl>
|
|
171
|
-
<FormMessage />
|
|
172
|
-
</FormItem>
|
|
173
|
-
)}
|
|
174
|
-
/>
|
|
175
|
-
<Button type="submit" className="w-full">Sign in</Button>
|
|
176
|
-
</form>
|
|
177
|
-
</Form>
|
|
178
|
-
)
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
## Example — Toast notifications (Sonner)
|
|
183
|
-
|
|
184
|
-
```bash
|
|
185
|
-
npx shadcn@latest add sonner
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
```tsx
|
|
189
|
-
// In your root layout — add the Toaster once
|
|
190
|
-
import { Toaster } from "@/components/ui/sonner"
|
|
191
|
-
export default function RootLayout({ children }) {
|
|
192
|
-
return (
|
|
193
|
-
<html>
|
|
194
|
-
<body>
|
|
195
|
-
{children}
|
|
196
|
-
<Toaster />
|
|
197
|
-
</body>
|
|
198
|
-
</html>
|
|
199
|
-
)
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Then anywhere in your app
|
|
203
|
-
import { toast } from "sonner"
|
|
204
|
-
|
|
205
|
-
toast("Event created")
|
|
206
|
-
toast.success("Profile saved")
|
|
207
|
-
toast.error("Something went wrong")
|
|
208
|
-
toast.promise(saveData(), {
|
|
209
|
-
loading: "Saving...",
|
|
210
|
-
success: "Saved!",
|
|
211
|
-
error: "Failed to save",
|
|
212
|
-
})
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
## The cn() utility
|
|
216
|
-
|
|
217
|
-
shadcn uses `clsx` + `tailwind-merge` via a `cn()` helper for conditional classes:
|
|
218
|
-
|
|
219
|
-
```tsx
|
|
220
|
-
import { cn } from "@/lib/utils"
|
|
221
|
-
|
|
222
|
-
<div className={cn("base-class", isActive && "active-class", className)} />
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
## Notes
|
|
226
|
-
- Components are **copied into your project** (not a node_modules dependency) — edit them freely
|
|
227
|
-
- Requires **Tailwind CSS** configured in the project
|
|
228
|
-
- Uses **Radix UI** primitives for accessibility
|
|
229
|
-
- Components land in `src/components/ui/` by default
|
|
230
|
-
- Run `npx shadcn@latest diff` to see if upstream components have changed
|
|
231
|
-
- Check `components.json` for path and style config
|
|
232
|
-
- Use Sonner (`sonner`) instead of the legacy `toast` component for notifications
|
|
Binary file
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# Skill: YouTube Transcript
|
|
2
|
-
|
|
3
|
-
Fetch and save transcripts from YouTube videos.
|
|
4
|
-
|
|
5
|
-
## When to use
|
|
6
|
-
When the user asks to get a transcript, subtitles, captions, or summary from a YouTube video URL.
|
|
7
|
-
|
|
8
|
-
## How to execute
|
|
9
|
-
|
|
10
|
-
yt-dlp is installed on this system. Use this exact command:
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
yt-dlp --skip-download --write-auto-sub --sub-lang en --convert-subs srt -o "/tmp/yt-%(id)s" "<VIDEO_URL>"
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
This downloads auto-generated English subtitles as an SRT file to /tmp/yt-{video-id}.en.srt
|
|
17
|
-
|
|
18
|
-
Then read the SRT file and strip the timing markers to get clean transcript text.
|
|
19
|
-
|
|
20
|
-
## Output
|
|
21
|
-
Save the cleaned transcript to the session workspace as `library/youtube-{video-id}-transcript.md` with:
|
|
22
|
-
- Video title and URL at the top
|
|
23
|
-
- Cleaned transcript text (strip SRT timing markers and duplicate lines)
|
|
24
|
-
- Key timestamps preserved as section markers if meaningful breaks exist
|
package/caresource-apply.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
const { chromium } = require('playwright');
|
|
2
|
-
|
|
3
|
-
(async () => {
|
|
4
|
-
const browser = await chromium.launch({ headless: false });
|
|
5
|
-
const page = await browser.newPage();
|
|
6
|
-
|
|
7
|
-
await page.goto('https://caresource.wd1.myworkdayjobs.com/CareSource/job/Remote/AI-Developer_R10487/apply', { waitUntil: 'networkidle' });
|
|
8
|
-
await page.waitForTimeout(2000);
|
|
9
|
-
|
|
10
|
-
// Click Apply Manually
|
|
11
|
-
console.log('Clicking Apply Manually...');
|
|
12
|
-
await page.click('text=Apply Manually');
|
|
13
|
-
await page.waitForTimeout(3000);
|
|
14
|
-
|
|
15
|
-
// Fill in email
|
|
16
|
-
console.log('Filling email field...');
|
|
17
|
-
const emailInput = await page.$('input[type="email"]');
|
|
18
|
-
if (emailInput) {
|
|
19
|
-
await emailInput.fill('osbornojure@gmail.com');
|
|
20
|
-
console.log('Email filled: osbornojure@gmail.com');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Fill in password
|
|
24
|
-
console.log('Filling password fields...');
|
|
25
|
-
const passwordInputs = await page.$$('input[type="password"]');
|
|
26
|
-
if (passwordInputs.length >= 2) {
|
|
27
|
-
await passwordInputs[0].fill('workday2026!');
|
|
28
|
-
await passwordInputs[1].fill('workday2026!');
|
|
29
|
-
console.log('Passwords filled');
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
await page.waitForTimeout(1000);
|
|
33
|
-
|
|
34
|
-
// Click Create Account
|
|
35
|
-
const createBtn = await page.$('text=Create Account');
|
|
36
|
-
if (createBtn) {
|
|
37
|
-
console.log('Clicking Create Account...');
|
|
38
|
-
await createBtn.click();
|
|
39
|
-
await page.waitForTimeout(3000);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Take screenshot
|
|
43
|
-
await page.screenshot({ path: '/tmp/caresource-step1.png' });
|
|
44
|
-
console.log('Screenshot saved to /tmp/caresource-step1.png');
|
|
45
|
-
|
|
46
|
-
// Get current page text
|
|
47
|
-
const text = await page.evaluate(() => document.body.innerText);
|
|
48
|
-
console.log('\n--- PAGE CONTENT ---');
|
|
49
|
-
console.log(text);
|
|
50
|
-
})();
|
package/caresource-apply.mjs
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { chromium } from 'playwright';
|
|
2
|
-
|
|
3
|
-
(async () => {
|
|
4
|
-
const browser = await chromium.launch({ headless: false });
|
|
5
|
-
const page = await browser.newPage();
|
|
6
|
-
|
|
7
|
-
console.log('🌐 Navigating to CareSource...');
|
|
8
|
-
await page.goto('https://caresource.wd1.myworkdayjobs.com/CareSource/job/Remote/AI-Developer_R10487/apply', { waitUntil: 'networkidle' });
|
|
9
|
-
await page.waitForTimeout(2000);
|
|
10
|
-
|
|
11
|
-
console.log('📋 Clicking Apply Manually...');
|
|
12
|
-
await page.click('text=Apply Manually');
|
|
13
|
-
await page.waitForTimeout(3000);
|
|
14
|
-
|
|
15
|
-
console.log('📧 Filling email...');
|
|
16
|
-
const emailInput = await page.$('input[type="email"]');
|
|
17
|
-
if (emailInput) {
|
|
18
|
-
await emailInput.fill('osbornojure@gmail.com');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
console.log('🔐 Filling passwords...');
|
|
22
|
-
const passwordInputs = await page.$$('input[type="password"]');
|
|
23
|
-
if (passwordInputs.length >= 2) {
|
|
24
|
-
await passwordInputs[0].fill('workday2026!');
|
|
25
|
-
await passwordInputs[1].fill('workday2026!');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
await page.waitForTimeout(1000);
|
|
29
|
-
await page.screenshot({ path: '/tmp/caresource-step1.png' });
|
|
30
|
-
|
|
31
|
-
console.log('✅ Account form filled. Screenshot saved.');
|
|
32
|
-
console.log('\n📝 Browser is now open. You can review before submitting.');
|
|
33
|
-
console.log('Keep this window open and ready to proceed.\n');
|
|
34
|
-
})();
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Conversation Brain - Gemini 2.5 Pro powered conversation manager
|
|
3
|
-
*
|
|
4
|
-
* This is the "smart brain" that:
|
|
5
|
-
* 1. Keeps conversation alive with relevant questions
|
|
6
|
-
* 2. Builds context until we understand what user wants
|
|
7
|
-
* 3. Dispatches background research agents
|
|
8
|
-
* 4. Receives progress updates and decides when to execute
|
|
9
|
-
* 5. Handles direct commands immediately
|
|
10
|
-
*/
|
|
11
|
-
export interface ConversationMessage {
|
|
12
|
-
role: 'user' | 'assistant' | 'system';
|
|
13
|
-
content: string;
|
|
14
|
-
timestamp: Date;
|
|
15
|
-
}
|
|
16
|
-
export interface ResearchTask {
|
|
17
|
-
id: string;
|
|
18
|
-
query: string;
|
|
19
|
-
status: 'pending' | 'running' | 'completed' | 'failed';
|
|
20
|
-
result?: string;
|
|
21
|
-
startedAt?: Date;
|
|
22
|
-
completedAt?: Date;
|
|
23
|
-
}
|
|
24
|
-
export interface BrainDecision {
|
|
25
|
-
action: 'speak' | 'research' | 'execute' | 'clarify' | 'direct_command';
|
|
26
|
-
speech?: string;
|
|
27
|
-
researchQueries?: string[];
|
|
28
|
-
executeTask?: string;
|
|
29
|
-
directCommand?: string;
|
|
30
|
-
reasoning?: string;
|
|
31
|
-
}
|
|
32
|
-
export interface BrainState {
|
|
33
|
-
conversationHistory: ConversationMessage[];
|
|
34
|
-
userGoal: string | null;
|
|
35
|
-
userGoalConfidence: number;
|
|
36
|
-
pendingResearch: ResearchTask[];
|
|
37
|
-
completedResearch: ResearchTask[];
|
|
38
|
-
readyToExecute: boolean;
|
|
39
|
-
executionPlan: string | null;
|
|
40
|
-
}
|
|
41
|
-
export declare class ConversationBrain {
|
|
42
|
-
private llm;
|
|
43
|
-
private state;
|
|
44
|
-
private workingDir;
|
|
45
|
-
private onSpeak;
|
|
46
|
-
private onStateChange;
|
|
47
|
-
constructor(config: {
|
|
48
|
-
workingDir: string;
|
|
49
|
-
onSpeak: (text: string) => Promise<void>;
|
|
50
|
-
onStateChange: (state: string) => Promise<void>;
|
|
51
|
-
});
|
|
52
|
-
/**
|
|
53
|
-
* Process user input and decide what to do
|
|
54
|
-
*/
|
|
55
|
-
processUserInput(input: string): Promise<BrainDecision>;
|
|
56
|
-
/**
|
|
57
|
-
* Receive research results from background agents
|
|
58
|
-
*/
|
|
59
|
-
receiveResearchResult(taskId: string, result: string, success: boolean): void;
|
|
60
|
-
/**
|
|
61
|
-
* Check if we should provide a status update
|
|
62
|
-
*/
|
|
63
|
-
shouldProvideUpdate(): boolean;
|
|
64
|
-
/**
|
|
65
|
-
* Generate a status update based on completed research
|
|
66
|
-
*/
|
|
67
|
-
generateStatusUpdate(): Promise<string | null>;
|
|
68
|
-
/**
|
|
69
|
-
* Get current state for debugging/display
|
|
70
|
-
*/
|
|
71
|
-
getState(): BrainState;
|
|
72
|
-
/**
|
|
73
|
-
* Reset conversation state
|
|
74
|
-
*/
|
|
75
|
-
reset(): void;
|
|
76
|
-
private buildAnalysisPrompt;
|
|
77
|
-
private parseDecision;
|
|
78
|
-
private updateState;
|
|
79
|
-
/**
|
|
80
|
-
* Create research tasks for background agents
|
|
81
|
-
*/
|
|
82
|
-
getPendingResearchTasks(): ResearchTask[];
|
|
83
|
-
/**
|
|
84
|
-
* Mark a research task as running
|
|
85
|
-
*/
|
|
86
|
-
markResearchRunning(taskId: string): void;
|
|
87
|
-
}
|
|
88
|
-
export declare function createConversationBrain(config: {
|
|
89
|
-
workingDir: string;
|
|
90
|
-
onSpeak: (text: string) => Promise<void>;
|
|
91
|
-
onStateChange: (state: string) => Promise<void>;
|
|
92
|
-
}): ConversationBrain;
|