Archipelago — open-source initial import

This commit is contained in:
Archipelago
2026-08-12 10:55:49 +00:00
commit e3bcd9fca9
2056 changed files with 468069 additions and 0 deletions
@@ -0,0 +1,160 @@
# Plan: Overhaul Content Detection + Add Apps Tab
## Context
The content surfacing system misses many common AI response patterns. Example: AI responds about Nostr (mentioning damus.io, primal.net, snort.social) but the Nostr tab never surfaces. Query/response classifiers use narrow regexes that miss natural language variations. There's no "topic detection" layer, no app detection, and bare domains in AI text aren't extracted as websites.
**Goals:**
1. Fix content detection to handle how AIs actually respond
2. Add Nostr tab surfacing (currently only via `/nostr` command)
3. Add Apps tab with curated Nostr + Bitcoin ecosystem apps (local DB + AI extraction fallback)
4. Extract bare domains from AI text (e.g. "check out damus.io")
---
## Part 1: Expand Query & Response Classifiers
**File:** `packages/app/src/composables/contentFiltering.ts`
### 1A. Add Nostr classifiers (new functions)
- `isNostrQuery(q)` — matches: nostr, npub, nip-\d, damus, primal, snort, amethyst, coracle, zap, relay, note1, nevent, nprofile, fiatjaf, nostrich, "decentralized social"
- `isNostrLikeResponse(text)` — requires literal "nostr" OR 2+ Nostr-specific signals (npub, nip-, client names, relay+wss, zap+lightning)
### 1B. Add App classifiers (new functions)
- `isAppQuery(q)` — matches: app, client, wallet, tool, software, download, install, "what app", "best app for", "recommend.*app"
- `isAppLikeResponse(text)` — matches: "you can use", "popular clients include", "I'd recommend", "available on", "download from"
### 1C. Expand existing classifiers with broader patterns
| Classifier | Add these patterns |
|---|---|
| `isNewsQuery` | "what happened today", "any updates on", "trending", "catch me up", "brief me", "current events" |
| `isMusicQuery` | "genre", "spotify", "bandcamp", "grammys", "billboard", "mixtape", "discography", "banger", "favorite jam" |
| `isBookQuery` | "what should I read", "favorite reads", "reading list", "book club", "memoir", "audiobook", "goodreads", "worth reading" |
| `isTVQuery` | "what's good on netflix", "anything to binge", "hbo", "disney+", "apple tv", "amazon prime", "docuseries", "limited series" |
| `isPlaceQuery` | "hungry", "food near me", "best brunch spot", "happy hour", "speakeasy", "rooftop bar", "food truck" |
| `isWebsitesQuery` | "point me to", "link me", "any good sites", "tools for", "platforms for" |
| `isWebsitesLikeResponse` | "here are some resources", "I'd recommend checking", "you can visit", "useful resources" |
| `isNewsLikeResponse` | "I can't access the web but", "having trouble reaching", "unable to browse but" |
### 1D. Update `preferredFirstTab()` — add nostr + app checks
### 1E. Update `filterTabsByContext()` — add `hasNostr` and `hasApps` params, integrate into tab ordering
---
## Part 2: Bare Domain Extraction
**File:** `packages/app/src/composables/contentExtraction.ts`
Add `extractBareDomainLinks(text)`:
- Detect plain-text domains like "damus.io", "primal.net" not inside markdown links or bold patterns
- Skip positions covered by existing extractors (markdown links, bold-domain, full URLs)
- Require known TLDs (.com, .org, .io, .net, .social, .app, etc.)
- Block file extensions (.js, .ts, .vue, .json, .css)
- Use existing `normUrl()` for dedup
---
## Part 3: Apps Tab — Curated Database + AI Extraction
### 3A. Create app database
**New file:** `packages/app/src/data/apps.ts`
```ts
interface AppEntry {
id: string
name: string
description: string // One-liner
longDescription: string // Why use this, how it works
category: 'nostr-client' | 'lightning-wallet' | 'bitcoin-wallet' | 'privacy' | 'node' | 'dev-tool' | 'relay'
platforms: ('ios' | 'android' | 'web' | 'desktop' | 'cli' | 'nodeos')[]
url: string
icon?: string
keywords: string[] // For matching AI responses
howTo?: string[] // Getting started steps
relatedApps?: string[] // IDs of related apps
}
```
**Initial curated apps (~25-30):**
- Nostr clients: Damus, Primal, Snort, Amethyst, Coracle, Iris, Nostrudel, nos.social
- Lightning wallets: Phoenix, Mutiny, Breez, Zeus, Alby, Wallet of Satoshi
- Bitcoin wallets: Sparrow, Blue Wallet, Nunchuk, Coldcard, Green
- Privacy tools: Tor, SimpleX Chat, Signal, Mullvad VPN
- Node software: Start9, Umbrel, RaspiBlitz, myNode
- Dev tools: NDK, nostr-tools, Nak
### 3B. Add app extraction
**File:** `packages/app/src/composables/contentExtraction.ts`
Add `extractApps(text, userQuery)`:
1. Match AI text against known app names/keywords from database
2. If app query detected OR 2+ known apps mentioned → return matched apps
3. For unknown apps, create basic entries from context (name + URL if bare domain found)
### 3C. Create UI components
**New files:**
- `packages/app/src/components/content/AppsGrid.vue` — Grid of app cards (icon, name, category badge, one-liner)
- `packages/app/src/components/content/AppDetail.vue` — Detail: icon, name, platforms, long description, how-to steps, link, related apps
Follow existing grid/detail patterns (e.g. `BookGrid.vue`/`BookDetail.vue`).
### 3D. Register in ContentPanel.vue
Add rendering for `activeTab === 'app'`, add `'app'` to `ContentTab` type.
---
## Part 4: Wire Everything Together
**File:** `packages/app/src/composables/useContentPanel.ts`
In `updatePanelFromText()`:
- Call `extractBareDomainLinks(text)`, merge with website sources
- Call `extractApps(text, userQuery)`
- Compute `hasNostr = isNostrQuery(userQuery) || isNostrLikeResponse(text)`
- Compute `hasApps = apps.length > 0`
- Pass `hasNostr` and `hasApps` to `filterTabsByContext()`
- Add `panelApps` ref, title logic for apps/nostr tabs
Same changes in `getContextualInlineContent()`.
Broaden magazine detection: add tech/protocol keywords, surface magazine for 3+ sections with no other structured content.
---
## Part 5: PromptIndex badges
**File:** `packages/app/src/components/chat/PromptIndex.vue`
Add 'Nostr' and 'Apps' badge detection.
---
## Implementation Order
1. `contentFiltering.ts` — classifiers + filterTabsByContext signature
2. `contentExtraction.ts``extractBareDomainLinks()` + `extractApps()`
3. `data/apps.ts` — curated app database
4. `useContentPanel.ts` — wire everything
5. `AppsGrid.vue` + `AppDetail.vue` — UI components
6. `ContentPanel.vue` — register tab + components
7. `PromptIndex.vue` — badges
8. Typecheck + manual test
## Verification
1. `pnpm typecheck` passes
2. "tell me about Nostr" → Nostr + magazine tabs surface
3. "best Nostr clients?" → Apps tab with Damus, Primal, Snort
4. "recommend a bitcoin wallet" → Apps tab with Phoenix, Sparrow
5. "what happened with BIP 110?" → Magazine tab (regression)
6. "best movies of 2024" → Films tab (regression)
7. Bare domains in AI text extracted as websites
8. PromptIndex badges show Nostr/Apps
@@ -0,0 +1,74 @@
# Plan: Code Mode UI — Orange Input, Design System Context, File Browser Context
## Context
The user wants three connected features that enhance the coding experience in AIUI:
1. Visual indication when in code mode (orange input container, "Code" label)
2. Ability to select design system items as coding context
3. Ability to select files from file browser as coding context
After this, the user wants to circle back and create a flawless version of content extraction/tab surfacing.
## Changes
### 1. Orange Code Mode Input Container
**Files**: `ChatWindow.vue`, `ChatInput.vue`
**ChatWindow.vue** (line 106-115):
- Pass `activeTab` to ChatInput as a prop: `:active-tab="activeTab"`
- Change placeholder logic: `activeTab === 'code' ? 'Code...' : isStreaming ? 'Waiting for response...' : 'Message AIUI...'`
**ChatInput.vue**:
- Add `activeTab` prop (optional string, default `''`)
- Conditionally style the container div (line 79-81):
- When `activeTab === 'code'`: use `bg-accent/15 border border-accent/25 backdrop-blur-xl` instead of `path-glass-bubble`
- Keep the `rounded-2xl px-4 py-3 flex items-end gap-2 transition-all duration-300` classes
- Conditionally style the send button orange when in code mode
### 2. Design System Item Selection for Coding Context
**Files**: `useCodeContext.ts`, `DesignSystemGrid.vue`
**useCodeContext.ts**:
- Add `selectedDesignTokens: ref<string[]>([])` to module state (stores item IDs)
- Add `toggleDesignToken(id)` — adds/removes from selection array
- Add `clearDesignTokens()` — clears selection
- Add `isDesignTokenSelected(id)` — checks if item is in selection
- Clear on `exitCodeMode()`
- Export all new state/actions
**DesignSystemGrid.vue**:
- Import `useCodeContext`
- When `codeMode` is true, show a selection indicator (accent ring + checkmark) on items
- `selectItem` should call `toggleDesignToken(item.id)` when in code mode (instead of `openDesignSystemItem`)
- When NOT in code mode, keep existing behavior (open detail view)
- Selected items get `ring-2 ring-accent/50 bg-accent/10` styling
### 3. File Browser Selection for Coding Context
**Files**: `useCodeContext.ts`, `ProjectGrid.vue`
**useCodeContext.ts**:
- Add `selectedFiles: ref<string[]>([])` — paths of files selected for context
- Add `toggleFileSelection(path)` — adds/removes from selection
- Add `clearFileSelection()` — clears all
- Add `isFileSelected(path)` — checks if file in selection
- Clear on `exitCodeMode()`
- Export new state/actions
**ProjectGrid.vue**:
- Import `useCodeContext`
- When `codeMode` is true, file clicks toggle selection instead of (or in addition to) opening
- Show visual selection state (accent highlight/checkmark) on selected files in FileTreeNode
## Files to Modify
1. `packages/app/src/components/chat/ChatWindow.vue` — pass activeTab prop
2. `packages/app/src/components/chat/ChatInput.vue` — conditional orange styling + "Code" placeholder
3. `packages/app/src/composables/useCodeContext.ts` — add design token + file selection state
4. `packages/app/src/components/content/DesignSystemGrid.vue` — toggle selection in code mode
5. `packages/app/src/components/content/ProjectGrid.vue` — toggle file selection in code mode
## Verification
1. `pnpm typecheck` — no type errors
2. `pnpm lint` — no new lint errors
3. Manual: `/code` command → input turns orange with "Code..." placeholder
4. Manual: In code mode, design system tab → clicking items toggles selection (accent ring)
5. Manual: In code mode, file browser → clicking files toggles selection
6. Manual: Exiting code mode clears all selections