@yottagraph-app/aether-instructions 1.1.41 → 1.1.43
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/AGENTS.md +18 -191
- package/README.md +13 -9
- package/commands/build_my_app.md +7 -8
- package/commands/deploy_agent.md +7 -7
- package/commands/update_branding.md +1 -1
- package/commands/update_instructions.md +25 -17
- package/package.json +2 -4
- package/skills/aether/SKILL.md +57 -0
- package/{rules/agents-data.mdc → skills/aether/agents-data.md} +3 -6
- package/{rules/agents.mdc → skills/aether/agents.md} +49 -28
- package/{rules/architecture.mdc → skills/aether/architecture.md} +14 -21
- package/{rules/branding.mdc → skills/aether/branding.md} +7 -12
- package/{rules/cookbook-data.mdc → skills/aether/cookbook-data.md} +13 -28
- package/{rules/cookbook.mdc → skills/aether/cookbook.md} +2 -9
- package/skills/aether/cursor-cloud.md +57 -0
- package/{rules/data.mdc → skills/aether/data.md} +80 -70
- package/skills/aether/deployment.md +14 -0
- package/{rules/design.mdc → skills/aether/design.md} +1 -6
- package/skills/aether/env.md +10 -0
- package/{rules/git-support.mdc → skills/aether/git-support.md} +4 -9
- package/{rules/instructions_warning.mdc → skills/aether/instructions_warning.md} +6 -12
- package/skills/aether/local-setup.md +15 -0
- package/{rules/mcp-servers.mdc → skills/aether/mcp-servers.md} +3 -7
- package/{rules/pref.mdc → skills/aether/pref.md} +9 -14
- package/skills/aether/server-data.md +48 -0
- package/skills/aether/server.md +60 -0
- package/{rules/something-broke.mdc → skills/aether/something-broke.md} +3 -7
- package/{rules/server.mdc → skills/aether/storage.md} +78 -108
- package/{rules/ui.mdc → skills/aether/ui.md} +2 -6
- package/skills/elemental-mcp-patterns/SKILL.md +57 -51
- package/variants/mcp-only/commands/build_my_app.md +6 -6
- package/variants/mcp-only/{rules/agents-data.mdc → skills/aether/agents-data.md} +0 -6
- package/variants/mcp-only/{rules/cookbook-data.mdc → skills/aether/cookbook-data.md} +3 -6
- package/variants/mcp-only/{rules/data.mdc → skills/aether/data.md} +1 -6
- package/variants/mcp-only/{rules/server-data.mdc → skills/aether/server-data.md} +9 -15
- package/rules/aether.mdc +0 -21
- package/rules/server-data.mdc +0 -54
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Rules for developing ADK agents in the agents/ directory
|
|
3
|
-
globs: agents/**
|
|
4
|
-
alwaysApply: false
|
|
5
|
-
---
|
|
6
|
-
|
|
7
1
|
# Agent Development (Google ADK)
|
|
8
2
|
|
|
9
3
|
This project supports developing and deploying AI agents alongside the UI. Agents live in the `agents/` directory and deploy to Vertex AI Agent Engine via the `/deploy_agent` command.
|
|
10
4
|
|
|
5
|
+
## Starter agent
|
|
6
|
+
|
|
7
|
+
`agents/example_agent/` is a working starter agent that queries the Elemental
|
|
8
|
+
Knowledge Graph. It includes schema discovery, entity search, property lookup,
|
|
9
|
+
and optional MCP server integration. Use it as a starting point — customize the
|
|
10
|
+
instruction, add tools, and follow the patterns described below.
|
|
11
|
+
|
|
11
12
|
## Directory Structure
|
|
12
13
|
|
|
13
14
|
Each agent is a self-contained Python package. **Directory names must use underscores, not hyphens** (ADK uses the directory name as a Python identifier).
|
|
@@ -42,14 +43,15 @@ root_agent = Agent(
|
|
|
42
43
|
```
|
|
43
44
|
|
|
44
45
|
Key rules:
|
|
46
|
+
|
|
45
47
|
- The `agent.py` file MUST export a variable named `root_agent`
|
|
46
48
|
- Tool functions should have detailed docstrings -- the LLM reads these to understand when and how to use each tool
|
|
47
49
|
- Use `google-adk` for the agent framework, `httpx` for HTTP calls
|
|
48
50
|
- Pin dependency versions in `requirements.txt` for reproducible deployments
|
|
49
51
|
|
|
50
52
|
For agents that call the **Elemental API** (`broadchurch_auth`, endpoints,
|
|
51
|
-
local `ELEMENTAL_*` env vars), see
|
|
52
|
-
using **Elemental MCP tools**,
|
|
53
|
+
local `ELEMENTAL_*` env vars), see [agents-data.md](agents-data.md) in this skill. For agents
|
|
54
|
+
using **Elemental MCP tools**, [agents-data.md](agents-data.md) also covers
|
|
53
55
|
`McpToolset` wiring — use `StreamableHTTPConnectionParams` (not
|
|
54
56
|
`SseConnectionParams`) and read the `elemental-mcp-patterns` skill for
|
|
55
57
|
response handling patterns.
|
|
@@ -153,17 +155,18 @@ The response includes an `agents` array:
|
|
|
153
155
|
|
|
154
156
|
Each agent entry has:
|
|
155
157
|
|
|
156
|
-
| Field
|
|
157
|
-
|
|
158
|
-
| `name`
|
|
159
|
-
| `display_name` | `string` | Human-readable name for the UI
|
|
160
|
-
| `engine_id`
|
|
158
|
+
| Field | Type | Description |
|
|
159
|
+
| -------------- | -------- | ----------------------------------------------------------------------------- |
|
|
160
|
+
| `name` | `string` | Agent directory name (e.g. `filing_analyst`) |
|
|
161
|
+
| `display_name` | `string` | Human-readable name for the UI |
|
|
162
|
+
| `engine_id` | `string` | Vertex AI Agent Engine resource ID — used as `{agentId}` in query/stream URLs |
|
|
161
163
|
|
|
162
164
|
The `engine_id` is the key value — it becomes the `{agentId}` path
|
|
163
165
|
parameter in `/api/agent/{agentId}/stream` (the local Nitro route) and
|
|
164
166
|
the portal's `/authorize` endpoint.
|
|
165
167
|
|
|
166
168
|
**How agents get populated:** The portal discovers agents from two sources:
|
|
169
|
+
|
|
167
170
|
1. **Firestore** — agents registered by the deploy workflow (`deploy-agent.yml`
|
|
168
171
|
calls `POST /api/agents/{tenantId}` to register)
|
|
169
172
|
2. **Agent Engine API** — the portal also queries Vertex AI for reasoning
|
|
@@ -219,9 +222,26 @@ A typical stream for an agent that uses a tool:
|
|
|
219
222
|
|
|
220
223
|
```json
|
|
221
224
|
[
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
+
{
|
|
226
|
+
"content": {
|
|
227
|
+
"parts": [{ "functionCall": { "name": "search", "args": { "q": "AAPL 8-K" } } }],
|
|
228
|
+
"role": "model"
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"content": {
|
|
233
|
+
"parts": [
|
|
234
|
+
{ "functionResponse": { "name": "search", "response": { "results": ["..."] } } }
|
|
235
|
+
],
|
|
236
|
+
"role": "tool"
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"content": {
|
|
241
|
+
"parts": [{ "text": "Here is the summary of the 8-K filing..." }],
|
|
242
|
+
"role": "model"
|
|
243
|
+
}
|
|
244
|
+
}
|
|
225
245
|
]
|
|
226
246
|
```
|
|
227
247
|
|
|
@@ -252,13 +272,13 @@ automatically.
|
|
|
252
272
|
|
|
253
273
|
SSE event types:
|
|
254
274
|
|
|
255
|
-
| Event
|
|
256
|
-
|
|
257
|
-
| `text`
|
|
258
|
-
| `function_call`
|
|
259
|
-
| `function_response` | `{ "name": "...", "response": {...} }`
|
|
260
|
-
| `error`
|
|
261
|
-
| `done`
|
|
275
|
+
| Event | Data Shape | Description |
|
|
276
|
+
| ------------------- | ---------------------------------------- | ------------------------------------------------------------------------ |
|
|
277
|
+
| `text` | `{ "text": "..." }` | Agent text output (replaces previous text) |
|
|
278
|
+
| `function_call` | `{ "name": "...", "args": {...} }` | Agent is calling a tool |
|
|
279
|
+
| `function_response` | `{ "name": "...", "response": {...} }` | Tool returned a result |
|
|
280
|
+
| `error` | `{ "message": "...", "code": "..." }` | Error during processing (`code` is `PERMISSION_DENIED` for IAM failures) |
|
|
281
|
+
| `done` | `{ "session_id": "...", "text": "..." }` | Stream complete with final text |
|
|
262
282
|
|
|
263
283
|
For custom agent UIs that need streaming, import `readSSE`:
|
|
264
284
|
|
|
@@ -292,14 +312,14 @@ to the original plain object are invisible to the template.
|
|
|
292
312
|
// WRONG — local ref bypasses Vue's reactivity, UI won't update:
|
|
293
313
|
const msg: ChatMessage = { id: '...', role: 'agent', text: '', streaming: true };
|
|
294
314
|
messages.value.push(msg);
|
|
295
|
-
msg.text = 'hello';
|
|
296
|
-
msg.streaming = false;
|
|
315
|
+
msg.text = 'hello'; // data changes, but Vue doesn't know
|
|
316
|
+
msg.streaming = false; // template still shows typing indicator
|
|
297
317
|
|
|
298
318
|
// CORRECT — access through the reactive array:
|
|
299
319
|
messages.value.push({ id: '...', role: 'agent', text: '', streaming: true });
|
|
300
320
|
const idx = messages.value.length - 1;
|
|
301
|
-
messages.value[idx].text = 'hello';
|
|
302
|
-
messages.value[idx].streaming = false;
|
|
321
|
+
messages.value[idx].text = 'hello'; // Vue detects this
|
|
322
|
+
messages.value[idx].streaming = false; // template re-renders
|
|
303
323
|
```
|
|
304
324
|
|
|
305
325
|
The `useAgentChat` composable uses the correct pattern internally (via an
|
|
@@ -342,7 +362,7 @@ agents (MCP or REST-backed):
|
|
|
342
362
|
|
|
343
363
|
This applies to ADK agent tools, where the LLM reads tool output directly.
|
|
344
364
|
MCP server tools follow different conventions (structured dicts/lists) — see
|
|
345
|
-
|
|
365
|
+
[mcp-servers.md](mcp-servers.md).
|
|
346
366
|
|
|
347
367
|
The agent's LLM will try to interpret whatever the tool returns. Raw API
|
|
348
368
|
responses with nested dicts, numeric IDs, and arrays of unlabeled values
|
|
@@ -465,6 +485,7 @@ Passing a raw `McpToolset` as the agent's only tool source and writing a
|
|
|
465
485
|
long system prompt does **not** satisfy the spec.
|
|
466
486
|
|
|
467
487
|
`McpToolset` passthrough means:
|
|
488
|
+
|
|
468
489
|
- The LLM receives raw JSON responses — no Markdown formatting, no
|
|
469
490
|
human-readable reports
|
|
470
491
|
- No session-state caching — repeated queries for the same entity make
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Project structure, navigation patterns, data architecture, server routes, agents, MCP servers. Read when adding pages, navigation, or server-side functionality."
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
|
-
|
|
6
1
|
# Aether Architecture
|
|
7
2
|
|
|
8
3
|
Aether is an app framework built on Nuxt 3 + Vue 3 + Vuetify 3 + TypeScript. It follows standard Nuxt conventions -- pages in `pages/`, components in `components/`, composables in `composables/`, server routes in `server/api/`.
|
|
9
4
|
|
|
10
5
|
**Tech stack**: Nuxt 3 (SPA), Vue 3 Composition API (`<script setup>`), Vuetify 3, TypeScript (required), Auth0 (automatic).
|
|
11
6
|
|
|
12
|
-
**Data source**: This app runs on the Lovelace platform (entities, news, filings, sentiment, relationships, events). See
|
|
7
|
+
**Data source**: This app runs on the Lovelace platform (entities, news, filings, sentiment, relationships, events). See [data.md](data.md) in this skill for how your app accesses that data. Do not call external APIs for data the platform provides.
|
|
13
8
|
|
|
14
9
|
## Project Structure
|
|
15
10
|
|
|
@@ -26,14 +21,13 @@ mcp-servers/ # MCP servers (Python, deploy to Cloud Run)
|
|
|
26
21
|
|
|
27
22
|
## Data Architecture
|
|
28
23
|
|
|
29
|
-
| Store
|
|
30
|
-
|
|
31
|
-
| Platform data (Query Server / Postgres per your architecture) | Lovelace knowledge graph or synced local data | See
|
|
32
|
-
| KV (Upstash Redis)
|
|
33
|
-
| Neon Postgres
|
|
24
|
+
| Store | Purpose | When to use |
|
|
25
|
+
| ------------------------------------------------------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
26
|
+
| Platform data (Query Server / Postgres per your architecture) | Lovelace knowledge graph or synced local data | See [data.md](data.md) |
|
|
27
|
+
| KV (Upstash Redis) | User preferences, lightweight state | Settings, watchlists, UI state that should persist |
|
|
28
|
+
| Neon Postgres | App-specific relational data | Custom tables, complex queries (if provisioned — see [storage.md](storage.md) for how to check) |
|
|
34
29
|
|
|
35
|
-
|
|
36
|
-
Check `.env` for `DATABASE_URL` before using Neon Postgres (see `server` rule).
|
|
30
|
+
See [storage.md](storage.md) for backend selection and server-side usage (both KV and Neon Postgres), plus [pref.md](pref.md) for the client-side `Pref<T>` pattern.
|
|
37
31
|
|
|
38
32
|
## Adding Pages
|
|
39
33
|
|
|
@@ -116,8 +110,8 @@ Use server routes when you need to proxy external APIs (avoid CORS), access
|
|
|
116
110
|
data server-side, or keep secrets off the client. Call them from client code
|
|
117
111
|
with `$fetch('/api/my-data/fetch')`.
|
|
118
112
|
|
|
119
|
-
See
|
|
120
|
-
See
|
|
113
|
+
See [server.md](server.md) for file-routing conventions and [storage.md](storage.md) for Neon Postgres patterns.
|
|
114
|
+
See [server-data.md](server-data.md) when calling the platform Query Server from server routes.
|
|
121
115
|
|
|
122
116
|
## Beyond the UI: Agents, MCP Servers, and Server Routes
|
|
123
117
|
|
|
@@ -125,7 +119,7 @@ Aether apps are more than just a Nuxt SPA. The project contains three additional
|
|
|
125
119
|
|
|
126
120
|
### `agents/` -- ADK Agents (Python)
|
|
127
121
|
|
|
128
|
-
Each subdirectory is a self-contained Python agent that deploys to Vertex AI Agent Engine. See
|
|
122
|
+
Each subdirectory is a self-contained Python agent that deploys to Vertex AI Agent Engine. See [agents.md](agents.md) for development patterns. Agents are deployed via the Broadchurch Portal UI or the `/deploy_agent` Cursor command, both of which trigger `deploy-agent.yml`. Use the `useAgentChat` composable to build a chat UI that talks to them.
|
|
129
123
|
|
|
130
124
|
**Agent query path:** The app talks to Agent Engine directly — the portal is
|
|
131
125
|
only in the auth path. The flow is:
|
|
@@ -143,7 +137,7 @@ project detail page for IAM health status.
|
|
|
143
137
|
|
|
144
138
|
### `mcp-servers/` -- MCP Servers (Python)
|
|
145
139
|
|
|
146
|
-
Each subdirectory is a FastMCP server that deploys to Cloud Run. See
|
|
140
|
+
Each subdirectory is a FastMCP server that deploys to Cloud Run. See [mcp-servers.md](mcp-servers.md). Deployed via Portal UI or `/deploy_mcp`, triggering `deploy-mcp.yml`. Agents can connect to MCP servers as tool providers.
|
|
147
141
|
|
|
148
142
|
### `broadchurch.yaml`
|
|
149
143
|
|
|
@@ -158,11 +152,10 @@ Use these to build whatever UI fits the app:
|
|
|
158
152
|
local Nitro streaming route (`/api/agent/:agentId/stream`) which calls
|
|
159
153
|
Agent Engine directly with a tenant SA token. Handles streaming, session
|
|
160
154
|
management, and response parsing. Shows clear error messages when IAM
|
|
161
|
-
permissions are missing. See
|
|
155
|
+
permissions are missing. See [agents.md](agents.md) for details.
|
|
162
156
|
- **`useTenantConfig()`** -- Fetch the tenant's runtime config (deployed
|
|
163
157
|
agents, feature flags, MCP servers) from the Portal Gateway.
|
|
164
158
|
- **`useElementalClient()`** -- When using the Elemental API from the client,
|
|
165
|
-
see
|
|
159
|
+
see [data.md](data.md).
|
|
166
160
|
- **`usePrefsStore()` / `Pref<T>`** -- KV-backed user preferences. See
|
|
167
|
-
|
|
168
|
-
|
|
161
|
+
[pref.md](pref.md).
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Apply when working on visual styling, colors, typography, theming, branding, or UI appearance.
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
|
-
|
|
6
1
|
# Lovelace Branding
|
|
7
2
|
|
|
8
3
|
The `lovelace-branding` skill (`skills/lovelace-branding/`) is the single source of truth for all brand specifics -- colors, typography, patterns, assets, and usage guidelines. Read the skill before making branding decisions. Start with `SKILL.md` for the file index.
|
|
@@ -15,13 +10,13 @@ Single dark theme. No light mode, no theme switching.
|
|
|
15
10
|
|
|
16
11
|
These files are project-owned. Consult the branding skill for the values and patterns they should implement.
|
|
17
12
|
|
|
18
|
-
| File
|
|
19
|
-
|
|
20
|
-
| `assets/brand-globals.css`
|
|
21
|
-
| `assets/fonts.css`
|
|
22
|
-
| `assets/theme-styles.css`
|
|
23
|
-
| `composables/useLovelaceTheme.ts` | Theme color palette and Vuetify theme activation
|
|
24
|
-
| `composables/useThemeClasses.ts`
|
|
13
|
+
| File | Role |
|
|
14
|
+
| --------------------------------- | -------------------------------------------------- |
|
|
15
|
+
| `assets/brand-globals.css` | `:root` CSS variables and global typography/layout |
|
|
16
|
+
| `assets/fonts.css` | `@font-face` declarations |
|
|
17
|
+
| `assets/theme-styles.css` | Theme-aware CSS utility classes |
|
|
18
|
+
| `composables/useLovelaceTheme.ts` | Theme color palette and Vuetify theme activation |
|
|
19
|
+
| `composables/useThemeClasses.ts` | Theme-aware class combination utilities |
|
|
25
20
|
|
|
26
21
|
## Integration
|
|
27
22
|
|
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Data-fetching UI recipes: entity search, news feed, filings, gateway helpers. Read with the `data` rule when building pages that use the Query Server or platform data."
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
|
-
|
|
6
1
|
# Data-fetching cookbook
|
|
7
2
|
|
|
8
|
-
Copy-paste patterns that call the Elemental API, gateway, or helpers. For platform API details see
|
|
3
|
+
Copy-paste patterns that call the Elemental API, gateway, or helpers. For platform API details see [data.md](data.md) in this skill. Pure UI patterns (tables, forms, charts) are in [cookbook.md](cookbook.md).
|
|
9
4
|
|
|
10
5
|
## 1. Entity Search Page
|
|
11
6
|
|
|
12
7
|
Search for entities by name and display results. Uses `$fetch` directly
|
|
13
8
|
because `POST /entities/search` (batch name resolution with scored ranking)
|
|
14
|
-
is not wrapped by the generated `useElementalClient()` — see
|
|
9
|
+
is not wrapped by the generated `useElementalClient()` — see [data.md](data.md).
|
|
15
10
|
|
|
16
11
|
```vue
|
|
17
12
|
<template>
|
|
@@ -182,8 +177,8 @@ for runtime flavor/PID discovery and `buildGatewayUrl()` for gateway access.
|
|
|
182
177
|
const vals = valueMap.get(neid) ?? {};
|
|
183
178
|
return {
|
|
184
179
|
neid,
|
|
185
|
-
name: namePid ? (vals[namePid] as string) ?? neid : neid,
|
|
186
|
-
sentiment: sentimentPid ? (vals[sentimentPid] as number) ?? null : null,
|
|
180
|
+
name: namePid ? ((vals[namePid] as string) ?? neid) : neid,
|
|
181
|
+
sentiment: sentimentPid ? ((vals[sentimentPid] as number) ?? null) : null,
|
|
187
182
|
};
|
|
188
183
|
});
|
|
189
184
|
} catch (e: any) {
|
|
@@ -215,12 +210,7 @@ Simpler version of recipe #1 using the pre-built `searchEntities()` helper.
|
|
|
215
210
|
{{ error }}
|
|
216
211
|
</v-alert>
|
|
217
212
|
<v-list v-if="results.length" class="mt-4">
|
|
218
|
-
<v-list-item
|
|
219
|
-
v-for="r in results"
|
|
220
|
-
:key="r.neid"
|
|
221
|
-
:title="r.name"
|
|
222
|
-
:subtitle="r.neid"
|
|
223
|
-
/>
|
|
213
|
+
<v-list-item v-for="r in results" :key="r.neid" :title="r.name" :subtitle="r.neid" />
|
|
224
214
|
</v-list>
|
|
225
215
|
<v-empty-state
|
|
226
216
|
v-else-if="searched && !loading"
|
|
@@ -266,7 +256,7 @@ properties are then fetched via `useElementalClient()`.
|
|
|
266
256
|
**Important:** For graph-layer entities (person, organization, location),
|
|
267
257
|
use `findEntities` with a `linked` expression. For property-layer entities
|
|
268
258
|
(documents, filings, articles), use `getPropertyValues` with the
|
|
269
|
-
relationship PID. See
|
|
259
|
+
relationship PID. See [data.md](data.md) for the two-layer architecture.
|
|
270
260
|
|
|
271
261
|
```vue
|
|
272
262
|
<template>
|
|
@@ -366,7 +356,7 @@ relationship PID. See the `data` rule for the two-layer architecture.
|
|
|
366
356
|
});
|
|
367
357
|
|
|
368
358
|
const docNeids = (propRes.values ?? []).map((v: any) =>
|
|
369
|
-
String(v.value).padStart(20, '0')
|
|
359
|
+
String(v.value).padStart(20, '0')
|
|
370
360
|
);
|
|
371
361
|
|
|
372
362
|
function getEntityNameUrl(neid: string) {
|
|
@@ -379,15 +369,14 @@ relationship PID. See the `data` rule for the two-layer architecture.
|
|
|
379
369
|
const names = await Promise.all(
|
|
380
370
|
docNeids.map(async (neid: string) => {
|
|
381
371
|
try {
|
|
382
|
-
const res = await $fetch<{ name: string }>(
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
);
|
|
372
|
+
const res = await $fetch<{ name: string }>(getEntityNameUrl(neid), {
|
|
373
|
+
headers: { 'X-Api-Key': getApiKey() },
|
|
374
|
+
});
|
|
386
375
|
return res.name || neid;
|
|
387
376
|
} catch {
|
|
388
377
|
return neid;
|
|
389
378
|
}
|
|
390
|
-
})
|
|
379
|
+
})
|
|
391
380
|
);
|
|
392
381
|
|
|
393
382
|
filings.value = docNeids.map((neid: string, i: number) => ({
|
|
@@ -430,11 +419,7 @@ Type-ahead search that shows results in a dropdown as the user types. Uses
|
|
|
430
419
|
@click:clear="onClear"
|
|
431
420
|
/>
|
|
432
421
|
|
|
433
|
-
<v-card
|
|
434
|
-
v-if="showMenu && suggestions.length > 0"
|
|
435
|
-
class="search-dropdown"
|
|
436
|
-
elevation="8"
|
|
437
|
-
>
|
|
422
|
+
<v-card v-if="showMenu && suggestions.length > 0" class="search-dropdown" elevation="8">
|
|
438
423
|
<v-list density="compact">
|
|
439
424
|
<v-list-item
|
|
440
425
|
v-for="item in suggestions"
|
|
@@ -457,7 +442,7 @@ Type-ahead search that shows results in a dropdown as the user types. Uses
|
|
|
457
442
|
icon?: string;
|
|
458
443
|
flavors?: string[];
|
|
459
444
|
}>(),
|
|
460
|
-
{ label: 'Search', icon: 'mdi-magnify', flavors: undefined }
|
|
445
|
+
{ label: 'Search', icon: 'mdi-magnify', flavors: undefined }
|
|
461
446
|
);
|
|
462
447
|
|
|
463
448
|
const emit = defineEmits<{
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Copy-paste UI patterns for common pages: data table, form, chart, dialog, master-detail. For Query Server / data-fetching recipes see `cookbook-data`."
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
|
-
|
|
6
1
|
# UI Pattern Cookbook
|
|
7
2
|
|
|
8
3
|
Copy-paste patterns using the project's actual composables and Vuetify components. Adapt to your needs.
|
|
9
4
|
|
|
10
|
-
**Data-fetching recipes** (entity search, news feed, filings, gateway helpers) live in
|
|
5
|
+
**Data-fetching recipes** (entity search, news feed, filings, gateway helpers) live in [cookbook-data.md](cookbook-data.md).
|
|
11
6
|
|
|
12
7
|
## 2. Data Table Page
|
|
13
8
|
|
|
@@ -98,9 +93,7 @@ Form with field validation, submit handler, and user feedback.
|
|
|
98
93
|
variant="outlined"
|
|
99
94
|
class="mb-3"
|
|
100
95
|
/>
|
|
101
|
-
<v-btn type="submit" color="primary" :loading="saving" :disabled="!valid">
|
|
102
|
-
Save
|
|
103
|
-
</v-btn>
|
|
96
|
+
<v-btn type="submit" color="primary" :loading="saving" :disabled="!valid"> Save </v-btn>
|
|
104
97
|
</v-form>
|
|
105
98
|
</v-container>
|
|
106
99
|
</template>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
If you are in Cursor Cloud, the `environment.json` install step runs
|
|
2
|
+
`init-project.js` and `npm install` automatically, and starts a dev server
|
|
3
|
+
on port 3000.
|
|
4
|
+
|
|
5
|
+
**Verify before starting:** check that `.env` exists and `node_modules/` is
|
|
6
|
+
present. If either is missing, run: `node init-project.js && npm install`
|
|
7
|
+
|
|
8
|
+
**Do NOT** manually run `nvm install` or `nvm use` — Node version is managed
|
|
9
|
+
by the environment.
|
|
10
|
+
|
|
11
|
+
### Initial environment setup only
|
|
12
|
+
|
|
13
|
+
This subsection applies ONLY when first asked to "set up the development
|
|
14
|
+
environment" or "demonstrate that the environment is working." It does
|
|
15
|
+
**NOT** apply to ongoing development — once the app is built, use the
|
|
16
|
+
browser normally to test and verify UI changes.
|
|
17
|
+
|
|
18
|
+
**During initial setup**, skip browser/UI testing. The starter UI is a
|
|
19
|
+
placeholder template that will be replaced by `/build_my_app`. Do not
|
|
20
|
+
launch a browser, record videos, or take screenshots at this stage.
|
|
21
|
+
Verifying `npm run build` passes is sufficient.
|
|
22
|
+
|
|
23
|
+
1. Check the "Dev Server" terminal output for a line containing
|
|
24
|
+
`Listening on` or `Local: http://localhost:3000`. If present, the
|
|
25
|
+
environment is working.
|
|
26
|
+
2. If the dev server is NOT running, start it with `npm run dev` and wait
|
|
27
|
+
for the "Listening on" line.
|
|
28
|
+
3. Run `npm run build` to verify the project compiles.
|
|
29
|
+
4. Once confirmed, tell the user the environment is ready, then
|
|
30
|
+
immediately run the `/build_my_app` command.
|
|
31
|
+
|
|
32
|
+
### MCP tools
|
|
33
|
+
|
|
34
|
+
Lovelace MCP servers (`lovelace-elemental`, `lovelace-stocks`, etc.)
|
|
35
|
+
should be available if configured at the org level. Check your tool list
|
|
36
|
+
for `elemental_*` tools. If they're not available, use the Elemental API
|
|
37
|
+
client (`useElementalClient()`) and the skill docs in
|
|
38
|
+
`.cursor/skills/elemental-api/` and `.cursor/skills/data-model/` for platform data access instead.
|
|
39
|
+
|
|
40
|
+
### Technical details
|
|
41
|
+
|
|
42
|
+
Node 20 is the baseline (`.nvmrc`). The `environment.json` install step
|
|
43
|
+
handles this via `nvm install 20 && nvm alias default 20`. Newer Node
|
|
44
|
+
versions (22, 25) generally work but may produce `EBADENGINE` warnings
|
|
45
|
+
during install — safe to ignore.
|
|
46
|
+
|
|
47
|
+
The install step runs `node init-project.js --local` (creates `.env` if
|
|
48
|
+
absent) then `npm install` (triggers `postinstall` → `nuxt prepare`).
|
|
49
|
+
Auth0 is bypassed via `NUXT_PUBLIC_USER_NAME=dev-user`
|
|
50
|
+
in the generated `.env`.
|
|
51
|
+
|
|
52
|
+
**No automated test suite.** Verification is `npm run build` (compile
|
|
53
|
+
check) and `npm run format:check` (Prettier). See Verification Commands.
|
|
54
|
+
|
|
55
|
+
**Before committing:** always run `npm run format` — the husky pre-commit
|
|
56
|
+
hook runs `lint-staged` with `prettier --check` and will reject
|
|
57
|
+
unformatted files.
|