Skip to content
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 4 additions & 2 deletions docs/search.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,12 @@ let { data: matching } = await indexer.search({
The Query object may have a `page` property, which controls pagination of search results. This allows you to retrieve results in smaller chunks for better performance and user experience.

The `page` object has the following properties:

- `number`: The page number (0-based indexing)
- `size`: The number of results per page. If not provided, there is no default size and will just behave like a regular search.
- `size`: The number of results per page. If not provided, there is no default size and will just behave like a regular search.

The search response includes a `meta` object with pagination information:

- `meta.page.total`: The total number of results across all pages

#### Examples
Expand Down Expand Up @@ -186,7 +188,7 @@ let { data: matching, meta } = await indexer.search({
},
sort: [
{
by: 'title',
by: 'cardTitle',
on: { module: `https://my.realm/article`, name: 'Article' },
direction: 'asc',
},
Expand Down
6 changes: 3 additions & 3 deletions packages/base/Skill/boxel-development.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions packages/base/Skill/boxel-environment.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@
"requiresApproval": false
}
],
"title": "Boxel Environment",
"description": "Help users navigate Boxel efficiently, switching between modes and orchestrating workflows",
"thumbnailURL": null
"cardTitle": "Boxel Environment",
"cardDescription": "Help users navigate Boxel efficiently, switching between modes and orchestrating workflows",
"cardThumbnailURL": null
},
"meta": {
"adoptsFrom": {
Expand Down
6 changes: 3 additions & 3 deletions packages/base/Skill/catalog-listing.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
"requiresApproval": false
}
],
"title": "Catalog Listing",
"description": null,
"thumbnailURL": null
"cardTitle": "Catalog Listing",
"cardDescription": null,
"cardThumbnailURL": null
},
"meta": {
"adoptsFrom": {
Expand Down
6 changes: 3 additions & 3 deletions packages/base/Skill/source-code-editing.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"attributes": {
"instructions": "# Source Code Editing\n\nWhen you infer that the user wants to make changes to the attached files, which is usually a card definition, or create new files, you must use a SEARCH/REPLACE block.\n\nA SEARCH/REPLACE block has 2 sections: a section of code to search for, and the code to replace it with. All code within the SEARCH will be replaced. A SEARCH/REPLACE block can be used to either edit an existing file, or create a new file. \n\nThis is ABSOLUTELY CRUCIAL, WITHOUT THIS THE CODE PATCH WON'T WORK: in the beginning of the code block, before ╔═══ SEARCH ════╗ marker, add a line with the file url. If you are editing, this should be the attached file's url. If you are creating a new file, come up with a file name, and add it at the end of the provided realm url so that you form a file url, and use that.\n\nExample adding an import:\n\n```gts\nhttps://example.com/attached-file-example.gts\n╔═══ SEARCH ════╗\nimport { Component } from 'https://cardstack.com/base/card-api';\nimport { or } from '@cardstack/boxel-ui/helpers';\n╠═══════════════╣\nimport { Component } from 'https://cardstack.com/base/card-api';\nimport { MarkdownField } from 'https://cardstack.com/base/markdown';\nimport { or } from '@cardstack/boxel-ui/helpers';\n╚═══ REPLACE ═══╝\n```\n\nExample deleting a field by having an empty replace block:\n\n```gts\nhttps://example.com/attached-file-example.gts\n╔═══ SEARCH ════╗\n @field description = contains(StringField);\n @field categories = containsMany(Category);\n @field attemptsRemaining = contains(NumberField, {\n computeVia: function() {\n return 4; // Start with 4 attempts\n }\n });\n╠═══════════════╣\n @field description = contains(StringField);\n @field categories = containsMany(Category);\n╚═══ REPLACE ═══╝\n```\n\nExample changing text within a template:\n\n```gts\nhttps://example.com/attached-file-example.gts\n╔═══ SEARCH ════╗\n <template>\n <div class=\"connections-game\">\n <header class=\"game-header\">\n <h1 class=\"game-title\">Connections</h1>\n <div class=\"game-description\">{{@model.description}}</div>\n </header>\n╠═══════════════╣\n <template>\n <div class=\"connections-game\">\n <header class=\"game-header\">\n <h1 class=\"game-title\">Connections Game</h1>\n <div class=\"game-description\">{{@model.description}}</div>\n </header>\n╚═══ REPLACE ═══╝\n```\n\nExample creating a new file:\n\n```gts\nhttp://users-realm/new-file-example.gts (new)\n╔═══ SEARCH ════╗\n╠═══════════════╣\nimport { CardDef } from 'https://cardstack.com/base/card-api';\nimport { Component } from 'https://cardstack.com/base/card-api';\nexport class NewFileExample extends CardDef {\n static displayName = \"New file example\";\n}\n╚═══ REPLACE ═══╝\n```\n\n \nEvery *SEARCH/REPLACE block* must use this format:\n1. The opening fence and code language, eg: ```gts\n2. File url. If you are creating a new file, add '(new)', for example: https://example.com/file.gts (new). If you are editing, output just the url, without '(new') \n4. In a new line, the start of search block: ╔═══ SEARCH ════╗\n3. A contiguous chunk of lines to search for in the existing source code\n4. The dividing line: ╠═══════════════╣\n5. The lines to replace into the source code\n6. The end of the replace block: ╚═══ REPLACE ═══╝\n7. The closing fence: ```\n\nEvery *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc.\nIf the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup.\n\n*SEARCH/REPLACE* blocks will *only* replace the first match occurrence.\nIncluding multiple unique *SEARCH/REPLACE* blocks if needed.\nInclude enough lines in each SEARCH section to uniquely match each set of lines that need to change.\n\nKeep *SEARCH/REPLACE* blocks concise.\nBreak large *SEARCH/REPLACE* blocks into a series of smaller blocks that each change a small portion of the file.\nInclude just the changing lines, and a few surrounding lines if needed for uniqueness.\nDo not include long runs of unchanging lines in *SEARCH/REPLACE* blocks.\n\nTo move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location, 1 to insert it in the new location.\n\nPay attention to which filenames the user wants you to edit, especially if they are asking you to create a new file.\n\nIf you want to put code in a new file, use a *SEARCH/REPLACE block* with:\n- A new file url which you form using the provided realm url and suggested file name\n- An empty `SEARCH` section\n- The new file's contents in the `REPLACE` section. \n\nAvoid detailed description of the search/replace blocks. For every search/replace block write 1 sentence description max. \n\nIf you propose a search/replace block for file edits, it must be for the currently attached file(s), and not for those attached before the most recent one (unless you ask and get the user's approval). \n\nYour new SEARCH/REPLACE blocks must target ONLY the content of currently attached files - the search portion must not target any of your previous suggestions since it is not guaranteed that your previous SEARCH/REPLACE blocks were applied. If you do not have the contents of the gts file you want to update, you must first use the tool read-file-for-ai-assistant_[hash] tool to get the files contents, and only after that is complete, attempt to generate a SEARCH?REPLACe change.\n\nIf you recognize the user wants to edit a template, do a visual change to a card, or describe a certain implementation or style, then you must use a SEARCH/REPLACE block to perform an edit to the attached gts file, by default in the isolated template. Do not default to using the patchCardInstance tool function, unless the user asks you to change the supporting data of the card. \n\nWhen you respond with a SEARCH/REPLACE block, do not refer to it as a SEARCH/REPLACE block in your prose responses, as this is an internal code structure that will get shown to user in a different format. If you need to refer to it, talk about it in a semantic way. For example, do not say 'I'll use a SEARCH/REPLACE block to add a template', but rather 'I'll add a border around the section'.\n\nNever respond with '[Omitting previously suggested code change]', or '[Omitting previously suggested and applied code change]'. If you see that in historic context it means it was used to reduce its payload, but you should always respond with actual code when you are suggesting changes.",
"commands": [],
"title": "Source Code Editing",
"description": "A skill to guide models to create SEARCH/REPLACE blocks to edit code, modified from Aider - https://aider.chat/",
"thumbnailURL": null
"cardTitle": "Source Code Editing",
"cardDescription": "A skill to guide models to create SEARCH/REPLACE blocks to edit code, modified from Aider - https://aider.chat/",
"cardThumbnailURL": null
},
"meta": {
"adoptsFrom": {
Expand Down
17 changes: 10 additions & 7 deletions packages/base/ai-app-generator.gts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@ import { AskAiInput } from './command';
import { tracked } from '@glimmer/tracking';

export class SuggestionField extends FieldDef {
@field title = contains(StringField);
@field description = contains(StringField);
@field cardTitle = contains(StringField);
@field cardDescription = contains(StringField);

static displayName = 'Suggestion';
}

export class AiAppGenerator extends CardDef {
static displayName = 'AI App Generator';

@field title = contains(StringField);
@field description = contains(StringField);
@field cardTitle = contains(StringField);
@field cardDescription = contains(StringField);
@field suggestions = containsMany(SuggestionField);
@tracked promptValue =
'Create a sprint-planning tool that lets users define backlogs, estimate stories, assign owners, and track burndown.';
Expand Down Expand Up @@ -110,10 +110,13 @@ export class AiAppGenerator extends CardDef {
<BoxelButton
@kind='secondary'
@size='small'
title={{suggestion.title}}
{{on 'click' (fn this.setPromptValue suggestion.description)}}
title={{suggestion.cardTitle}}
{{on
'click'
(fn this.setPromptValue suggestion.cardDescription)
}}
>
{{suggestion.title}}
{{suggestion.cardTitle}}
</BoxelButton>
{{/each}}
</div>
Expand Down
36 changes: 18 additions & 18 deletions packages/base/ai-app-generator.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,41 @@
"data": {
"type": "card",
"attributes": {
"title": "AI App Generator",
"description": "Design your own app UI by describing what you want to build",
"cardTitle": "AI App Generator",
"cardDescription": "Design your own app UI by describing what you want to build",
"prompt": "Create a sprint-planning tool that lets users define backlogs, estimate stories, assign owners, and track burndown.",
"suggestions": [
{
"title": "Link in Bio",
"description": "Create a simple link-in-bio page with social media links and a bio section"
"cardTitle": "Link in Bio",
"cardDescription": "Create a simple link-in-bio page with social media links and a bio section"
},
{
"title": "About Me",
"description": "Build a personal portfolio page with your background, skills, and contact information"
"cardTitle": "About Me",
"cardDescription": "Build a personal portfolio page with your background, skills, and contact information"
},
{
"title": "Recipe Database",
"description": "Create a recipe management app with search, categories, and cooking instructions"
"cardTitle": "Recipe Database",
"cardDescription": "Create a recipe management app with search, categories, and cooking instructions"
},
{
"title": "To Do List",
"description": "Build a task management app with lists, priorities, and completion tracking"
"cardTitle": "To Do List",
"cardDescription": "Build a task management app with lists, priorities, and completion tracking"
},
{
"title": "Creative Portfolio",
"description": "Design a showcase for creative work with galleries, project details, and contact forms"
"cardTitle": "Creative Portfolio",
"cardDescription": "Design a showcase for creative work with galleries, project details, and contact forms"
},
{
"title": "Event Calendar",
"description": "Build an event management app with calendar views, RSVP tracking, and event details"
"cardTitle": "Event Calendar",
"cardDescription": "Build an event management app with calendar views, RSVP tracking, and event details"
},
{
"title": "Fitness Tracker",
"description": "Create a workout tracking app with exercise logs, progress charts, and goal setting"
"cardTitle": "Fitness Tracker",
"cardDescription": "Create a workout tracking app with exercise logs, progress charts, and goal setting"
},
{
"title": "Budget Manager",
"description": "Design a personal finance app with expense tracking, budget categories, and spending insights"
"cardTitle": "Budget Manager",
"cardDescription": "Design a personal finance app with expense tracking, budget categories, and spending insights"
}
]
},
Expand Down
32 changes: 16 additions & 16 deletions packages/base/brand-guide.gts
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ class BrandGuideIsolated extends Component<typeof BrandGuide> {
<:header>
<ThemeDashboardHeader
class='brand-guide-dashboard-header'
@title={{@model.title}}
@description={{@model.description}}
@title={{@model.cardTitle}}
@description={{@model.cardDescription}}
@isDarkMode={{this.isDarkMode}}
>
<:meta>
Expand Down Expand Up @@ -663,10 +663,10 @@ export default class BrandGuide extends DetailedStyleRef {
},
});

@field thumbnailURL = contains(StringField, {
@field cardThumbnailURL = contains(StringField, {
computeVia: function (this: BrandGuide) {
return this.cardInfo?.thumbnailURL?.length
? this.cardInfo?.thumbnailURL
return this.cardInfo?.cardThumbnailURL?.length
? this.cardInfo?.cardThumbnailURL
: this.markUsage?.socialMediaProfileIcon;
},
});
Expand All @@ -675,15 +675,15 @@ export default class BrandGuide extends DetailedStyleRef {
static fitted = class Fitted extends Component<typeof this> {
<template>
<BasicFitted
@primary={{@model.title}}
@primary={{@model.cardTitle}}
@secondary={{cardTypeDisplayName @model}}
@description={{@model.description}}
@description={{@model.cardDescription}}
>
<:thumbnail>
{{#if @model.thumbnailURL}}
{{#if @model.cardThumbnailURL}}
<div
class='brand-logo-thumbnail'
style={{cssUrl 'background-image' @model.thumbnailURL}}
style={{cssUrl 'background-image' @model.cardThumbnailURL}}
/>
{{else}}
<@model.constructor.icon
Expand Down Expand Up @@ -717,19 +717,19 @@ export default class BrandGuide extends DetailedStyleRef {
<div
class='thumbnail-image'
style={{if
@model.thumbnailURL
(cssUrl 'background-image' @model.thumbnailURL)
@model.cardThumbnailURL
(cssUrl 'background-image' @model.cardThumbnailURL)
}}
role={{if @model.thumbnailURL 'img'}}
alt={{if @model.thumbnailURL @model.title}}
role={{if @model.cardThumbnailURL 'img'}}
alt={{if @model.cardThumbnailURL @model.cardTitle}}
>
{{#unless @model.thumbnailURL}}
{{#unless @model.cardThumbnailURL}}
<@model.constructor.icon width='30' height='30' />
{{/unless}}
</div>
<div class='content'>
<h3><@fields.title /></h3>
<p><@fields.description /></p>
<h3><@fields.cardTitle /></h3>
<p><@fields.cardDescription /></p>
</div>
</article>

Expand Down
20 changes: 10 additions & 10 deletions packages/base/card-api.gts
Original file line number Diff line number Diff line change
Expand Up @@ -2321,9 +2321,9 @@ export class MarkdownField extends StringField {

export class CardInfoField extends FieldDef {
static displayName = 'Card Info';
@field title = contains(StringField);
@field description = contains(StringField);
@field thumbnailURL = contains(MaybeBase64Field);
@field name = contains(StringField);
@field summary = contains(StringField);
@field cardThumbnailURL = contains(MaybeBase64Field);
@field theme = linksTo(() => Theme);
@field notes = contains(MarkdownField);
}
Expand All @@ -2350,24 +2350,24 @@ export class CardDef extends BaseDef {
}
@field id = contains(ReadOnlyField);
@field cardInfo = contains(CardInfoField);
@field title = contains(StringField, {
@field cardTitle = contains(StringField, {
computeVia: function (this: CardDef) {
return this.cardInfo.title?.trim()?.length
? this.cardInfo.title
return this.cardInfo.name?.trim()?.length
? this.cardInfo.name
: `Untitled ${this.constructor.displayName}`;
},
});
@field description = contains(StringField, {
@field cardDescription = contains(StringField, {
computeVia: function (this: CardDef) {
return this.cardInfo.description;
return this.cardInfo.summary;
},
});
// TODO: this will probably be an image or image url field card when we have it
// UPDATE: we now have a Base64ImageField card. we can probably refactor this
// to use it directly now (or wait until a better image field comes along)
@field thumbnailURL = contains(MaybeBase64Field, {
@field cardThumbnailURL = contains(MaybeBase64Field, {
computeVia: function (this: CardDef) {
return this.cardInfo.thumbnailURL;
return this.cardInfo.cardThumbnailURL;
},
});
static displayName = 'Card';
Expand Down
2 changes: 1 addition & 1 deletion packages/base/cards-grid.gts
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ export class CardsGrid extends CardDef {
return this[realmInfo]?.name;
},
});
@field title = contains(StringField, {
@field cardTitle = contains(StringField, {
computeVia: function (this: CardsGrid) {
return this.realmName;
},
Expand Down
4 changes: 2 additions & 2 deletions packages/base/cards/ai-app-generator.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"data": {
"type": "card",
"attributes": {
"title": "AI App Generator",
"description": "Design your own app UI by describing what you want to build",
"cardTitle": "AI App Generator",
"cardDescription": "Design your own app UI by describing what you want to build",
"specType": "card",
"ref": {
"module": "https://cardstack.com/base/ai-app-generator",
Expand Down
4 changes: 2 additions & 2 deletions packages/base/cards/brand-guide.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"data": {
"type": "card",
"attributes": {
"title": "Brand Guide",
"description": "Guide to brand elements and visual style",
"cardTitle": "Brand Guide",
"cardDescription": "Guide to brand elements and visual style",
"specType": "card",
"ref": {
"module": "https://cardstack.com/base/brand-guide",
Expand Down
4 changes: 2 additions & 2 deletions packages/base/cards/detailed-style-reference.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"data": {
"type": "card",
"attributes": {
"title": "Detailed Style Reference",
"cardTitle": "Detailed Style Reference",
"specType": "card",
"description": "Comprehensive reference card for documenting a product’s visual language and theme variables.",
"cardDescription": "Comprehensive reference card for documenting a product’s visual language and theme variables.",
"ref": {
"module": "https://cardstack.com/base/detailed-style-reference",
"name": "default"
Expand Down
Loading
Loading