Archipelago — open-source initial import

This commit is contained in:
Archipelago
2026-08-12 10:55:49 +00:00
commit 851a1bc137
2139 changed files with 467510 additions and 0 deletions
@@ -0,0 +1,43 @@
---
name: add-content-type
description: Scaffold a complete new content type (tag, extraction, grid, detail, prompt)
allowed-tools: Bash(*), Read, Edit, Write, Glob, Grep, Agent
---
Add a complete new content type to AIUI. The user will provide the content type name (e.g., "event", "product", "video").
Follow ALL steps — this is the full pipeline for a content type:
1. **Tag format**: Add a new `[[{type}_ext:Field1|Field2|...]]` regex to `packages/app/src/composables/contentExtraction.ts` alongside the existing ones (FILM_EXT_RE, SONG_EXT_RE, etc.)
2. **Type definition**: Add the TypeScript interface to `packages/core/src/types/content.ts` if it doesn't exist
3. **Extraction function**: Add `extractAll{Type}s(text, userQuery)` to `contentExtraction.ts` following the pattern of `extractAllFilms` or `extractAllBooks`
4. **Strip tags function**: Add `strip{Type}Tags()` and include it in `stripContentTags()`
5. **Query classifier**: Add `is{Type}Query()` and optionally `is{Type}LikeResponse()` to `contentFiltering.ts`
6. **ContentTab type**: Add the new tab name to the `ContentTab` union in `contentFiltering.ts`
7. **Tab filtering**: Update `filterTabsByContext()` and `preferredFirstTab()` in `contentFiltering.ts`
8. **Grid component**: Create `packages/app/src/components/content/{Type}Grid.vue` following the glass-morphism pattern of existing grids (BookGrid.vue is a good template)
9. **Detail component**: Create `packages/app/src/components/content/{Type}Detail.vue` following the pattern of BookDetail.vue
10. **Wire into ContentPanel.vue**: Add import, grid render block, detail render block, and panel state refs
11. **Wire into ContentGridView.vue**: Add import, props, and grid render block
12. **Wire into ChatPage.vue**: Pass the new panel data as props to ContentGridView
13. **Wire into useContentPanel.ts**: Add panel ref, selected ref, open/close functions, extraction call in `updatePanelFromText()`
14. **System prompt**: Add tag format instructions to the `SYSTEM_PROMPT` in `useAI.ts`
15. **Tab label**: Add to `TAB_LABELS` in `ContentPanel.vue`
16. **Verify**: Run `pnpm typecheck` and fix any errors
Report what was created and the tag format to use.
+32
View File
@@ -0,0 +1,32 @@
---
name: add-tool
description: Add a new AI tool (function call) to the Claude proxy for the AI to use
allowed-tools: Bash(*), Read, Edit, Write, Glob, Grep
---
Add a new tool that the AI model can call via Claude's tool_use API. The user will describe what the tool should do (e.g., "search local files", "get app status", "browse media").
## Steps
1. **Read the proxy**: Read `packages/app/server/claude-proxy.ts` to understand the existing tool_use loop and `SEARCH_WEB_TOOL` definition.
2. **Define the tool**: Add a new tool definition following the Claude tool_use format:
```ts
const NEW_TOOL = {
name: 'tool_name',
description: 'What this tool does...',
input_schema: {
type: 'object',
properties: { ... },
required: [...]
}
}
```
3. **Add handler**: In the tool_use loop (where `search_web` calls are handled), add a handler for the new tool name.
4. **Implement backend**: If the tool needs a new API endpoint (e.g., `/api/media/scan`), create a Vite plugin or add a route to the proxy.
5. **Update system prompt**: Add instructions in `useAI.ts` SYSTEM_PROMPT telling the AI when and how to use the new tool.
6. **Verify**: Run `pnpm typecheck` and test the proxy starts without errors.
@@ -0,0 +1,37 @@
---
name: audit-prompts
description: Deep audit of AI system prompts — find gaps, test extraction coverage, verify tag formats
allowed-tools: Bash(*), Read, Glob, Grep, Agent
---
Perform a comprehensive audit of AIUI's AI prompt system. Do NOT make changes — report findings only.
## Steps
1. **Read the full system prompt**: Read `packages/app/src/composables/useAI.ts` and reconstruct the complete system prompt including all dynamic sections (persona, Wavlake, memory, web search, Archy context, code context).
2. **Catalog all tag formats**: List every `[[type:...]]` and `[[type_ext:...]]` format defined in the prompt. Cross-reference with regexes in `contentExtraction.ts`.
3. **Check for gaps**: For each content type in `ContentTab` (contentFiltering.ts), verify:
- Is there a tag format in the system prompt?
- Is there a matching extraction regex?
- Is there a query classifier?
- Is there a grid + detail component?
- Is the tab wired in ContentPanel.vue and ContentGridView.vue?
4. **Test extraction coverage**: Read the seed prompts in `src/__tests__/fixtures/seedPrompts.ts`. For each seed, verify:
- Does the extraction function find the expected number of items?
- Are there edge cases that would break extraction?
5. **Analyze prompt quality**: Check for:
- Conflicting instructions
- Missing edge case handling (e.g., "what if the AI can't find a match?")
- Overly vague instructions
- Missing content types that should have tag formats
6. **Check proxy tools**: Read `server/claude-proxy.ts` and verify tool definitions match what the prompt claims.
7. **Report**: Create a structured summary with:
- Content type coverage matrix (tag/extraction/grid/detail/prompt)
- Identified gaps and inconsistencies
- Priority recommendations
+17
View File
@@ -0,0 +1,17 @@
---
name: check
description: Run all quality checks (typecheck, lint, test) and auto-fix errors
allowed-tools: Bash(*), Read, Edit, Glob, Grep, Agent
---
Run all quality checks for the AIUI project and fix any issues found. Execute in order:
1. **TypeScript**: Run `pnpm typecheck`. If errors found, read the failing files and fix the type errors.
2. **Lint**: Run `pnpm lint`. If fixable errors, run `pnpm lint --fix` first, then fix remaining manually.
3. **Tests**: Run `pnpm --filter @aiui/app test -- --run`. For each failure:
- Read the test file and the source file it tests
- Determine if the test is wrong (outdated assertion) or the source has a bug
- Fix whichever is incorrect
4. Report a summary: pass/fail counts, what was fixed.
Important: Do NOT change test expectations just to make them pass — understand WHY they fail first.
+32
View File
@@ -0,0 +1,32 @@
---
name: deploy
description: Build and prepare AIUI for deployment to Archy node
allowed-tools: Bash(*), Read, Edit, Glob, Grep
---
Build AIUI for production deployment. Steps:
1. **Pre-flight checks**:
- `pnpm typecheck` — must pass
- `pnpm lint` — must pass
- `pnpm --filter @aiui/app test -- --run` — report failures but continue
2. **Build**:
- `pnpm build`
- Verify `packages/app/dist/` exists and contains `index.html`
3. **Bundle analysis**:
- Report total dist size and gzip estimate
- List the 5 largest chunks
- Check against 250KB gzipped budget (warn if over)
4. **Verify nginx config**:
- Read `packages/app/server/nginx-archy.conf`
- Verify SPA routing (`try_files $uri $uri/ /aiui/index.html`)
- Verify proxy paths for Claude API
5. **Container build** (if Dockerfile exists):
- `podman build -t aiui:latest packages/app/`
- Report image size
6. **Report**: Build status, bundle size, any warnings.
+33
View File
@@ -0,0 +1,33 @@
---
name: fix-tab
description: Diagnose and fix a broken content panel tab (extraction, routing, rendering)
allowed-tools: Bash(*), Read, Edit, Glob, Grep, Agent
---
Diagnose and fix a broken content panel tab. The user will specify which tab (e.g., "app", "code", "image", "nostr").
## Diagnostic pipeline — check each layer:
1. **System prompt**: Does `useAI.ts` SYSTEM_PROMPT tell the AI to use the tag format for this content type? If not, add instructions.
2. **Tag regex**: Does `contentExtraction.ts` have a regex for this content type's tags? If not, add one.
3. **Extraction function**: Does `extractAll{Type}s()` or `extract{Type}s()` exist and work correctly? Test with sample input.
4. **Query classifier**: Do `is{Type}Query()` and/or `is{Type}LikeResponse()` exist in `contentFiltering.ts`?
5. **Tab filtering**: Is the tab included in `filterTabsByContext()` and `preferredFirstTab()`? Check the boolean flag is wired.
6. **useContentPanel.ts**: Is the extraction called in `updatePanelFromText()`? Is the panel ref populated? Is the tab added to `availableTabs`?
7. **ContentPanel.vue**: Is there a grid render block for `activeTab === '{tab}'`? Are imports present? Is the tab in TAB_LABELS?
8. **ContentGridView.vue**: Same checks for the wide desktop view.
9. **ChatPage.vue**: Are the panel data props passed to ContentGridView?
10. **Grid component**: Does the grid component exist and render correctly?
11. **Detail component**: Does the detail component exist?
Fix each broken layer. Run `pnpm typecheck` after all fixes.
+32
View File
@@ -0,0 +1,32 @@
---
name: mock-archy
description: Enable/configure mock Archy data for standalone dev testing
allowed-tools: Bash(*), Read, Edit, Glob, Grep
---
Set up or modify mock Archy data for testing the Archipelago integration without a real Archy host.
## How it works
Mock data is in `packages/app/src/mocks/archy.ts`. When enabled, `useArchy.ts` loads this data instead of waiting for the Archy bridge.
## Enable mock mode
Two ways:
1. Add `VITE_MOCK_ARCHY=true` to `.env.local`
2. Add `?mockArchy` to the URL: `http://localhost:5173/?mockArchy`
## Customization
The user may ask to:
- Add/remove mock apps from the installed list
- Change wallet balance or channel count
- Add/modify files in the mock file list
- Change system info or network status
- Test specific scenarios (e.g., "node is syncing", "wallet offline", "no files")
Edit `packages/app/src/mocks/archy.ts` accordingly.
## Verify
After changes, check that `buildArchyContext()` in `useArchy.ts` produces the expected system prompt section by reading the function and tracing the mock data through it.
+27
View File
@@ -0,0 +1,27 @@
---
name: new-detail
description: Generate a detail view component following AIUI glass-morphism patterns
allowed-tools: Read, Write, Edit, Glob, Grep
---
Create a new detail view component at `packages/app/src/components/content/{Name}Detail.vue`.
## Requirements
1. **Read a reference**: Read `BookDetail.vue` or `PlaceDetail.vue` as a template.
2. **Follow conventions**:
- `<script setup lang="ts">` with single item prop
- Back button at top (emits 'back' event)
- Hero image/banner area with gradient overlay and fallback
- Title, subtitle, and metadata section
- Description/long text body with proper typography
- Action buttons (external links, share, etc.) with glass-button styling
- Dark/light mode via `useTheme()`
- Smooth scroll, overflow-y-auto
3. **Props**: Accept single item of the content type
4. **Emits**: `back` event for navigation
5. **Responsive**: Full height, works in sidebar and mobile overlay
The user will specify the content type and which fields to display.
+27
View File
@@ -0,0 +1,27 @@
---
name: new-grid
description: Generate a content grid component following AIUI glass-morphism patterns
allowed-tools: Read, Write, Edit, Glob, Grep
---
Create a new content grid component at `packages/app/src/components/content/{Name}Grid.vue`.
## Requirements
1. **Read a reference**: Read `BookGrid.vue` or `PlaceGrid.vue` as a template — they show the standard pattern.
2. **Follow conventions**:
- `<script setup lang="ts">` with props and emits
- Glass morphism styling (bg-white/5, rounded-xl, hover:bg-white/10)
- Dark/light mode support via `useTheme()`
- Search input at top (if the content type has enough items)
- Grid of cards with image fallback, title, subtitle, metadata
- Touch targets min 44x44px
- Empty state message when no items match
- Custom scrollbar class
3. **Props**: Accept array of items + title string
4. **Emits**: `select-{type}` event when a card is clicked
5. **Responsive**: Works on mobile (full width) and desktop (sidebar width)
The user will specify the content type and its fields.
+19
View File
@@ -0,0 +1,19 @@
---
name: overnight
description: Commit, branch, and start the overnight automation loop
disable-model-invocation: true
allowed-tools: Bash(*), Read, Write, Edit, Glob, Grep
---
Prepare and launch the overnight automation loop. Do ALL steps in order, stopping on any failure:
1. Stage and commit all uncommitted changes: `git add -A && git commit -m "chore: pre-overnight snapshot"` (skip if working tree is clean)
2. Push current branch to origin
3. Get today's date as YYYY-MM-DD. Check if `overnight/$DATE` branch exists:
- If yes: `git checkout overnight/$DATE`
- If no: run `./loop/prepare.sh`
4. Verify `loop/plan.md` has unchecked tasks (`grep -c '^\- \[ \]' loop/plan.md`)
5. Commit plan files if modified: `git add loop/plan.md loop/prompt.md && git commit -m "chore: overnight plan $DATE"` (skip if clean)
6. Push: `git push -u origin overnight/$DATE`
7. Start the loop: run `caffeinate -i ./loop/loop.sh` with `run_in_background: true`
8. Report: branch name, number of tasks, and confirm the loop is running in background
@@ -0,0 +1,102 @@
---
name: pwa-icon-cache-fix
description: Use when the user reports a PWA icon not updating, stale PWA icon, wrong icon after install, or any PWA caching issue. Also applies when changing PWA icons in a Vite + vite-plugin-pwa project.
version: 2.0.0
---
# PWA Icon Cache Fix
## Problem
PWA icons are cached at FOUR independent layers:
1. **Service worker cache** (Workbox precache)
2. **Browser HTTP cache**
3. **Browser manifest resources** (Chromium stores resized icons in its profile data, keyed by a permanent extension ID tied to the origin — NEVER re-fetched even after uninstall/reinstall)
4. **macOS .app bundle** (`.icns` file baked into the `.app` in `~/Applications/`)
Query string cache busting (`?v=2`) and uninstall/reinstall do NOT fix this. Chromium reuses the same extension ID for the same origin, so it keeps the old cached icons.
## Fix Steps
### 1. Verify icon files on disk and server are correct
```bash
# Visual check
Read packages/app/public/pwa-192x192.png
Read packages/app/public/pwa-512x512.png
# Hash match check
curl -s http://localhost:5173/pwa-192x192.png | md5
md5 -q packages/app/public/pwa-192x192.png
```
### 2. Find the PWA's Chromium extension ID
Read the installed `.app` bundle's `Info.plist` to get the `CrAppModeShortcutID`:
```bash
plutil -p "~/Applications/Brave Browser Apps.localized/AIUI.app/Contents/Info.plist" | grep CrAppModeShortcutID
```
This returns an ID like `idemibpphagihbobmgmaojhjfidlfpdl`.
### 3. Overwrite the cached icons in browser profile
Chromium stores resized icons at:
`~/Library/Application Support/BraveSoftware/Brave-Browser/Default/Web Applications/Manifest Resources/{ID}/Icons/`
Overwrite every size using `sips`:
```bash
ICON_DIR="~/Library/Application Support/BraveSoftware/Brave-Browser/Default/Web Applications/Manifest Resources/{ID}/Icons"
SRC="packages/app/public/pwa-512x512.png"
for size in 32 48 64 96 128 192 256 512; do
sips -z $size $size "$SRC" --out "${ICON_DIR}/${size}.png"
done
```
### 4. Rebuild the macOS .icns in the .app bundle
```bash
ICONSET="/tmp/aiui.iconset"
mkdir -p "$ICONSET"
SRC="packages/app/public/pwa-512x512.png"
sips -z 16 16 "$SRC" --out "$ICONSET/icon_16x16.png"
sips -z 32 32 "$SRC" --out "$ICONSET/icon_16x16@2x.png"
sips -z 32 32 "$SRC" --out "$ICONSET/icon_32x32.png"
sips -z 64 64 "$SRC" --out "$ICONSET/icon_32x32@2x.png"
sips -z 128 128 "$SRC" --out "$ICONSET/icon_128x128.png"
sips -z 256 256 "$SRC" --out "$ICONSET/icon_128x128@2x.png"
sips -z 256 256 "$SRC" --out "$ICONSET/icon_256x256.png"
sips -z 512 512 "$SRC" --out "$ICONSET/icon_256x256@2x.png"
sips -z 512 512 "$SRC" --out "$ICONSET/icon_512x512.png"
cp "$SRC" "$ICONSET/icon_512x512@2x.png"
iconutil -c icns "$ICONSET" -o "~/Applications/Brave Browser Apps.localized/AIUI.app/Contents/Resources/app.icns"
```
### 5. Flush macOS icon cache
```bash
touch "~/Applications/Brave Browser Apps.localized/AIUI.app"
killall Finder
killall Dock
```
### 6. Bump PWA_CACHE_VERSION in main.ts
Increment the `PWA_CACHE_VERSION` constant — this nukes all SW caches on next page load for web-layer caching.
### 7. Delete stale build artifacts
Remove old `dist/` and `dev-dist/` SW/manifest files.
## Browser-Specific Paths
- **Brave**: `~/Library/Application Support/BraveSoftware/Brave-Browser/Default/Web Applications/`
- **Chrome**: `~/Library/Application Support/Google/Chrome/Default/Web Applications/`
- **PWA apps (Brave)**: `~/Applications/Brave Browser Apps.localized/`
- **PWA apps (Chrome)**: `~/Applications/Chrome Apps.localized/`
## Key Insight
Chromium assigns a permanent extension ID per origin (e.g., `localhost:5173`). This ID persists across uninstall/reinstall. The icon cache in `Manifest Resources/{ID}/Icons/` is populated ONCE and never refreshed from the manifest. The only fix is to overwrite the files directly on disk.
+26
View File
@@ -0,0 +1,26 @@
---
name: test-prompts
description: Test AI prompt quality by simulating queries and checking extraction results
allowed-tools: Bash(*), Read, Edit, Glob, Grep, Agent
---
Test the AIUI AI prompt and content extraction pipeline end-to-end. This skill does NOT call the actual AI — it uses the seed prompts and extraction functions directly.
## Steps
1. **Read seed prompts**: Read `packages/app/src/__tests__/fixtures/seedPrompts.ts` to get all test cases.
2. **Run extraction tests**: For each seed prompt, run the test via `pnpm --filter @aiui/app test -- --run -t "seed"` and report results.
3. **Test edge cases**: Create and test these additional scenarios by calling extraction functions in a test:
- Mixed content response (films + songs + books in one response)
- App recommendation response (should trigger app tab)
- News query with web search results
- Place/restaurant recommendations
- Code response with 3+ code blocks
- Nostr-related query
- Empty/minimal response
4. **Verify tab routing**: For each scenario, check that `filterTabsByContext()` returns the expected tabs in the expected order.
5. **Report**: Summary of what works, what's broken, and what's missing. Include specific test cases that fail.
+28
View File
@@ -0,0 +1,28 @@
---
name: trace
description: End-to-end trace of a query through prompt, extraction, tabs, and rendering
allowed-tools: Bash(*), Read, Glob, Grep, Agent
---
Trace how a specific user query flows through the entire AIUI pipeline. The user will provide a sample query (e.g., "best nostr apps", "recommend some films", "bitcoin news").
## Trace each stage:
1. **Query classifiers**: Run the query through each classifier in `contentFiltering.ts`:
- `isNewsQuery()`, `isMusicQuery()`, `isBookQuery()`, `isTVQuery()`, `isImageQuery()`, `isPlaceQuery()`, `isRecipeQuery()`, `isCodeQuery()`, `isNostrQuery()`, `isAppQuery()`, `isWebsitesQuery()`
- Report which ones return true
2. **Preferred tab**: What does `preferredFirstTab()` return for this query?
3. **System prompt**: What would `buildSystemPrompt()` include? Read `useAI.ts` and trace all dynamic sections.
4. **Expected AI response**: Based on the system prompt instructions, what tags would the AI likely use? Construct a realistic sample response.
5. **Extraction**: Run the sample response through each extraction function and report what gets found:
- `extractAllFilms()`, `extractAllSongs()`, `extractAllPodcasts()`, `extractAllBooks()`, `extractAllTVSeries()`, `extractAllImages()`, `extractAllPlaces()`, `extractApps()`, `extractCodeBlocks()`, `extractRecipes()`
6. **Tab filtering**: What tabs would `filterTabsByContext()` return? In what order?
7. **Rendering**: Which grid component would render? Trace through ContentPanel.vue and/or ContentGridView.vue.
8. **Report**: Complete flow diagram showing: Query -> Classifiers -> Prompt -> Expected Response -> Extraction -> Tabs -> Grid