@yottagraph-app/aether-instructions 1.1.4 → 1.1.6

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.
@@ -73,8 +73,8 @@ Key capabilities:
73
73
  - **Query Server / Elemental API** -- the primary data source. Use `useElementalClient()` from `@yottagraph-app/elemental-api/client`. See the `api` rule.
74
74
  - **KV storage** -- always available for preferences and lightweight data (see `pref` rule)
75
75
  - **Supabase** -- check if `NUXT_PUBLIC_SUPABASE_URL` is in `.env` for database access
76
- - **AI agent chat** -- `pages/chat.vue` exists for agent interactions
77
- - **MCP Explorer** -- `pages/mcp.vue` for testing MCP tools
76
+ - **AI agent chat** -- use the `useAgentChat` composable to build a chat UI for deployed agents
77
+ - **MCP servers** -- Lovelace MCP servers may be available (check `.cursor/mcp.json`)
78
78
  - **Components** -- Vuetify 3 component library is available
79
79
 
80
80
  ---
@@ -96,7 +96,7 @@ Plan what you'll build:
96
96
  3. What shared logic belongs in `composables/`
97
97
  4. What data needs to be persisted (and whether KV or Supabase is appropriate)
98
98
  5. Whether the app needs AI agents or MCP servers
99
- 6. Whether to keep, modify, or remove the built-in pages (`chat.vue`, `mcp.vue`, `entity-lookup.vue`)
99
+ 6. Whether the app needs an agent chat page (use the `useAgentChat` composable)
100
100
  7. Whether `app.vue` needs a sidebar, tabs, or other navigation (and what it should look like)
101
101
 
102
102
  Present the plan to the user and ask for approval before proceeding.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yottagraph-app/aether-instructions",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "Cursor rules, commands, and skills for Aether development",
5
5
  "files": [
6
6
  "rules",
package/rules/agents.mdc CHANGED
@@ -161,22 +161,76 @@ adk deploy agent_engine \
161
161
  agents/<agent-name>/
162
162
  ```
163
163
 
164
- ## How Agents Reach the Chat UI
164
+ ## How Agents Reach the App
165
165
 
166
166
  Once deployed, the agent is reachable through the Portal Gateway:
167
167
 
168
168
  ```
169
- Chat UI (pages/chat.vue)
169
+ App (useAgentChat composable)
170
170
  → POST NUXT_PUBLIC_GATEWAY_URL/api/agents/{tenantId}/{agentId}/query
171
171
  → Portal Gateway proxies to Vertex AI Agent Engine (streamQuery)
172
172
  → Agent runs (may invoke tools, make multiple LLM calls)
173
173
  → Gateway collects the ADK event stream, extracts final text
174
- Chat UI displays it
174
+ App displays it
175
175
  ```
176
176
 
177
177
  The gateway URL and tenant ID come from `broadchurch.yaml` (injected as
178
- `NUXT_PUBLIC_GATEWAY_URL` and `NUXT_PUBLIC_TENANT_ORG_ID`). The chat page
179
- discovers available agents from the Portal config endpoint.
178
+ `NUXT_PUBLIC_GATEWAY_URL` and `NUXT_PUBLIC_TENANT_ORG_ID`).
179
+
180
+ ### Agent Discovery
181
+
182
+ The app discovers deployed agents by fetching the tenant config:
183
+
184
+ ```
185
+ GET {NUXT_PUBLIC_GATEWAY_URL}/api/config/{NUXT_PUBLIC_TENANT_ORG_ID}
186
+ ```
187
+
188
+ The response includes an `agents` array:
189
+
190
+ ```json
191
+ {
192
+ "agents": [
193
+ { "name": "filing_analyst", "display_name": "Filing Analyst", "engine_id": "1234567890" },
194
+ { "name": "research_bot", "display_name": "Research Bot", "engine_id": "0987654321" }
195
+ ],
196
+ "features": { "chat": true, ... },
197
+ ...
198
+ }
199
+ ```
200
+
201
+ Each agent entry has:
202
+
203
+ | Field | Type | Description |
204
+ |---|---|---|
205
+ | `name` | `string` | Agent directory name (e.g. `filing_analyst`) |
206
+ | `display_name` | `string` | Human-readable name for the UI |
207
+ | `engine_id` | `string` | Vertex AI Agent Engine resource ID — used as `{agentId}` in query/stream URLs |
208
+
209
+ The `engine_id` is the key value — it becomes the `{agentId}` path
210
+ parameter in `POST /api/agents/{tenantId}/{agentId}/query`.
211
+
212
+ **How agents get populated:** The portal discovers agents from two sources:
213
+ 1. **Firestore** — agents registered by the deploy workflow (`deploy-agent.yml`
214
+ calls `POST /api/agents/{tenantId}` to register)
215
+ 2. **Agent Engine API** — the portal also queries Vertex AI for reasoning
216
+ engines whose display name starts with the project name (e.g.
217
+ `my-project--filing_analyst`), catching agents that were deployed but
218
+ not yet registered
219
+
220
+ Both sources are merged and deduplicated by name. If the config endpoint
221
+ returns an empty `agents` array, no agents have been deployed yet.
222
+
223
+ Use `useTenantConfig()` to fetch this config from Vue code:
224
+
225
+ ```typescript
226
+ import { useTenantConfig } from '~/composables/useTenantConfig';
227
+
228
+ const { config, fetchConfig } = useTenantConfig();
229
+ await fetchConfig();
230
+
231
+ const agents = config.value?.agents ?? [];
232
+ const agentId = agents[0]?.engine_id; // use as {agentId} in query URLs
233
+ ```
180
234
 
181
235
  ### Gateway Request
182
236
 
package/rules/api.mdc CHANGED
@@ -20,7 +20,9 @@ For full endpoint documentation, read the **elemental-api skill** in
20
20
  `skills/elemental-api/`. Start with `SKILL.md`, then `overview.md`.
21
21
  These files are copied from `@yottagraph-app/elemental-api-skill` during
22
22
  `npm install` (postinstall step) — if the directory is empty, run
23
- `npm install` first.
23
+ `npm install` first. The skill docs contain detailed response shapes and
24
+ edge cases that go beyond this rule's quick reference — **run `npm install`
25
+ early** to make them available during initial exploration.
24
26
 
25
27
  Key files:
26
28
  - `entities.md` — entity search, details, and properties
@@ -153,6 +155,28 @@ const flavors = res.schema?.flavors ?? (res as any).flavors ?? [];
153
155
  The `(res as any).properties` fallback is there in case the API is ever
154
156
  fixed to match the types. Use this pattern every time.
155
157
 
158
+ ### `getNamedEntityReport()` response is nested under `.report`
159
+
160
+ Same problem as `getSchema()`. The TypeScript types suggest entity fields
161
+ (`name`, `aliases`, `type`) exist at the top level. **They don't.** The
162
+ API wraps them in a `.report` container. The generated client does NOT
163
+ unwrap this automatically.
164
+
165
+ ```typescript
166
+ // WRONG — name will be undefined:
167
+ const res = await client.getNamedEntityReport(neid);
168
+ const name = res.name; // undefined!
169
+
170
+ // CORRECT — always access through .report:
171
+ const res = await client.getNamedEntityReport(neid);
172
+ const name = res.report?.name ?? (res as any).name ?? neid;
173
+ const aliases = res.report?.aliases ?? (res as any).aliases ?? [];
174
+ const type = res.report?.type ?? (res as any).type;
175
+ ```
176
+
177
+ The `(res as any).name` fallback handles the case where the client is
178
+ eventually fixed to unwrap the response.
179
+
156
180
  > **WARNING -- `getPropertyValues()` takes JSON-stringified arrays**: The `eids`
157
181
  > and `pids` parameters must be JSON-encoded strings, NOT native arrays. The
158
182
  > TypeScript type is `string`, not `string[]`. Passing a raw array will silently
@@ -175,6 +199,17 @@ financial instruments, events, and all other types are excluded — even
175
199
  though the schema shows relationships like `filed` connecting organizations
176
200
  to documents.
177
201
 
202
+ **Why?** The knowledge graph has two layers. The **graph layer** models
203
+ first-class entities (people, organizations, locations) as nodes with
204
+ edges between them — this is what `getLinkedEntities` traverses. The
205
+ **property layer** attaches everything else (documents, filings, financial
206
+ instruments, events) as property values on graph nodes. Documents aren't
207
+ "lesser" entities — they're stored differently because they're associated
208
+ with specific graph nodes rather than standing independently in the graph.
209
+ Understanding this distinction helps you generalize: if a target entity
210
+ type doesn't appear in the `getLinkedEntities` response, it's a property-
211
+ layer entity and you need `getPropertyValues` with the relationship PID.
212
+
178
213
  To traverse relationships to non-graph-node types, use `getPropertyValues`
179
214
  with the relationship PID instead. Relationship properties (`data_nindex`)
180
215
  return linked entity IDs as values. Zero-pad the returned IDs to 20
@@ -236,9 +271,12 @@ const res = await client.getPropertyValues({
236
271
  // 3. Pad IDs to 20 chars to form valid NEIDs
237
272
  const docNeids = res.values.map((v: any) => String(v.value).padStart(20, '0'));
238
273
 
239
- // 4. Get details for each linked entity
274
+ // 4. Get details for each linked entity (response is nested under .report)
240
275
  const reports = await Promise.all(
241
- docNeids.map((neid: string) => client.getNamedEntityReport(neid)),
276
+ docNeids.map(async (neid: string) => {
277
+ const r = await client.getNamedEntityReport(neid);
278
+ return r.report ?? r;
279
+ }),
242
280
  );
243
281
  ```
244
282
 
@@ -291,8 +329,8 @@ the servers route through the Portal Gateway proxy (no credentials needed).
291
329
  For local development without a gateway, the servers require an
292
330
  `AUTH0_M2M_DEV_TOKEN` environment variable.
293
331
 
294
- The MCP Explorer page (`pages/mcp.vue`) also connects to these servers
295
- through the Portal Gateway for interactive exploration in the browser.
332
+ These servers are also accessible from the browser through the Portal
333
+ Gateway, so you can build MCP tool exploration UIs if needed.
296
334
 
297
335
  ### When MCP Servers Are Available
298
336
 
@@ -121,7 +121,7 @@ Aether apps are more than just a Nuxt SPA. The project contains three additional
121
121
 
122
122
  ### `agents/` -- ADK Agents (Python)
123
123
 
124
- Each subdirectory is a self-contained Python agent that deploys to Vertex AI Agent Engine. See the `agents` cursor rule for development patterns. Agents are deployed via the Broadchurch Portal UI or the `/deploy_agent` Cursor command, both of which trigger `deploy-agent.yml`. Once deployed, the chat UI at `pages/chat.vue` talks to agents through the Portal Gateway (`NUXT_PUBLIC_GATEWAY_URL`).
124
+ Each subdirectory is a self-contained Python agent that deploys to Vertex AI Agent Engine. See the `agents` cursor rule for development patterns. Agents are deployed via the Broadchurch Portal UI or the `/deploy_agent` Cursor command, both of which trigger `deploy-agent.yml`. Once deployed, agents are reachable through the Portal Gateway (`NUXT_PUBLIC_GATEWAY_URL`). Use the `useAgentChat` composable to build a chat UI that talks to them.
125
125
 
126
126
  ### `mcp-servers/` -- MCP Servers (Python)
127
127
 
@@ -131,19 +131,19 @@ Each subdirectory is a FastMCP server that deploys to Cloud Run. See the `mcp-se
131
131
 
132
132
  Tenant-specific configuration generated during provisioning. Contains GCP project, org ID, service account, gateway URL, and query server URL. Read by deploy commands and GitHub Actions workflows. Don't edit manually.
133
133
 
134
- ## Built-in Pages
135
-
136
- These pages ship with the template and can be kept, modified, or removed
137
- based on the app's needs:
138
-
139
- - `pages/chat.vue` -- Agent chat UI. Talks to deployed ADK agents through
140
- the Portal Gateway with streaming support. Keep if the app uses AI agents.
141
- - `pages/mcp.vue` -- MCP Explorer. Browse and test MCP server tools. Keep
142
- if the app uses MCP servers.
143
- - `pages/entity-lookup.vue` -- Entity search tool. Useful for looking up
144
- NEIDs. Keep or remove based on the app.
145
-
146
- If any of these pages are missing from your project, your project may have
147
- been created from an older template version. Copy them from the latest
148
- aether-dev source or run `/update_instructions` to check for updates.
134
+ ## Available Composables for Platform Features
135
+
136
+ The template ships composables for interacting with the Lovelace platform.
137
+ Use these to build whatever UI fits the app:
138
+
139
+ - **`useAgentChat()`** -- Send messages to deployed ADK agents through the
140
+ Portal Gateway. Handles streaming, session management, and response
141
+ parsing. See the `agents` cursor rule for gateway endpoints and response
142
+ formats.
143
+ - **`useTenantConfig()`** -- Fetch the tenant's runtime config (deployed
144
+ agents, feature flags, MCP servers) from the Portal Gateway.
145
+ - **`useElementalClient()`** -- Query Server client for entities, news,
146
+ filings, etc. See the `api` rule.
147
+ - **`usePrefsStore()` / `Pref<T>`** -- KV-backed user preferences. See
148
+ the `pref` rule.
149
149
 
@@ -467,7 +467,7 @@ NOT supported — use `getPropertyValues` with the relationship PID instead.
467
467
  docNeids.map(async (neid: string) => {
468
468
  try {
469
469
  const r = await client.getNamedEntityReport(neid);
470
- return r.name || neid;
470
+ return r.report?.name ?? (r as any).name ?? neid;
471
471
  } catch {
472
472
  return neid;
473
473
  }
package/rules/design.mdc CHANGED
@@ -15,16 +15,13 @@ The sections of the design doc are flexible and you should add or remove section
15
15
 
16
16
  # Starter App is a Placeholder
17
17
 
18
- The default UI that ships with this template (home page, chat page, entity
19
- lookup) is **placeholder content** meant to demonstrate capabilities. When
20
- building from a project brief or user request, feel free to:
18
+ The default UI that ships with this template is **placeholder content**.
19
+ When building from a project brief or user request, feel free to:
21
20
 
22
21
  - **Replace** `pages/index.vue` with the app's real home page
23
- - **Remove** example pages (`entity-lookup.vue`, `chat.vue`, `mcp.vue`)
24
- if the app doesn't need them
22
+ - **Remove** any pages that don't fit the app
25
23
  - **Restructure** the navigation, layout, and branding entirely
26
- - **Keep** only the infrastructure: `composables/`, `server/api/kv/`,
27
- `agents/`, and `pages/chat.vue` (if the app uses agent chat)
24
+ - **Keep** the infrastructure: `composables/`, `server/api/kv/`, `agents/`
28
25
 
29
26
  Do NOT treat the existing UI as something to preserve. Build what the
30
27
  user described, using the template's infrastructure and patterns but not