@yottagraph-app/aether-instructions 1.1.4 → 1.1.5

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/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.5",
4
4
  "description": "Cursor rules, commands, and skills for Aether development",
5
5
  "files": [
6
6
  "rules",
package/rules/agents.mdc CHANGED
@@ -175,8 +175,62 @@ Chat UI (pages/chat.vue)
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 chat page 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
 
@@ -133,17 +133,21 @@ Tenant-specific configuration generated during provisioning. Contains GCP projec
133
133
 
134
134
  ## Built-in Pages
135
135
 
136
- These pages ship with the template and can be kept, modified, or removed
137
- based on the app's needs:
136
+ Recent template versions include these pages. They can be kept, modified,
137
+ or removed based on the app's needs:
138
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.
139
+ - `pages/chat.vue` -- Agent chat UI. Uses `useAgentChat()` and
140
+ `useTenantConfig()` to discover deployed agents and stream responses
141
+ through the Portal Gateway. Keep if the app uses AI agents.
141
142
  - `pages/mcp.vue` -- MCP Explorer. Browse and test MCP server tools. Keep
142
143
  if the app uses MCP servers.
143
144
  - `pages/entity-lookup.vue` -- Entity search tool. Useful for looking up
144
145
  NEIDs. Keep or remove based on the app.
145
146
 
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.
147
+ **If these pages are missing** from your project, your project was created
148
+ from an older template version. Create them from scratch — they're
149
+ straightforward Vuetify pages. The key composables (`useAgentChat`,
150
+ `useTenantConfig`) are included in all template versions and provide the
151
+ connection logic. See the `agents` cursor rule for the gateway endpoints
152
+ and response formats these pages use.
149
153
 
@@ -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
  }