@yottagraph-app/aether-instructions 1.1.42 → 1.1.44
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 +12 -30
- package/CLAUDE.md +1 -0
- 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 +34 -21
- package/package.json +4 -5
- 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} +42 -28
- package/{rules/architecture.mdc → skills/aether/architecture.md} +14 -20
- 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/{rules/cursor-cloud.mdc → skills/aether/cursor-cloud.md} +1 -6
- package/{rules/data.mdc → skills/aether/data.md} +80 -70
- package/{rules/deployment.mdc → skills/aether/deployment.md} +1 -6
- package/{rules/design.mdc → skills/aether/design.md} +1 -6
- package/{rules/env.mdc → skills/aether/env.md} +0 -5
- package/{rules/git-support.mdc → skills/aether/git-support.md} +4 -9
- package/{rules/instructions_warning.mdc → skills/aether/instructions_warning.md} +12 -13
- package/{rules/local-setup.mdc → skills/aether/local-setup.md} +1 -6
- 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/server-data.mdc +0 -54
- package/rules/storage.mdc +0 -54
|
@@ -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,13 +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
|
-
See
|
|
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.
|
|
36
31
|
|
|
37
32
|
## Adding Pages
|
|
38
33
|
|
|
@@ -115,8 +110,8 @@ Use server routes when you need to proxy external APIs (avoid CORS), access
|
|
|
115
110
|
data server-side, or keep secrets off the client. Call them from client code
|
|
116
111
|
with `$fetch('/api/my-data/fetch')`.
|
|
117
112
|
|
|
118
|
-
See
|
|
119
|
-
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.
|
|
120
115
|
|
|
121
116
|
## Beyond the UI: Agents, MCP Servers, and Server Routes
|
|
122
117
|
|
|
@@ -124,7 +119,7 @@ Aether apps are more than just a Nuxt SPA. The project contains three additional
|
|
|
124
119
|
|
|
125
120
|
### `agents/` -- ADK Agents (Python)
|
|
126
121
|
|
|
127
|
-
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.
|
|
128
123
|
|
|
129
124
|
**Agent query path:** The app talks to Agent Engine directly — the portal is
|
|
130
125
|
only in the auth path. The flow is:
|
|
@@ -142,7 +137,7 @@ project detail page for IAM health status.
|
|
|
142
137
|
|
|
143
138
|
### `mcp-servers/` -- MCP Servers (Python)
|
|
144
139
|
|
|
145
|
-
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.
|
|
146
141
|
|
|
147
142
|
### `broadchurch.yaml`
|
|
148
143
|
|
|
@@ -157,11 +152,10 @@ Use these to build whatever UI fits the app:
|
|
|
157
152
|
local Nitro streaming route (`/api/agent/:agentId/stream`) which calls
|
|
158
153
|
Agent Engine directly with a tenant SA token. Handles streaming, session
|
|
159
154
|
management, and response parsing. Shows clear error messages when IAM
|
|
160
|
-
permissions are missing. See
|
|
155
|
+
permissions are missing. See [agents.md](agents.md) for details.
|
|
161
156
|
- **`useTenantConfig()`** -- Fetch the tenant's runtime config (deployed
|
|
162
157
|
agents, feature flags, MCP servers) from the Portal Gateway.
|
|
163
158
|
- **`useElementalClient()`** -- When using the Elemental API from the client,
|
|
164
|
-
see
|
|
159
|
+
see [data.md](data.md).
|
|
165
160
|
- **`usePrefsStore()` / `Pref<T>`** -- KV-backed user preferences. See
|
|
166
|
-
|
|
167
|
-
|
|
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>
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Cursor Cloud environment quirks (Node managed by env, dev server auto-started, skip browser testing during initial setup). Apply when the environment check in AGENTS.md indicates Cursor Cloud ($HOME under /root or /home/ubuntu, or a dev-server terminal was auto-started), or when the user mentions Cursor Cloud.
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
|
-
|
|
6
1
|
If you are in Cursor Cloud, the `environment.json` install step runs
|
|
7
2
|
`init-project.js` and `npm install` automatically, and starts a dev server
|
|
8
3
|
on port 3000.
|
|
@@ -59,4 +54,4 @@ check) and `npm run format:check` (Prettier). See Verification Commands.
|
|
|
59
54
|
|
|
60
55
|
**Before committing:** always run `npm run format` — the husky pre-commit
|
|
61
56
|
hook runs `lint-staged` with `prettier --check` and will reject
|
|
62
|
-
unformatted files.
|
|
57
|
+
unformatted files.
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Data access via Elemental API: client usage, schema discovery, entity search, API gotchas, MCP servers. Read when building features that fetch or display data from the Query Server."
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
1
|
# Data — Elemental API (platform data source)
|
|
6
2
|
|
|
7
3
|
**This app is built on the Lovelace platform.** The Query Server is the
|
|
@@ -81,10 +77,10 @@ Test those with curl before implementing them in code.
|
|
|
81
77
|
The gateway proxy authenticates on your behalf — no Auth0 tokens needed.
|
|
82
78
|
Read `broadchurch.yaml` for the three values you need:
|
|
83
79
|
|
|
84
|
-
| YAML path
|
|
85
|
-
|
|
86
|
-
| `gateway.url`
|
|
87
|
-
| `tenant.org_id`
|
|
80
|
+
| YAML path | Purpose |
|
|
81
|
+
| -------------------- | ------------------------------------ |
|
|
82
|
+
| `gateway.url` | Portal Gateway base URL |
|
|
83
|
+
| `tenant.org_id` | Your tenant ID (path segment) |
|
|
88
84
|
| `gateway.qs_api_key` | API key (sent as `X-Api-Key` header) |
|
|
89
85
|
|
|
90
86
|
Build the request URL as `{gateway.url}/api/qs/{tenant.org_id}/{endpoint}`
|
|
@@ -141,9 +137,9 @@ Elemental API patterns. **Use these instead of writing from scratch:**
|
|
|
141
137
|
|
|
142
138
|
```typescript
|
|
143
139
|
const { flavors, properties, flavorByName, pidByName, refresh } = useElementalSchema();
|
|
144
|
-
await refresh();
|
|
145
|
-
const articleFid = flavorByName('article');
|
|
146
|
-
const namePid = pidByName('name');
|
|
140
|
+
await refresh(); // fetches once, then cached
|
|
141
|
+
const articleFid = flavorByName('article'); // → string | null
|
|
142
|
+
const namePid = pidByName('name'); // → string | null
|
|
147
143
|
```
|
|
148
144
|
|
|
149
145
|
Handles the dual response shapes (`res.schema.flavors` vs `res.flavors`)
|
|
@@ -152,14 +148,20 @@ and the `fid`/`findex` naming inconsistency automatically.
|
|
|
152
148
|
### `utils/elementalHelpers` — Gateway URL Helpers
|
|
153
149
|
|
|
154
150
|
```typescript
|
|
155
|
-
import {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
151
|
+
import {
|
|
152
|
+
buildGatewayUrl,
|
|
153
|
+
getApiKey,
|
|
154
|
+
padNeid,
|
|
155
|
+
searchEntities,
|
|
156
|
+
getEntityName,
|
|
157
|
+
} from '~/utils/elementalHelpers';
|
|
158
|
+
|
|
159
|
+
const url = buildGatewayUrl('entities/search'); // full gateway URL
|
|
160
|
+
const key = getApiKey(); // from runtimeConfig
|
|
161
|
+
const neid = padNeid('4926132345040704022'); // → "04926132345040704022"
|
|
160
162
|
|
|
161
163
|
const results = await searchEntities('Microsoft'); // batch name search
|
|
162
|
-
const name = await getEntityName(neid);
|
|
164
|
+
const name = await getEntityName(neid); // display name lookup
|
|
163
165
|
```
|
|
164
166
|
|
|
165
167
|
## Client Usage
|
|
@@ -174,7 +176,10 @@ const client = useElementalClient();
|
|
|
174
176
|
|
|
175
177
|
const schema = await client.getSchema();
|
|
176
178
|
const entities = await client.findEntities({
|
|
177
|
-
expression: JSON.stringify({
|
|
179
|
+
expression: JSON.stringify({
|
|
180
|
+
type: 'comparison',
|
|
181
|
+
comparison: { operator: 'string_like', pid: 8, value: 'Apple' },
|
|
182
|
+
}),
|
|
178
183
|
limit: 5,
|
|
179
184
|
});
|
|
180
185
|
```
|
|
@@ -185,8 +190,8 @@ All methods return data directly and throw on non-2xx responses.
|
|
|
185
190
|
|
|
186
191
|
**Entity search and lookup:**
|
|
187
192
|
|
|
188
|
-
| Method
|
|
189
|
-
|
|
193
|
+
| Method | Signature | Purpose |
|
|
194
|
+
| -------------- | -------------------------- | --------------------------------------- |
|
|
190
195
|
| `findEntities` | `(body: FindEntitiesBody)` | Expression-based search (see `find.md`) |
|
|
191
196
|
|
|
192
197
|
> **Entity search**: Use `findEntities()` with `string_like` on the name PID
|
|
@@ -201,25 +206,25 @@ All methods return data directly and throw on non-2xx responses.
|
|
|
201
206
|
|
|
202
207
|
**Properties and schema:**
|
|
203
208
|
|
|
204
|
-
| Method
|
|
205
|
-
|
|
206
|
-
| `getSchema`
|
|
209
|
+
| Method | Signature | Purpose |
|
|
210
|
+
| ------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------ |
|
|
211
|
+
| `getSchema` | `()` | All entity types (flavors) and properties (PIDs) |
|
|
207
212
|
| `getPropertyValues` | `(body: { eids: string, pids: string })` | Property values (eids: JSON array of NEID strings; pids: JSON array of numeric PIDs) |
|
|
208
|
-
| `summarizeProperty` | `(pid: number)`
|
|
213
|
+
| `summarizeProperty` | `(pid: number)` | Summary stats for a property |
|
|
209
214
|
|
|
210
215
|
**Relationships and graph:**
|
|
211
216
|
|
|
212
|
-
| Method
|
|
213
|
-
|
|
217
|
+
| Method | Signature | Purpose |
|
|
218
|
+
| -------------- | -------------------------------- | ------------------------------------------------------------ |
|
|
214
219
|
| `findEntities` | `(body: { expression, limit? })` | Find linked entities via `linked` expression (see `find.md`) |
|
|
215
220
|
|
|
216
221
|
**Other:**
|
|
217
222
|
|
|
218
|
-
| Method
|
|
219
|
-
|
|
220
|
-
| `getHealth`
|
|
221
|
-
| `getStatus`
|
|
222
|
-
| `adaMessage` | `(body: AdaMessageBody)` | Ada AI chat
|
|
223
|
+
| Method | Signature | Purpose |
|
|
224
|
+
| ------------ | ------------------------ | ------------------------------ |
|
|
225
|
+
| `getHealth` | `()` | Health check |
|
|
226
|
+
| `getStatus` | `()` | Server status and capabilities |
|
|
227
|
+
| `adaMessage` | `(body: AdaMessageBody)` | Ada AI chat |
|
|
223
228
|
|
|
224
229
|
## Discovery-First Pattern
|
|
225
230
|
|
|
@@ -230,16 +235,16 @@ types or property names. Instead, discover them at runtime:
|
|
|
230
235
|
1. **Get the schema** — `client.getSchema()` returns all entity types (flavors)
|
|
231
236
|
and properties (PIDs) available in the system. See `schema.md`.
|
|
232
237
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
238
|
+
The schema response contains:
|
|
239
|
+
- **Flavors** (entity types): Company, Person, GovernmentOrg, etc.
|
|
240
|
+
Each flavor has a numeric ID and a human-readable name.
|
|
241
|
+
- **PIDs** (properties): name, country, industry, lei_code, etc.
|
|
242
|
+
Each PID has a type (`data_str`, `data_int`, `data_nindex`, etc.).
|
|
243
|
+
- Properties with type `data_nindex` are references to other entities —
|
|
244
|
+
resolve them with another `getPropertyValues` call.
|
|
240
245
|
|
|
241
|
-
|
|
242
|
-
|
|
246
|
+
Use flavor names in `findEntities()` expressions and PID names in
|
|
247
|
+
`getPropertyValues()`.
|
|
243
248
|
|
|
244
249
|
2. **Search with expressions** — `client.findEntities()` uses a JSON expression
|
|
245
250
|
language to search by type, property value, or relationship. See `find.md`.
|
|
@@ -269,10 +274,10 @@ For reliable agent behavior, prefer typed semantics over string heuristics:
|
|
|
269
274
|
|
|
270
275
|
There are two schema endpoints with **different response shapes**:
|
|
271
276
|
|
|
272
|
-
| Endpoint
|
|
273
|
-
|
|
274
|
-
| `GET /schema`
|
|
275
|
-
| `GET /elemental/metadata/schema` | nested (`res.schema.flavors`) | `fid`
|
|
277
|
+
| Endpoint | Flavors at | Flavor ID field | Detail level |
|
|
278
|
+
| -------------------------------- | ----------------------------- | --------------- | ------------------------------------ |
|
|
279
|
+
| `GET /schema` | top-level (`res.flavors`) | `findex` | Rich (display names, units, domains) |
|
|
280
|
+
| `GET /elemental/metadata/schema` | nested (`res.schema.flavors`) | `fid` | Basic (name + type only) |
|
|
276
281
|
|
|
277
282
|
The TypeScript client's `getSchema()` calls `/elemental/metadata/schema`,
|
|
278
283
|
so the response nests data under `.schema`. The generated types may suggest
|
|
@@ -296,12 +301,12 @@ The flavor identifier has **different field names** depending on the endpoint:
|
|
|
296
301
|
Same value, different key. Always use a fallback:
|
|
297
302
|
|
|
298
303
|
```typescript
|
|
299
|
-
const articleFlavor = flavors.find(f => f.name === 'article');
|
|
304
|
+
const articleFlavor = flavors.find((f) => f.name === 'article');
|
|
300
305
|
// Always use String() — safe for small IDs (12) and required for large ones
|
|
301
306
|
const articleFid = String(articleFlavor?.fid ?? articleFlavor?.findex ?? '');
|
|
302
307
|
|
|
303
308
|
// When building a FID lookup map:
|
|
304
|
-
const fidMap = new Map(flavors.map(f => [String(f.fid ?? f.findex), f.name]));
|
|
309
|
+
const fidMap = new Map(flavors.map((f) => [String(f.fid ?? f.findex), f.name]));
|
|
305
310
|
```
|
|
306
311
|
|
|
307
312
|
The `is_type` expression in `/elemental/find` always uses the `fid` key
|
|
@@ -352,14 +357,14 @@ const filingNeid = String(res.values[0].value).padStart(20, '0'); // "0492613234
|
|
|
352
357
|
```typescript
|
|
353
358
|
// WRONG — PIDs are numbers, not strings:
|
|
354
359
|
const values = await client.getPropertyValues({
|
|
355
|
-
|
|
356
|
-
|
|
360
|
+
eids: JSON.stringify(['00416400910670863867']),
|
|
361
|
+
pids: JSON.stringify(['name', 'country', 'industry']), // FAILS
|
|
357
362
|
});
|
|
358
363
|
|
|
359
364
|
// CORRECT — use numeric PIDs from getSchema():
|
|
360
365
|
const values = await client.getPropertyValues({
|
|
361
|
-
|
|
362
|
-
|
|
366
|
+
eids: JSON.stringify(['00416400910670863867']),
|
|
367
|
+
pids: JSON.stringify([8, 313]), // 8=name, 313=country (from schema)
|
|
363
368
|
});
|
|
364
369
|
```
|
|
365
370
|
|
|
@@ -409,7 +414,7 @@ const res = await client.getPropertyValues({
|
|
|
409
414
|
const docNeids = (res.values ?? []).map((v) => String(v.value).padStart(20, '0'));
|
|
410
415
|
```
|
|
411
416
|
|
|
412
|
-
See
|
|
417
|
+
See [cookbook-data.md](cookbook-data.md) in this skill for a full "Get filings for a company" recipe.
|
|
413
418
|
|
|
414
419
|
### Expression language pitfalls
|
|
415
420
|
|
|
@@ -455,14 +460,17 @@ source-specific schemas.
|
|
|
455
460
|
`getPropertyValues()` with the relationship PID. Values are entity IDs
|
|
456
461
|
that must be zero-padded to 20 characters.
|
|
457
462
|
|
|
458
|
-
See
|
|
463
|
+
See [cookbook-data.md](cookbook-data.md) (news feed recipe) for a full example.
|
|
459
464
|
|
|
460
465
|
## Error Handling
|
|
461
466
|
|
|
462
467
|
```typescript
|
|
463
468
|
try {
|
|
464
469
|
const data = await client.findEntities({
|
|
465
|
-
expression: JSON.stringify({
|
|
470
|
+
expression: JSON.stringify({
|
|
471
|
+
type: 'comparison',
|
|
472
|
+
comparison: { operator: 'string_like', pid: 8, value: 'Apple' },
|
|
473
|
+
}),
|
|
466
474
|
limit: 5,
|
|
467
475
|
});
|
|
468
476
|
} catch (error) {
|
|
@@ -479,7 +487,9 @@ functions instead:
|
|
|
479
487
|
import { getArticle } from '@yottagraph-app/elemental-api/client';
|
|
480
488
|
|
|
481
489
|
const response = await getArticle(artid);
|
|
482
|
-
if (response.status === 404) {
|
|
490
|
+
if (response.status === 404) {
|
|
491
|
+
/* handle not found */
|
|
492
|
+
}
|
|
483
493
|
```
|
|
484
494
|
|
|
485
495
|
## Lovelace MCP Servers
|
|
@@ -490,25 +500,25 @@ data exploration. **Check your tool list** — if tools like
|
|
|
490
500
|
exploration interface before writing code. If they don't appear, the
|
|
491
501
|
servers aren't connected; use curl and the skill docs instead.
|
|
492
502
|
|
|
493
|
-
| Server
|
|
494
|
-
|
|
495
|
-
| `lovelace-elemental`
|
|
496
|
-
| `lovelace-stocks`
|
|
497
|
-
| `lovelace-wiki`
|
|
498
|
-
| `lovelace-polymarket` | Prediction market data
|
|
503
|
+
| Server | What it provides |
|
|
504
|
+
| --------------------- | ----------------------------------------------------------------------------- |
|
|
505
|
+
| `lovelace-elemental` | Knowledge Graph: entities, relationships, events, sentiment, schema discovery |
|
|
506
|
+
| `lovelace-stocks` | Stock/financial market data |
|
|
507
|
+
| `lovelace-wiki` | Wikipedia entity enrichment |
|
|
508
|
+
| `lovelace-polymarket` | Prediction market data |
|
|
499
509
|
|
|
500
510
|
### MCP Tool Quick Reference
|
|
501
511
|
|
|
502
|
-
| Tool
|
|
503
|
-
|
|
504
|
-
| `elemental_get_schema`
|
|
505
|
-
| `elemental_get_entity`
|
|
506
|
-
| `elemental_get_related`
|
|
507
|
-
| `elemental_get_relationships`
|
|
508
|
-
| `elemental_graph_neighborhood` | Most influential neighbors of an entity
|
|
509
|
-
| `elemental_graph_sentiment`
|
|
510
|
-
| `elemental_get_events`
|
|
511
|
-
| `elemental_health`
|
|
512
|
+
| Tool | Purpose | Use to verify... |
|
|
513
|
+
| ------------------------------ | -------------------------------------------------------------- | ------------------------------------ |
|
|
514
|
+
| `elemental_get_schema` | Discover entity types (flavors), properties, and relationships | Flavor IDs, property IDs, data types |
|
|
515
|
+
| `elemental_get_entity` | Look up entity by name or NEID; returns properties | Entity resolution, property shapes |
|
|
516
|
+
| `elemental_get_related` | Related entities with type/relationship filters | Relationship types and traversal |
|
|
517
|
+
| `elemental_get_relationships` | Relationship types and counts between two entities | Edge types between specific entities |
|
|
518
|
+
| `elemental_graph_neighborhood` | Most influential neighbors of an entity | Graph connectivity |
|
|
519
|
+
| `elemental_graph_sentiment` | Sentiment analysis from news articles | Sentiment data availability |
|
|
520
|
+
| `elemental_get_events` | Events for an entity or by search query | Event categories and shapes |
|
|
521
|
+
| `elemental_health` | Health check | Server connectivity |
|
|
512
522
|
|
|
513
523
|
MCP tools handle entity resolution, PID lookups, and NEID formatting
|
|
514
524
|
automatically. Use them to discover IDs and verify data exists before
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: App, agent, and MCP server deployment targets (Vercel, Vertex AI Agent Engine, Cloud Run). Apply when pushing to main, running /deploy_agent or /deploy_mcp, or explaining how code reaches production.
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
|
-
|
|
6
1
|
### App (Nuxt UI + server routes)
|
|
7
2
|
|
|
8
3
|
Vercel auto-deploys on every push to `main`. Preview deployments are created for
|
|
@@ -16,4 +11,4 @@ the Portal UI or `/deploy_agent` in Cursor.
|
|
|
16
11
|
### MCP Servers (`mcp-servers/`)
|
|
17
12
|
|
|
18
13
|
Each subdirectory in `mcp-servers/` is a Python FastMCP server. Deploy via
|
|
19
|
-
the Portal UI or `/deploy_mcp` in Cursor.
|
|
14
|
+
the Portal UI or `/deploy_mcp` in Cursor.
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "DESIGN.md workflow, feature docs, starter app is placeholder. Read when starting work, planning features, or updating project design."
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
|
-
|
|
6
1
|
# Design
|
|
7
2
|
|
|
8
3
|
Read `DESIGN.md` before starting any work. It is the source of truth for project vision, architecture, and current implementation status.
|
|
@@ -58,4 +53,4 @@ If the user is implementing a change that has no feature doc, encourage them to
|
|
|
58
53
|
|
|
59
54
|
**Exception for initial app builds:** When building a new app from scratch via `/build_my_app`, skip per-page feature docs. They add overhead during greenfield builds where the entire app is being created at once. Start using feature docs once the initial app is built and you're iterating on individual features.
|
|
60
55
|
|
|
61
|
-
It is a good practice to close out one feature doc and start a new one as the focus of the work shifts. It is acceptable to be working with multiple feature docs at once, if the user is working on multiple unconnected or loosely connected features. The sections of the feature doc are flexible and you should add or remove sections to fit the needs of the project.
|
|
56
|
+
It is a good practice to close out one feature doc and start a new one as the focus of the work shifts. It is acceptable to be working with multiple feature docs at once, if the user is working on multiple unconnected or loosely connected features. The sections of the feature doc are flexible and you should add or remove sections to fit the needs of the project.
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: .env variable reference (APP_ID, USER_NAME, QUERY_SERVER_ADDRESS, etc.). Apply when adding env vars, configuring Auth0 bypass, or inspecting runtime config.
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
|
-
|
|
6
1
|
| Variable | Purpose | Default |
|
|
7
2
|
| ---------------------------------- | -------------------------------- | --------------------------------------- |
|
|
8
3
|
| `NUXT_PUBLIC_APP_ID` | Unique app identifier | derived from directory name |
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Git commit workflow and conventions. Apply when finishing implementation work, making commits, or troubleshooting git/pre-commit failures."
|
|
3
|
-
alwaysApply: false
|
|
4
|
-
---
|
|
5
|
-
|
|
6
1
|
# Git Workflow
|
|
7
2
|
|
|
8
|
-
This
|
|
3
|
+
This guidance applies both when an agent is committing its own work and when helping a user commit theirs.
|
|
9
4
|
|
|
10
5
|
## Committing
|
|
11
6
|
|
|
@@ -14,9 +9,9 @@ Commit when you finish a meaningful unit of work — a feature, a fix, a refacto
|
|
|
14
9
|
### Steps
|
|
15
10
|
|
|
16
11
|
1. **Run formatting first** — this is required or the commit will fail:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
```bash
|
|
13
|
+
npm run format
|
|
14
|
+
```
|
|
20
15
|
2. **Stage all files** — always use `git add -A`.
|
|
21
16
|
3. **Commit** with the message format below.
|
|
22
17
|
4. **Verify the commit succeeded** with `git status`. If it failed, see Pre-commit Failure Troubleshooting below. Do not proceed until the commit is confirmed.
|