|
1 | | -<!-- Read this when authoring objective strings — for either `kane-cli run "..."` or step bodies inside a `_test.md`. Owns the full catalog of action verbs, assertion patterns, checkpoint analyze methods (Visual, Textual/DOM, URL, Title, DevTools→Network/Console/Performance/Cookies/localStorage), operators, extraction patterns, chaining, variables, and common pitfalls. The same objective grammar applies to one-shot runs and testmd steps. --> |
| 1 | +<!-- Read this when authoring objective strings — for either `kane-cli run "..."` or step bodies inside a `_test.md`. Owns the full catalog of action verbs, assertion patterns, checkpoint analyze methods (Visual, Textual/DOM, URL, Title, DevTools→Network/Console/Performance/Cookies/localStorage), operators, extraction patterns, direct API calls, chaining, variables, and common pitfalls. The same objective grammar applies to one-shot runs and testmd steps. --> |
2 | 2 |
|
3 | 3 | # Writing Kane-CLI Objectives — Pattern Cookbook |
4 | 4 |
|
@@ -81,6 +81,8 @@ Five subdomains. Each one is the right choice when the data you care about lives |
81 | 81 |
|
82 | 82 | The agent captures every HTTP request/response per step. **Resets each step** — assert on traffic in the same step it happens (or extract and carry forward). |
83 | 83 |
|
| 84 | +These assertions also cover API calls **you** make directly in an objective (§3.5), not just the requests the page makes on its own — the agent records its own calls and you query them with the same fields below. |
| 85 | + |
84 | 86 | Queryable fields: `method`, `url`, `domain`, `path`, `query_params`, `resource_type`, `request_headers`, `request_body`, `response_status`, `response_headers`, `response_body`, `timing.duration_ms`, `timing.ttfb_ms`, `failed`, `failure_reason`. |
85 | 87 |
|
86 | 88 | ```text |
@@ -217,6 +219,43 @@ Assertions support these comparisons. Phrase them naturally — the agent maps t |
217 | 219 |
|
218 | 220 | If you're not sure which method, default to **Visual** — that's what the agent does too. |
219 | 221 |
|
| 222 | +### 3.5 Calling an API directly |
| 223 | + |
| 224 | +Distinct from observing the page's network traffic (§3.2): you can have the agent **make an HTTP request itself** as part of an objective — to seed data, hit a backend, or check a service — then assert on or reuse the response. |
| 225 | + |
| 226 | +Phrase an explicit call and name the response with "save the response as …": |
| 227 | + |
| 228 | +```text |
| 229 | +Call POST https://api.example.com/orders with body {"item": "sku_42", "qty": 1}, save the response as order |
| 230 | +Hit GET https://api.example.com/orders/123, save the response as fetched |
| 231 | +``` |
| 232 | + |
| 233 | +A pasted `curl` works too and is kept verbatim (method, headers, body, auth): |
| 234 | + |
| 235 | +```text |
| 236 | +curl -X POST https://api.example.com/login -H 'Content-Type: application/json' -d '{"u":"a","p":"b"}', save the response as login |
| 237 | +``` |
| 238 | + |
| 239 | +Once saved, reference the response by name: |
| 240 | + |
| 241 | +| Reference | Resolves to | |
| 242 | +|---|---| |
| 243 | +| `{{order.status}}` | the HTTP status code (e.g. `201`) | |
| 244 | +| `{{order.response_body}}` | the whole response body | |
| 245 | +| `{{order.response_body.<field>}}` | a field from the JSON response body | |
| 246 | + |
| 247 | +Then assert or chain on it — API calls and browser actions mix freely in one objective: |
| 248 | + |
| 249 | +```text |
| 250 | +Call POST https://api.example.com/login with body {"u": "{{user}}", "p": "{{password}}"}, save the response as login, |
| 251 | +assert {{login.status}} is 200, |
| 252 | +then open https://app.example.com and verify the dashboard loads |
| 253 | +``` |
| 254 | + |
| 255 | +**Direct call vs. DevTools/Network (§3.2):** use a **direct call** when *you* want the agent to make the request (seed a record, call a backend, set up state). Use **DevTools/Network** when you want to **observe the requests the page itself makes** during a UI flow. They compose: seed via a direct call, drive the UI, then assert on the page's traffic. |
| 256 | + |
| 257 | +**Tokens:** put any credential/token in a variable marked `secret: true` (§6) so it's masked and never logged. |
| 258 | + |
220 | 259 | --- |
221 | 260 |
|
222 | 261 | ## 4. Extraction — the "store as" rule |
@@ -394,3 +433,15 @@ Store the order number as 'order_id'. |
394 | 433 | ``` |
395 | 434 |
|
396 | 435 | The step body is exactly the same grammar as `kane-cli run`. Everything in this cookbook applies. |
| 436 | + |
| 437 | +### Example D — Seed via API, then verify in the UI |
| 438 | + |
| 439 | +```text |
| 440 | +"Call POST https://api.example.com/orders with body {"item": "sku_42", "qty": 1}, |
| 441 | + save the response as order, |
| 442 | + assert {{order.status}} is 201, |
| 443 | + then open https://app.example.com/orders, |
| 444 | + assert an order for 'sku_42' is visible" |
| 445 | +``` |
| 446 | + |
| 447 | +The agent makes the API call directly, captures the response, asserts on its status, then drives the UI to confirm the seeded data appears. (Direct call → UI verify — contrast with §3.2, where you observe the page's own traffic.) |
0 commit comments