Skip to content

Commit 5cafd1a

Browse files
committed
feat(tools): reddit + hackernews tools (T-0020, T-0021)
1 parent 66ff64d commit 5cafd1a

6 files changed

Lines changed: 119 additions & 0 deletions

File tree

docs/stories/054-tool-reddit.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# 054 - Tool: reddit
2+
3+
**Persona:** [CLI User](../personas/cli-user.md),
4+
[AI Coding Assistant](../personas/ai-coding-assistant.md)
5+
6+
## Goal
7+
8+
Search Reddit for posts matching a query and extract structured metadata
9+
(title, subreddit, score, comment count, URL, snippet) for each result.
10+
11+
## Stories
12+
13+
- As a CLI user, I run `ibr tool reddit --param query=rust async` to retrieve
14+
a list of Reddit posts with title, subreddit, score, comment_count, url, and snippet.
15+
- As a CLI user, I pass `--param subreddit=rust` to scope results to a single subreddit.
16+
- As a CLI user, I pass `--param sort=hot` to sort by hot posts.
17+
- As a CLI user, I pass `--param max_results=10` to control how many results are returned.
18+
- As a CLI user, omitting `query` produces a non-zero exit with a clear error message.
19+
20+
## Acceptance Criteria
21+
22+
- Navigates to `https://www.reddit.com/search/?q={{query}}&sort={{sort}}` by default.
23+
- When `subreddit` is set, navigates to
24+
`https://www.reddit.com/r/{{subreddit}}/search/?q={{query}}&sort={{sort}}` instead.
25+
- Extracts up to `max_results` (default 5) posts per run.
26+
- Each extracted item contains: `title`, `subreddit`, `score`, `comment_count`,
27+
`url`, `snippet`.
28+
- `sort` defaults to `relevance`; accepted values: relevance, hot, new, top.
29+
- Missing required param `query` → non-zero exit with "Missing required param: query".
30+
- Exit code 0 on successful extraction; stdout contains "Task execution completed".
31+
32+
## E2E Coverage
33+
34+
- `test/e2e/cli-tool-vcr.test.js` — VCR: exits 0, no config errors; required param
35+
validation.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# 055 - Tool: hackernews
2+
3+
**Persona:** [CLI User](../personas/cli-user.md),
4+
[AI Coding Assistant](../personas/ai-coding-assistant.md)
5+
6+
## Goal
7+
8+
Search Hacker News via Algolia and extract structured metadata (title, points,
9+
comment count, author, URL, HN URL) for each result.
10+
11+
## Stories
12+
13+
- As a CLI user, I run `ibr tool hackernews --param query=rust async` to retrieve
14+
a list of HN posts with title, points, comment_count, author, url, and hn_url.
15+
- As a CLI user, I pass `--param type=job` to filter to job posts.
16+
- As a CLI user, I pass `--param sort=date` to sort by most recent.
17+
- As a CLI user, I pass `--param max_results=5` to control how many results are returned.
18+
- As a CLI user, omitting `query` produces a non-zero exit with a clear error message.
19+
20+
## Acceptance Criteria
21+
22+
- Navigates to `https://hn.algolia.com/?q={{query}}&type={{type}}&sort=by{{sort}}`.
23+
- Extracts up to `max_results` (default 10) items per run.
24+
- Each extracted item contains: `title`, `points`, `comment_count`, `author`,
25+
`url`, `hn_url`.
26+
- `type` defaults to `story`; accepted values: story, comment, job, poll.
27+
- `sort` defaults to `popularity`; accepted values: date, popularity.
28+
- Missing required param `query` → non-zero exit with "Missing required param: query".
29+
- Exit code 0 on successful extraction; stdout contains "Task execution completed".
30+
31+
## E2E Coverage
32+
33+
- `test/e2e/cli-tool-vcr.test.js` — VCR: exits 0, no config errors; required param
34+
validation.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[
2+
"{\"url\":\"{SERVER_URL}/tool-results.html\",\"instructions\":[{\"name\":\"extract\",\"prompt\":\"extract HN stories with title, points, comment_count, author, url, and hn_url\"}]}",
3+
"[{\"title\":\"Rust async runtimes compared\",\"points\":342,\"comment_count\":94,\"author\":\"tptacek\",\"url\":\"https://example.com/rust-async\",\"hn_url\":\"https://news.ycombinator.com/item?id=12345678\"}]"
4+
]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[
2+
"{\"url\":\"{SERVER_URL}/tool-results.html\",\"instructions\":[{\"name\":\"extract\",\"prompt\":\"extract Reddit posts with title, subreddit, score, comment_count, url, and snippet\"}]}",
3+
"[{\"title\":\"Why I switched to Rust for async services\",\"subreddit\":\"rust\",\"score\":1240,\"comment_count\":87,\"url\":\"https://example.com/rust-async\",\"snippet\":\"After struggling with Go concurrency...\"}]"
4+
]

tools/hackernews.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: hackernews
2+
description: Search Hacker News via Algolia and extract story title, points, comment count, author, URL, and HN URL
3+
params:
4+
- name: query
5+
description: Search terms
6+
required: true
7+
- name: type
8+
description: Item type — story, comment, job, or poll
9+
default: "story"
10+
- name: sort
11+
description: Sort order — date or popularity
12+
default: "popularity"
13+
- name: max_results
14+
description: Maximum number of results to extract
15+
default: "10"
16+
url: "https://hn.algolia.com/?q={{query}}&type={{type}}&sort=by{{sort}}"
17+
instructions:
18+
- wait for search results to load
19+
- extract the top {{max_results}} results; for each result include title, points,
20+
comment_count, author, url, and hn_url

tools/reddit.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: reddit
2+
description: Search Reddit and extract post title, subreddit, score, comment count, URL, and snippet
3+
params:
4+
- name: query
5+
description: Search terms
6+
required: true
7+
- name: subreddit
8+
description: Scope search to a specific subreddit (leave empty for site-wide)
9+
default: ""
10+
- name: sort
11+
description: Sort order — relevance, hot, new, or top
12+
default: "relevance"
13+
- name: max_results
14+
description: Maximum number of results to extract
15+
default: "5"
16+
url: "https://www.reddit.com/search/?q={{query}}&sort={{sort}}"
17+
instructions:
18+
- if subreddit param is non-empty, navigate to
19+
https://www.reddit.com/r/{{subreddit}}/search/?q={{query}}&sort={{sort}} instead
20+
- wait for search results to load
21+
- extract the top {{max_results}} results; for each result include title, subreddit,
22+
score, comment_count, url, and snippet

0 commit comments

Comments
 (0)