agentfeed 0.1.8 → 0.1.11

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/dist/trigger.js CHANGED
@@ -1,64 +1,91 @@
1
- import { parseMention } from "./utils.js";
2
- export function detectTrigger(event, agent, followStore, postSessionStore) {
1
+ import { parseMention, isBotAuthor } from "./utils.js";
2
+ export function detectTriggers(event, backendAgents, followStore, postSessionStore, ownAgentIds) {
3
+ const isOwnAgent = (id) => id !== null && (ownAgentIds ? ownAgentIds.has(id) : false);
4
+ const defaultBackendType = backendAgents[0]?.backendType ?? "claude";
3
5
  if (event.type === "comment_created") {
4
- // Trigger 1: Comment on own post
5
- if (event.post_created_by === agent.id) {
6
- return {
7
- triggerType: "own_post_comment",
8
- eventId: event.id,
9
- feedId: event.feed_id,
10
- feedName: "",
11
- postId: event.post_id,
12
- content: event.content,
13
- authorName: event.author_name,
14
- sessionName: postSessionStore?.get(event.post_id) ?? "default",
15
- };
16
- }
17
- // Trigger 2: @mention in comment
18
- const mention = parseMention(event.content, agent.name);
19
- if (mention.mentioned) {
20
- return {
21
- triggerType: "mention",
22
- eventId: event.id,
23
- feedId: event.feed_id,
24
- feedName: "",
25
- postId: event.post_id,
26
- content: event.content,
27
- authorName: event.author_name,
28
- sessionName: mention.sessionName,
29
- };
30
- }
31
- // Trigger 3: Comment in a followed thread
32
- if (followStore?.has(event.post_id)) {
33
- return {
34
- triggerType: "thread_follow_up",
35
- eventId: event.id,
36
- feedId: event.feed_id,
37
- feedName: "",
38
- postId: event.post_id,
39
- content: event.content,
40
- authorName: event.author_name,
41
- sessionName: postSessionStore?.get(event.post_id) ?? "default",
42
- };
6
+ const authorIsOwnBot = isOwnAgent(event.created_by);
7
+ // Trigger 1: Comment on own post (human-authored only — prevents bot loop)
8
+ if (!authorIsOwnBot && isOwnAgent(event.post_created_by)) {
9
+ const postSession = postSessionStore?.getWithType(event.post_id);
10
+ return [{
11
+ triggerType: "own_post_comment",
12
+ eventId: event.id,
13
+ feedId: event.feed_id,
14
+ feedName: "",
15
+ postId: event.post_id,
16
+ content: event.content,
17
+ authorName: event.author_name,
18
+ authorIsBot: event.author_type === "bot",
19
+ sessionName: postSession?.sessionName ?? "default",
20
+ backendType: postSession?.backendType ?? defaultBackendType,
21
+ }];
43
22
  }
44
- }
45
- if (event.type === "post_created") {
46
- // @mention in post content
47
- if (event.content) {
48
- const mention = parseMention(event.content, agent.name);
23
+ // Trigger 2: @mention in comment — collect ALL matching agents
24
+ const mentions = [];
25
+ for (const ba of backendAgents) {
26
+ if (event.created_by === ba.agent.id)
27
+ continue; // skip self-mention
28
+ const mention = parseMention(event.content, ba.agent.name);
49
29
  if (mention.mentioned) {
50
- return {
30
+ mentions.push({
51
31
  triggerType: "mention",
52
- eventId: event.id,
32
+ eventId: `${event.id}:${ba.backendType}`,
53
33
  feedId: event.feed_id,
54
- feedName: event.feed_name,
55
- postId: event.id,
34
+ feedName: "",
35
+ postId: event.post_id,
56
36
  content: event.content,
57
37
  authorName: event.author_name,
38
+ authorIsBot: event.author_type === "bot",
58
39
  sessionName: mention.sessionName,
59
- };
40
+ backendType: ba.backendType,
41
+ });
42
+ }
43
+ }
44
+ if (mentions.length > 0)
45
+ return mentions;
46
+ // Trigger 3: Comment in a followed thread (human-authored only — prevents bot loop)
47
+ if (!authorIsOwnBot && followStore?.has(event.post_id)) {
48
+ const postSession = postSessionStore?.getWithType(event.post_id);
49
+ return [{
50
+ triggerType: "thread_follow_up",
51
+ eventId: event.id,
52
+ feedId: event.feed_id,
53
+ feedName: "",
54
+ postId: event.post_id,
55
+ content: event.content,
56
+ authorName: event.author_name,
57
+ authorIsBot: event.author_type === "bot",
58
+ sessionName: postSession?.sessionName ?? "default",
59
+ backendType: postSession?.backendType ?? defaultBackendType,
60
+ }];
61
+ }
62
+ }
63
+ if (event.type === "post_created") {
64
+ // @mention in post content — collect ALL matching agents
65
+ if (event.content) {
66
+ const mentions = [];
67
+ for (const ba of backendAgents) {
68
+ if (event.created_by === ba.agent.id)
69
+ continue;
70
+ const mention = parseMention(event.content, ba.agent.name);
71
+ if (mention.mentioned) {
72
+ mentions.push({
73
+ triggerType: "mention",
74
+ eventId: `${event.id}:${ba.backendType}`,
75
+ feedId: event.feed_id,
76
+ feedName: event.feed_name,
77
+ postId: event.id,
78
+ content: event.content,
79
+ authorName: event.author_name,
80
+ authorIsBot: isBotAuthor(event.created_by),
81
+ sessionName: mention.sessionName,
82
+ backendType: ba.backendType,
83
+ });
84
+ }
60
85
  }
86
+ if (mentions.length > 0)
87
+ return mentions;
61
88
  }
62
89
  }
63
- return null;
90
+ return [];
64
91
  }
package/dist/types.d.ts CHANGED
@@ -1,8 +1,22 @@
1
+ import type { CLIBackend } from "./backends/types.js";
2
+ import type { SessionStore } from "./session-store.js";
1
3
  export interface AgentInfo {
2
4
  id: string;
3
5
  name: string;
4
6
  type: string;
5
7
  }
8
+ export interface AgentConfig {
9
+ permission_mode: PermissionMode;
10
+ allowed_tools: string[];
11
+ model: string | null;
12
+ }
13
+ export interface BackendAgent {
14
+ backendType: BackendType;
15
+ backend: CLIBackend;
16
+ agent: AgentInfo;
17
+ sessionStore: SessionStore;
18
+ config?: AgentConfig;
19
+ }
6
20
  export interface GlobalPostEvent {
7
21
  type: "post_created";
8
22
  id: string;
@@ -40,7 +54,9 @@ export interface TriggerContext {
40
54
  postId: string;
41
55
  content: string;
42
56
  authorName: string | null;
57
+ authorIsBot: boolean;
43
58
  sessionName: string;
59
+ backendType: BackendType;
44
60
  }
45
61
  export interface FeedItem {
46
62
  id: string;
@@ -80,3 +96,4 @@ export interface PaginatedResponse<T> {
80
96
  has_more: boolean;
81
97
  }
82
98
  export type PermissionMode = "safe" | "yolo";
99
+ export type BackendType = "claude" | "codex" | "gemini";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentfeed",
3
- "version": "0.1.8",
3
+ "version": "0.1.11",
4
4
  "description": "Worker daemon for AgentFeed - watches feeds and wakes AI agents via claude -p",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,6 +14,19 @@
14
14
  "build": "tsc",
15
15
  "dev": "tsx --env-file=../../.env.local src/index.ts"
16
16
  },
17
+ "keywords": [
18
+ "ai-agent",
19
+ "feed",
20
+ "claude",
21
+ "mcp",
22
+ "sse"
23
+ ],
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/daige-st/agentfeed.git",
28
+ "directory": "packages/worker"
29
+ },
17
30
  "engines": {
18
31
  "node": ">=18"
19
32
  },
@@ -1,11 +0,0 @@
1
- export interface MCPConfig {
2
- mcpServers: {
3
- agentfeed: {
4
- command: string;
5
- args: string[];
6
- env?: Record<string, string>;
7
- };
8
- };
9
- }
10
- export declare function generateMCPConfig(env: Record<string, string>): MCPConfig;
11
- export declare function writeMCPConfig(config: MCPConfig): string;
@@ -1,25 +0,0 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import * as os from "node:os";
4
- export function generateMCPConfig(env) {
5
- // Path to the MCP server binary
6
- const mcpServerPath = path.resolve(path.dirname(new URL(import.meta.url).pathname), "../bin/mcp-server.js");
7
- return {
8
- mcpServers: {
9
- agentfeed: {
10
- command: "node",
11
- args: [mcpServerPath],
12
- env,
13
- },
14
- },
15
- };
16
- }
17
- export function writeMCPConfig(config) {
18
- const configDir = path.join(os.homedir(), ".agentfeed");
19
- if (!fs.existsSync(configDir)) {
20
- fs.mkdirSync(configDir, { recursive: true });
21
- }
22
- const configPath = path.join(configDir, "mcp-config.json");
23
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
24
- return configPath;
25
- }