@signal4/s4 2.2.0 → 2.5.0

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.
Files changed (50) hide show
  1. package/README.md +145 -17
  2. package/bin/s4.js +0 -0
  3. package/bin/signal4-mcp.js +0 -0
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +414 -37
  6. package/dist/cli.js.map +1 -1
  7. package/dist/client.d.ts +151 -5
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +214 -8
  10. package/dist/client.js.map +1 -1
  11. package/dist/format.d.ts +23 -1
  12. package/dist/format.d.ts.map +1 -1
  13. package/dist/format.js +454 -8
  14. package/dist/format.js.map +1 -1
  15. package/dist/handlers/ads.d.ts.map +1 -1
  16. package/dist/handlers/ads.js +20 -2
  17. package/dist/handlers/ads.js.map +1 -1
  18. package/dist/handlers/analyze.d.ts +1 -0
  19. package/dist/handlers/analyze.d.ts.map +1 -1
  20. package/dist/handlers/analyze.js +28 -6
  21. package/dist/handlers/analyze.js.map +1 -1
  22. package/dist/handlers/claim_detail.d.ts +4 -0
  23. package/dist/handlers/claim_detail.d.ts.map +1 -0
  24. package/dist/handlers/claim_detail.js +29 -0
  25. package/dist/handlers/claim_detail.js.map +1 -0
  26. package/dist/handlers/claims.d.ts +12 -1
  27. package/dist/handlers/claims.d.ts.map +1 -1
  28. package/dist/handlers/claims.js +189 -12
  29. package/dist/handlers/claims.js.map +1 -1
  30. package/dist/handlers/explore.d.ts.map +1 -1
  31. package/dist/handlers/explore.js +103 -20
  32. package/dist/handlers/explore.js.map +1 -1
  33. package/dist/handlers/registry.d.ts.map +1 -1
  34. package/dist/handlers/registry.js +18 -2
  35. package/dist/handlers/registry.js.map +1 -1
  36. package/dist/handlers/reports.d.ts.map +1 -1
  37. package/dist/handlers/reports.js +69 -10
  38. package/dist/handlers/reports.js.map +1 -1
  39. package/dist/handlers/search.d.ts.map +1 -1
  40. package/dist/handlers/search.js +29 -12
  41. package/dist/handlers/search.js.map +1 -1
  42. package/dist/handlers/timeline.d.ts +4 -0
  43. package/dist/handlers/timeline.d.ts.map +1 -0
  44. package/dist/handlers/timeline.js +28 -0
  45. package/dist/handlers/timeline.js.map +1 -0
  46. package/dist/index.js +9 -1
  47. package/dist/index.js.map +1 -1
  48. package/dist/types.d.ts +336 -0
  49. package/dist/types.d.ts.map +1 -1
  50. package/package.json +13 -1
package/README.md CHANGED
@@ -1,24 +1,155 @@
1
1
  # @signal4/s4
2
2
 
3
- Media intelligence CLI and MCP server for AI agents.
3
+ Media intelligence platform — CLI, MCP server, and TypeScript client.
4
4
 
5
5
  Search quotes, analyze discourse, track trends, and explore speakers across thousands of hours of audiovisual content.
6
6
 
7
- ## CLI
7
+ ## Architecture
8
+
9
+ This package contains three surfaces backed by one HTTP client:
10
+
11
+ ```
12
+ @signal4/s4
13
+ ├── client.ts ← Typed HTTP client (38 functions wrapping the REST API)
14
+ ├── types.ts ← TypeScript types for all API responses
15
+ ├── config.ts ← Config loader (~/.signal4/config)
16
+ ├── cli.ts ← Terminal interface (s4 search, s4 speaker, ...)
17
+ ├── index.ts ← MCP server for Claude Desktop / Cursor
18
+ └── handlers/ ← Human-readable formatters (shared by CLI + MCP)
19
+ ```
20
+
21
+ **Client** is the core — everything else is a consumer. Use it directly for programmatic access; use the CLI or MCP server for interactive use.
22
+
23
+ | Surface | Entry point | Reads from | Formats with |
24
+ |---------|-------------|------------|-------------|
25
+ | TypeScript client | `import from '@signal4/s4/client'` | `client.ts` | — (raw typed responses) |
26
+ | CLI | `npx @signal4/s4 search ...` | `client.ts` | `handlers/` → text |
27
+ | MCP server | `s4 --mcp` | `client.ts` | `handlers/` → text |
28
+
29
+ ## TypeScript Client
30
+
31
+ For applications that need typed access to the Signal4 API (frontends, agents, pipelines, scripts):
32
+
33
+ ```typescript
34
+ import { searchQuotes, getSpeaker, analyze } from '@signal4/s4/client';
35
+ import type { QuoteSearchResult, SpeakerProfile } from '@signal4/s4/types';
36
+
37
+ // Search for quotes about a topic
38
+ const results = await searchQuotes({
39
+ topic: 'AI regulation',
40
+ speaker_name: 'Tucker Carlson',
41
+ limit: 10,
42
+ start_date: '2026-05-01',
43
+ });
44
+
45
+ // Get a speaker profile
46
+ const speaker = await getSpeaker(12345);
47
+
48
+ // Run an AI analysis
49
+ const analysis = await analyze({
50
+ query: 'How are podcasters talking about tariffs?',
51
+ workflow: 'deep_analysis',
52
+ days: 30,
53
+ });
54
+ ```
55
+
56
+ ### Sub-path exports
57
+
58
+ ```typescript
59
+ import { searchQuotes, detectTrend, ... } from '@signal4/s4/client'; // HTTP client
60
+ import type { Quote, SpeakerProfile, ... } from '@signal4/s4/types'; // TypeScript types
61
+ import { applyConfig } from '@signal4/s4/config'; // Config loader
62
+ ```
63
+
64
+ ### Configuration
65
+
66
+ The client reads from environment variables:
67
+
68
+ | Variable | Purpose | Default |
69
+ |----------|---------|---------|
70
+ | `SIGNAL4_API_KEY` | API key (required) | — |
71
+ | `SIGNAL4_API_URL` | API base URL | `https://api.signal4.ca` |
72
+ | `SIGNAL4_CLIENT_ID` | Client identifier for analytics | — |
73
+
74
+ `applyConfig()` loads these from `~/.signal4/config` if not already set in the environment. The CLI and MCP server call this automatically; programmatic consumers should call it explicitly if they want the file-based fallback.
75
+
76
+ ### Client functions
77
+
78
+ **Search**
79
+ - `searchQuotes(params)` — Semantic/keyword search across transcripts
80
+ - `searchClaims(params)` — Search extracted claims with stance and observation counts
81
+ - `detectTrend(params)` — Compare recent vs baseline mention volume
82
+ - `getTimeline(params)` — Topic mention volume over time
83
+
84
+ **Entities**
85
+ - `searchSpeakers(query, limit?)` — Autocomplete speaker search
86
+ - `getSpeaker(id)` / `getSpeakerByName(name)` — Speaker profile
87
+ - `getSpeakerSegments(params)` — Recent segments by speaker
88
+ - `searchSpeakerSegments(params)` — Semantic search within a speaker's segments
89
+ - `getChannel(id)` / `getChannelByName(name)` — Channel profile
90
+ - `getEpisode(contentId)` — Episode details
91
+ - `getTranscript(contentId)` — Full episode transcript
92
+ - `getSegment(segmentId)` — Single segment with audio clip URL
93
+ - `getSegmentThread(segmentId, n?)` — Conversation context around a segment
94
+
95
+ **Analysis** (SSE streaming, handled internally)
96
+ - `analyze(params)` — AI-powered analysis (workflows: `simple_rag`, `deep_analysis`, `speaker_compare`, `speaker_dossier`, `contradiction_check`)
97
+
98
+ **Reports**
99
+ - `getTopSpeakers(params)` / `getTopChannels(params)` — Leaderboards
100
+ - `getSpeakerNetwork(params)` — Co-appearance network graph
101
+ - `getTopics(params)` — Trending topic clusters
102
+ - `getReportStats(days?)` / `getProjectStats()` — Platform statistics
103
+ - `getDiscourseSummary(params)` — AI discourse briefing
104
+
105
+ **Claims**
106
+ - `getClaim(claimId)` — Full claim detail
107
+ - `getClaimObservations(params)` — Observations supporting a claim
108
+ - `getRelatedClaims(claimId)` — Similar/related claims
109
+
110
+ **Ads**
111
+ - `getAdStats(days?)` / `getAdvertisers(params)` / `getAdvertiser(id)` — Ad intelligence
112
+ - `getAdsByChannel(channelId, days?)` / `getAdTrends(days?)` — Channel-level and trending ads
113
+
114
+ **Bookmarks**
115
+ - `createBookmark(params)` / `listBookmarks(params)` / `deleteBookmark(id)`
116
+
117
+ **Auth**
118
+ - `whoami()` — Verify key and see access scope
119
+
120
+ ### Error handling
121
+
122
+ All functions throw on error. HTTP 502/503 are retried automatically (3 attempts with backoff). Wrap calls in try/catch:
123
+
124
+ ```typescript
125
+ try {
126
+ const result = await searchQuotes({ topic: 'tariffs' });
127
+ } catch (err) {
128
+ console.error((err as Error).message); // "HTTP 401: ..."
129
+ }
130
+ ```
131
+
132
+ ### Installing as a dependency
133
+
134
+ For projects within the signal4 monorepo:
8
135
 
9
136
  ```bash
10
- # Install globally
11
- npm install -g @signal4/s4
137
+ pnpm add @signal4/s4@file:../mcp
138
+ ```
139
+
140
+ For external projects (once published):
12
141
 
13
- # Or run directly
14
- npx @signal4/s4 search "tariffs" --speaker "Trudeau" --days 7
142
+ ```bash
143
+ npm install @signal4/s4
15
144
  ```
16
145
 
17
- ### Setup
146
+ ## CLI
18
147
 
19
148
  ```bash
20
- s4 setup # Save your API key
21
- s4 whoami # Verify access
149
+ npm install -g @signal4/s4
150
+
151
+ s4 setup # Save your API key to ~/.signal4/config
152
+ s4 whoami # Verify access and see available commands
22
153
  ```
23
154
 
24
155
  ### Commands
@@ -28,6 +159,7 @@ s4 whoami # Verify access
28
159
  s4 search "immigration" --speaker "Tucker Carlson"
29
160
  s4 claims "AI regulation" --entity "OpenAI"
30
161
  s4 trend "tariffs"
162
+ s4 timeline "carbon tax" --days 90
31
163
 
32
164
  # Explore
33
165
  s4 speaker "Joe Rogan"
@@ -37,8 +169,9 @@ s4 episode pod_8f1e55513f70 --transcript
37
169
  s4 segment 28553756
38
170
  s4 thread 28553756
39
171
 
40
- # Analyze
172
+ # Analyze (AI-powered, slower)
41
173
  s4 analyze "carbon tax" --days 14
174
+ s4 frames "midterm elections" --days 30
42
175
  s4 compare "tariffs" --speakers "Trump,Biden"
43
176
  s4 dossier "immigration" --speaker "Carlson"
44
177
  s4 contradictions "vaccines" --speaker "Trump"
@@ -59,7 +192,7 @@ s4 bookmarks
59
192
  s4 bookmarks add segment 12345 --note "key quote"
60
193
  ```
61
194
 
62
- All commands support `--json` for raw JSON output.
195
+ All commands support `--json` for raw JSON output (bypasses the handler formatting layer and calls the client directly).
63
196
 
64
197
  ## MCP Server
65
198
 
@@ -79,14 +212,9 @@ For Claude Desktop, Cursor, or other MCP clients:
79
212
  }
80
213
  ```
81
214
 
82
- Tool definitions are loaded dynamically from the API based on your key's access level.
215
+ Tool definitions are loaded dynamically from the API based on your key's access level. The MCP server uses the same handlers as the CLI for formatting responses.
83
216
 
84
217
  ## Requirements
85
218
 
86
219
  - Node.js 18+
87
220
  - A Signal4 API key ([signal4.ca](https://signal4.ca))
88
-
89
- ## Links
90
-
91
- - [Signal4](https://signal4.ca)
92
- - [API docs](https://signal4.ca/docs/api)
package/bin/s4.js CHANGED
File without changes
File without changes
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,6EAA6E;AA+vB7E,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAwD1C"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAmkC7E,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAwD1C"}