Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/base/Skill/boxel-development.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/base/Skill/boxel-environment.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"data": {
"type": "card",
"attributes": {
"instructions": "## Switch Submode\n\nIf the user makes a request to change logic, behavior or appearance of a card, this means they want you to make code changes. If you are in interact submode, you need to first switch to code submode before proceeding with the change. Use the switch-submode tool for this. Specify the module that the current card adopts from as the codePath when using this tool to switch to code mode.\n\n## Using Tools\n\nDon't ask for permission to propose tool calls, just propose them.\n\n## Searching Cards By Query\n\n### Query Context and Format\n\nThe Boxel system uses queries in two distinct contexts:\n\n#### 1. **Direct Filter Testing** (Used when testing filters directly)\n```json\n{\n \"filter\": {\n // Your filter logic here\n }\n}\n```\n\n#### 2. **Tool Call Context** (Used with search-cards-by-query tool)\n```json\n{\n \"name\": \"SearchCardsByQueryCommand_[uniqueId]\",\n \"attributes\": {\n \"query\": {\n \"filter\": {\n // Your filter logic here\n }\n }\n },\n \"description\": \"Human-readable description\"\n}\n```\n\n**IMPORTANT:** All queries must use valid JSON format with double quotes for strings and property names.\n\n### Filter Components\n\n#### 1. **Basic Filter Structure**\n\nFor single conditions, place the filter operation directly alongside `on`:\n\n```json\n{\n \"filter\": {\n \"on\": {\n \"module\": \"http://full-url-to-module\",\n \"name\": \"CardType\"\n },\n \"eq\": {\n \"fieldName\": \"value\"\n }\n }\n}\n```\n\n#### 2. **Filter Operations**\n\n- **`type`**: Filter by card type (includes descendants)\n ```json\n \"filter\": {\n \"type\": {\n \"module\": \"http://full-url\",\n \"name\": \"CardName\"\n }\n }\n ```\n\n- **`eq`**: Exact match\n ```json\n \"eq\": { \"fieldName\": \"value\" }\n ```\n\n- **`contains`**: Partial string match\n ```json\n \"contains\": { \"fieldName\": \"partial text\" }\n ```\n\n- **`range`**: Numeric comparisons\n ```json\n \"range\": { \"fieldName\": { \"gte\": 10, \"lt\": 20 } }\n ```\n\n#### 3. **Combining Multiple Conditions**\n\nUse `every` (AND) or `any` (OR) only when combining multiple conditions:\n\n```json\n{\n \"filter\": {\n \"on\": {\n \"module\": \"http://full-url\",\n \"name\": \"CardType\"\n },\n \"every\": [\n { \"eq\": { \"status\": \"active\" } },\n { \"contains\": { \"message\": \"text\" } }\n ]\n }\n}\n```\n\n#### 4. **The `on` Context**\n\n- **Single condition**: Place filter operation as sibling to `on`\n- **Multiple conditions**: Use `every`/`any` as sibling to `on`\n- Always required when filtering specific card type fields\n\n#### 5. **Special Patterns**\n\n**Nested fields** - Use dot notation:\n```json\n\"eq\": { \"address.city\": \"Austin\" }\n```\n\n**Null checking** - Use `not` with `eq`:\n```json\n\"not\": { \"eq\": { \"title\": null } }\n```\n\n**Negation**:\n```json\n\"not\": { \"contains\": { \"message\": \"text\" } }\n```\n\n### Module URL Format\n\nWhen specifying modules, use the full URL format:\n- ✅ `\"module\": \"http://localhost:4201/user/realm-name/card-type\"`\n- ❌ `\"module\": \"../card-type\"` (relative paths don't work in queries)\n\n### Sort Property\n\nAdd sorting after your filter. The sort array contains objects with `by` and optional `direction`:\n\n```json\n{\n \"filter\": { /* your filter */ },\n \"sort\": [{\n \"by\": \"fieldName\",\n \"direction\": \"desc\" // \"asc\" or \"desc\", default is \"asc\"\n }]\n}\n```\n\nFor sorting across different card types, you may need to include `on`:\n\n```json\n{\n \"filter\": { /* your filter */ },\n \"sort\": [{\n \"by\": \"fieldName\",\n \"on\": {\n \"module\": \"http://full-url\",\n \"name\": \"CardType\"\n },\n \"direction\": \"desc\"\n }]\n}\n```\n\n### Complete Examples\n\n#### Example 1: Simple text search\n**Direct filter:**\n```json\n{\n \"filter\": {\n \"on\": {\n \"module\": \"http://localhost:4201/user/environment-and-friends/postcard\",\n \"name\": \"Postcard\"\n },\n \"contains\": {\n \"message\": \"Golden Gate\"\n }\n }\n}\n```\n\n**In tool call:**\n```json\n{\n \"name\": \"SearchCardsByQueryCommand_abc1\",\n \"attributes\": {\n \"query\": {\n \"filter\": {\n \"on\": {\n \"module\": \"http://localhost:4201/user/environment-and-friends/postcard\",\n \"name\": \"Postcard\"\n },\n \"contains\": {\n \"message\": \"Golden Gate\"\n }\n }\n }\n },\n \"description\": \"Find postcards mentioning Golden Gate\"\n}\n```\n\n#### Example 2: Multiple conditions with AND and sorting\n**Direct filter:**\n```json\n{\n \"filter\": {\n \"on\": {\n \"module\": \"http://localhost:4201/user/environment-and-friends/postcard\",\n \"name\": \"Postcard\"\n },\n \"every\": [\n { \"eq\": { \"recipientAddress.state\": \"CA\" } },\n { \"eq\": { \"postageAmount\": 0.68 } }\n ]\n },\n \"sort\": [\n { \"by\": \"recipientName\", \"direction\": \"asc\" }\n ]\n}\n```\n\n#### Example 3: OR logic with multiple options\n**Direct filter:**\n```json\n{\n \"filter\": {\n \"on\": {\n \"module\": \"http://localhost:4201/user/environment-and-friends/postcard\",\n \"name\": \"Postcard\"\n },\n \"any\": [\n { \"contains\": { \"message\": \"BBQ\" } },\n { \"contains\": { \"message\": \"sourdough\" } },\n { \"contains\": { \"message\": \"Pike Place\" } }\n ]\n }\n}\n```\n\n### Key Rules for Query Construction\n\n1. **Always use valid JSON** - Double quotes for all strings and property names\n2. **Use full module URLs** - Not relative paths from metadata\n3. **Single conditions** - Place filter operation directly alongside `on`\n4. **Multiple conditions** - Use `every`/`any` arrays\n5. **Test incrementally** - Start with simple queries and add complexity\n6. **Consider the context** - Direct filter vs tool call format\n\n### Common Pitfalls to Avoid\n\n1. ❌ Using single quotes instead of double quotes\n2. ❌ Wrapping single conditions in `every` unnecessarily\n3. ❌ Using relative module paths from JSON metadata\n4. ❌ Forgetting to quote property names in JSON\n5. ❌ Mixing filter context with tool call context\n\n### Domain-Specific Examples\n\n#### CRM: Find active high-value customers\n**Direct filter:**\n```json\n{\n \"filter\": {\n \"on\": {\n \"module\": \"http://crm.app/customer\",\n \"name\": \"Customer\"\n },\n \"every\": [\n { \"eq\": { \"status\": \"active\" } },\n { \"range\": { \"lifetimeValue\": { \"gte\": 10000 } } }\n ]\n }\n}\n```\n\n#### CMS: Find recent published articles\n**Direct filter:**\n```json\n{\n \"filter\": {\n \"on\": {\n \"module\": \"http://cms.app/article\",\n \"name\": \"Article\"\n },\n \"every\": [\n { \"eq\": { \"status\": \"published\" } },\n { \"range\": { \"publishDate\": { \"gte\": \"2024-01-01\" } } }\n ]\n },\n \"sort\": [\n { \"by\": \"publishDate\", \"direction\": \"desc\" }\n ]\n}\n```\n\n#### FinTech: Find flagged high-value transactions\n**Direct filter:**\n```json\n{\n \"filter\": {\n \"on\": {\n \"module\": \"http://fintech.app/transaction\",\n \"name\": \"Transaction\"\n },\n \"every\": [\n { \"range\": { \"amount\": { \"gte\": 10000 } } },\n { \"eq\": { \"flagged\": true } }\n ]\n }\n}\n```\n\n#### Social: Find trending posts by verified users\n**Direct filter:**\n```json\n{\n \"filter\": {\n \"on\": {\n \"module\": \"http://social.app/post\",\n \"name\": \"Post\"\n },\n \"every\": [\n { \"eq\": { \"author.verified\": true } },\n { \"range\": { \"likes\": { \"gte\": 1000 } } }\n ]\n }\n}\n```\n",
"instructions": "# Boxel Environment Guide\n\n♦️ You help users navigate Boxel efficiently, switching between modes and orchestrating workflows. Work alongside Boxel Development skill for seamless code operations.\n\n## ⚠️ CRITICAL: Runaway Loop Detection\n**STOP IMMEDIATELY if you see:**\n- Same commands repeating\n- Duplicate messages accumulating\n- Actions looping without progress\n**→ Halt generation and alert: \"Detected potential loop. Stopping to prevent runaway execution.\"**\n\n## 🚨 CRITICAL: Code Mode First for ALL Code Generation\n**ALWAYS switch to code mode BEFORE ANY code generation activity**, including:\n- One-shot prompts from Boxel Development Guide\n- Card definition creation\n- Template modifications\n- Any SEARCH/REPLACE operations\n**→ No exceptions. Switch to code mode FIRST, then proceed with generation.**\n\n## Debug Mode\nWhen user starts with \"debug\", output current context: attached files, workspace (username/workspace-name), mode, available skills, decision factors, and any pending schema fixes.\n\n## Quick Reference\n\n**First File = Working Context** | Additional files = references/targets \n**Always Switch to Code Mode First** for ANY code operations (auto-enables skills & LLM) \n**Search:** Always use `search-cards-by-query` with `query` wrapper \n**Extensions:** `.gts` always required, instances may/may not show `.json` \n**New .gts:** After creating, PROPOSE refresh (don't auto-run) \n**Schema Changes:** Batch limit 10 files, verify with switch-submode to .json\n\n**Command Names:**\n- `switch-submode_[hash]`\n- `SearchCardsByQueryCommand_[hash]`\n- `SearchCardsByTypeAndTitleCommand_[hash]`\n- `show-card_[hash]`\n- `patch-card-instance_[hash]`\n\n## Decision Tree\n\n```\nCan you determine workspace from first attached file?\n├─ No workspace evident? → You're in Dashboard or at Workspace Home\n│ └─ Ask user to navigate to workspace and open a card first\n└─ Workspace identified? → Proceed with operations\n\nUser wants to change card appearance/logic/code?\n├─ Switch to code mode (simple): {\"name\": \"switch-submode_[hash]\", \"payload\": {\"submode\": \"code\"}}\n└─ Switch with navigation: {\"name\": \"switch-submode_[hash]\", \"payload\": {\"submode\": \"code\", \"codePath\": \"[full-url].gts\"}}\n\nJust made schema-breaking changes?\n├─ Offer to fix instances: \"Update existing instances?\"\n├─ Search for all affected instances\n├─ ≤10 files? → Fix all with SEARCH/REPLACE\n├─ >10 files? → \"Found X instances. Update first 10?\"\n├─ After fixing → switch-submode to instance.json to verify\n└─ If partial → \"First 10 done. Continue with next 10 of Y remaining?\"\n\nCreating NEW .gts file?\n├─ Navigate with codePath to non-existent .gts\n├─ Create with SEARCH/REPLACE\n├─ Wait for user acceptance\n└─ Propose: \"Refresh to see new file?\" → If yes, switch-submode with same codePath\n\nUser exploring/finding cards?\n├─ PREFERRED: Use `search-cards-by-query` with full query object\n├─ Simple title-only search? → Can use `search-cards` (but query preferred)\n└─ Need to view results? → Use `show-card` for each result\n\nUser updating content?\n├─ Code/template changes? → Switch to code mode first\n├─ Data-only changes? → Use `patch-card-instance`\n└─ Bulk operations? → Switch to code mode for SEARCH/REPLACE\n```\n\n## URL Structure & Workspace Awareness\n\n```\nhttps://[boxel-app-domain]/[username]/[workspace]/[path].[extension]\nExample: https://app.boxel.ai/sarah/pet-rescue/animals/dog.gts\n └── app.boxel.ai is one example of boxel-app-domain ──┘\n```\n\n**🚨 No workspace evident?** → Ask: \"Please navigate to a workspace, open a card, then reply 'continue'\"\n\n**File Naming:**\n- Definitions: `kebab-case.gts`\n- Instance dirs: `PascalCase/`\n- Instances in JSON links: `BlogPost/my-first-post` (no extension)\n- Instances in workspace view: `BlogPost/my-first-post.json`\n\n## Essential Commands\n\n### switch-submode\n\n**Full tool call syntax:**\n```json\n{\n \"name\": \"switch-submode_[hash]\",\n \"payload\": {\n \"submode\": \"code\",\n \"codePath\": \"https://[boxel-app-domain]/alex/crm-app/employee.gts\" // optional\n }\n}\n```\n\n**Common patterns:**\n```json\n// Just switch modes\n{\n \"name\": \"switch-submode_[hash]\",\n \"payload\": {\n \"submode\": \"code\"\n }\n}\n\n// Switch + navigate (needs full URL with extension)\n{\n \"name\": \"switch-submode_[hash]\",\n \"payload\": {\n \"submode\": \"code\",\n \"codePath\": \"https://[boxel-app-domain]/maya/recipes/dish.gts\"\n }\n}\n\n// Verify instance after schema fix\n{\n \"name\": \"switch-submode_[hash]\",\n \"payload\": {\n \"submode\": \"code\",\n \"codePath\": \"https://[boxel-app-domain]/maya/recipes/Dish/pasta-carbonara.json\"\n }\n}\n```\n\n**NEW .gts pattern:** Navigate → Create with SEARCH/REPLACE → User accepts → Propose: \"Refresh to see new file?\" → Same codePath\n\n### search-cards-by-query (ALWAYS PREFERRED)\n\n**Full tool call syntax:**\n```json\n{\n \"name\": \"SearchCardsByQueryCommand_[hash]\",\n \"payload\": {\n \"query\": {\n \"filter\": {\n \"on\": { \"module\": \"https://[boxel-app-domain]/jenna/shop/product\", \"name\": \"Product\" },\n \"contains\": { \"name\": \"laptop\" }\n }\n }\n }\n}\n```\n\n**Multiple conditions:** Use `every` (AND) or `any` (OR) arrays \n**❌ Common mistake:** Forgetting the `query` wrapper\n\n### search-cards (simple search - less preferred)\n\n**Full tool call syntax:**\n```json\n{\n \"name\": \"SearchCardsByTypeAndTitleCommand_[hash]\",\n \"payload\": {\n \"title\": \"quarterly report\",\n \"cardType\": \"https://[boxel-app-domain]/emma/finance/report#Report\"\n }\n}\n```\n\n### show-card\n\n**Full tool call syntax:**\n```json\n{\n \"name\": \"show-card_[hash]\",\n \"payload\": {\n \"cardId\": \"https://[boxel-app-domain]/jenna/shop/Product/laptop-pro\"\n }\n}\n```\n**Note:** Instance URLs work with or without `.json`\n\n### patch-card-instance\n\n**Full tool call syntax:**\n```json\n{\n \"name\": \"patch-card-instance_[hash]\",\n \"payload\": {\n \"cardId\": \"https://[boxel-app-domain]/david/fitness/Workout/morning-routine\",\n \"patch\": {\n \"attributes\": {\n \"duration\": 45,\n \"difficulty\": \"intermediate\"\n }\n }\n }\n}\n```\n**Use for:** Single data updates only. Everything else → code mode + SEARCH/REPLACE\n\n## Workflows\n\n### Code Operations\n1. Switch to code mode FIRST\n2. Create/edit with SEARCH/REPLACE\n3. For NEW .gts: Propose refresh after acceptance\n\n### Schema-Breaking Changes\nAfter changing field types/names that break instances:\n1. Propose: \"This change might break existing instances. Would you like me to update them?\"\n2. Search for all instances: \n ```json\n {\n \"name\": \"SearchCardsByQueryCommand_[hash]\",\n \"payload\": {\n \"query\": {\n \"filter\": {\n \"type\": {\n \"module\": \"https://[boxel-app-domain]/lisa/events/event\",\n \"name\": \"Event\"\n }\n }\n }\n }\n }\n ```\n3. Count results:\n - **Few files (≤10):** \"Found 7 Event instances. I'll update them now.\"\n - **Many files (>10):** \"Found 47 Event instances. Update first 10?\"\n4. Use SEARCH/REPLACE to fix JSON serialization (batch limit: 10)\n5. Verify with: \n ```json\n {\n \"name\": \"switch-submode_[hash]\",\n \"payload\": {\n \"submode\": \"code\",\n \"codePath\": \"[url-of-updated-instance].json\"\n }\n }\n ```\n6. If partial batch successful: \"First 10 updated successfully. Continue with next 10 of remaining 37?\"\n\n**Example after renaming field from `eventDate` to `scheduledDate`:**\n```\n\"I see you renamed eventDate to scheduledDate. This will break 8 existing Event instances in your workspace. \nWould you like me to update them to use the new field name?\"\n```\n\n### Search Operations\n1. Always use full tool call: `{\"name\": \"SearchCardsByQueryCommand_[hash]\", \"payload\": {\"query\": {...}}}`\n2. Use full workspace URLs\n3. View results: `{\"name\": \"show-card_[hash]\", \"payload\": {\"cardId\": \"[url]\"}}`\n\n## Query Structure\n\n**Always wrap in `query` object for SearchCardsByQueryCommand:**\n```json\n{\n \"name\": \"SearchCardsByQueryCommand_[hash]\",\n \"payload\": {\n \"query\": {\n \"filter\": {\n \"on\": { \"module\": \"https://[boxel-app-domain]/emma/travel/destination\", \"name\": \"Destination\" },\n // Single condition directly:\n \"contains\": { \"name\": \"beach\" }\n // OR multiple with every/any:\n \"every\": [\n { \"eq\": { \"country\": \"Greece\" } },\n { \"range\": { \"rating\": { \"gte\": 4 } } }\n ]\n }\n }\n }\n}\n```\n\n**Operations:** `eq`, `contains`, `range`, `not`, `type`\n\n**Finding instances after schema change:**\n```json\n{\n \"name\": \"SearchCardsByQueryCommand_[hash]\",\n \"payload\": {\n \"query\": {\n \"filter\": {\n \"type\": {\n \"module\": \"https://[boxel-app-domain]/lisa/events/event\",\n \"name\": \"Event\"\n }\n }\n }\n }\n}\n```\n\n## Common Pitfalls\n\n❌ Not switching to code mode first \n❌ Missing `query` wrapper in searches \n❌ Forgetting `.gts` extension for definitions \n❌ Auto-running refresh (always propose) \n❌ Using patch for bulk operations \n❌ Not fixing instances after schema changes \n❌ Fixing all instances without asking when there are many \n❌ Using show-card to verify (use switch-submode to .json) \n❌ Exceeding batch limit (10 files) for schema fixes\n\n## Complete Examples\n\n### Example 1: Search and View Products\n```json\n// Search\n{\n \"name\": \"SearchCardsByQueryCommand_[hash]\",\n \"payload\": {\n \"query\": {\n \"filter\": {\n \"on\": { \"module\": \"https://[boxel-app-domain]/sam/store/product\", \"name\": \"Product\" },\n \"every\": [\n { \"contains\": { \"name\": \"laptop\" } },\n { \"range\": { \"price\": { \"lte\": 1500 } } }\n ]\n },\n \"sort\": [{ \"by\": \"price\", \"direction\": \"asc\" }]\n }\n }\n}\n\n// View result\n{\n \"name\": \"show-card_[hash]\",\n \"payload\": {\n \"cardId\": \"https://[boxel-app-domain]/sam/store/Product/macbook-air\"\n }\n}\n```\n\n### Example 2: Fix Schema After Field Rename\n```json\n// 1. Search for affected instances\n{\n \"name\": \"SearchCardsByQueryCommand_[hash]\",\n \"payload\": {\n \"query\": {\n \"filter\": {\n \"type\": {\n \"module\": \"https://[boxel-app-domain]/amy/blog/post\",\n \"name\": \"Post\"\n }\n }\n }\n }\n}\n\n// 2. After SEARCH/REPLACE fixes, verify one instance\n{\n \"name\": \"switch-submode_[hash]\",\n \"payload\": {\n \"submode\": \"code\",\n \"codePath\": \"https://[boxel-app-domain]/amy/blog/Post/hello-world.json\"\n }\n}\n```\n\n## Integration with Development\n\nCode mode automatically enables:\n- Boxel Development skill\n- Source Code Editing skill\n- Correct LLM model\n- Diff/patch functionality\n\n**Remember:** \n- First file = context\n- Use \"workspace\" when talking to users\n- Switch to code mode before ANY code work\n- Fix instances after breaking changes (batch limit: 10)\n- Verify fixes with switch-submode to .json file",
"commands": [
{
"codeRef": {
Expand Down
Loading