nod-shout 0.3.0 → 0.3.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"agent-instructions.d.ts","sourceRoot":"","sources":["../src/agent-instructions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA2CzE,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,QAoC/D"}
1
+ {"version":3,"file":"agent-instructions.d.ts","sourceRoot":"","sources":["../src/agent-instructions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA8CzE,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,QAoC/D"}
@@ -9,9 +9,12 @@ LINK HARVESTING (do this throughout every conversation):
9
9
  - if the user explicitly says "shout this" or "save this", use shout_link directly instead
10
10
 
11
11
  DAILY REVIEW:
12
- - at natural pauses in conversation or when prompted, use review_queue to show pending links
12
+ - the user has a preferred review time (check shout_settings for review_hour, default 8pm local)
13
+ - at that time (or the nearest natural pause after it), use review_queue to show pending links
13
14
  - present them casually: "hey, you shared a few interesting links today — want to shout any of these?"
14
15
  - let the user pick which to shout, dismiss, or skip
16
+ - if the user says "change my review time to 6pm" or similar, update it with shout_settings
17
+ - if the user's agent doesn't support scheduling, just prompt at natural conversation breaks
15
18
 
16
19
  TEXT POSTS & OBSERVATIONS:
17
20
  - use agent_observe to log interesting moments: milestones, shipping updates, pattern shifts
@@ -1 +1 @@
1
- {"version":3,"file":"agent-instructions.js","sourceRoot":"","sources":["../src/agent-instructions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;AAErC,MAAM,wBAAwB,GAAG,0CAA0C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oDAmC9B,OAAO;iEACM,CAAC;AAElE,MAAM,UAAU,8BAA8B,CAAC,MAAiB;IAC9D,0DAA0D;IAC1D,MAAM,CAAC,QAAQ,CACb,oBAAoB,EACpB,gCAAgC,EAChC;QACE,WAAW,EAAE,0FAA0F;QACvG,QAAQ,EAAE,YAAY;KACvB,EACD,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,GAAG,EAAE,gCAAgC;gBACrC,QAAQ,EAAE,YAAY;gBACtB,IAAI,EAAE,wBAAwB;aAC/B;SACF;KACF,CAAC,CACH,CAAC;IAEF,gEAAgE;IAChE,MAAM,CAAC,MAAM,CACX,aAAa,EACb,4FAA4F,EAC5F,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,wBAAwB;iBAC/B;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"agent-instructions.js","sourceRoot":"","sources":["../src/agent-instructions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;AAErC,MAAM,wBAAwB,GAAG,0CAA0C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oDAsC9B,OAAO;iEACM,CAAC;AAElE,MAAM,UAAU,8BAA8B,CAAC,MAAiB;IAC9D,0DAA0D;IAC1D,MAAM,CAAC,QAAQ,CACb,oBAAoB,EACpB,gCAAgC,EAChC;QACE,WAAW,EAAE,0FAA0F;QACvG,QAAQ,EAAE,YAAY;KACvB,EACD,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,GAAG,EAAE,gCAAgC;gBACrC,QAAQ,EAAE,YAAY;gBACtB,IAAI,EAAE,wBAAwB;aAC/B;SACF;KACF,CAAC,CACH,CAAC;IAEF,gEAAgE;IAChE,MAAM,CAAC,MAAM,CACX,aAAa,EACb,4FAA4F,EAC5F,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,wBAAwB;iBAC/B;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"social.d.ts","sourceRoot":"","sources":["../../src/tools/social.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,QA4MpD"}
1
+ {"version":3,"file":"social.d.ts","sourceRoot":"","sources":["../../src/tools/social.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,QAwWpD"}
@@ -169,5 +169,136 @@ export function registerSocialTools(server) {
169
169
  ],
170
170
  };
171
171
  });
172
+ // shout_curate_feed - ai-curated feed based on your interests
173
+ server.tool("shout_curate_feed", "get a curated feed from people you follow, ranked by relevance to your interests. compares your shout history (tags, topics) against your follows' recent shouts and returns the best matches with relevance scores. use this when the user asks 'what's good from my follows?' or 'curate my feed'.", {
174
+ user_id: z.string().uuid().optional().describe("your user id (auto-resolved if omitted)"),
175
+ limit: z.number().optional().default(10).describe("max curated results to return"),
176
+ days: z.number().optional().default(7).describe("how many days back to look"),
177
+ }, async ({ user_id: rawUserId4, limit, days }) => {
178
+ const user_id = rawUserId4 || await resolveUserId();
179
+ // 1. build interest profile from user's own shouts
180
+ const { data: myShouts } = await supabase
181
+ .from("shouts")
182
+ .select("tags, category")
183
+ .eq("user_id", user_id)
184
+ .order("created_at", { ascending: false })
185
+ .limit(50);
186
+ const tagCounts = {};
187
+ const catCounts = {};
188
+ for (const s of myShouts || []) {
189
+ for (const tag of (s.tags || [])) {
190
+ tagCounts[tag] = (tagCounts[tag] || 0) + 1;
191
+ }
192
+ if (s.category) {
193
+ catCounts[s.category] = (catCounts[s.category] || 0) + 1;
194
+ }
195
+ }
196
+ const totalTags = Object.values(tagCounts).reduce((a, b) => a + b, 0) || 1;
197
+ const tagWeights = {};
198
+ for (const [tag, count] of Object.entries(tagCounts)) {
199
+ tagWeights[tag] = count / totalTags;
200
+ }
201
+ // 2. get followed users
202
+ const { data: subs } = await supabase
203
+ .from("subscriptions")
204
+ .select("following_id")
205
+ .eq("follower_id", user_id);
206
+ if (!subs || subs.length === 0) {
207
+ return {
208
+ content: [{
209
+ type: "text",
210
+ text: "you're not following anyone yet. use shout_follow to subscribe to someone's shouts.",
211
+ }],
212
+ };
213
+ }
214
+ const followingIds = subs.map((s) => s.following_id);
215
+ // 3. fetch recent shouts from follows
216
+ const since = new Date();
217
+ since.setDate(since.getDate() - (days || 7));
218
+ const { data: feedShouts, error } = await supabase
219
+ .from("shouts")
220
+ .select("*, profiles!inner(username, display_name)")
221
+ .in("user_id", followingIds)
222
+ .eq("visibility", "public")
223
+ .gte("created_at", since.toISOString())
224
+ .order("created_at", { ascending: false })
225
+ .limit(100);
226
+ if (error || !feedShouts || feedShouts.length === 0) {
227
+ return {
228
+ content: [{
229
+ type: "text",
230
+ text: error ? `error: ${error.message}` : "no recent shouts from your follows.",
231
+ }],
232
+ };
233
+ }
234
+ // 4. score each shout by relevance
235
+ const scored = feedShouts.map((s) => {
236
+ let score = 0;
237
+ const shoutTags = s.tags || [];
238
+ const matchedTags = [];
239
+ // tag overlap scoring
240
+ for (const tag of shoutTags) {
241
+ const normalTag = tag.toLowerCase().replace(/[^a-z0-9-]/g, "");
242
+ // direct match
243
+ if (tagWeights[tag]) {
244
+ score += tagWeights[tag] * 10;
245
+ matchedTags.push(tag);
246
+ }
247
+ // partial match (e.g. "ai-agents" matches "ai")
248
+ for (const [myTag, weight] of Object.entries(tagWeights)) {
249
+ if (normalTag.includes(myTag) || myTag.includes(normalTag)) {
250
+ score += weight * 5;
251
+ if (!matchedTags.includes(myTag))
252
+ matchedTags.push(myTag);
253
+ }
254
+ }
255
+ }
256
+ // category match bonus
257
+ if (s.category && catCounts[s.category]) {
258
+ score += 2;
259
+ }
260
+ // recency bonus (newer = higher)
261
+ const ageHours = (Date.now() - new Date(s.created_at).getTime()) / (1000 * 60 * 60);
262
+ score += Math.max(0, 5 - (ageHours / 24)); // up to 5 bonus points for very recent
263
+ return {
264
+ ...s,
265
+ relevanceScore: Math.round(score * 100) / 100,
266
+ matchedInterests: matchedTags,
267
+ };
268
+ });
269
+ // 5. sort by score, take top N
270
+ scored.sort((a, b) => b.relevanceScore - a.relevanceScore);
271
+ const topItems = scored.slice(0, limit || 10);
272
+ if (topItems.every((s) => s.relevanceScore === 0)) {
273
+ // no tag overlap — just return most recent
274
+ const lines = topItems.map((s, i) => {
275
+ const who = s.profiles?.username || "unknown";
276
+ return `${i + 1}. @${who}: ${s.title || s.url}\n ${s.summary || ""}\n tags: ${(s.tags || []).join(", ")}`;
277
+ });
278
+ return {
279
+ content: [{
280
+ type: "text",
281
+ text: `no strong interest matches yet (you and your follows may cover different topics). here are the most recent:\n\n${lines.join("\n\n")}`,
282
+ }],
283
+ };
284
+ }
285
+ const lines = topItems.map((s, i) => {
286
+ const who = s.profiles?.username || "unknown";
287
+ const matchNote = s.matchedInterests.length > 0
288
+ ? `(matches your interests: ${s.matchedInterests.join(", ")})`
289
+ : "";
290
+ return `${i + 1}. [score: ${s.relevanceScore}] @${who}: ${s.title || s.url}\n ${s.summary || ""}\n tags: ${(s.tags || []).join(", ")} ${matchNote}`;
291
+ });
292
+ const myTopTags = Object.entries(tagCounts)
293
+ .sort((a, b) => b[1] - a[1])
294
+ .slice(0, 5)
295
+ .map(([t]) => t);
296
+ return {
297
+ content: [{
298
+ type: "text",
299
+ text: `curated feed (${topItems.length} picks from ${feedShouts.length} total, based on your interests: ${myTopTags.join(", ")}):\n\n${lines.join("\n\n")}`,
300
+ }],
301
+ };
302
+ });
172
303
  }
173
304
  //# sourceMappingURL=social.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"social.js","sourceRoot":"","sources":["../../src/tools/social.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"social.js","sourceRoot":"","sources":["../../src/tools/social.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nod-shout",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "mcp server for nod social - turn links into curated public pages",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -12,9 +12,12 @@ LINK HARVESTING (do this throughout every conversation):
12
12
  - if the user explicitly says "shout this" or "save this", use shout_link directly instead
13
13
 
14
14
  DAILY REVIEW:
15
- - at natural pauses in conversation or when prompted, use review_queue to show pending links
15
+ - the user has a preferred review time (check shout_settings for review_hour, default 8pm local)
16
+ - at that time (or the nearest natural pause after it), use review_queue to show pending links
16
17
  - present them casually: "hey, you shared a few interesting links today — want to shout any of these?"
17
18
  - let the user pick which to shout, dismiss, or skip
19
+ - if the user says "change my review time to 6pm" or similar, update it with shout_settings
20
+ - if the user's agent doesn't support scheduling, just prompt at natural conversation breaks
18
21
 
19
22
  TEXT POSTS & OBSERVATIONS:
20
23
  - use agent_observe to log interesting moments: milestones, shipping updates, pattern shifts
@@ -207,4 +207,160 @@ export function registerSocialTools(server: McpServer) {
207
207
  };
208
208
  }
209
209
  );
210
+
211
+ // shout_curate_feed - ai-curated feed based on your interests
212
+ server.tool(
213
+ "shout_curate_feed",
214
+ "get a curated feed from people you follow, ranked by relevance to your interests. compares your shout history (tags, topics) against your follows' recent shouts and returns the best matches with relevance scores. use this when the user asks 'what's good from my follows?' or 'curate my feed'.",
215
+ {
216
+ user_id: z.string().uuid().optional().describe("your user id (auto-resolved if omitted)"),
217
+ limit: z.number().optional().default(10).describe("max curated results to return"),
218
+ days: z.number().optional().default(7).describe("how many days back to look"),
219
+ },
220
+ async ({ user_id: rawUserId4, limit, days }) => {
221
+ const user_id = rawUserId4 || await resolveUserId();
222
+
223
+ // 1. build interest profile from user's own shouts
224
+ const { data: myShouts } = await supabase
225
+ .from("shouts")
226
+ .select("tags, category")
227
+ .eq("user_id", user_id)
228
+ .order("created_at", { ascending: false })
229
+ .limit(50);
230
+
231
+ const tagCounts: Record<string, number> = {};
232
+ const catCounts: Record<string, number> = {};
233
+ for (const s of myShouts || []) {
234
+ for (const tag of (s.tags || [])) {
235
+ tagCounts[tag] = (tagCounts[tag] || 0) + 1;
236
+ }
237
+ if (s.category) {
238
+ catCounts[s.category] = (catCounts[s.category] || 0) + 1;
239
+ }
240
+ }
241
+
242
+ const totalTags = Object.values(tagCounts).reduce((a, b) => a + b, 0) || 1;
243
+ const tagWeights: Record<string, number> = {};
244
+ for (const [tag, count] of Object.entries(tagCounts)) {
245
+ tagWeights[tag] = count / totalTags;
246
+ }
247
+
248
+ // 2. get followed users
249
+ const { data: subs } = await supabase
250
+ .from("subscriptions")
251
+ .select("following_id")
252
+ .eq("follower_id", user_id);
253
+
254
+ if (!subs || subs.length === 0) {
255
+ return {
256
+ content: [{
257
+ type: "text" as const,
258
+ text: "you're not following anyone yet. use shout_follow to subscribe to someone's shouts.",
259
+ }],
260
+ };
261
+ }
262
+
263
+ const followingIds = subs.map((s: any) => s.following_id);
264
+
265
+ // 3. fetch recent shouts from follows
266
+ const since = new Date();
267
+ since.setDate(since.getDate() - (days || 7));
268
+
269
+ const { data: feedShouts, error } = await supabase
270
+ .from("shouts")
271
+ .select("*, profiles!inner(username, display_name)")
272
+ .in("user_id", followingIds)
273
+ .eq("visibility", "public")
274
+ .gte("created_at", since.toISOString())
275
+ .order("created_at", { ascending: false })
276
+ .limit(100);
277
+
278
+ if (error || !feedShouts || feedShouts.length === 0) {
279
+ return {
280
+ content: [{
281
+ type: "text" as const,
282
+ text: error ? `error: ${error.message}` : "no recent shouts from your follows.",
283
+ }],
284
+ };
285
+ }
286
+
287
+ // 4. score each shout by relevance
288
+ const scored = feedShouts.map((s: any) => {
289
+ let score = 0;
290
+ const shoutTags = s.tags || [];
291
+ const matchedTags: string[] = [];
292
+
293
+ // tag overlap scoring
294
+ for (const tag of shoutTags) {
295
+ const normalTag = tag.toLowerCase().replace(/[^a-z0-9-]/g, "");
296
+ // direct match
297
+ if (tagWeights[tag]) {
298
+ score += tagWeights[tag] * 10;
299
+ matchedTags.push(tag);
300
+ }
301
+ // partial match (e.g. "ai-agents" matches "ai")
302
+ for (const [myTag, weight] of Object.entries(tagWeights)) {
303
+ if (normalTag.includes(myTag) || myTag.includes(normalTag)) {
304
+ score += weight * 5;
305
+ if (!matchedTags.includes(myTag)) matchedTags.push(myTag);
306
+ }
307
+ }
308
+ }
309
+
310
+ // category match bonus
311
+ if (s.category && catCounts[s.category]) {
312
+ score += 2;
313
+ }
314
+
315
+ // recency bonus (newer = higher)
316
+ const ageHours = (Date.now() - new Date(s.created_at).getTime()) / (1000 * 60 * 60);
317
+ score += Math.max(0, 5 - (ageHours / 24)); // up to 5 bonus points for very recent
318
+
319
+ return {
320
+ ...s,
321
+ relevanceScore: Math.round(score * 100) / 100,
322
+ matchedInterests: matchedTags,
323
+ };
324
+ });
325
+
326
+ // 5. sort by score, take top N
327
+ scored.sort((a: any, b: any) => b.relevanceScore - a.relevanceScore);
328
+ const topItems = scored.slice(0, limit || 10);
329
+
330
+ if (topItems.every((s: any) => s.relevanceScore === 0)) {
331
+ // no tag overlap — just return most recent
332
+ const lines = topItems.map((s: any, i: number) => {
333
+ const who = s.profiles?.username || "unknown";
334
+ return `${i + 1}. @${who}: ${s.title || s.url}\n ${s.summary || ""}\n tags: ${(s.tags || []).join(", ")}`;
335
+ });
336
+
337
+ return {
338
+ content: [{
339
+ type: "text" as const,
340
+ text: `no strong interest matches yet (you and your follows may cover different topics). here are the most recent:\n\n${lines.join("\n\n")}`,
341
+ }],
342
+ };
343
+ }
344
+
345
+ const lines = topItems.map((s: any, i: number) => {
346
+ const who = s.profiles?.username || "unknown";
347
+ const matchNote = s.matchedInterests.length > 0
348
+ ? `(matches your interests: ${s.matchedInterests.join(", ")})`
349
+ : "";
350
+ return `${i + 1}. [score: ${s.relevanceScore}] @${who}: ${s.title || s.url}\n ${s.summary || ""}\n tags: ${(s.tags || []).join(", ")} ${matchNote}`;
351
+ });
352
+
353
+ const myTopTags = Object.entries(tagCounts)
354
+ .sort((a, b) => b[1] - a[1])
355
+ .slice(0, 5)
356
+ .map(([t]) => t);
357
+
358
+ return {
359
+ content: [{
360
+ type: "text" as const,
361
+ text: `curated feed (${topItems.length} picks from ${feedShouts.length} total, based on your interests: ${myTopTags.join(", ")}):\n\n${lines.join("\n\n")}`,
362
+ }],
363
+ };
364
+ }
365
+ );
210
366
  }