peak6-x-intelligence-plugin 0.1.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.
package/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # X Intelligence Plugin
2
+
3
+ X/Twitter intelligence plugin for Paperclip
4
+
5
+ ## Development
6
+
7
+ ```bash
8
+ pnpm install
9
+ pnpm dev # watch builds
10
+ pnpm dev:ui # local dev server with hot-reload events
11
+ pnpm test
12
+ ```
13
+
14
+ This scaffold snapshots `@paperclipai/plugin-sdk` and `@paperclipai/shared` from a local Paperclip checkout at:
15
+
16
+ `/Users/zshin/Projects/attention-machine/packages/plugins/sdk`
17
+
18
+ The packed tarballs live in `.paperclip-sdk/` for local development. Before publishing this plugin, switch those dependencies to published package versions once they are available on npm.
19
+
20
+
21
+
22
+ ## Install Into Paperclip
23
+
24
+ ```bash
25
+ curl -X POST http://127.0.0.1:3100/api/plugins/install \
26
+ -H "Content-Type: application/json" \
27
+ -d '{"packageName":"/Users/zshin/Projects/paperclip/x-intelligence-plugin","isLocalPath":true}'
28
+ ```
29
+
30
+ ## Build Options
31
+
32
+ - `pnpm build` uses esbuild presets from `@paperclipai/plugin-sdk/bundlers`.
33
+ - `pnpm build:rollup` uses rollup presets from the same SDK.
@@ -0,0 +1,375 @@
1
+ // src/constants.ts
2
+ var PLUGIN_ID = "peak6-labs.x-intelligence";
3
+ var PLUGIN_VERSION = "0.1.0";
4
+ var JOB_KEYS = {
5
+ discoveryRun: "discovery-run",
6
+ authorityDecay: "authority-decay",
7
+ complianceCheck: "compliance-check",
8
+ corpusRetention: "corpus-retention"
9
+ };
10
+ var TOOL_NAMES = {
11
+ searchCorpus: "search-corpus",
12
+ getToday: "get-today",
13
+ getAuthorities: "get-authorities",
14
+ suggestHandles: "suggest-handles",
15
+ trackHandle: "track-handle"
16
+ };
17
+ var SLOT_IDS = {
18
+ dashboardWidget: "x-intelligence-dashboard",
19
+ settingsPage: "x-intelligence-settings"
20
+ };
21
+ var EXPORT_NAMES = {
22
+ dashboardWidget: "DashboardWidget",
23
+ settingsPage: "SettingsPage"
24
+ };
25
+ var DEFAULT_CONFIG = {
26
+ company_id: "",
27
+ xai_api_key_ref: "XAI_API_KEY",
28
+ x_api_bearer_ref: "BEARER_TOKEN",
29
+ semantic_topics: [
30
+ "institutional investors discussing market structure reform",
31
+ "fintech companies disrupting traditional trading",
32
+ "SEC regulatory changes affecting options trading",
33
+ "algorithmic trading and quantitative strategies",
34
+ "venture capital investing in financial infrastructure",
35
+ "PEAK6",
36
+ "options market making technology",
37
+ "Chicago trading community news"
38
+ ],
39
+ keyword_searches: [
40
+ '"PEAK6 Investments" OR "PEAK6" trading fintech',
41
+ "fintech and trading technology",
42
+ "market structure and regulation",
43
+ "options trading strategies and platforms"
44
+ ],
45
+ content_pillars: [
46
+ "market structure & regulation",
47
+ "fintech & trading technology",
48
+ "venture capital & investment",
49
+ "Chicago business ecosystem",
50
+ "company culture & talent"
51
+ ],
52
+ scoring_weights: {
53
+ relevance: 0.45,
54
+ recency: 0.25,
55
+ engagement: 0.3
56
+ },
57
+ engagement_sub_weights: {
58
+ likes: 0.55,
59
+ reposts: 0.25,
60
+ replies: 0.15,
61
+ quotes: 0.05
62
+ },
63
+ max_corpus_size: 200,
64
+ dedup_threshold: 0.7,
65
+ authority_boost: 0.15,
66
+ authority_lists: {
67
+ market_structure: {
68
+ description: "Market structure, regulation, SEC reform, options trading",
69
+ handles: [
70
+ "LizAnnSonders",
71
+ "matt_levine",
72
+ "unusual_whales",
73
+ "CMEGroup",
74
+ "CBOE",
75
+ "OptionsHawk",
76
+ "InvestorDenis"
77
+ ],
78
+ last_reviewed: "2026-03-29"
79
+ },
80
+ fintech: {
81
+ description: "Fintech, trading technology, AI in finance",
82
+ handles: [
83
+ "twifintech",
84
+ "IBSIntelligence",
85
+ "privy_io",
86
+ "i_Know_First",
87
+ "fintech_germany",
88
+ "venture_radar"
89
+ ],
90
+ last_reviewed: "2026-03-29"
91
+ },
92
+ venture_capital: {
93
+ description: "Venture capital investing in financial infrastructure",
94
+ handles: [
95
+ "a16z",
96
+ "FundersVC"
97
+ ],
98
+ last_reviewed: "2026-03-29"
99
+ },
100
+ chicago_trading: {
101
+ description: "Chicago trading community, prop firms, PEAK6 ecosystem",
102
+ handles: [
103
+ "CBOE",
104
+ "CMEGroup",
105
+ "boogeymantradez",
106
+ "adealafia"
107
+ ],
108
+ last_reviewed: "2026-03-29"
109
+ }
110
+ },
111
+ global_excluded: ["elonmusk", "openai", "google", "microsoft"],
112
+ authority_promotion_policy: {
113
+ auto_promote_threshold: {
114
+ min_appearances: 7,
115
+ min_avg_relevance: 0.8,
116
+ min_mutual_overlap: 3
117
+ },
118
+ candidate_threshold: {
119
+ min_appearances: 5,
120
+ min_avg_relevance: 0.7,
121
+ min_mutual_overlap: 2
122
+ },
123
+ tracking_window_days: 14
124
+ },
125
+ corpus_retention_days: 90
126
+ };
127
+
128
+ // src/manifest.ts
129
+ var manifest = {
130
+ id: PLUGIN_ID,
131
+ apiVersion: 1,
132
+ version: PLUGIN_VERSION,
133
+ displayName: "X Intelligence",
134
+ description: "Automated X/Twitter intelligence pipeline \u2014 discovery, enrichment, scoring, deduplication, authority list management, and corpus storage.",
135
+ author: "peak6-labs",
136
+ categories: ["connector", "automation"],
137
+ capabilities: [
138
+ "http.outbound",
139
+ "secrets.read-ref",
140
+ "jobs.schedule",
141
+ "agent.tools.register",
142
+ "plugin.state.read",
143
+ "plugin.state.write",
144
+ "events.subscribe",
145
+ "events.emit",
146
+ "issues.read",
147
+ "issues.create",
148
+ "activity.log.write",
149
+ "metrics.write",
150
+ "instance.settings.register",
151
+ "ui.dashboardWidget.register"
152
+ ],
153
+ entrypoints: {
154
+ worker: "./dist/worker.js",
155
+ ui: "./dist/ui"
156
+ },
157
+ instanceConfigSchema: {
158
+ type: "object",
159
+ properties: {
160
+ company_id: {
161
+ type: "string",
162
+ title: "Company ID",
163
+ description: "UUID of the company this plugin serves (required for events and activity logging)",
164
+ default: DEFAULT_CONFIG.company_id
165
+ },
166
+ xai_api_key_ref: {
167
+ type: "string",
168
+ title: "xAI API Key Secret Reference",
169
+ default: DEFAULT_CONFIG.xai_api_key_ref
170
+ },
171
+ x_api_bearer_ref: {
172
+ type: "string",
173
+ title: "X API Bearer Token Secret Reference",
174
+ default: DEFAULT_CONFIG.x_api_bearer_ref
175
+ },
176
+ semantic_topics: {
177
+ type: "array",
178
+ title: "Semantic Discovery Topics",
179
+ items: { type: "string" },
180
+ default: DEFAULT_CONFIG.semantic_topics
181
+ },
182
+ keyword_searches: {
183
+ type: "array",
184
+ title: "Keyword Searches",
185
+ items: { type: "string" },
186
+ default: DEFAULT_CONFIG.keyword_searches
187
+ },
188
+ content_pillars: {
189
+ type: "array",
190
+ title: "Content Pillars",
191
+ items: { type: "string" },
192
+ default: DEFAULT_CONFIG.content_pillars
193
+ },
194
+ scoring_weights: {
195
+ type: "object",
196
+ title: "Scoring Weights",
197
+ properties: {
198
+ relevance: { type: "number", default: 0.45 },
199
+ recency: { type: "number", default: 0.25 },
200
+ engagement: { type: "number", default: 0.3 }
201
+ },
202
+ default: DEFAULT_CONFIG.scoring_weights
203
+ },
204
+ engagement_sub_weights: {
205
+ type: "object",
206
+ title: "Engagement Sub-Weights",
207
+ properties: {
208
+ likes: { type: "number", default: 0.55 },
209
+ reposts: { type: "number", default: 0.25 },
210
+ replies: { type: "number", default: 0.15 },
211
+ quotes: { type: "number", default: 0.05 }
212
+ },
213
+ default: DEFAULT_CONFIG.engagement_sub_weights
214
+ },
215
+ max_corpus_size: {
216
+ type: "number",
217
+ title: "Max Corpus Size Per Day",
218
+ default: DEFAULT_CONFIG.max_corpus_size
219
+ },
220
+ dedup_threshold: {
221
+ type: "number",
222
+ title: "Dedup Jaccard Threshold",
223
+ default: DEFAULT_CONFIG.dedup_threshold
224
+ },
225
+ authority_boost: {
226
+ type: "number",
227
+ title: "Authority Score Boost",
228
+ default: DEFAULT_CONFIG.authority_boost
229
+ },
230
+ authority_lists: {
231
+ type: "object",
232
+ title: "Authority Handle Lists",
233
+ default: DEFAULT_CONFIG.authority_lists
234
+ },
235
+ global_excluded: {
236
+ type: "array",
237
+ title: "Globally Excluded Handles",
238
+ items: { type: "string" },
239
+ default: DEFAULT_CONFIG.global_excluded
240
+ },
241
+ authority_promotion_policy: {
242
+ type: "object",
243
+ title: "Authority Promotion Policy",
244
+ default: DEFAULT_CONFIG.authority_promotion_policy
245
+ },
246
+ corpus_retention_days: {
247
+ type: "number",
248
+ title: "Corpus Retention (days)",
249
+ default: DEFAULT_CONFIG.corpus_retention_days
250
+ }
251
+ }
252
+ },
253
+ jobs: [
254
+ {
255
+ jobKey: JOB_KEYS.discoveryRun,
256
+ displayName: "Discovery Run",
257
+ description: "Two-stage pipeline: xAI open + focused discovery, X API v2 enrichment, scoring, and corpus storage.",
258
+ schedule: "0 6 * * *"
259
+ },
260
+ {
261
+ jobKey: JOB_KEYS.authorityDecay,
262
+ displayName: "Authority Decay",
263
+ description: "Weekly handle decay \u2014 downgrade or remove handles not seen within the tracking window.",
264
+ schedule: "0 0 * * 0"
265
+ },
266
+ {
267
+ jobKey: JOB_KEYS.complianceCheck,
268
+ displayName: "Compliance Check",
269
+ description: "Weekly re-check of stored tweets \u2014 remove deleted or suspended content.",
270
+ schedule: "0 3 * * 0"
271
+ },
272
+ {
273
+ jobKey: JOB_KEYS.corpusRetention,
274
+ displayName: "Corpus Retention",
275
+ description: "Monthly archive/delete corpus older than the retention window.",
276
+ schedule: "0 4 1 * *"
277
+ }
278
+ ],
279
+ tools: [
280
+ {
281
+ name: TOOL_NAMES.searchCorpus,
282
+ displayName: "Search X Corpus",
283
+ description: "Search the scored X intelligence corpus by query text, date range, and content pillar.",
284
+ parametersSchema: {
285
+ type: "object",
286
+ properties: {
287
+ query: { type: "string", description: "Search query" },
288
+ date: {
289
+ type: "string",
290
+ description: "Date filter (YYYY-MM-DD)"
291
+ },
292
+ pillar: {
293
+ type: "string",
294
+ description: "Content pillar filter"
295
+ },
296
+ limit: { type: "number", description: "Max results (default 20)" }
297
+ },
298
+ required: ["query"]
299
+ }
300
+ },
301
+ {
302
+ name: TOOL_NAMES.getToday,
303
+ displayName: "Get Today's Intelligence",
304
+ description: "Get today's scored X intelligence corpus, optionally filtered by pillar.",
305
+ parametersSchema: {
306
+ type: "object",
307
+ properties: {
308
+ pillar: { type: "string", description: "Content pillar filter" },
309
+ limit: { type: "number", description: "Max results (default 20)" }
310
+ }
311
+ }
312
+ },
313
+ {
314
+ name: TOOL_NAMES.getAuthorities,
315
+ displayName: "Get Authority Handles",
316
+ description: "Get the authority handle list for a domain, or all domains if none specified.",
317
+ parametersSchema: {
318
+ type: "object",
319
+ properties: {
320
+ list_name: {
321
+ type: "string",
322
+ description: "Domain name (e.g. 'market_structure')"
323
+ }
324
+ }
325
+ }
326
+ },
327
+ {
328
+ name: TOOL_NAMES.suggestHandles,
329
+ displayName: "Suggest Handle Promotions",
330
+ description: "Get handles that are candidates for authority list promotion based on tracking data.",
331
+ parametersSchema: {
332
+ type: "object",
333
+ properties: {}
334
+ }
335
+ },
336
+ {
337
+ name: TOOL_NAMES.trackHandle,
338
+ displayName: "Track Handle",
339
+ description: "Record a handle appearance from agent discovery with relevance score and domain.",
340
+ parametersSchema: {
341
+ type: "object",
342
+ properties: {
343
+ handle: { type: "string", description: "X handle (without @)" },
344
+ relevance: {
345
+ type: "number",
346
+ description: "Relevance score (0-1)"
347
+ },
348
+ domain: { type: "string", description: "Domain/topic area" }
349
+ },
350
+ required: ["handle", "relevance", "domain"]
351
+ }
352
+ }
353
+ ],
354
+ ui: {
355
+ slots: [
356
+ {
357
+ type: "dashboardWidget",
358
+ id: SLOT_IDS.dashboardWidget,
359
+ displayName: "X Intelligence",
360
+ exportName: EXPORT_NAMES.dashboardWidget
361
+ },
362
+ {
363
+ type: "settingsPage",
364
+ id: SLOT_IDS.settingsPage,
365
+ displayName: "X Intelligence Settings",
366
+ exportName: EXPORT_NAMES.settingsPage
367
+ }
368
+ ]
369
+ }
370
+ };
371
+ var manifest_default = manifest;
372
+ export {
373
+ manifest_default as default
374
+ };
375
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/constants.ts", "../src/manifest.ts"],
4
+ "sourcesContent": ["export const PLUGIN_ID = \"peak6-labs.x-intelligence\";\nexport const PLUGIN_VERSION = \"0.1.0\";\n\nexport const JOB_KEYS = {\n discoveryRun: \"discovery-run\",\n authorityDecay: \"authority-decay\",\n complianceCheck: \"compliance-check\",\n corpusRetention: \"corpus-retention\",\n} as const;\n\nexport const TOOL_NAMES = {\n searchCorpus: \"search-corpus\",\n getToday: \"get-today\",\n getAuthorities: \"get-authorities\",\n suggestHandles: \"suggest-handles\",\n trackHandle: \"track-handle\",\n} as const;\n\nexport const SLOT_IDS = {\n dashboardWidget: \"x-intelligence-dashboard\",\n settingsPage: \"x-intelligence-settings\",\n} as const;\n\nexport const EXPORT_NAMES = {\n dashboardWidget: \"DashboardWidget\",\n settingsPage: \"SettingsPage\",\n} as const;\n\nexport const ENTITY_TYPES = {\n tweet: \"tweet\",\n handle: \"handle\",\n} as const;\n\nexport const STATE_KEYS = {\n corpusPrefix: \"corpus:\",\n lastDiscoveryRun: \"last-discovery-run\",\n pipelineStats: \"pipeline-stats\",\n} as const;\n\nexport const EVENT_NAMES = {\n corpusUpdated: \"corpus.updated\",\n handlePromoted: \"handle.promoted\",\n gapIdentified: \"gap.identified\",\n} as const;\n\nexport const DEFAULT_CONFIG = {\n company_id: \"\",\n xai_api_key_ref: \"XAI_API_KEY\",\n x_api_bearer_ref: \"BEARER_TOKEN\",\n semantic_topics: [\n \"institutional investors discussing market structure reform\",\n \"fintech companies disrupting traditional trading\",\n \"SEC regulatory changes affecting options trading\",\n \"algorithmic trading and quantitative strategies\",\n \"venture capital investing in financial infrastructure\",\n \"PEAK6\",\n \"options market making technology\",\n \"Chicago trading community news\",\n ],\n keyword_searches: [\n \"\\\"PEAK6 Investments\\\" OR \\\"PEAK6\\\" trading fintech\",\n \"fintech and trading technology\",\n \"market structure and regulation\",\n \"options trading strategies and platforms\",\n ],\n content_pillars: [\n \"market structure & regulation\",\n \"fintech & trading technology\",\n \"venture capital & investment\",\n \"Chicago business ecosystem\",\n \"company culture & talent\",\n ],\n scoring_weights: {\n relevance: 0.45,\n recency: 0.25,\n engagement: 0.30,\n },\n engagement_sub_weights: {\n likes: 0.55,\n reposts: 0.25,\n replies: 0.15,\n quotes: 0.05,\n },\n max_corpus_size: 200,\n dedup_threshold: 0.70,\n authority_boost: 0.15,\n authority_lists: {\n market_structure: {\n description: \"Market structure, regulation, SEC reform, options trading\",\n handles: [\n \"LizAnnSonders\",\n \"matt_levine\",\n \"unusual_whales\",\n \"CMEGroup\",\n \"CBOE\",\n \"OptionsHawk\",\n \"InvestorDenis\",\n ],\n last_reviewed: \"2026-03-29\",\n },\n fintech: {\n description: \"Fintech, trading technology, AI in finance\",\n handles: [\n \"twifintech\",\n \"IBSIntelligence\",\n \"privy_io\",\n \"i_Know_First\",\n \"fintech_germany\",\n \"venture_radar\",\n ],\n last_reviewed: \"2026-03-29\",\n },\n venture_capital: {\n description: \"Venture capital investing in financial infrastructure\",\n handles: [\n \"a16z\",\n \"FundersVC\",\n ],\n last_reviewed: \"2026-03-29\",\n },\n chicago_trading: {\n description: \"Chicago trading community, prop firms, PEAK6 ecosystem\",\n handles: [\n \"CBOE\",\n \"CMEGroup\",\n \"boogeymantradez\",\n \"adealafia\",\n ],\n last_reviewed: \"2026-03-29\",\n },\n } as Record<string, AuthorityList>,\n global_excluded: [\"elonmusk\", \"openai\", \"google\", \"microsoft\"],\n authority_promotion_policy: {\n auto_promote_threshold: {\n min_appearances: 7,\n min_avg_relevance: 0.8,\n min_mutual_overlap: 3,\n },\n candidate_threshold: {\n min_appearances: 5,\n min_avg_relevance: 0.7,\n min_mutual_overlap: 2,\n },\n tracking_window_days: 14,\n },\n corpus_retention_days: 90,\n} as const;\n\nexport interface AuthorityList {\n description: string;\n handles: string[];\n last_reviewed: string;\n}\n", "import type { PaperclipPluginManifestV1 } from \"@paperclipai/plugin-sdk\";\nimport {\n DEFAULT_CONFIG,\n EXPORT_NAMES,\n JOB_KEYS,\n PLUGIN_ID,\n PLUGIN_VERSION,\n SLOT_IDS,\n TOOL_NAMES,\n} from \"./constants.js\";\n\nconst manifest: PaperclipPluginManifestV1 = {\n id: PLUGIN_ID,\n apiVersion: 1,\n version: PLUGIN_VERSION,\n displayName: \"X Intelligence\",\n description:\n \"Automated X/Twitter intelligence pipeline \u2014 discovery, enrichment, scoring, deduplication, authority list management, and corpus storage.\",\n author: \"peak6-labs\",\n categories: [\"connector\", \"automation\"],\n capabilities: [\n \"http.outbound\",\n \"secrets.read-ref\",\n \"jobs.schedule\",\n \"agent.tools.register\",\n \"plugin.state.read\",\n \"plugin.state.write\",\n \"events.subscribe\",\n \"events.emit\",\n \"issues.read\",\n \"issues.create\",\n \"activity.log.write\",\n \"metrics.write\",\n \"instance.settings.register\",\n \"ui.dashboardWidget.register\",\n ],\n entrypoints: {\n worker: \"./dist/worker.js\",\n ui: \"./dist/ui\",\n },\n instanceConfigSchema: {\n type: \"object\",\n properties: {\n company_id: {\n type: \"string\",\n title: \"Company ID\",\n description: \"UUID of the company this plugin serves (required for events and activity logging)\",\n default: DEFAULT_CONFIG.company_id,\n },\n xai_api_key_ref: {\n type: \"string\",\n title: \"xAI API Key Secret Reference\",\n default: DEFAULT_CONFIG.xai_api_key_ref,\n },\n x_api_bearer_ref: {\n type: \"string\",\n title: \"X API Bearer Token Secret Reference\",\n default: DEFAULT_CONFIG.x_api_bearer_ref,\n },\n semantic_topics: {\n type: \"array\",\n title: \"Semantic Discovery Topics\",\n items: { type: \"string\" },\n default: DEFAULT_CONFIG.semantic_topics,\n },\n keyword_searches: {\n type: \"array\",\n title: \"Keyword Searches\",\n items: { type: \"string\" },\n default: DEFAULT_CONFIG.keyword_searches,\n },\n content_pillars: {\n type: \"array\",\n title: \"Content Pillars\",\n items: { type: \"string\" },\n default: DEFAULT_CONFIG.content_pillars,\n },\n scoring_weights: {\n type: \"object\",\n title: \"Scoring Weights\",\n properties: {\n relevance: { type: \"number\", default: 0.45 },\n recency: { type: \"number\", default: 0.25 },\n engagement: { type: \"number\", default: 0.30 },\n },\n default: DEFAULT_CONFIG.scoring_weights,\n },\n engagement_sub_weights: {\n type: \"object\",\n title: \"Engagement Sub-Weights\",\n properties: {\n likes: { type: \"number\", default: 0.55 },\n reposts: { type: \"number\", default: 0.25 },\n replies: { type: \"number\", default: 0.15 },\n quotes: { type: \"number\", default: 0.05 },\n },\n default: DEFAULT_CONFIG.engagement_sub_weights,\n },\n max_corpus_size: {\n type: \"number\",\n title: \"Max Corpus Size Per Day\",\n default: DEFAULT_CONFIG.max_corpus_size,\n },\n dedup_threshold: {\n type: \"number\",\n title: \"Dedup Jaccard Threshold\",\n default: DEFAULT_CONFIG.dedup_threshold,\n },\n authority_boost: {\n type: \"number\",\n title: \"Authority Score Boost\",\n default: DEFAULT_CONFIG.authority_boost,\n },\n authority_lists: {\n type: \"object\",\n title: \"Authority Handle Lists\",\n default: DEFAULT_CONFIG.authority_lists,\n },\n global_excluded: {\n type: \"array\",\n title: \"Globally Excluded Handles\",\n items: { type: \"string\" },\n default: DEFAULT_CONFIG.global_excluded,\n },\n authority_promotion_policy: {\n type: \"object\",\n title: \"Authority Promotion Policy\",\n default: DEFAULT_CONFIG.authority_promotion_policy,\n },\n corpus_retention_days: {\n type: \"number\",\n title: \"Corpus Retention (days)\",\n default: DEFAULT_CONFIG.corpus_retention_days,\n },\n },\n },\n jobs: [\n {\n jobKey: JOB_KEYS.discoveryRun,\n displayName: \"Discovery Run\",\n description:\n \"Two-stage pipeline: xAI open + focused discovery, X API v2 enrichment, scoring, and corpus storage.\",\n schedule: \"0 6 * * *\",\n },\n {\n jobKey: JOB_KEYS.authorityDecay,\n displayName: \"Authority Decay\",\n description:\n \"Weekly handle decay \u2014 downgrade or remove handles not seen within the tracking window.\",\n schedule: \"0 0 * * 0\",\n },\n {\n jobKey: JOB_KEYS.complianceCheck,\n displayName: \"Compliance Check\",\n description:\n \"Weekly re-check of stored tweets \u2014 remove deleted or suspended content.\",\n schedule: \"0 3 * * 0\",\n },\n {\n jobKey: JOB_KEYS.corpusRetention,\n displayName: \"Corpus Retention\",\n description:\n \"Monthly archive/delete corpus older than the retention window.\",\n schedule: \"0 4 1 * *\",\n },\n ],\n tools: [\n {\n name: TOOL_NAMES.searchCorpus,\n displayName: \"Search X Corpus\",\n description:\n \"Search the scored X intelligence corpus by query text, date range, and content pillar.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"Search query\" },\n date: {\n type: \"string\",\n description: \"Date filter (YYYY-MM-DD)\",\n },\n pillar: {\n type: \"string\",\n description: \"Content pillar filter\",\n },\n limit: { type: \"number\", description: \"Max results (default 20)\" },\n },\n required: [\"query\"],\n },\n },\n {\n name: TOOL_NAMES.getToday,\n displayName: \"Get Today's Intelligence\",\n description:\n \"Get today's scored X intelligence corpus, optionally filtered by pillar.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n pillar: { type: \"string\", description: \"Content pillar filter\" },\n limit: { type: \"number\", description: \"Max results (default 20)\" },\n },\n },\n },\n {\n name: TOOL_NAMES.getAuthorities,\n displayName: \"Get Authority Handles\",\n description:\n \"Get the authority handle list for a domain, or all domains if none specified.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n list_name: {\n type: \"string\",\n description: \"Domain name (e.g. 'market_structure')\",\n },\n },\n },\n },\n {\n name: TOOL_NAMES.suggestHandles,\n displayName: \"Suggest Handle Promotions\",\n description:\n \"Get handles that are candidates for authority list promotion based on tracking data.\",\n parametersSchema: {\n type: \"object\",\n properties: {},\n },\n },\n {\n name: TOOL_NAMES.trackHandle,\n displayName: \"Track Handle\",\n description:\n \"Record a handle appearance from agent discovery with relevance score and domain.\",\n parametersSchema: {\n type: \"object\",\n properties: {\n handle: { type: \"string\", description: \"X handle (without @)\" },\n relevance: {\n type: \"number\",\n description: \"Relevance score (0-1)\",\n },\n domain: { type: \"string\", description: \"Domain/topic area\" },\n },\n required: [\"handle\", \"relevance\", \"domain\"],\n },\n },\n ],\n ui: {\n slots: [\n {\n type: \"dashboardWidget\",\n id: SLOT_IDS.dashboardWidget,\n displayName: \"X Intelligence\",\n exportName: EXPORT_NAMES.dashboardWidget,\n },\n {\n type: \"settingsPage\",\n id: SLOT_IDS.settingsPage,\n displayName: \"X Intelligence Settings\",\n exportName: EXPORT_NAMES.settingsPage,\n },\n ],\n },\n};\n\nexport default manifest;\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,118 @@
1
+ // src/ui/index.tsx
2
+ import { usePluginAction, usePluginData } from "@paperclipai/plugin-sdk/ui";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ function DashboardWidget(_props) {
5
+ const { data, loading, error } = usePluginData("dashboard-summary");
6
+ const triggerDiscovery = usePluginAction("trigger-discovery");
7
+ if (loading) return /* @__PURE__ */ jsx("div", { style: { padding: "1rem" }, children: "Loading X Intelligence..." });
8
+ if (error) return /* @__PURE__ */ jsxs("div", { style: { padding: "1rem", color: "#ef4444" }, children: [
9
+ "Error: ",
10
+ error.message
11
+ ] });
12
+ const summary = data?.today;
13
+ const lastRun = data?.lastRun;
14
+ return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "0.75rem", padding: "0.5rem" }, children: [
15
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
16
+ /* @__PURE__ */ jsx("strong", { children: "X Intelligence" }),
17
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "0.75rem", opacity: 0.5 }, children: lastRun ? `Last run: ${lastRun.date}` : "No runs yet" })
18
+ ] }),
19
+ summary ? /* @__PURE__ */ jsxs(Fragment, { children: [
20
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: "0.5rem" }, children: [
21
+ /* @__PURE__ */ jsx(StatCard, { label: "Tweets", value: summary.total_tweets }),
22
+ /* @__PURE__ */ jsx(StatCard, { label: "Handles", value: data?.trackedHandles ?? 0 }),
23
+ /* @__PURE__ */ jsx(
24
+ StatCard,
25
+ {
26
+ label: "Cost",
27
+ value: `$${(summary.discovery_stats.xai_cost_estimate + summary.discovery_stats.x_api_cost_estimate).toFixed(2)}`
28
+ }
29
+ )
30
+ ] }),
31
+ /* @__PURE__ */ jsxs("div", { style: { fontSize: "0.8rem" }, children: [
32
+ /* @__PURE__ */ jsxs("div", { children: [
33
+ "Queries: ",
34
+ summary.discovery_stats.open_queries,
35
+ " open + ",
36
+ summary.discovery_stats.focused_queries,
37
+ " focused"
38
+ ] }),
39
+ /* @__PURE__ */ jsxs("div", { children: [
40
+ "New handles: ",
41
+ summary.discovery_stats.new_handles_discovered,
42
+ " | Promoted: ",
43
+ summary.discovery_stats.handles_promoted
44
+ ] })
45
+ ] }),
46
+ summary.top_items.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
47
+ /* @__PURE__ */ jsx("div", { style: { fontSize: "0.75rem", fontWeight: 600, marginBottom: "0.25rem" }, children: "Top Items" }),
48
+ summary.top_items.slice(0, 3).map((tweet) => /* @__PURE__ */ jsx(TweetCard, { tweet }, tweet.tweet_id))
49
+ ] })
50
+ ] }) : /* @__PURE__ */ jsx("div", { style: { opacity: 0.5, fontSize: "0.85rem" }, children: "No corpus for today. Discovery runs daily at 6:00 AM UTC." }),
51
+ /* @__PURE__ */ jsx(
52
+ "button",
53
+ {
54
+ onClick: () => void triggerDiscovery(),
55
+ style: {
56
+ padding: "0.4rem 0.75rem",
57
+ fontSize: "0.8rem",
58
+ border: "1px solid currentColor",
59
+ borderRadius: "4px",
60
+ background: "transparent",
61
+ color: "inherit",
62
+ opacity: 0.7,
63
+ cursor: "pointer"
64
+ },
65
+ children: "Trigger Discovery"
66
+ }
67
+ )
68
+ ] });
69
+ }
70
+ function StatCard({ label, value }) {
71
+ return /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", padding: "0.5rem", background: "rgba(128,128,128,0.1)", borderRadius: "4px" }, children: [
72
+ /* @__PURE__ */ jsx("div", { style: { fontSize: "1.1rem", fontWeight: 600 }, children: value }),
73
+ /* @__PURE__ */ jsx("div", { style: { fontSize: "0.7rem", opacity: 0.5 }, children: label })
74
+ ] });
75
+ }
76
+ function TweetCard({ tweet }) {
77
+ return /* @__PURE__ */ jsxs(
78
+ "div",
79
+ {
80
+ style: {
81
+ padding: "0.4rem",
82
+ marginBottom: "0.25rem",
83
+ background: "rgba(128,128,128,0.1)",
84
+ borderRadius: "4px",
85
+ fontSize: "0.8rem"
86
+ },
87
+ children: [
88
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
89
+ /* @__PURE__ */ jsxs("span", { style: { fontWeight: 600 }, children: [
90
+ "@",
91
+ tweet.author_username,
92
+ tweet.is_authority && /* @__PURE__ */ jsx("span", { style: { color: "#2563eb", marginLeft: "0.25rem" }, title: "Authority handle", children: "*" })
93
+ ] }),
94
+ /* @__PURE__ */ jsx("span", { style: { opacity: 0.5 }, children: tweet.score.toFixed(2) })
95
+ ] }),
96
+ /* @__PURE__ */ jsx("div", { style: { opacity: 0.7, marginTop: "0.15rem" }, children: tweet.text.length > 120 ? `${tweet.text.slice(0, 120)}...` : tweet.text })
97
+ ]
98
+ }
99
+ );
100
+ }
101
+ function SettingsPage() {
102
+ const { data, loading, error } = usePluginData("plugin-config");
103
+ if (loading) return /* @__PURE__ */ jsx("div", { children: "Loading settings..." });
104
+ if (error) return /* @__PURE__ */ jsxs("div", { children: [
105
+ "Error: ",
106
+ error.message
107
+ ] });
108
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "1rem" }, children: [
109
+ /* @__PURE__ */ jsx("h2", { children: "X Intelligence Settings" }),
110
+ /* @__PURE__ */ jsx("p", { style: { opacity: 0.5 }, children: "Configure authority lists, scoring weights, and discovery topics via the plugin configuration panel." }),
111
+ /* @__PURE__ */ jsx("pre", { style: { background: "rgba(128,128,128,0.1)", padding: "1rem", borderRadius: "4px", overflow: "auto", fontSize: "0.8rem" }, children: JSON.stringify(data, null, 2) })
112
+ ] });
113
+ }
114
+ export {
115
+ DashboardWidget,
116
+ SettingsPage
117
+ };
118
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ui/index.tsx"],
4
+ "sourcesContent": ["import { usePluginAction, usePluginData, type PluginWidgetProps } from \"@paperclipai/plugin-sdk/ui\";\nimport type { CorpusSummary, ScoredTweet } from \"../types.js\";\n\ntype DashboardData = {\n today: CorpusSummary | null;\n lastRun: { date: string; corpusSize: number; generatedAt: string } | null;\n trackedHandles: number;\n};\n\nexport function DashboardWidget(_props: PluginWidgetProps) {\n const { data, loading, error } = usePluginData<DashboardData>(\"dashboard-summary\");\n const triggerDiscovery = usePluginAction(\"trigger-discovery\");\n\n if (loading) return <div style={{ padding: \"1rem\" }}>Loading X Intelligence...</div>;\n if (error) return <div style={{ padding: \"1rem\", color: \"#ef4444\" }}>Error: {error.message}</div>;\n\n const summary = data?.today;\n const lastRun = data?.lastRun;\n\n return (\n <div style={{ display: \"grid\", gap: \"0.75rem\", padding: \"0.5rem\" }}>\n <div style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\" }}>\n <strong>X Intelligence</strong>\n <span style={{ fontSize: \"0.75rem\", opacity: 0.5 }}>\n {lastRun ? `Last run: ${lastRun.date}` : \"No runs yet\"}\n </span>\n </div>\n\n {summary ? (\n <>\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr 1fr\", gap: \"0.5rem\" }}>\n <StatCard label=\"Tweets\" value={summary.total_tweets} />\n <StatCard label=\"Handles\" value={data?.trackedHandles ?? 0} />\n <StatCard\n label=\"Cost\"\n value={`$${(\n summary.discovery_stats.xai_cost_estimate +\n summary.discovery_stats.x_api_cost_estimate\n ).toFixed(2)}`}\n />\n </div>\n\n <div style={{ fontSize: \"0.8rem\" }}>\n <div>\n Queries: {summary.discovery_stats.open_queries} open + {summary.discovery_stats.focused_queries} focused\n </div>\n <div>\n New handles: {summary.discovery_stats.new_handles_discovered} | Promoted: {summary.discovery_stats.handles_promoted}\n </div>\n </div>\n\n {summary.top_items.length > 0 && (\n <div>\n <div style={{ fontSize: \"0.75rem\", fontWeight: 600, marginBottom: \"0.25rem\" }}>Top Items</div>\n {summary.top_items.slice(0, 3).map((tweet) => (\n <TweetCard key={tweet.tweet_id} tweet={tweet} />\n ))}\n </div>\n )}\n </>\n ) : (\n <div style={{ opacity: 0.5, fontSize: \"0.85rem\" }}>\n No corpus for today. Discovery runs daily at 6:00 AM UTC.\n </div>\n )}\n\n <button\n onClick={() => void triggerDiscovery()}\n style={{\n padding: \"0.4rem 0.75rem\",\n fontSize: \"0.8rem\",\n border: \"1px solid currentColor\",\n borderRadius: \"4px\",\n background: \"transparent\",\n color: \"inherit\",\n opacity: 0.7,\n cursor: \"pointer\",\n }}\n >\n Trigger Discovery\n </button>\n </div>\n );\n}\n\nfunction StatCard({ label, value }: { label: string; value: string | number }) {\n return (\n <div style={{ textAlign: \"center\", padding: \"0.5rem\", background: \"rgba(128,128,128,0.1)\", borderRadius: \"4px\" }}>\n <div style={{ fontSize: \"1.1rem\", fontWeight: 600 }}>{value}</div>\n <div style={{ fontSize: \"0.7rem\", opacity: 0.5 }}>{label}</div>\n </div>\n );\n}\n\nfunction TweetCard({ tweet }: { tweet: ScoredTweet }) {\n return (\n <div\n style={{\n padding: \"0.4rem\",\n marginBottom: \"0.25rem\",\n background: \"rgba(128,128,128,0.1)\",\n borderRadius: \"4px\",\n fontSize: \"0.8rem\",\n }}\n >\n <div style={{ display: \"flex\", justifyContent: \"space-between\" }}>\n <span style={{ fontWeight: 600 }}>\n @{tweet.author_username}\n {tweet.is_authority && (\n <span style={{ color: \"#2563eb\", marginLeft: \"0.25rem\" }} title=\"Authority handle\">\n *\n </span>\n )}\n </span>\n <span style={{ opacity: 0.5 }}>{tweet.score.toFixed(2)}</span>\n </div>\n <div style={{ opacity: 0.7, marginTop: \"0.15rem\" }}>\n {tweet.text.length > 120 ? `${tweet.text.slice(0, 120)}...` : tweet.text}\n </div>\n </div>\n );\n}\n\nexport function SettingsPage() {\n const { data, loading, error } = usePluginData<Record<string, unknown>>(\"plugin-config\");\n\n if (loading) return <div>Loading settings...</div>;\n if (error) return <div>Error: {error.message}</div>;\n\n return (\n <div style={{ padding: \"1rem\" }}>\n <h2>X Intelligence Settings</h2>\n <p style={{ opacity: 0.5 }}>\n Configure authority lists, scoring weights, and discovery topics via the plugin configuration panel.\n </p>\n <pre style={{ background: \"rgba(128,128,128,0.1)\", padding: \"1rem\", borderRadius: \"4px\", overflow: \"auto\", fontSize: \"0.8rem\" }}>\n {JSON.stringify(data, null, 2)}\n </pre>\n </div>\n );\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }