@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
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
# Relationships
|
|
2
|
-
|
|
3
|
-
Relationships (also called "links") represent connections between entities in the Knowledge Graph. These connections are derived from articles.
|
|
4
|
-
|
|
5
|
-
## When to Use
|
|
6
|
-
|
|
7
|
-
- You want to find entities connected to a given entity
|
|
8
|
-
- You need to understand how two entities are related
|
|
9
|
-
- You're exploring a network of connections (e.g., "Who is connected to this person?")
|
|
10
|
-
- You need link counts or relationship strength between entities
|
|
11
|
-
|
|
12
|
-
## Key Concepts
|
|
13
|
-
|
|
14
|
-
- **Linked Entities**: Other entities that have a relationship with a given entity
|
|
15
|
-
- **Link Strength**: Represents the significance of the relationship between two entities
|
|
16
|
-
- **Link Counts**: Number of connections between entity pairs, useful for measuring relationship strength
|
|
17
|
-
- **Relationship Types**: Common types include:
|
|
18
|
-
- `competes_with`
|
|
19
|
-
- `compares_to`
|
|
20
|
-
- `customer_of`
|
|
21
|
-
- `partnered_with`
|
|
22
|
-
- `trades_with`
|
|
23
|
-
- `invests_in`
|
|
24
|
-
- `is_related_to`
|
|
25
|
-
- `sues`
|
|
26
|
-
- `provides_support_to`
|
|
27
|
-
|
|
28
|
-
## Tips
|
|
29
|
-
|
|
30
|
-
- Relationships are bidirectional—if A links to B, B links to A
|
|
31
|
-
- High link counts indicate stronger or more frequent connections in the news
|
|
32
|
-
- Use with graph endpoints to visualize relationship networks
|
|
33
|
-
- **`entity_type` filter limitation**: see the Guidance note on "Get linked entities" below — only three entity types are supported
|
|
34
|
-
|
|
35
|
-
<!-- BEGIN GENERATED CONTENT -->
|
|
36
|
-
|
|
37
|
-
## Endpoints
|
|
38
|
-
|
|
39
|
-
### Get linked entities
|
|
40
|
-
|
|
41
|
-
`GET /entities/{source_neid}/linked`
|
|
42
|
-
|
|
43
|
-
Get list of entities linked to a source entity, optionally filtered by entity type and link type
|
|
44
|
-
|
|
45
|
-
#### Parameters
|
|
46
|
-
|
|
47
|
-
| Name | Type | Required | Description |
|
|
48
|
-
|------|------|----------|-------------|
|
|
49
|
-
| source_neid | string | yes | Source entity NEID |
|
|
50
|
-
| entity_type | string[] | no | Filter by entity type(s) |
|
|
51
|
-
| link_type | string[] | no | Filter by link type(s) |
|
|
52
|
-
|
|
53
|
-
#### Responses
|
|
54
|
-
|
|
55
|
-
| Status | Description |
|
|
56
|
-
|--------|-------------|
|
|
57
|
-
| 200 | List of linked entity NEIDs (`GetLinkedEntitiesResponse`) |
|
|
58
|
-
| 400 | Invalid parameters (`Error`) |
|
|
59
|
-
| 404 | Source entity not found (`Error`) |
|
|
60
|
-
| 500 | Internal server error (`Error`) |
|
|
61
|
-
|
|
62
|
-
#### Example
|
|
63
|
-
|
|
64
|
-
**Request:**
|
|
65
|
-
|
|
66
|
-
```
|
|
67
|
-
GET /entities/00416400910670863867/linked
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
**Response:**
|
|
71
|
-
|
|
72
|
-
```json
|
|
73
|
-
{"entities": ["00416400910670863867"]}
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
|
-
### Get links between entities
|
|
79
|
-
|
|
80
|
-
`GET /entities/{source_neid}/links/{target_neid}`
|
|
81
|
-
|
|
82
|
-
Get list of links between source and target entities, optionally filtered by link type
|
|
83
|
-
|
|
84
|
-
#### Parameters
|
|
85
|
-
|
|
86
|
-
| Name | Type | Required | Description |
|
|
87
|
-
|------|------|----------|-------------|
|
|
88
|
-
| source_neid | string | yes | Source entity NEID |
|
|
89
|
-
| target_neid | string | yes | Target entity NEID |
|
|
90
|
-
| link_type | string[] | no | Filter by link type(s) |
|
|
91
|
-
| include_mentions | boolean | no | Include mention details in response |
|
|
92
|
-
| include_articles | boolean | no | Include article details in response |
|
|
93
|
-
|
|
94
|
-
#### Responses
|
|
95
|
-
|
|
96
|
-
| Status | Description |
|
|
97
|
-
|--------|-------------|
|
|
98
|
-
| 200 | List of entity links (`GetLinksResponse`) |
|
|
99
|
-
| 400 | Invalid parameters (`Error`) |
|
|
100
|
-
| 404 | Source or target entity not found (`Error`) |
|
|
101
|
-
| 500 | Internal server error (`Error`) |
|
|
102
|
-
|
|
103
|
-
#### Example
|
|
104
|
-
|
|
105
|
-
**Request:**
|
|
106
|
-
|
|
107
|
-
```
|
|
108
|
-
GET /entities/00416400910670863867/links/04358848009837283240
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
**Response:**
|
|
112
|
-
|
|
113
|
-
```json
|
|
114
|
-
{"links": []}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
---
|
|
118
|
-
|
|
119
|
-
### Get graph layout
|
|
120
|
-
|
|
121
|
-
`GET /graph/{center_neid}/layout`
|
|
122
|
-
|
|
123
|
-
Get nodes and edges layout data for visualizing a relationship graph. Response is cached for 5 minutes.
|
|
124
|
-
|
|
125
|
-
#### Guidance
|
|
126
|
-
|
|
127
|
-
Only use this endpoint if you care about graph-specific properties. Otherwise it is faster to use /entities/{source_neid}/links/{target_neid}. This should always be called with a non-empty list of neids. A typical pattern is to call /graph/{center_neid}/neighborhood and then use the returned NEIDs to call this endpoint.
|
|
128
|
-
|
|
129
|
-
#### Parameters
|
|
130
|
-
|
|
131
|
-
| Name | Type | Required | Description |
|
|
132
|
-
|------|------|----------|-------------|
|
|
133
|
-
| center_neid | string | yes | Center entity NEID |
|
|
134
|
-
| neid | string[] | no | Additional entity NEIDs to include in layout |
|
|
135
|
-
| borderMinX | number | no | Minimum X border for layout |
|
|
136
|
-
| borderMinY | number | no | Minimum Y border for layout |
|
|
137
|
-
| borderMaxX | number | no | Maximum X border for layout |
|
|
138
|
-
| borderMaxY | number | no | Maximum Y border for layout |
|
|
139
|
-
|
|
140
|
-
#### Responses
|
|
141
|
-
|
|
142
|
-
| Status | Description |
|
|
143
|
-
|--------|-------------|
|
|
144
|
-
| 200 | Graph layout with nodes and edges (`GraphLayoutResponse`) |
|
|
145
|
-
| 400 | Invalid parameters (`Error`) |
|
|
146
|
-
| 500 | Internal server error (`Error`) |
|
|
147
|
-
|
|
148
|
-
#### Example
|
|
149
|
-
|
|
150
|
-
**Request:**
|
|
151
|
-
|
|
152
|
-
```
|
|
153
|
-
GET /graph/00416400910670863867/layout?neid=04358848009837283240
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
**Response:**
|
|
157
|
-
|
|
158
|
-
```json
|
|
159
|
-
{"nodes": [{"neid": "00416400910670863867", "label": "organization|Apple|nationality: us...", "isCentralNode": true, "x": -333.33, "y": -200, "width": 666.67, "height": 266.67}], "edges": [{"source": "00416400910670863867", "target": "04358848009837283240", "label": "competes_with", "path": [{"X": 0, "Y": 0}, {"X": 0, "Y": 66.67}], "article_ids": ["02861951941133789623"], "snippets": ["Apple and Google are mentioned as companies..."], "weight": 0.0267}]}
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
### Get graph neighborhood
|
|
165
|
-
|
|
166
|
-
`GET /graph/{center_neid}/neighborhood`
|
|
167
|
-
|
|
168
|
-
Get list of neighboring entities in the relationship graph, optionally filtered by entity type. Response is cached for 5 minutes.
|
|
169
|
-
|
|
170
|
-
#### Guidance
|
|
171
|
-
|
|
172
|
-
Only use this endpoint if you care about graph-specific properties. Otherwise it is faster to use /entities/{source_neid}/linked. Response includes the center entity itself in the results with a weight of 1.0. The 'neighbors' and 'weights' arrays are parallel (same indices correspond).
|
|
173
|
-
|
|
174
|
-
#### Parameters
|
|
175
|
-
|
|
176
|
-
| Name | Type | Required | Description |
|
|
177
|
-
|------|------|----------|-------------|
|
|
178
|
-
| center_neid | string | yes | Center entity NEID |
|
|
179
|
-
| size | integer | no | Maximum number of neighbors to return |
|
|
180
|
-
| type | string[] | no | Filter by entity type(s) |
|
|
181
|
-
|
|
182
|
-
#### Responses
|
|
183
|
-
|
|
184
|
-
| Status | Description |
|
|
185
|
-
|--------|-------------|
|
|
186
|
-
| 200 | Neighbors and their weights (`GraphNeighborhoodResponse`) |
|
|
187
|
-
| 400 | Invalid parameters (`Error`) |
|
|
188
|
-
| 404 | Center entity not found (`Error`) |
|
|
189
|
-
| 500 | Internal server error (`Error`) |
|
|
190
|
-
|
|
191
|
-
#### Example
|
|
192
|
-
|
|
193
|
-
**Request:**
|
|
194
|
-
|
|
195
|
-
```
|
|
196
|
-
GET /graph/00416400910670863867/neighborhood?size=5
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
**Response:**
|
|
200
|
-
|
|
201
|
-
```json
|
|
202
|
-
{"neighbors": ["00416400910670863867", "04358848009837283240", "00315863961550087877"], "weights": [1, 0.0267, 0.0167]}
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
### Get link counts between entities
|
|
208
|
-
|
|
209
|
-
`GET /graph/{source_neid}/links/{target_neid}/counts`
|
|
210
|
-
|
|
211
|
-
Get counts of links between source and target entities over time
|
|
212
|
-
|
|
213
|
-
#### Guidance
|
|
214
|
-
|
|
215
|
-
Only use this endpoint if you care about graph-specific properties. Otherwise it is faster to use /entities/{source_neid}/links/{target_neid}. Returns link_counts object with relationship types as keys. Values are arrays of timestamps in Excel/OLE serial date format (days since 1899-12-30). Example: 46019.64453125 = 2025-12-28 15:28:07 UTC. The count for each relationship type is the array length (number of observations).
|
|
216
|
-
|
|
217
|
-
#### Parameters
|
|
218
|
-
|
|
219
|
-
| Name | Type | Required | Description |
|
|
220
|
-
|------|------|----------|-------------|
|
|
221
|
-
| source_neid | string | yes | Source entity NEID |
|
|
222
|
-
| target_neid | string | yes | Target entity NEID |
|
|
223
|
-
|
|
224
|
-
#### Responses
|
|
225
|
-
|
|
226
|
-
| Status | Description |
|
|
227
|
-
|--------|-------------|
|
|
228
|
-
| 200 | Link counts by type (`GetLinkCountsResponse`) |
|
|
229
|
-
| 400 | Invalid parameters (`Error`) |
|
|
230
|
-
| 500 | Internal server error (`Error`) |
|
|
231
|
-
|
|
232
|
-
#### Example
|
|
233
|
-
|
|
234
|
-
**Request:**
|
|
235
|
-
|
|
236
|
-
```
|
|
237
|
-
GET /graph/00416400910670863867/links/04358848009837283240/counts
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
**Response:**
|
|
241
|
-
|
|
242
|
-
```json
|
|
243
|
-
{"link_counts": {"compares_to": [46019.64453125, 45999.3515625], "competes_with": [45847.5625, 45850.60546875], "customer_of": [45836.9296875], "partnered_with": [], "trades_with": []}}
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
## Types
|
|
247
|
-
|
|
248
|
-
### EntityLink
|
|
249
|
-
|
|
250
|
-
A link between two entities
|
|
251
|
-
|
|
252
|
-
| Field | Type | Description |
|
|
253
|
-
|-------|------|-------------|
|
|
254
|
-
| article_ids | string[] | Article IDs where this link was found |
|
|
255
|
-
| recorded_at | string | Time when the link was recorded @Format date-time |
|
|
256
|
-
| source | string | Source entity NEID |
|
|
257
|
-
| target | string | Target entity NEID |
|
|
258
|
-
| type | string | Type of link/relationship |
|
|
259
|
-
|
|
260
|
-
### GetLinkCountsResponse
|
|
261
|
-
|
|
262
|
-
Response containing link counts between entities
|
|
263
|
-
|
|
264
|
-
| Field | Type | Description |
|
|
265
|
-
|-------|------|-------------|
|
|
266
|
-
| link_counts | object | Map of link type to count values |
|
|
267
|
-
|
|
268
|
-
### GetLinkedEntitiesResponse
|
|
269
|
-
|
|
270
|
-
Response containing linked entities
|
|
271
|
-
|
|
272
|
-
| Field | Type | Description |
|
|
273
|
-
|-------|------|-------------|
|
|
274
|
-
| entities | string[] | List of linked entity NEIDs |
|
|
275
|
-
|
|
276
|
-
### GetLinksResponse
|
|
277
|
-
|
|
278
|
-
Response containing links between entities
|
|
279
|
-
|
|
280
|
-
| Field | Type | Description |
|
|
281
|
-
|-------|------|-------------|
|
|
282
|
-
| articles | `ArticleDetail`[] | Articles tied to the returned links (only included when requested) |
|
|
283
|
-
| links | `EntityLink`[] | List of entity links |
|
|
284
|
-
| mentions | `MentionDetail`[] | Mentions tied to the returned links (only included when requested) |
|
|
285
|
-
|
|
286
|
-
### GraphNeighborhoodResponse
|
|
287
|
-
|
|
288
|
-
Response containing neighbors of an entity in the relationship graph
|
|
289
|
-
|
|
290
|
-
| Field | Type | Description |
|
|
291
|
-
|-------|------|-------------|
|
|
292
|
-
| neighbors | string[] | List of neighbor NEIDs |
|
|
293
|
-
| weights | number[] | Weights corresponding to each neighbor (same order as neighbors) |
|
|
294
|
-
|
|
295
|
-
### LinkedExpression
|
|
296
|
-
|
|
297
|
-
| Field | Type | Description |
|
|
298
|
-
|-------|------|-------------|
|
|
299
|
-
| **linked** | `Linked` | |
|
|
300
|
-
|
|
301
|
-
### Linked
|
|
302
|
-
|
|
303
|
-
| Field | Type | Description |
|
|
304
|
-
|-------|------|-------------|
|
|
305
|
-
| **distance** | integer | Maximum relationship distance to traverse |
|
|
306
|
-
| pids | integer[] | Property identifiers defining the relationship types to follow |
|
|
307
|
-
| to_entity | string | Target entity ID for relationship traversal |
|
|
308
|
-
| direction | string | Direction of relationship traversal. 'outgoing' (default) follows subject->value edges, 'incoming' follows value->subject (reverse) edges, 'both' unions outgoing and incoming results. |
|
|
309
|
-
|
|
310
|
-
<!-- END GENERATED CONTENT -->
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
# Sentiment
|
|
2
|
-
|
|
3
|
-
Sentiment analysis measures how positively or negatively an entity is portrayed in news coverage. The API provides both daily aggregate scores and scores for individual articles.
|
|
4
|
-
|
|
5
|
-
## When to Use
|
|
6
|
-
|
|
7
|
-
- You want to know if news coverage about an entity is positive or negative
|
|
8
|
-
- You need sentiment trends over time (e.g., "How has sentiment changed this month?")
|
|
9
|
-
- You're comparing sentiment between entities or time periods
|
|
10
|
-
|
|
11
|
-
## Key Concepts
|
|
12
|
-
|
|
13
|
-
- **Sentiment Score**: Ranges from -1 (very negative) to +1 (very positive), with 0 being neutral.
|
|
14
|
-
- Individual article/mention scores are discrete values: `-1`, `-0.75`, `-0.5`, `0`, `0.5`, `0.75`, `1`
|
|
15
|
-
- Daily aggregate scores can be any value between -1 and 1 (continuous)
|
|
16
|
-
- **Entity-level vs. Mention-level**: Aggregate sentiment for an entity vs. sentiment of a specific mention
|
|
17
|
-
|
|
18
|
-
## Tips
|
|
19
|
-
|
|
20
|
-
- Sentiment without a time range returns recent data; always specify dates for historical analysis
|
|
21
|
-
- High mention volume with neutral sentiment may indicate routine coverage
|
|
22
|
-
- Sudden sentiment shifts often correlate with specific events
|
|
23
|
-
|
|
24
|
-
<!-- BEGIN GENERATED CONTENT -->
|
|
25
|
-
|
|
26
|
-
## Endpoints
|
|
27
|
-
|
|
28
|
-
### Get entity sentiment data
|
|
29
|
-
|
|
30
|
-
`GET /graph/{neid}/sentiment`
|
|
31
|
-
|
|
32
|
-
Get sentiment analysis data for a named entity including scores, timestamps, and daily averages. Response is cached for 5 minutes.
|
|
33
|
-
|
|
34
|
-
#### Guidance
|
|
35
|
-
|
|
36
|
-
Response is wrapped in a 'sentiment' container object. The sentiment_scores field is a flat array of numbers (not timestamped objects). The time interval for the scores is provided separately in time_interval.start and time_interval.end.
|
|
37
|
-
|
|
38
|
-
#### Parameters
|
|
39
|
-
|
|
40
|
-
| Name | Type | Required | Description |
|
|
41
|
-
|------|------|----------|-------------|
|
|
42
|
-
| neid | string | yes | Named Entity ID |
|
|
43
|
-
|
|
44
|
-
#### Responses
|
|
45
|
-
|
|
46
|
-
| Status | Description |
|
|
47
|
-
|--------|-------------|
|
|
48
|
-
| 200 | Sentiment data for the entity (`GetNamedEntitySentimentResponse`) |
|
|
49
|
-
| 400 | Invalid NEID (`Error`) |
|
|
50
|
-
| 404 | Entity not found (`Error`) |
|
|
51
|
-
| 500 | Internal server error (`Error`) |
|
|
52
|
-
|
|
53
|
-
#### Example
|
|
54
|
-
|
|
55
|
-
**Request:**
|
|
56
|
-
|
|
57
|
-
```
|
|
58
|
-
GET /graph/00416400910670863867/sentiment
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
**Response:**
|
|
62
|
-
|
|
63
|
-
```json
|
|
64
|
-
{"sentiment": {"neid": "00416400910670863867", "time_interval": {"start": "2026-01-04T03:02:25.384Z", "end": "2026-02-03T03:02:25.384Z"}, "num_mentions": 28662, "sentiment_scores": [0.5, 0.5, 0.5, 0, 0.5, -0.5, 1]}}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## Types
|
|
68
|
-
|
|
69
|
-
### GetNamedEntitySentimentResponse
|
|
70
|
-
|
|
71
|
-
Response containing sentiment data for a named entity
|
|
72
|
-
|
|
73
|
-
| Field | Type | Description |
|
|
74
|
-
|-------|------|-------------|
|
|
75
|
-
| sentiment | `NamedEntitySentiment` | |
|
|
76
|
-
|
|
77
|
-
### NamedEntitySentiment
|
|
78
|
-
|
|
79
|
-
The sentiment data
|
|
80
|
-
|
|
81
|
-
| Field | Type | Description |
|
|
82
|
-
|-------|------|-------------|
|
|
83
|
-
| daily_timestamps | string[] | Timestamps associated with each daily sentiment trend |
|
|
84
|
-
| direct_sentiment_daily_averages | number[] | The average direct sentiment score for the entity for each day in the time interval |
|
|
85
|
-
| neid | string | Named Entity ID |
|
|
86
|
-
| num_mentions | integer | Number of times the entity has been directly mentioned in an article |
|
|
87
|
-
| propagated_sentiment_daily_averages | number[] | The average propagated sentiment score for the entity for each day in the time interval |
|
|
88
|
-
| sentiment_article_nindexes | string[] | Nindexes of the articles that correspond to each direct sentiment score |
|
|
89
|
-
| sentiment_scores | number[] | All direct sentiment scores for the entity |
|
|
90
|
-
| sentiment_timestamps | string[] | Timestamps associated with each direct sentiment score |
|
|
91
|
-
| time_interval | `TimeInterval` | |
|
|
92
|
-
|
|
93
|
-
<!-- END GENERATED CONTENT -->
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: test-api-queries
|
|
3
|
-
description: Test Elemental API queries before integrating into app code. Use when writing code that calls the query server.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Test API Queries
|
|
7
|
-
|
|
8
|
-
**When writing code that calls the Query Server, test queries with this CLI tool before integrating them into app code.**
|
|
9
|
-
|
|
10
|
-
This prevents wasted iteration cycles from incorrect assumptions about API responses.
|
|
11
|
-
|
|
12
|
-
## Workflow
|
|
13
|
-
|
|
14
|
-
1. **Test the query** using the CLI tool below
|
|
15
|
-
2. **Verify the response** matches what you expect
|
|
16
|
-
3. **Then write the app code** with confidence
|
|
17
|
-
|
|
18
|
-
## CLI Tool
|
|
19
|
-
|
|
20
|
-
Location: `~/.cursor/skills/test-api-queries/query-api.js`
|
|
21
|
-
|
|
22
|
-
### Requirements
|
|
23
|
-
|
|
24
|
-
The CLI reads these from the project's `.env` file or shell environment:
|
|
25
|
-
|
|
26
|
-
- `AUTH0_M2M_DEV_TOKEN` - Auth0 M2M dev token for API access
|
|
27
|
-
- `NUXT_PUBLIC_QUERY_SERVER_ADDRESS` - Query server URL
|
|
28
|
-
|
|
29
|
-
**Before using this tool**, check that both variables are set in the project's `.env` file. If either is missing or empty, add them to `.env` (see `.env.example` for the format). Tell the user to ask the engineering team for the token value if they don't have it.
|
|
30
|
-
|
|
31
|
-
### Usage
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
node ~/.cursor/skills/test-api-queries/query-api.js <METHOD> <ENDPOINT> [JSON_PARAMS]
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### Examples
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
# Search for entities by name
|
|
41
|
-
node ~/.cursor/skills/test-api-queries/query-api.js POST /entities/search \
|
|
42
|
-
'{"queries":[{"queryId":1,"query":"Apple"}],"maxResults":3}'
|
|
43
|
-
|
|
44
|
-
# Get entity details by ID
|
|
45
|
-
node ~/.cursor/skills/test-api-queries/query-api.js GET /entities/00416400910670863867
|
|
46
|
-
|
|
47
|
-
# Find entities by type
|
|
48
|
-
node ~/.cursor/skills/test-api-queries/query-api.js POST /elemental/find \
|
|
49
|
-
'{"expression":{"type":"is_type","is_type":{"fid":10}},"limit":5}'
|
|
50
|
-
|
|
51
|
-
# Find entities with a specific property
|
|
52
|
-
node ~/.cursor/skills/test-api-queries/query-api.js POST /elemental/find \
|
|
53
|
-
'{"expression":{"type":"comparison","comparison":{"operator":"has_value","pid":313}},"limit":10}'
|
|
54
|
-
|
|
55
|
-
# Get entity properties
|
|
56
|
-
node ~/.cursor/skills/test-api-queries/query-api.js POST /elemental/entities/properties \
|
|
57
|
-
'{"eids":["00416400910670863867"],"pids":[8,313]}'
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### Notes
|
|
61
|
-
|
|
62
|
-
- Run from the project directory so the `.env` file is found
|
|
63
|
-
- `/elemental/find` and `/elemental/entities/properties` require form-encoded bodies—the tool handles this automatically
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Simple CLI tool to query the Elemental API.
|
|
4
|
-
*
|
|
5
|
-
* Auth: set AUTH0_M2M_DEV_TOKEN as an env var or in your .env file.
|
|
6
|
-
* Server: set NUXT_PUBLIC_QUERY_SERVER_ADDRESS in your .env file.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const fs = require('fs');
|
|
10
|
-
const path = require('path');
|
|
11
|
-
|
|
12
|
-
const FORM_ENCODED_ENDPOINTS = ['/elemental/find', '/elemental/entities/properties'];
|
|
13
|
-
|
|
14
|
-
function loadEnvFile() {
|
|
15
|
-
// Try current working directory first (project .env), then script directory
|
|
16
|
-
const envPaths = [path.join(process.cwd(), '.env'), path.join(__dirname, '.env')];
|
|
17
|
-
|
|
18
|
-
for (const envPath of envPaths) {
|
|
19
|
-
try {
|
|
20
|
-
const contents = fs.readFileSync(envPath, 'utf8');
|
|
21
|
-
for (const line of contents.split('\n')) {
|
|
22
|
-
const trimmed = line.trim();
|
|
23
|
-
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
24
|
-
const eqIndex = trimmed.indexOf('=');
|
|
25
|
-
if (eqIndex === -1) continue;
|
|
26
|
-
const key = trimmed.slice(0, eqIndex).trim();
|
|
27
|
-
const value = trimmed.slice(eqIndex + 1).trim();
|
|
28
|
-
if (!process.env[key]) {
|
|
29
|
-
process.env[key] = value;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return; // Stop after first successful load
|
|
33
|
-
} catch {
|
|
34
|
-
// Try next path
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function requiresFormEncoding(endpoint) {
|
|
40
|
-
return FORM_ENCODED_ENDPOINTS.some((e) => endpoint.startsWith(e));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function buildFormBody(endpoint, params) {
|
|
44
|
-
const formParams = new URLSearchParams();
|
|
45
|
-
for (const [key, value] of Object.entries(params)) {
|
|
46
|
-
if (typeof value === 'object') {
|
|
47
|
-
formParams.append(key, JSON.stringify(value));
|
|
48
|
-
} else {
|
|
49
|
-
formParams.append(key, String(value));
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return formParams.toString();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async function main() {
|
|
56
|
-
loadEnvFile();
|
|
57
|
-
|
|
58
|
-
const args = process.argv.slice(2);
|
|
59
|
-
|
|
60
|
-
if (args.length < 2 || args[0] === '--help' || args[0] === '-h') {
|
|
61
|
-
console.log(`
|
|
62
|
-
Elemental API Query Tool
|
|
63
|
-
|
|
64
|
-
Usage:
|
|
65
|
-
node query-api.js <METHOD> <ENDPOINT> [JSON_PARAMS]
|
|
66
|
-
|
|
67
|
-
Examples:
|
|
68
|
-
# Search for entities (JSON body)
|
|
69
|
-
node query-api.js POST /entities/search '{"queries":[{"queryId":1,"query":"Apple"}],"maxResults":3}'
|
|
70
|
-
|
|
71
|
-
# Get entity details
|
|
72
|
-
node query-api.js GET /entities/00416400910670863867
|
|
73
|
-
|
|
74
|
-
# Find entities by expression (auto form-encoded)
|
|
75
|
-
node query-api.js POST /elemental/find '{"expression":{"type":"is_type","is_type":{"fid":10}},"limit":5}'
|
|
76
|
-
|
|
77
|
-
# Find entities with a property value
|
|
78
|
-
node query-api.js POST /elemental/find '{"expression":{"type":"comparison","comparison":{"operator":"has_value","pid":313}},"limit":10}'
|
|
79
|
-
|
|
80
|
-
# Get entity properties (auto form-encoded)
|
|
81
|
-
node query-api.js POST /elemental/entities/properties '{"eids":["00416400910670863867"],"pids":[8,313]}'
|
|
82
|
-
|
|
83
|
-
Environment variables (required):
|
|
84
|
-
AUTH0_M2M_DEV_TOKEN Bearer token for API auth
|
|
85
|
-
NUXT_PUBLIC_QUERY_SERVER_ADDRESS Query server URL (e.g. https://query.news.prod.g.lovelace.ai)
|
|
86
|
-
|
|
87
|
-
Setup:
|
|
88
|
-
1. Get a dev token from your team
|
|
89
|
-
2. Add AUTH0_M2M_DEV_TOKEN to your .env file or export in your shell
|
|
90
|
-
(NUXT_PUBLIC_QUERY_SERVER_ADDRESS should already be in your .env from project init)
|
|
91
|
-
|
|
92
|
-
Note: /elemental/find and /elemental/entities/properties require form-encoded bodies.
|
|
93
|
-
This tool automatically handles the encoding for these endpoints.
|
|
94
|
-
`);
|
|
95
|
-
process.exit(0);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const [method, endpoint, jsonParams] = args;
|
|
99
|
-
|
|
100
|
-
const token = process.env.AUTH0_M2M_DEV_TOKEN;
|
|
101
|
-
if (!token) {
|
|
102
|
-
console.error('Error: AUTH0_M2M_DEV_TOKEN is not set.');
|
|
103
|
-
console.error('Add it to your .env file or export it in your shell.');
|
|
104
|
-
console.error('Run: node query-api.js --help');
|
|
105
|
-
process.exit(1);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
let params = {};
|
|
109
|
-
if (jsonParams) {
|
|
110
|
-
try {
|
|
111
|
-
params = JSON.parse(jsonParams);
|
|
112
|
-
} catch (err) {
|
|
113
|
-
console.error('Error: Invalid JSON parameters');
|
|
114
|
-
console.error(err.message);
|
|
115
|
-
process.exit(1);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const server = process.env.NUXT_PUBLIC_QUERY_SERVER_ADDRESS;
|
|
120
|
-
if (!server) {
|
|
121
|
-
console.error('Error: NUXT_PUBLIC_QUERY_SERVER_ADDRESS is not set.');
|
|
122
|
-
console.error('Add it to your .env file or export it in your shell.');
|
|
123
|
-
console.error('Run: node query-api.js --help');
|
|
124
|
-
process.exit(1);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const normalizedEndpoint = endpoint.startsWith('/') ? endpoint : '/' + endpoint;
|
|
128
|
-
let url = `${server}${normalizedEndpoint}`;
|
|
129
|
-
|
|
130
|
-
const useFormEncoding = requiresFormEncoding(normalizedEndpoint);
|
|
131
|
-
const fetchOptions = {
|
|
132
|
-
method: method.toUpperCase(),
|
|
133
|
-
headers: {
|
|
134
|
-
Authorization: `Bearer ${token}`,
|
|
135
|
-
'Content-Type': useFormEncoding
|
|
136
|
-
? 'application/x-www-form-urlencoded'
|
|
137
|
-
: 'application/json',
|
|
138
|
-
Accept: 'application/json',
|
|
139
|
-
},
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
if (method.toUpperCase() === 'GET' && Object.keys(params).length > 0) {
|
|
143
|
-
const queryString = new URLSearchParams(params).toString();
|
|
144
|
-
url = `${url}?${queryString}`;
|
|
145
|
-
} else if (method.toUpperCase() !== 'GET' && Object.keys(params).length > 0) {
|
|
146
|
-
if (useFormEncoding) {
|
|
147
|
-
fetchOptions.body = buildFormBody(normalizedEndpoint, params);
|
|
148
|
-
} else {
|
|
149
|
-
fetchOptions.body = JSON.stringify(params);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
console.error(`\n📡 ${method.toUpperCase()} ${url}\n`);
|
|
154
|
-
|
|
155
|
-
try {
|
|
156
|
-
const response = await fetch(url, fetchOptions);
|
|
157
|
-
const data = await response.json();
|
|
158
|
-
|
|
159
|
-
if (!response.ok) {
|
|
160
|
-
console.error(`❌ Error ${response.status}: ${response.statusText}`);
|
|
161
|
-
} else {
|
|
162
|
-
console.error(`✅ Success (${response.status})\n`);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
console.log(JSON.stringify(data, null, 2));
|
|
166
|
-
} catch (err) {
|
|
167
|
-
console.error('❌ Request failed:', err.message);
|
|
168
|
-
process.exit(1);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
main();
|