@hoverlover/cc-discord 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 (46) hide show
  1. package/.claude/settings.template.json +94 -0
  2. package/.env.example +41 -0
  3. package/.env.relay.example +46 -0
  4. package/.env.worker.example +40 -0
  5. package/README.md +313 -0
  6. package/hooks/check-discord-messages.ts +204 -0
  7. package/hooks/cleanup-attachment.ts +47 -0
  8. package/hooks/safe-bash.ts +157 -0
  9. package/hooks/steer-send.ts +108 -0
  10. package/hooks/track-activity.ts +220 -0
  11. package/memory/README.md +60 -0
  12. package/memory/core/MemoryCoordinator.ts +703 -0
  13. package/memory/core/MemoryStore.ts +72 -0
  14. package/memory/core/session-key.ts +14 -0
  15. package/memory/core/types.ts +59 -0
  16. package/memory/index.ts +19 -0
  17. package/memory/providers/sqlite/SqliteMemoryStore.ts +838 -0
  18. package/memory/providers/sqlite/index.ts +1 -0
  19. package/package.json +45 -0
  20. package/prompts/autoreply-system.md +32 -0
  21. package/prompts/channel-system.md +22 -0
  22. package/prompts/orchestrator-system.md +56 -0
  23. package/scripts/channel-agent.sh +159 -0
  24. package/scripts/generate-settings.sh +17 -0
  25. package/scripts/load-env.sh +79 -0
  26. package/scripts/migrate-memory-to-channel-keys.ts +148 -0
  27. package/scripts/orchestrator.sh +325 -0
  28. package/scripts/parse-claude-stream.ts +349 -0
  29. package/scripts/start-orchestrator.sh +82 -0
  30. package/scripts/start-relay.sh +17 -0
  31. package/scripts/start.sh +175 -0
  32. package/server/attachment.ts +182 -0
  33. package/server/busy-notify.ts +69 -0
  34. package/server/config.ts +121 -0
  35. package/server/db.ts +249 -0
  36. package/server/index.ts +311 -0
  37. package/server/memory.ts +88 -0
  38. package/server/messages.ts +111 -0
  39. package/server/trace-thread.ts +340 -0
  40. package/server/typing.ts +101 -0
  41. package/tools/memory-inspect.ts +94 -0
  42. package/tools/memory-smoke.ts +173 -0
  43. package/tools/send-discord +2 -0
  44. package/tools/send-discord.ts +82 -0
  45. package/tools/wait-for-discord-messages +2 -0
  46. package/tools/wait-for-discord-messages.ts +369 -0
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Base class for memory stores.
3
+ * Implementations should override all async methods.
4
+ */
5
+ export class MemoryStore {
6
+ id: string;
7
+ caps: { atomicBatch: boolean; fullTextSearch: boolean; vectorSearch: boolean; bidirectionalSync: boolean };
8
+
9
+ /**
10
+ * @param {string} id
11
+ * @param {{ atomicBatch: boolean, fullTextSearch: boolean, vectorSearch: boolean, bidirectionalSync: boolean }} caps
12
+ */
13
+ constructor(
14
+ id: string,
15
+ caps: { atomicBatch: boolean; fullTextSearch: boolean; vectorSearch: boolean; bidirectionalSync: boolean },
16
+ ) {
17
+ this.id = id;
18
+ this.caps = caps;
19
+ }
20
+
21
+ async init(): Promise<void> {
22
+ throw new Error("MemoryStore.init() not implemented");
23
+ }
24
+
25
+ async health(): Promise<any> {
26
+ throw new Error("MemoryStore.health() not implemented");
27
+ }
28
+
29
+ async writeBatch(_batch: any): Promise<any> {
30
+ throw new Error("MemoryStore.writeBatch() not implemented");
31
+ }
32
+
33
+ async readSessionSnapshot(_sessionKey: any): Promise<any> {
34
+ throw new Error("MemoryStore.readSessionSnapshot() not implemented");
35
+ }
36
+
37
+ async listTurns(_input: any): Promise<any> {
38
+ throw new Error("MemoryStore.listTurns() not implemented");
39
+ }
40
+
41
+ async listRecentTurns(_input: any): Promise<any> {
42
+ throw new Error("MemoryStore.listRecentTurns() not implemented");
43
+ }
44
+
45
+ async queryCards(_input: any): Promise<any> {
46
+ throw new Error("MemoryStore.queryCards() not implemented");
47
+ }
48
+
49
+ async readCompactionState(_sessionKey: any): Promise<any> {
50
+ throw new Error("MemoryStore.readCompactionState() not implemented");
51
+ }
52
+
53
+ async getTurnById(_input: any): Promise<any> {
54
+ throw new Error("MemoryStore.getTurnById() not implemented");
55
+ }
56
+
57
+ async readRuntimeState(_sessionKey: any): Promise<any> {
58
+ throw new Error("MemoryStore.readRuntimeState() not implemented");
59
+ }
60
+
61
+ async upsertRuntimeState(_input: any): Promise<any> {
62
+ throw new Error("MemoryStore.upsertRuntimeState() not implemented");
63
+ }
64
+
65
+ async bumpRuntimeContext(_input: any): Promise<any> {
66
+ throw new Error("MemoryStore.bumpRuntimeContext() not implemented");
67
+ }
68
+
69
+ async close(): Promise<void> {
70
+ // Optional for stores that keep sockets or db handles
71
+ }
72
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Build a deterministic memory session key for a Claude route.
3
+ *
4
+ * @param {{ sessionId?: string, agentId?: string, channelId?: string }} input
5
+ */
6
+ export function buildMemorySessionKey(input: { sessionId?: string; agentId?: string; channelId?: string } = {}) {
7
+ const sessionId = String(input.sessionId || "default").trim() || "default";
8
+ const agentId = String(input.agentId || "claude").trim() || "claude";
9
+ const channelId = input.channelId ? String(input.channelId).trim() : "";
10
+ if (channelId) {
11
+ return `discord:${sessionId}:${agentId}:ch-${channelId}`;
12
+ }
13
+ return `discord:${sessionId}:${agentId}`;
14
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Canonical memory model helpers (store-agnostic).
3
+ *
4
+ * This file intentionally uses plain JS + JSDoc so the project can stay
5
+ * lightweight without a TypeScript build step.
6
+ */
7
+
8
+ export const MemoryScopes = Object.freeze({
9
+ SESSION: "session",
10
+ USER: "user",
11
+ GLOBAL: "global",
12
+ });
13
+
14
+ export const MemoryCardTypes = Object.freeze({
15
+ DECISION: "decision",
16
+ CONSTRAINT: "constraint",
17
+ PREFERENCE: "preference",
18
+ TODO: "todo",
19
+ CONTEXT: "context",
20
+ });
21
+
22
+ /**
23
+ * @param {unknown} value
24
+ * @param {any} fallback
25
+ */
26
+ export function safeJsonParse(value: unknown, fallback: unknown) {
27
+ if (value === null || value === undefined || value === "") return fallback;
28
+ if (typeof value !== "string") return fallback;
29
+ try {
30
+ return JSON.parse(value);
31
+ } catch {
32
+ return fallback;
33
+ }
34
+ }
35
+
36
+ /**
37
+ * @param {unknown} value
38
+ * @param {string} fallback
39
+ */
40
+ export function safeJsonStringify(value: unknown, fallback: string = "null") {
41
+ try {
42
+ return JSON.stringify(value);
43
+ } catch {
44
+ return fallback;
45
+ }
46
+ }
47
+
48
+ export function nowIso() {
49
+ return new Date().toISOString();
50
+ }
51
+
52
+ /**
53
+ * @param {number} value
54
+ * @param {number} min
55
+ * @param {number} max
56
+ */
57
+ export function clamp(value: number, min: number, max: number) {
58
+ return Math.max(min, Math.min(max, value));
59
+ }
@@ -0,0 +1,19 @@
1
+ export { MemoryCoordinator } from "./core/MemoryCoordinator.ts";
2
+ export { MemoryStore } from "./core/MemoryStore.ts";
3
+ export { buildMemorySessionKey } from "./core/session-key.ts";
4
+ export {
5
+ clamp,
6
+ MemoryCardTypes,
7
+ MemoryScopes,
8
+ nowIso,
9
+ safeJsonParse,
10
+ safeJsonStringify,
11
+ } from "./core/types.ts";
12
+
13
+ /**
14
+ * Lazy-load sqlite provider to avoid forcing sqlite initialization on all imports.
15
+ */
16
+ export async function loadSqliteMemoryStore() {
17
+ const mod = await import("./providers/sqlite/SqliteMemoryStore.ts");
18
+ return mod.SqliteMemoryStore;
19
+ }