ccgateway 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.
Files changed (75) hide show
  1. package/README.md +252 -0
  2. package/bin/ccg-dev.sh +3 -0
  3. package/dist/agents.d.ts +17 -0
  4. package/dist/agents.d.ts.map +1 -0
  5. package/dist/agents.js +45 -0
  6. package/dist/agents.js.map +1 -0
  7. package/dist/chat.d.ts +14 -0
  8. package/dist/chat.d.ts.map +1 -0
  9. package/dist/chat.js +104 -0
  10. package/dist/chat.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +501 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/config.d.ts +53 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/config.js +70 -0
  18. package/dist/config.js.map +1 -0
  19. package/dist/context.d.ts +45 -0
  20. package/dist/context.d.ts.map +1 -0
  21. package/dist/context.js +201 -0
  22. package/dist/context.js.map +1 -0
  23. package/dist/daemon.d.ts +27 -0
  24. package/dist/daemon.d.ts.map +1 -0
  25. package/dist/daemon.js +207 -0
  26. package/dist/daemon.js.map +1 -0
  27. package/dist/heartbeat.d.ts +42 -0
  28. package/dist/heartbeat.d.ts.map +1 -0
  29. package/dist/heartbeat.js +153 -0
  30. package/dist/heartbeat.js.map +1 -0
  31. package/dist/logger.d.ts +15 -0
  32. package/dist/logger.d.ts.map +1 -0
  33. package/dist/logger.js +70 -0
  34. package/dist/logger.js.map +1 -0
  35. package/dist/messaging.d.ts +43 -0
  36. package/dist/messaging.d.ts.map +1 -0
  37. package/dist/messaging.js +132 -0
  38. package/dist/messaging.js.map +1 -0
  39. package/dist/migrate.d.ts +24 -0
  40. package/dist/migrate.d.ts.map +1 -0
  41. package/dist/migrate.js +356 -0
  42. package/dist/migrate.js.map +1 -0
  43. package/dist/plugin.d.ts +63 -0
  44. package/dist/plugin.d.ts.map +1 -0
  45. package/dist/plugin.js +93 -0
  46. package/dist/plugin.js.map +1 -0
  47. package/dist/plugins/discord-gateway.d.ts +32 -0
  48. package/dist/plugins/discord-gateway.d.ts.map +1 -0
  49. package/dist/plugins/discord-gateway.js +208 -0
  50. package/dist/plugins/discord-gateway.js.map +1 -0
  51. package/dist/plugins/slack-gateway.d.ts +35 -0
  52. package/dist/plugins/slack-gateway.d.ts.map +1 -0
  53. package/dist/plugins/slack-gateway.js +291 -0
  54. package/dist/plugins/slack-gateway.js.map +1 -0
  55. package/dist/router.d.ts +44 -0
  56. package/dist/router.d.ts.map +1 -0
  57. package/dist/router.js +103 -0
  58. package/dist/router.js.map +1 -0
  59. package/dist/sessions.d.ts +55 -0
  60. package/dist/sessions.d.ts.map +1 -0
  61. package/dist/sessions.js +160 -0
  62. package/dist/sessions.js.map +1 -0
  63. package/dist/skills.d.ts +58 -0
  64. package/dist/skills.d.ts.map +1 -0
  65. package/dist/skills.js +194 -0
  66. package/dist/skills.js.map +1 -0
  67. package/dist/spawner.d.ts +29 -0
  68. package/dist/spawner.d.ts.map +1 -0
  69. package/dist/spawner.js +54 -0
  70. package/dist/spawner.js.map +1 -0
  71. package/dist/types.d.ts +22 -0
  72. package/dist/types.d.ts.map +1 -0
  73. package/dist/types.js +4 -0
  74. package/dist/types.js.map +1 -0
  75. package/package.json +48 -0
@@ -0,0 +1,45 @@
1
+ import type { SessionManager } from "./sessions.js";
2
+ import type { SkillManager } from "./skills.js";
3
+ import type { AgentRegistry } from "./agents.js";
4
+ export interface InboxMessage {
5
+ from: string;
6
+ content: string;
7
+ ts: number;
8
+ read: boolean;
9
+ }
10
+ export declare class ContextBuilder {
11
+ private sessions;
12
+ private skills;
13
+ private ccgHome;
14
+ private agents?;
15
+ constructor(sessions: SessionManager, skills: SkillManager, ccgHome: string, agents?: AgentRegistry | undefined);
16
+ /**
17
+ * Build the complete context string for an agent turn.
18
+ * Assembles in this order:
19
+ * 1. Conversation history (windowed from session JSONL)
20
+ * 2. Skill index
21
+ * 3. Inbox messages (unread, for non-gateway agents)
22
+ * 4. Memory hints (today's date, daily log path, recent daily log contents)
23
+ */
24
+ build(agentId: string, sessionKey: string): Promise<string>;
25
+ private buildSessionInfo;
26
+ /**
27
+ * Resolve the workspace path for an agent.
28
+ * Returns undefined if no AgentRegistry is available or agent not found.
29
+ */
30
+ private getWorkspace;
31
+ /**
32
+ * Read identity files from the agent's workspace.
33
+ * Loads CLAUDE.md, SOUL.md, IDENTITY.md, AGENTS.md (whichever exist).
34
+ */
35
+ private buildIdentitySection;
36
+ private buildHistorySection;
37
+ private buildInboxSection;
38
+ private buildMemorySection;
39
+ /**
40
+ * Read a daily log file. Checks the agent's workspace memory/ dir first,
41
+ * then falls back to $CCG_HOME/agents/{agentId}/memory/.
42
+ */
43
+ private readDailyLog;
44
+ }
45
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,CAAC;CACf;AAaD,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,MAAM,CAAC;gBAHP,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,aAAa,YAAA;IAGhC;;;;;;;OAOG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA8BjE,OAAO,CAAC,gBAAgB;IAoBxB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAMpB;;;OAGG;YACW,oBAAoB;YAuBpB,mBAAmB;YAwBnB,iBAAiB;YA2CjB,kBAAkB;IAkChC;;;OAGG;YACW,YAAY;CAuB3B"}
@@ -0,0 +1,201 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ // ── Identity files loaded from workspace ──────────────────────────────────
5
+ const IDENTITY_FILES = [
6
+ "CLAUDE.md",
7
+ "SOUL.md",
8
+ "IDENTITY.md",
9
+ "AGENTS.md",
10
+ ];
11
+ // ── ContextBuilder ─────────────────────────────────────────────────────────
12
+ export class ContextBuilder {
13
+ sessions;
14
+ skills;
15
+ ccgHome;
16
+ agents;
17
+ constructor(sessions, skills, ccgHome, agents) {
18
+ this.sessions = sessions;
19
+ this.skills = skills;
20
+ this.ccgHome = ccgHome;
21
+ this.agents = agents;
22
+ }
23
+ /**
24
+ * Build the complete context string for an agent turn.
25
+ * Assembles in this order:
26
+ * 1. Conversation history (windowed from session JSONL)
27
+ * 2. Skill index
28
+ * 3. Inbox messages (unread, for non-gateway agents)
29
+ * 4. Memory hints (today's date, daily log path, recent daily log contents)
30
+ */
31
+ async build(agentId, sessionKey) {
32
+ const parts = [];
33
+ // 0. Session context — tell the agent where this conversation is happening
34
+ parts.push(this.buildSessionInfo(sessionKey));
35
+ // 1. Agent identity (CLAUDE.md, SOUL.md, IDENTITY.md, AGENTS.md from workspace)
36
+ const identitySection = await this.buildIdentitySection(agentId);
37
+ if (identitySection) {
38
+ parts.push(identitySection);
39
+ }
40
+ // 2. Conversation history
41
+ parts.push(await this.buildHistorySection(agentId, sessionKey));
42
+ // 3. Skill index
43
+ parts.push(await this.skills.buildSkillIndex(agentId));
44
+ // 4. Inbox messages
45
+ const inboxSection = await this.buildInboxSection(agentId);
46
+ if (inboxSection) {
47
+ parts.push(inboxSection);
48
+ }
49
+ // 5. Memory section
50
+ parts.push(await this.buildMemorySection(agentId));
51
+ return parts.join("\n\n");
52
+ }
53
+ buildSessionInfo(sessionKey) {
54
+ // sessionKey format: agentId:source:sourceId
55
+ const [agentId, source, ...rest] = sessionKey.split(":");
56
+ const sourceId = rest.join(":");
57
+ const lines = ["--- Session ---"];
58
+ lines.push(`Agent: ${agentId}`);
59
+ lines.push(`Source: ${source}`);
60
+ if (source === "discord") {
61
+ lines.push(`Discord channel ID: ${sourceId}`);
62
+ }
63
+ else if (source === "slack") {
64
+ lines.push(`Slack channel ID: ${sourceId}`);
65
+ }
66
+ else if (source === "cli") {
67
+ lines.push("Direct CLI chat session");
68
+ }
69
+ lines.push(`Session key: ${sessionKey}`);
70
+ return lines.join("\n");
71
+ }
72
+ // ── Private helpers ─────────────────────────────────────────────────────
73
+ /**
74
+ * Resolve the workspace path for an agent.
75
+ * Returns undefined if no AgentRegistry is available or agent not found.
76
+ */
77
+ getWorkspace(agentId) {
78
+ if (!this.agents)
79
+ return undefined;
80
+ const agent = this.agents.getAgent(agentId);
81
+ return agent?.workspace;
82
+ }
83
+ /**
84
+ * Read identity files from the agent's workspace.
85
+ * Loads CLAUDE.md, SOUL.md, IDENTITY.md, AGENTS.md (whichever exist).
86
+ */
87
+ async buildIdentitySection(agentId) {
88
+ const workspace = this.getWorkspace(agentId);
89
+ if (!workspace)
90
+ return null;
91
+ const parts = [];
92
+ for (const filename of IDENTITY_FILES) {
93
+ const filePath = join(workspace, filename);
94
+ if (existsSync(filePath)) {
95
+ try {
96
+ const content = await readFile(filePath, "utf-8");
97
+ parts.push(`=== ${filename} ===\n${content.trim()}`);
98
+ }
99
+ catch {
100
+ // Skip unreadable files
101
+ }
102
+ }
103
+ }
104
+ if (parts.length === 0)
105
+ return null;
106
+ return `--- Agent Identity ---\n${parts.join("\n\n")}`;
107
+ }
108
+ async buildHistorySection(agentId, sessionKey) {
109
+ const messages = await this.sessions.getWindowedHistory(agentId, sessionKey);
110
+ if (messages.length === 0) {
111
+ return "--- Conversation History ---\n(empty)";
112
+ }
113
+ const lines = messages.map((msg) => {
114
+ if (msg.role === "user") {
115
+ const name = msg.sourceUser || "User";
116
+ return `[user] ${name}: ${msg.content}`;
117
+ }
118
+ return `[assistant]: ${msg.content}`;
119
+ });
120
+ return `--- Conversation History ---\n${lines.join("\n")}`;
121
+ }
122
+ async buildInboxSection(agentId) {
123
+ const inboxPath = join(this.ccgHome, "agents", agentId, "inbox.jsonl");
124
+ if (!existsSync(inboxPath)) {
125
+ return null;
126
+ }
127
+ const raw = await readFile(inboxPath, "utf-8");
128
+ const lines = raw.split("\n").filter((l) => l.trim().length > 0);
129
+ if (lines.length === 0) {
130
+ return null;
131
+ }
132
+ const allMessages = lines.map((line) => JSON.parse(line));
133
+ const unread = allMessages.filter((m) => !m.read);
134
+ if (unread.length === 0) {
135
+ return null;
136
+ }
137
+ // Build the section
138
+ const header = `--- Inbox (${unread.length} unread) ---`;
139
+ const msgLines = unread.map((m) => `[${m.from} → you] ${m.content}`);
140
+ // Mark messages as read: rewrite the file with all messages marked read
141
+ const updated = allMessages.map((m) => ({ ...m, read: true }));
142
+ const updatedContent = updated.map((m) => JSON.stringify(m)).join("\n") + "\n";
143
+ await writeFile(inboxPath, updatedContent, "utf-8");
144
+ return `${header}\n${msgLines.join("\n")}`;
145
+ }
146
+ async buildMemorySection(agentId) {
147
+ const today = new Date();
148
+ const todayStr = formatDate(today);
149
+ const yesterday = new Date(today);
150
+ yesterday.setDate(yesterday.getDate() - 1);
151
+ const yesterdayStr = formatDate(yesterday);
152
+ const parts = [];
153
+ parts.push("--- Memory ---");
154
+ parts.push(`Today's date: ${todayStr}`);
155
+ parts.push(`Daily log: memory/${todayStr}.md (create if missing, append observations)`);
156
+ // Read today's daily log
157
+ const todayLog = await this.readDailyLog(agentId, todayStr);
158
+ if (todayLog !== null) {
159
+ parts.push("");
160
+ parts.push(`=== memory/${todayStr}.md ===`);
161
+ parts.push(todayLog);
162
+ }
163
+ // Read yesterday's daily log
164
+ const yesterdayLog = await this.readDailyLog(agentId, yesterdayStr);
165
+ if (yesterdayLog !== null) {
166
+ parts.push("");
167
+ parts.push(`=== memory/${yesterdayStr}.md ===`);
168
+ parts.push(yesterdayLog);
169
+ }
170
+ return parts.join("\n");
171
+ }
172
+ /**
173
+ * Read a daily log file. Checks the agent's workspace memory/ dir first,
174
+ * then falls back to $CCG_HOME/agents/{agentId}/memory/.
175
+ */
176
+ async readDailyLog(agentId, dateStr) {
177
+ const filename = `${dateStr}.md`;
178
+ // 1. Try workspace memory/ dir
179
+ const workspace = this.getWorkspace(agentId);
180
+ if (workspace) {
181
+ const wsPath = join(workspace, "memory", filename);
182
+ if (existsSync(wsPath)) {
183
+ return readFile(wsPath, "utf-8");
184
+ }
185
+ }
186
+ // 2. Fallback to $CCG_HOME/agents/{agentId}/memory/
187
+ const ccgPath = join(this.ccgHome, "agents", agentId, "memory", filename);
188
+ if (existsSync(ccgPath)) {
189
+ return readFile(ccgPath, "utf-8");
190
+ }
191
+ return null;
192
+ }
193
+ }
194
+ // ── Helpers ────────────────────────────────────────────────────────────────
195
+ function formatDate(date) {
196
+ const y = date.getFullYear();
197
+ const m = String(date.getMonth() + 1).padStart(2, "0");
198
+ const d = String(date.getDate()).padStart(2, "0");
199
+ return `${y}-${m}-${d}`;
200
+ }
201
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAcjC,6EAA6E;AAE7E,MAAM,cAAc,GAAG;IACrB,WAAW;IACX,SAAS;IACT,aAAa;IACb,WAAW;CACZ,CAAC;AAEF,8EAA8E;AAE9E,MAAM,OAAO,cAAc;IAEf;IACA;IACA;IACA;IAJV,YACU,QAAwB,EACxB,MAAoB,EACpB,OAAe,EACf,MAAsB;QAHtB,aAAQ,GAAR,QAAQ,CAAgB;QACxB,WAAM,GAAN,MAAM,CAAc;QACpB,YAAO,GAAP,OAAO,CAAQ;QACf,WAAM,GAAN,MAAM,CAAgB;IAC7B,CAAC;IAEJ;;;;;;;OAOG;IACH,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,UAAkB;QAC7C,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,2EAA2E;QAC3E,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC;QAE9C,gFAAgF;QAChF,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACjE,IAAI,eAAe,EAAE,CAAC;YACpB,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC9B,CAAC;QAED,0BAA0B;QAC1B,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;QAEhE,iBAAiB;QACjB,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;QAEvD,oBAAoB;QACpB,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,YAAY,EAAE,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3B,CAAC;QAED,oBAAoB;QACpB,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;QAEnD,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAEO,gBAAgB,CAAC,UAAkB;QACzC,6CAA6C;QAC7C,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC;QAChC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,uBAAuB,QAAQ,EAAE,CAAC,CAAC;QAChD,CAAC;aAAM,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;QAC9C,CAAC;aAAM,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,gBAAgB,UAAU,EAAE,CAAC,CAAC;QACzC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,2EAA2E;IAE3E;;;OAGG;IACK,YAAY,CAAC,OAAe;QAClC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC5C,OAAO,KAAK,EAAE,SAAS,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,oBAAoB,CAAC,OAAe;QAChD,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAE5B,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,KAAK,MAAM,QAAQ,IAAI,cAAc,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAC3C,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;oBAClD,KAAK,CAAC,IAAI,CAAC,OAAO,QAAQ,SAAS,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACvD,CAAC;gBAAC,MAAM,CAAC;oBACP,wBAAwB;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEpC,OAAO,2BAA2B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IACzD,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAC/B,OAAe,EACf,UAAkB;QAElB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CACrD,OAAO,EACP,UAAU,CACX,CAAC;QAEF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,uCAAuC,CAAC;QACjD,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACjC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACxB,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,IAAI,MAAM,CAAC;gBACtC,OAAO,UAAU,IAAI,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC;YAC1C,CAAC;YACD,OAAO,gBAAgB,GAAG,CAAC,OAAO,EAAE,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,OAAO,iCAAiC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAC7D,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,OAAe;QAC7C,MAAM,SAAS,GAAG,IAAI,CACpB,IAAI,CAAC,OAAO,EACZ,QAAQ,EACR,OAAO,EACP,aAAa,CACd,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEjE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,WAAW,GAAmB,KAAK,CAAC,GAAG,CAC3C,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAiB,CAC3C,CAAC;QACF,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAElD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,oBAAoB;QACpB,MAAM,MAAM,GAAG,cAAc,MAAM,CAAC,MAAM,cAAc,CAAC;QACzD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CACzB,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,OAAO,EAAE,CACxC,CAAC;QAEF,wEAAwE;QACxE,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC/D,MAAM,cAAc,GAClB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QAC1D,MAAM,SAAS,CAAC,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAEpD,OAAO,GAAG,MAAM,KAAK,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAC7C,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,OAAe;QAC9C,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAEnC,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3C,MAAM,YAAY,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QAE3C,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,CACR,qBAAqB,QAAQ,8CAA8C,CAC5E,CAAC;QAEF,yBAAyB;QACzB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC5D,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,cAAc,QAAQ,SAAS,CAAC,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;QAED,6BAA6B;QAC7B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QACpE,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,cAAc,YAAY,SAAS,CAAC,CAAC;YAChD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3B,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,YAAY,CACxB,OAAe,EACf,OAAe;QAEf,MAAM,QAAQ,GAAG,GAAG,OAAO,KAAK,CAAC;QAEjC,+BAA+B;QAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACnD,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvB,OAAO,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAED,oDAAoD;QACpD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC1E,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,OAAO,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACpC,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,8EAA8E;AAE9E,SAAS,UAAU,CAAC,IAAU;IAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Start the ccgateway daemon (foreground).
3
+ *
4
+ * 1. Loads config and ensures directory structure
5
+ * 2. Builds core components (AgentRegistry, SessionManager, etc.)
6
+ * 3. Loads and starts all enabled plugins
7
+ * 4. Writes PID file for lifecycle management
8
+ * 5. Sets up signal handlers for graceful shutdown
9
+ */
10
+ export declare function startDaemon(): Promise<void>;
11
+ /**
12
+ * Stop the running ccgateway daemon.
13
+ *
14
+ * Reads the PID file, sends SIGTERM, waits briefly, then SIGKILL if needed.
15
+ */
16
+ export declare function stopDaemon(): void;
17
+ /**
18
+ * Get the status of the ccgateway daemon.
19
+ */
20
+ export declare function getDaemonStatus(): {
21
+ running: boolean;
22
+ pid?: number;
23
+ uptime?: number;
24
+ };
25
+ /** Get the PID file path. */
26
+ export declare function pidPath(): string;
27
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAwBA;;;;;;;;GAQG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAwGjD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAgDjC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAuBrF;AAID,6BAA6B;AAC7B,wBAAgB,OAAO,IAAI,MAAM,CAEhC"}
package/dist/daemon.js ADDED
@@ -0,0 +1,207 @@
1
+ import { loadConfig, getCcgHome, ensureDirectories } from './config.js';
2
+ import { AgentRegistry } from './agents.js';
3
+ import { SessionManager } from './sessions.js';
4
+ import { SkillManager } from './skills.js';
5
+ import { ContextBuilder } from './context.js';
6
+ import { CCSpawner } from './spawner.js';
7
+ import { MessageRouter } from './router.js';
8
+ import { PluginLoader } from './plugin.js';
9
+ import { CrossAgentMessenger } from './messaging.js';
10
+ import { configureLogger, logger } from './logger.js';
11
+ import { writeFileSync, readFileSync, existsSync, unlinkSync, statSync } from 'node:fs';
12
+ import { join } from 'node:path';
13
+ // Built-in plugin factories
14
+ import createDiscordGateway from './plugins/discord-gateway.js';
15
+ import createSlackGateway from './plugins/slack-gateway.js';
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ const BUILTIN_PLUGINS = {
18
+ 'discord-gateway': createDiscordGateway,
19
+ 'slack-gateway': createSlackGateway,
20
+ };
21
+ /**
22
+ * Start the ccgateway daemon (foreground).
23
+ *
24
+ * 1. Loads config and ensures directory structure
25
+ * 2. Builds core components (AgentRegistry, SessionManager, etc.)
26
+ * 3. Loads and starts all enabled plugins
27
+ * 4. Writes PID file for lifecycle management
28
+ * 5. Sets up signal handlers for graceful shutdown
29
+ */
30
+ export async function startDaemon() {
31
+ // 1. Load config
32
+ const config = await loadConfig();
33
+ // 2. Ensure directories
34
+ await ensureDirectories();
35
+ // 3. Enable file logging for daemon mode
36
+ configureLogger({ file: true });
37
+ // 4. Create core components
38
+ const ccgHome = getCcgHome();
39
+ const registry = new AgentRegistry(config);
40
+ const sessions = new SessionManager(ccgHome);
41
+ const skills = new SkillManager(ccgHome);
42
+ const context = new ContextBuilder(sessions, skills, ccgHome, registry);
43
+ const spawner = new CCSpawner();
44
+ const router = new MessageRouter(registry, sessions, context, spawner, config.bindings);
45
+ // 5. Create PluginLoader and messenger (messenger needs loader reference)
46
+ const loader = new PluginLoader();
47
+ const messenger = new CrossAgentMessenger(registry, config.bindings, loader, ccgHome);
48
+ messenger.setRouter(router);
49
+ // 6. Build CcgCore object for plugins
50
+ const core = {
51
+ config,
52
+ agents: registry,
53
+ sessions,
54
+ router,
55
+ async send(agentId, message, fromAgent) {
56
+ await messenger.send(agentId, message, fromAgent);
57
+ },
58
+ };
59
+ // 7. Load built-in plugins + any external plugins
60
+ for (const entry of config.plugins) {
61
+ if (!entry.enabled)
62
+ continue;
63
+ let plugin;
64
+ const builtinFactory = BUILTIN_PLUGINS[entry.name];
65
+ if (builtinFactory) {
66
+ plugin = builtinFactory(entry.config);
67
+ }
68
+ else {
69
+ // Fall back to generic import for external plugins
70
+ await loader.loadPlugins({ ...config, plugins: [entry] }, core);
71
+ continue;
72
+ }
73
+ await plugin.init(core);
74
+ loader.registerPlugin(plugin);
75
+ logger.info(`plugin: loaded built-in "${plugin.name}" (type=${plugin.type})`);
76
+ }
77
+ // 8. Start all plugins
78
+ await loader.startAll();
79
+ // 9. Write PID file
80
+ const pid = process.pid;
81
+ writeFileSync(pidPath(), String(pid), 'utf-8');
82
+ // 10. Set up signal handlers for graceful shutdown
83
+ const shutdown = async (signal) => {
84
+ logger.info(`ccgateway received ${signal}, shutting down...`);
85
+ try {
86
+ await loader.stopAll();
87
+ }
88
+ catch (err) {
89
+ logger.error(`Error stopping plugins: ${err.message}`);
90
+ }
91
+ removePidFile();
92
+ logger.info('ccgateway stopped.');
93
+ process.exit(0);
94
+ };
95
+ process.on('SIGTERM', () => { void shutdown('SIGTERM'); });
96
+ process.on('SIGINT', () => { void shutdown('SIGINT'); });
97
+ // 11. Log startup
98
+ const agentCount = registry.listAgents().length;
99
+ const pluginCount = loader.getPlugins().length;
100
+ logger.info(`ccgateway started (pid=${pid}, agents=${agentCount}, plugins=${pluginCount})`);
101
+ console.log(`ccgateway started (pid=${pid}, agents=${agentCount}, plugins=${pluginCount})`);
102
+ // 12. Keep process alive — plugins maintain connections via event loops.
103
+ // If no plugins are keeping the event loop alive, use a heartbeat interval.
104
+ const keepAlive = setInterval(() => {
105
+ // no-op: keeps the event loop alive
106
+ }, 60_000);
107
+ keepAlive.unref(); // allow process to exit if all plugins stop
108
+ }
109
+ /**
110
+ * Stop the running ccgateway daemon.
111
+ *
112
+ * Reads the PID file, sends SIGTERM, waits briefly, then SIGKILL if needed.
113
+ */
114
+ export function stopDaemon() {
115
+ const path = pidPath();
116
+ if (!existsSync(path)) {
117
+ console.error('ccgateway is not running (no PID file found).');
118
+ process.exitCode = 1;
119
+ return;
120
+ }
121
+ const pid = parseInt(readFileSync(path, 'utf-8').trim(), 10);
122
+ if (isNaN(pid)) {
123
+ console.error('Invalid PID file. Removing it.');
124
+ removePidFile();
125
+ process.exitCode = 1;
126
+ return;
127
+ }
128
+ // Check if process is actually running
129
+ if (!isProcessRunning(pid)) {
130
+ console.log('ccgateway process is not running. Cleaning up stale PID file.');
131
+ removePidFile();
132
+ return;
133
+ }
134
+ // Send SIGTERM for graceful shutdown
135
+ try {
136
+ process.kill(pid, 'SIGTERM');
137
+ console.log(`Sent SIGTERM to ccgateway (pid=${pid}).`);
138
+ }
139
+ catch {
140
+ console.error(`Failed to send SIGTERM to pid ${pid}. Removing stale PID file.`);
141
+ removePidFile();
142
+ process.exitCode = 1;
143
+ return;
144
+ }
145
+ // Wait briefly and check if still running, then SIGKILL
146
+ setTimeout(() => {
147
+ if (isProcessRunning(pid)) {
148
+ try {
149
+ process.kill(pid, 'SIGKILL');
150
+ console.log(`Process did not exit gracefully. Sent SIGKILL to pid=${pid}.`);
151
+ }
152
+ catch {
153
+ // Process may have exited between check and kill
154
+ }
155
+ }
156
+ removePidFile();
157
+ }, 3000);
158
+ }
159
+ /**
160
+ * Get the status of the ccgateway daemon.
161
+ */
162
+ export function getDaemonStatus() {
163
+ const path = pidPath();
164
+ if (!existsSync(path)) {
165
+ return { running: false };
166
+ }
167
+ const raw = readFileSync(path, 'utf-8').trim();
168
+ const pid = parseInt(raw, 10);
169
+ if (isNaN(pid)) {
170
+ return { running: false };
171
+ }
172
+ if (!isProcessRunning(pid)) {
173
+ return { running: false, pid };
174
+ }
175
+ // Estimate uptime from PID file modification time
176
+ const { mtimeMs } = statSync(path);
177
+ const uptime = Math.floor((Date.now() - mtimeMs) / 1000);
178
+ return { running: true, pid, uptime };
179
+ }
180
+ // ── Helpers ───────────────────────────────────────────────────────────────────
181
+ /** Get the PID file path. */
182
+ export function pidPath() {
183
+ return join(getCcgHome(), 'ccgateway.pid');
184
+ }
185
+ /** Check if a process is running. */
186
+ function isProcessRunning(pid) {
187
+ try {
188
+ process.kill(pid, 0);
189
+ return true;
190
+ }
191
+ catch {
192
+ return false;
193
+ }
194
+ }
195
+ /** Remove the PID file if it exists. */
196
+ function removePidFile() {
197
+ const path = pidPath();
198
+ if (existsSync(path)) {
199
+ try {
200
+ unlinkSync(path);
201
+ }
202
+ catch {
203
+ // ignore removal errors
204
+ }
205
+ }
206
+ }
207
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { AgentRegistry } from "./agents.js";
2
+ import type { CCSpawner } from "./spawner.js";
3
+ import type { HeartbeatConfig } from "./config.js";
4
+ export declare class HeartbeatManager {
5
+ private agents;
6
+ private spawner;
7
+ private heartbeats;
8
+ constructor(agents: AgentRegistry, spawner: CCSpawner, heartbeats: HeartbeatConfig[]);
9
+ /**
10
+ * Run a heartbeat for an agent.
11
+ * - If no HEARTBEAT.md exists in the workspace, returns silent.
12
+ * - If the agent responds with "HEARTBEAT_OK", returns silent.
13
+ * - Otherwise returns the response.
14
+ */
15
+ runHeartbeat(agentId: string): Promise<{
16
+ silent: boolean;
17
+ response?: string;
18
+ }>;
19
+ /**
20
+ * Generate crontab lines from heartbeats config.
21
+ * Format: <cron> TZ=<tz> ccg heartbeat run <agent>
22
+ */
23
+ generateCronLines(): string[];
24
+ /**
25
+ * Install cron jobs to system crontab.
26
+ * Returns the generated crontab lines (for display).
27
+ */
28
+ installCron(): string;
29
+ /**
30
+ * Remove ccgateway cron jobs from system crontab.
31
+ */
32
+ uninstallCron(): void;
33
+ /**
34
+ * List configured heartbeats.
35
+ */
36
+ listHeartbeats(): HeartbeatConfig[];
37
+ /**
38
+ * Remove the ccgateway section from crontab content.
39
+ */
40
+ private removeCcgSection;
41
+ }
42
+ //# sourceMappingURL=heartbeat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAYnD,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,UAAU;gBAFV,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,SAAS,EAClB,UAAU,EAAE,eAAe,EAAE;IAGvC;;;;;OAKG;IACG,YAAY,CAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAgClD;;;OAGG;IACH,iBAAiB,IAAI,MAAM,EAAE;IAM7B;;;OAGG;IACH,WAAW,IAAI,MAAM;IAuCrB;;OAEG;IACH,aAAa,IAAI,IAAI;IA0BrB;;OAEG;IACH,cAAc,IAAI,eAAe,EAAE;IAMnC;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAqBzB"}