@yottagraph-app/aether-instructions 1.1.17 → 1.1.19
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 +1 -1
- package/rules/agents.mdc +27 -2
- package/rules/api.mdc +135 -93
- package/rules/cookbook.mdc +49 -16
- package/skills/data-model/newsdata/schema.yaml +10 -0
- package/skills/elemental-api/SKILL.md +4 -10
- package/skills/elemental-api/entities.md +37 -112
- package/skills/elemental-api/find.md +19 -4
- package/skills/elemental-api/graph.md +3 -3
- package/skills/elemental-api/overview.md +46 -22
- package/skills/elemental-api/schema.md +10 -30
- package/skills/elemental-api/articles.md +0 -386
- package/skills/elemental-api/events.md +0 -145
- package/skills/elemental-api/llm.md +0 -18
- package/skills/elemental-api/relationships.md +0 -310
- package/skills/elemental-api/sentiment.md +0 -93
- package/skills/test-api-queries/SKILL.md +0 -63
- package/skills/test-api-queries/query-api.js +0 -172
package/package.json
CHANGED
package/rules/agents.mdc
CHANGED
|
@@ -88,9 +88,9 @@ dev (`agents/` on sys.path → absolute import) and Agent Engine runtime
|
|
|
88
88
|
|
|
89
89
|
Key endpoints:
|
|
90
90
|
- `GET /elemental/metadata/schema` — entity types and properties
|
|
91
|
-
- `POST /elemental/find` — search for entities
|
|
91
|
+
- `POST /elemental/find` — search for entities by expression
|
|
92
|
+
- `POST /entities/search` — search for entities by name (batch, scored)
|
|
92
93
|
- `POST /elemental/entities/properties` — get entity property values
|
|
93
|
-
- `GET /entities/lookup?q=<name>` — look up entity by name
|
|
94
94
|
|
|
95
95
|
Requirements for agents using the Elemental API (add to `requirements.txt`):
|
|
96
96
|
```
|
|
@@ -352,6 +352,31 @@ for await (const { event, data } of readSSE(res)) {
|
|
|
352
352
|
The `done` event always includes the final extracted text, so you don't
|
|
353
353
|
need to track text deltas yourself.
|
|
354
354
|
|
|
355
|
+
## useAgentChat Gotcha — Vue Reactivity
|
|
356
|
+
|
|
357
|
+
When building a chat UI with `useAgentChat`, do NOT hold a local reference
|
|
358
|
+
to a message object after pushing it into the `messages` array. Vue's
|
|
359
|
+
reactivity only tracks mutations made through the reactive Proxy — writes
|
|
360
|
+
to the original plain object are invisible to the template.
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
// WRONG — local ref bypasses Vue's reactivity, UI won't update:
|
|
364
|
+
const msg: ChatMessage = { id: '...', role: 'agent', text: '', streaming: true };
|
|
365
|
+
messages.value.push(msg);
|
|
366
|
+
msg.text = 'hello'; // data changes, but Vue doesn't know
|
|
367
|
+
msg.streaming = false; // template still shows typing indicator
|
|
368
|
+
|
|
369
|
+
// CORRECT — access through the reactive array:
|
|
370
|
+
messages.value.push({ id: '...', role: 'agent', text: '', streaming: true });
|
|
371
|
+
const idx = messages.value.length - 1;
|
|
372
|
+
messages.value[idx].text = 'hello'; // Vue detects this
|
|
373
|
+
messages.value[idx].streaming = false; // template re-renders
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
The `useAgentChat` composable uses the correct pattern internally (via an
|
|
377
|
+
`updateAgent()` helper that writes through the array index). If you build a
|
|
378
|
+
custom chat composable or modify `sendMessage`, follow the same approach.
|
|
379
|
+
|
|
355
380
|
## Agent Design Guidelines
|
|
356
381
|
|
|
357
382
|
- Keep agents focused: one agent per domain or task type
|
package/rules/api.mdc
CHANGED
|
@@ -26,6 +26,52 @@ the directory is missing, run `/update_instructions` to install it.
|
|
|
26
26
|
|
|
27
27
|
For Lovelace **entity types, properties, relationships, and per-source schemas** (EDGAR, FRED, FDIC, etc.), read the **data-model skill** in `.cursor/skills/data-model/`. Start with `SKILL.md`, then `overview.md` and the source-specific folders. Both skills are distributed via `@yottagraph-app/aether-instructions` and installed during project init.
|
|
28
28
|
|
|
29
|
+
## Test Before You Build
|
|
30
|
+
|
|
31
|
+
**Before writing app code that calls the Query Server, test the actual API
|
|
32
|
+
call first and verify the response shape.** This avoids wasted iteration from incorrect
|
|
33
|
+
assumptions about response shapes.
|
|
34
|
+
|
|
35
|
+
### How to test
|
|
36
|
+
|
|
37
|
+
The gateway proxy authenticates on your behalf — no Auth0 tokens needed.
|
|
38
|
+
Read `broadchurch.yaml` for the three values you need:
|
|
39
|
+
|
|
40
|
+
| YAML path | Purpose |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `gateway.url` | Portal Gateway base URL |
|
|
43
|
+
| `tenant.org_id` | Your tenant ID (path segment) |
|
|
44
|
+
| `gateway.qs_api_key` | API key (sent as `X-Api-Key` header) |
|
|
45
|
+
|
|
46
|
+
Build the request URL as `{gateway.url}/api/qs/{tenant.org_id}/{endpoint}`
|
|
47
|
+
and include the header `X-Api-Key: {gateway.qs_api_key}`.
|
|
48
|
+
|
|
49
|
+
### Example calls
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Variables — read these from broadchurch.yaml
|
|
53
|
+
GW="https://broadchurch-portal-194773164895.us-central1.run.app"
|
|
54
|
+
ORG="org_abc123"
|
|
55
|
+
KEY="qs_..."
|
|
56
|
+
|
|
57
|
+
# Search for an entity by name
|
|
58
|
+
curl -s "$GW/api/qs/$ORG/entities/search" \
|
|
59
|
+
-X POST -H "Content-Type: application/json" \
|
|
60
|
+
-H "X-Api-Key: $KEY" \
|
|
61
|
+
-d '{"queries":[{"queryId":1,"query":"Microsoft"}],"maxResults":3}'
|
|
62
|
+
|
|
63
|
+
# Get entity properties (form-encoded)
|
|
64
|
+
curl -s -X POST "$GW/api/qs/$ORG/elemental/entities/properties" \
|
|
65
|
+
-H "X-Api-Key: $KEY" \
|
|
66
|
+
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
67
|
+
--data-urlencode 'eids=["00416400910670863867"]' \
|
|
68
|
+
--data-urlencode 'pids=[8,313]' | jq .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`/elemental/find` and `/elemental/entities/properties` require
|
|
72
|
+
`application/x-www-form-urlencoded` with JSON-stringified parameter values.
|
|
73
|
+
All other endpoints accept `application/json`.
|
|
74
|
+
|
|
29
75
|
## Client Usage
|
|
30
76
|
|
|
31
77
|
All API calls go through `useElementalClient()` from `@yottagraph-app/elemental-api/client`.
|
|
@@ -36,15 +82,18 @@ import { useElementalClient } from '@yottagraph-app/elemental-api/client';
|
|
|
36
82
|
|
|
37
83
|
const client = useElementalClient();
|
|
38
84
|
|
|
39
|
-
const results = await client.getNEID({ entityName: 'Apple', maxResults: 5 });
|
|
40
|
-
const report = await client.getNamedEntityReport(results.neids[0]);
|
|
41
85
|
const schema = await client.getSchema();
|
|
86
|
+
const report = await client.getNamedEntityReport('00508379502570440213');
|
|
87
|
+
const entities = await client.findEntities({
|
|
88
|
+
expression: JSON.stringify({ type: 'comparison', comparison: { operator: 'string_like', pid: 8, value: 'Apple' } }),
|
|
89
|
+
limit: 5,
|
|
90
|
+
});
|
|
42
91
|
```
|
|
43
92
|
|
|
44
93
|
Types are also imported from the client:
|
|
45
94
|
|
|
46
95
|
```typescript
|
|
47
|
-
import type { NamedEntityReport
|
|
96
|
+
import type { NamedEntityReport } from '@yottagraph-app/elemental-api/client';
|
|
48
97
|
```
|
|
49
98
|
|
|
50
99
|
### Client Method Quick Reference
|
|
@@ -55,11 +104,15 @@ All methods return data directly and throw on non-2xx responses.
|
|
|
55
104
|
|
|
56
105
|
| Method | Signature | Purpose |
|
|
57
106
|
|---|---|---|
|
|
58
|
-
| `getNEID` | `(params: { entityName, maxResults?, includeNames? })` | Lookup entity by name |
|
|
59
107
|
| `findEntities` | `(body: FindEntitiesBody)` | Expression-based search (see `find.md`) |
|
|
60
108
|
| `getNamedEntityReport` | `(neid: string)` | Entity details (name, aliases, type) |
|
|
61
109
|
| `getEntityDetails` | `(neid: string)` | Alias for entity reports |
|
|
62
110
|
|
|
111
|
+
> **Entity search**: Use `findEntities()` with `string_like` on the name PID
|
|
112
|
+
> for name-based searches, or call `POST /entities/search` directly via
|
|
113
|
+
> `$fetch` for batch name resolution with scored ranking (this endpoint is
|
|
114
|
+
> not wrapped by the generated client).
|
|
115
|
+
|
|
63
116
|
**Properties and schema:**
|
|
64
117
|
|
|
65
118
|
| Method | Signature | Purpose |
|
|
@@ -72,23 +125,7 @@ All methods return data directly and throw on non-2xx responses.
|
|
|
72
125
|
|
|
73
126
|
| Method | Signature | Purpose |
|
|
74
127
|
|---|---|---|
|
|
75
|
-
| `
|
|
76
|
-
| `getLinks` | `(sourceNeid, targetNeid, params?)` | Links between two specific entities |
|
|
77
|
-
| `getLinkCounts` | `(sourceNeid, targetNeid)` | Link counts between entities |
|
|
78
|
-
| `getNeighborhood` | `(centerNeid, params?)` | Neighboring entities |
|
|
79
|
-
| `getGraphLayout` | `(centerNeid, params?)` | Graph layout for visualization |
|
|
80
|
-
|
|
81
|
-
**News, events, and sentiment:**
|
|
82
|
-
|
|
83
|
-
| Method | Signature | Purpose |
|
|
84
|
-
|---|---|---|
|
|
85
|
-
| `getArticle` | `(artid: string)` | Article by ID |
|
|
86
|
-
| `getArticleText` | `(artid: string)` | Article full text |
|
|
87
|
-
| `getEvent` | `(eveid: string)` | Event by ID |
|
|
88
|
-
| `getEventsForEntity` | `(params: { neid, startTime?, endTime? })` | Events involving an entity |
|
|
89
|
-
| `getMentions` | `(params: { neid, startTime?, endTime? })` | Mention codes for entities |
|
|
90
|
-
| `getMentionCounts` | `(params: { neid, ... })` | Bucketed mention counts |
|
|
91
|
-
| `getNamedEntitySentiment` | `(neid: string)` | Sentiment for an entity |
|
|
128
|
+
| `findEntities` | `(body: { expression, limit? })` | Find linked entities via `linked` expression (see `find.md`) |
|
|
92
129
|
|
|
93
130
|
**Other:**
|
|
94
131
|
|
|
@@ -171,6 +208,22 @@ const type = res.report?.type ?? (res as any).type;
|
|
|
171
208
|
The `(res as any).name` fallback handles the case where the client is
|
|
172
209
|
eventually fixed to unwrap the response.
|
|
173
210
|
|
|
211
|
+
### Relationship property values need zero-padding to form valid NEIDs
|
|
212
|
+
|
|
213
|
+
Relationship properties (`data_nindex`) return linked entity IDs as raw
|
|
214
|
+
numbers (e.g. `4926132345040704022`). These must be **zero-padded to 20
|
|
215
|
+
characters** to form valid NEIDs. This is easy to miss and causes silent
|
|
216
|
+
failures — `getNamedEntityReport` returns a 404, `getPropertyValues`
|
|
217
|
+
returns empty results.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
// WRONG — raw value is NOT a valid NEID:
|
|
221
|
+
const filingId = res.values[0].value; // "4926132345040704022" (19 chars)
|
|
222
|
+
|
|
223
|
+
// CORRECT — always pad to 20 characters:
|
|
224
|
+
const filingNeid = String(res.values[0].value).padStart(20, '0'); // "04926132345040704022"
|
|
225
|
+
```
|
|
226
|
+
|
|
174
227
|
> **WARNING -- `getPropertyValues()` takes JSON-stringified arrays**: The `eids`
|
|
175
228
|
> and `pids` parameters must be JSON-encoded strings, NOT native arrays. The
|
|
176
229
|
> TypeScript type is `string`, not `string[]`. Passing a raw array will silently
|
|
@@ -183,31 +236,41 @@ const values = await client.getPropertyValues({
|
|
|
183
236
|
});
|
|
184
237
|
```
|
|
185
238
|
|
|
186
|
-
###
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
type
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
239
|
+
### Traversing relationships: graph-layer vs property-layer entities
|
|
240
|
+
|
|
241
|
+
The knowledge graph has two layers:
|
|
242
|
+
|
|
243
|
+
- **Graph layer** — people, organizations, and locations are first-class
|
|
244
|
+
nodes with edges between them. Use `findEntities()` with a `linked`
|
|
245
|
+
expression to traverse these (see `find.md`).
|
|
246
|
+
- **Property layer** — documents, filings, articles, financial instruments,
|
|
247
|
+
events, and all other types are attached as property values on graph
|
|
248
|
+
nodes. Use `getPropertyValues()` with the relationship PID to traverse
|
|
249
|
+
these.
|
|
250
|
+
|
|
251
|
+
If you need to find people linked to an organization, use `findEntities`
|
|
252
|
+
with a `linked` expression:
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
const res = await client.findEntities({
|
|
256
|
+
expression: JSON.stringify({
|
|
257
|
+
type: 'linked',
|
|
258
|
+
linked: {
|
|
259
|
+
to_entity: orgNeid,
|
|
260
|
+
distance: 1,
|
|
261
|
+
pids: [isOfficerPid, isDirectorPid, worksAtPid],
|
|
262
|
+
direction: 'incoming',
|
|
263
|
+
},
|
|
264
|
+
}),
|
|
265
|
+
limit: 50,
|
|
266
|
+
});
|
|
267
|
+
const personNeids = (res as any).eids ?? [];
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
For non-graph-node types (filings, documents, etc.), use `getPropertyValues`
|
|
271
|
+
with the relationship PID. Relationship properties (`data_nindex`) return
|
|
272
|
+
linked entity IDs as values. Zero-pad the returned IDs to 20 characters
|
|
273
|
+
to form valid NEIDs.
|
|
211
274
|
|
|
212
275
|
```typescript
|
|
213
276
|
const pidMap = await getPropertyPidMap(client);
|
|
@@ -216,69 +279,48 @@ const res = await client.getPropertyValues({
|
|
|
216
279
|
eids: JSON.stringify([orgNeid]),
|
|
217
280
|
pids: JSON.stringify([filedPid]),
|
|
218
281
|
});
|
|
219
|
-
const docNeids = res.values.map((v) => String(v.value).padStart(20, '0'));
|
|
282
|
+
const docNeids = (res.values ?? []).map((v) => String(v.value).padStart(20, '0'));
|
|
220
283
|
```
|
|
221
284
|
|
|
222
285
|
See the **cookbook** rule for a full "Get filings for a company" recipe.
|
|
223
286
|
|
|
224
|
-
###
|
|
225
|
-
|
|
226
|
-
- **`client.getNEID()`** -- simple single-entity lookup by name
|
|
227
|
-
(`GET /entities/lookup`). Best for resolving one company/person name.
|
|
228
|
-
- **`client.findEntities()`** -- expression-based search
|
|
229
|
-
(`POST /elemental/find`). Best for filtered searches (by type, property,
|
|
230
|
-
relationship). See `find.md` for the expression language.
|
|
287
|
+
### Entity Search
|
|
231
288
|
|
|
232
|
-
|
|
289
|
+
Use `client.findEntities()` (`POST /elemental/find`) for entity search.
|
|
290
|
+
It supports filtering by type, property value, and relationship via the
|
|
291
|
+
expression language (see `find.md`). For name-based lookups, use
|
|
292
|
+
`string_like` on the name property (PID 8).
|
|
233
293
|
|
|
234
|
-
|
|
235
|
-
|
|
294
|
+
For batch name resolution with scored ranking, call `POST /entities/search`
|
|
295
|
+
directly via `$fetch` (not on the generated client). See the
|
|
296
|
+
**elemental-api skill** (`entities.md`) for request/response shapes.
|
|
236
297
|
|
|
237
|
-
|
|
238
|
-
|---|---|---|---|
|
|
239
|
-
| Organization | `filed` | Document (filings) | `getPropertyValues` with the `filed` PID on the org's NEID |
|
|
240
|
-
| Organization | `employs` | Person | `getLinkedEntities` (person is a graph node type) |
|
|
241
|
-
| Person | `employed_by` | Organization | `getLinkedEntities` (organization is a graph node type) |
|
|
242
|
-
| Organization | `headquartered_in` | Location | `getLinkedEntities` (location is a graph node type) |
|
|
243
|
-
| Any entity | `related_to` | Any entity | `getLinkedEntities` for person/org/location; `getPropertyValues` for others |
|
|
298
|
+
## Traversing Relationships
|
|
244
299
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
the
|
|
249
|
-
|
|
300
|
+
Relationships between entities are discoverable via the schema — use
|
|
301
|
+
`getSchema()` to find relationship properties (`data_nindex` type) and
|
|
302
|
+
their PIDs. Do NOT hardcode relationship names or PIDs; they can change
|
|
303
|
+
as the knowledge graph evolves. See the **data-model skill** for
|
|
304
|
+
source-specific schemas.
|
|
250
305
|
|
|
251
|
-
**
|
|
306
|
+
**Two traversal methods:**
|
|
252
307
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
// 2. Get linked entity IDs via getPropertyValues
|
|
260
|
-
const res = await client.getPropertyValues({
|
|
261
|
-
eids: JSON.stringify([orgNeid]),
|
|
262
|
-
pids: JSON.stringify([filedPid]),
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
// 3. Pad IDs to 20 chars to form valid NEIDs
|
|
266
|
-
const docNeids = res.values.map((v: any) => String(v.value).padStart(20, '0'));
|
|
308
|
+
- **Graph-layer entities** (person, organization, location): Use
|
|
309
|
+
`findEntities()` with a `linked` expression. See `find.md`.
|
|
310
|
+
- **Property-layer entities** (documents, filings, articles, etc.): Use
|
|
311
|
+
`getPropertyValues()` with the relationship PID. Values are entity IDs
|
|
312
|
+
that must be zero-padded to 20 characters.
|
|
267
313
|
|
|
268
|
-
|
|
269
|
-
const reports = await Promise.all(
|
|
270
|
-
docNeids.map(async (neid: string) => {
|
|
271
|
-
const r = await client.getNamedEntityReport(neid);
|
|
272
|
-
return r.report ?? r;
|
|
273
|
-
}),
|
|
274
|
-
);
|
|
275
|
-
```
|
|
314
|
+
See the **cookbook** rule (recipe #7) for a full example.
|
|
276
315
|
|
|
277
316
|
## Error Handling
|
|
278
317
|
|
|
279
318
|
```typescript
|
|
280
319
|
try {
|
|
281
|
-
const data = await client.
|
|
320
|
+
const data = await client.findEntities({
|
|
321
|
+
expression: JSON.stringify({ type: 'comparison', comparison: { operator: 'string_like', pid: 8, value: 'Apple' } }),
|
|
322
|
+
limit: 5,
|
|
323
|
+
});
|
|
282
324
|
} catch (error) {
|
|
283
325
|
console.error('API Error:', error);
|
|
284
326
|
showError('Failed to load data. Please try again.');
|
package/rules/cookbook.mdc
CHANGED
|
@@ -53,19 +53,35 @@ Search for entities by name and display results.
|
|
|
53
53
|
const error = ref<string | null>(null);
|
|
54
54
|
const searched = ref(false);
|
|
55
55
|
|
|
56
|
+
function getSearchUrl() {
|
|
57
|
+
const config = useRuntimeConfig();
|
|
58
|
+
const gw = (config.public as any).gatewayUrl as string;
|
|
59
|
+
const org = (config.public as any).tenantOrgId as string;
|
|
60
|
+
return `${gw}/api/qs/${org}/entities/search`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getApiKey() {
|
|
64
|
+
return (useRuntimeConfig().public as any).qsApiKey as string;
|
|
65
|
+
}
|
|
66
|
+
|
|
56
67
|
async function search() {
|
|
57
68
|
if (!query.value.trim()) return;
|
|
58
69
|
loading.value = true;
|
|
59
70
|
error.value = null;
|
|
60
71
|
searched.value = true;
|
|
61
72
|
try {
|
|
62
|
-
const res = await
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
73
|
+
const res = await $fetch<any>(getSearchUrl(), {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
headers: { 'Content-Type': 'application/json', 'X-Api-Key': getApiKey() },
|
|
76
|
+
body: {
|
|
77
|
+
queries: [{ queryId: 1, query: query.value.trim() }],
|
|
78
|
+
maxResults: 10,
|
|
79
|
+
includeNames: true,
|
|
80
|
+
},
|
|
66
81
|
});
|
|
67
|
-
|
|
68
|
-
|
|
82
|
+
const matches = res?.results?.[0]?.matches ?? [];
|
|
83
|
+
results.value = matches.map((m: any) => m.neid);
|
|
84
|
+
names.value = matches.map((m: any) => m.name || m.neid);
|
|
69
85
|
} catch (e: any) {
|
|
70
86
|
error.value = e.message || 'Search failed';
|
|
71
87
|
results.value = [];
|
|
@@ -374,9 +390,10 @@ Two-column layout with selectable list and detail panel.
|
|
|
374
390
|
|
|
375
391
|
Fetch Edgar filings (or any relationship-linked documents) for an organization.
|
|
376
392
|
|
|
377
|
-
**Important:**
|
|
378
|
-
|
|
379
|
-
|
|
393
|
+
**Important:** For graph-layer entities (person, organization, location),
|
|
394
|
+
use `findEntities` with a `linked` expression. For property-layer entities
|
|
395
|
+
(documents, filings, articles), use `getPropertyValues` with the
|
|
396
|
+
relationship PID. See the `api` rule for the two-layer architecture.
|
|
380
397
|
|
|
381
398
|
```vue
|
|
382
399
|
<template>
|
|
@@ -430,22 +447,38 @@ NOT supported — use `getPropertyValues` with the relationship PID instead.
|
|
|
430
447
|
return new Map(properties.map((p: any) => [p.name, p.pid]));
|
|
431
448
|
}
|
|
432
449
|
|
|
450
|
+
function getSearchUrl() {
|
|
451
|
+
const config = useRuntimeConfig();
|
|
452
|
+
const gw = (config.public as any).gatewayUrl as string;
|
|
453
|
+
const org = (config.public as any).tenantOrgId as string;
|
|
454
|
+
return `${gw}/api/qs/${org}/entities/search`;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function getApiKey() {
|
|
458
|
+
return (useRuntimeConfig().public as any).qsApiKey as string;
|
|
459
|
+
}
|
|
460
|
+
|
|
433
461
|
async function search() {
|
|
434
462
|
if (!query.value.trim()) return;
|
|
435
463
|
loading.value = true;
|
|
436
464
|
error.value = null;
|
|
437
465
|
searched.value = true;
|
|
438
466
|
try {
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
467
|
+
const res = await $fetch<any>(getSearchUrl(), {
|
|
468
|
+
method: 'POST',
|
|
469
|
+
headers: { 'Content-Type': 'application/json', 'X-Api-Key': getApiKey() },
|
|
470
|
+
body: {
|
|
471
|
+
queries: [{ queryId: 1, query: query.value.trim(), flavors: ['organization'] }],
|
|
472
|
+
maxResults: 1,
|
|
473
|
+
includeNames: true,
|
|
474
|
+
},
|
|
443
475
|
});
|
|
444
|
-
|
|
476
|
+
const matches = res?.results?.[0]?.matches ?? [];
|
|
477
|
+
if (!matches.length) {
|
|
445
478
|
filings.value = [];
|
|
446
479
|
return;
|
|
447
480
|
}
|
|
448
|
-
const orgNeid =
|
|
481
|
+
const orgNeid = matches[0].neid;
|
|
449
482
|
|
|
450
483
|
const pidMap = await getPropertyPidMap(client);
|
|
451
484
|
const filedPid = pidMap.get('filed');
|
|
@@ -459,7 +492,7 @@ NOT supported — use `getPropertyValues` with the relationship PID instead.
|
|
|
459
492
|
pids: JSON.stringify([filedPid]),
|
|
460
493
|
});
|
|
461
494
|
|
|
462
|
-
const docNeids = res.values.map((v: any) =>
|
|
495
|
+
const docNeids = (res.values ?? []).map((v: any) =>
|
|
463
496
|
String(v.value).padStart(20, '0'),
|
|
464
497
|
);
|
|
465
498
|
|
|
@@ -62,12 +62,14 @@ flavors:
|
|
|
62
62
|
description: "A news article or press release being processed"
|
|
63
63
|
display_name: "Article"
|
|
64
64
|
mergeability: not_mergeable
|
|
65
|
+
strong_id_properties: ["newsdata_id"]
|
|
65
66
|
passive: true
|
|
66
67
|
|
|
67
68
|
- name: "publication"
|
|
68
69
|
description: "A news publication or media outlet identified by its home URL"
|
|
69
70
|
display_name: "Publication"
|
|
70
71
|
mergeability: not_mergeable
|
|
72
|
+
strong_id_properties: ["homeUrl"]
|
|
71
73
|
passive: true
|
|
72
74
|
|
|
73
75
|
# =============================================================================
|
|
@@ -389,6 +391,14 @@ properties:
|
|
|
389
391
|
domain_flavors: ["article"]
|
|
390
392
|
passive: true
|
|
391
393
|
|
|
394
|
+
- name: "newsdata_id"
|
|
395
|
+
type: string
|
|
396
|
+
description: "Unique article identifier from the NewsData API"
|
|
397
|
+
display_name: "NewsData ID"
|
|
398
|
+
mergeability: not_mergeable
|
|
399
|
+
domain_flavors: ["article"]
|
|
400
|
+
passive: true
|
|
401
|
+
|
|
392
402
|
- name: "title"
|
|
393
403
|
type: string
|
|
394
404
|
description: "Title of the entity"
|
|
@@ -11,17 +11,15 @@ This skill provides documentation for the Lovelace Elemental API, the primary in
|
|
|
11
11
|
|
|
12
12
|
Use this skill when you need to:
|
|
13
13
|
- Look up entities (companies, people, organizations) by name or ID
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
- Explore relationships and connections between entities
|
|
17
|
-
- Retrieve events involving specific entities
|
|
14
|
+
- Search for entities by type, property values, or relationships using the expression language
|
|
15
|
+
- Get entity metadata (types/flavors, properties)
|
|
18
16
|
- Build knowledge graphs of entity networks
|
|
19
17
|
|
|
20
18
|
## Quick Start
|
|
21
19
|
|
|
22
20
|
1. **Find an entity**: Use `entities.md` to look up a company or person by name and get their NEID (Named Entity ID)
|
|
23
|
-
2. **Get information**: Use the NEID to query
|
|
24
|
-
3. **
|
|
21
|
+
2. **Get information**: Use the NEID to query entity properties or explore the graph
|
|
22
|
+
3. **Search**: Use `find.md` for expression-based entity searches
|
|
25
23
|
|
|
26
24
|
## Files in This Skill
|
|
27
25
|
|
|
@@ -29,9 +27,5 @@ See [overview.md](overview.md) for descriptions of each endpoint category:
|
|
|
29
27
|
- `entities.md` - Entity search, details, and properties
|
|
30
28
|
- `find.md` - Expression language for searching entities by type, property values, and relationships
|
|
31
29
|
- `schema.md` - Data model: entity types (flavors), properties, and schema endpoints
|
|
32
|
-
- `sentiment.md` - Sentiment analysis
|
|
33
|
-
- `articles.md` - Articles mentioning entities and full article content
|
|
34
|
-
- `events.md` - Events involving entities
|
|
35
|
-
- `relationships.md` - Entity connections
|
|
36
30
|
- `graph.md` - Visual graph generation
|
|
37
31
|
- `server.md` - Server status and health
|