@gonzih/cc-wire 0.1.7 → 0.3.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.
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCcWire = createCcWire;
4
+ const channels_js_1 = require("./channels.cjs");
5
+ // ─── Private key helpers (not exported) ──────────────────────────────────────
6
+ const channelHashKey = (channelId) => `cca:discord:channel:${channelId}`;
7
+ const CHANNELS_SET = "cca:discord:channels:index";
8
+ const discordNotifyLogKey = (ns) => `cca:discord:notify-log:${ns}`;
9
+ const TG_NOTIFY_LOG = "cca:tg:notify-log";
10
+ const SPAWN_QUEUE = "cca:spawn:queue";
11
+ const MASTER_TOKEN_KEY = "cca:token:master";
12
+ // ─── Factory ──────────────────────────────────────────────────────────────────
13
+ function createCcWire(redis) {
14
+ return {
15
+ // ── discord ──────────────────────────────────────────────────────────────
16
+ discord: {
17
+ async enqueue(ns, msg) {
18
+ await redis.rpush((0, channels_js_1.discordMetaInputKey)(ns), JSON.stringify(msg));
19
+ },
20
+ async dequeue(ns) {
21
+ const val = await redis.rpop((0, channels_js_1.discordMetaInputKey)(ns));
22
+ return val ? JSON.parse(val) : null;
23
+ },
24
+ async publishOutgoing(ns, msg) {
25
+ const json = JSON.stringify(msg);
26
+ const pl = redis.pipeline();
27
+ pl.publish((0, channels_js_1.discordChatOutgoing)(ns), json);
28
+ pl.lpush((0, channels_js_1.discordChatLog)(ns), json);
29
+ pl.ltrim((0, channels_js_1.discordChatLog)(ns), 0, channels_js_1.CAP.CHAT_LOG - 1);
30
+ await pl.exec();
31
+ },
32
+ subscribeOutgoing(ns, cb) {
33
+ const sub = redis.duplicate();
34
+ sub.subscribe((0, channels_js_1.discordChatOutgoing)(ns));
35
+ sub.on("message", (channel, message) => {
36
+ if (channel === (0, channels_js_1.discordChatOutgoing)(ns)) {
37
+ cb(JSON.parse(message));
38
+ }
39
+ });
40
+ },
41
+ async setStatus(ns, status) {
42
+ await redis.set((0, channels_js_1.discordMetaStatusKey)(ns), JSON.stringify(status), "EX", channels_js_1.TTL.JOB_SECONDS);
43
+ },
44
+ async getStatus(ns) {
45
+ const val = await redis.get((0, channels_js_1.discordMetaStatusKey)(ns));
46
+ return val ? JSON.parse(val) : null;
47
+ },
48
+ async writeChatLog(ns, msg) {
49
+ const pl = redis.pipeline();
50
+ pl.lpush((0, channels_js_1.discordChatLog)(ns), JSON.stringify(msg));
51
+ pl.ltrim((0, channels_js_1.discordChatLog)(ns), 0, channels_js_1.CAP.CHAT_LOG - 1);
52
+ await pl.exec();
53
+ },
54
+ async getChatLog(ns, limit = 50) {
55
+ const items = await redis.lrange((0, channels_js_1.discordChatLog)(ns), 0, limit - 1);
56
+ return items
57
+ .map((i) => JSON.parse(i))
58
+ .reverse();
59
+ },
60
+ async notify(ns, payload) {
61
+ const json = JSON.stringify(payload);
62
+ const pl = redis.pipeline();
63
+ pl.publish((0, channels_js_1.discordNotify)(ns), json);
64
+ pl.rpush((0, channels_js_1.discordNotify)(ns), json);
65
+ pl.lpush(discordNotifyLogKey(ns), json);
66
+ pl.ltrim(discordNotifyLogKey(ns), 0, channels_js_1.CAP.NOTIFY_LOG - 1);
67
+ await pl.exec();
68
+ },
69
+ async pollNotify(ns) {
70
+ const val = await redis.rpop((0, channels_js_1.discordNotify)(ns));
71
+ return val ? JSON.parse(val) : null;
72
+ },
73
+ async registerChannel(channelId, ns, repoUrl) {
74
+ const pl = redis.pipeline();
75
+ pl.hset(channelHashKey(channelId), { namespace: ns, repoUrl });
76
+ pl.sadd(CHANNELS_SET, channelId);
77
+ await pl.exec();
78
+ },
79
+ async getChannel(channelId) {
80
+ const data = await redis.hgetall(channelHashKey(channelId));
81
+ if (!data || !data["namespace"])
82
+ return null;
83
+ return { namespace: data["namespace"], repoUrl: data["repoUrl"] ?? "" };
84
+ },
85
+ async listChannels() {
86
+ const ids = await redis.smembers(CHANNELS_SET);
87
+ const rows = await Promise.all(ids.map(async (channelId) => {
88
+ const data = await redis.hgetall(channelHashKey(channelId));
89
+ if (!data || !data["namespace"])
90
+ return null;
91
+ return {
92
+ channelId,
93
+ namespace: data["namespace"],
94
+ repoUrl: data["repoUrl"] ?? "",
95
+ };
96
+ }));
97
+ return rows.filter((r) => r !== null);
98
+ },
99
+ },
100
+ // ── tg ───────────────────────────────────────────────────────────────────
101
+ tg: {
102
+ async publishOutgoing(msg) {
103
+ const json = JSON.stringify(msg);
104
+ const pl = redis.pipeline();
105
+ pl.publish((0, channels_js_1.tgChatOutgoing)(), json);
106
+ pl.lpush("cca:tg:chat:log", json);
107
+ pl.ltrim("cca:tg:chat:log", 0, channels_js_1.CAP.CHAT_LOG - 1);
108
+ await pl.exec();
109
+ },
110
+ subscribeOutgoing(cb) {
111
+ const sub = redis.duplicate();
112
+ sub.subscribe((0, channels_js_1.tgChatOutgoing)());
113
+ sub.on("message", (_channel, message) => {
114
+ cb(JSON.parse(message));
115
+ });
116
+ },
117
+ async notify(payload) {
118
+ const json = JSON.stringify(payload);
119
+ const pl = redis.pipeline();
120
+ pl.publish((0, channels_js_1.tgNotify)(), json);
121
+ pl.rpush((0, channels_js_1.tgNotify)(), json);
122
+ pl.lpush(TG_NOTIFY_LOG, json);
123
+ pl.ltrim(TG_NOTIFY_LOG, 0, channels_js_1.CAP.NOTIFY_LOG - 1);
124
+ await pl.exec();
125
+ },
126
+ async pollNotify() {
127
+ const val = await redis.rpop((0, channels_js_1.tgNotify)());
128
+ return val ? JSON.parse(val) : null;
129
+ },
130
+ },
131
+ // ── jobs ─────────────────────────────────────────────────────────────────
132
+ jobs: {
133
+ async enqueue(job) {
134
+ const pl = redis.pipeline();
135
+ pl.set((0, channels_js_1.jobKey)(job.id), JSON.stringify({ ...job, status: "pending" }), "EX", channels_js_1.TTL.JOB_SECONDS);
136
+ pl.lpush(SPAWN_QUEUE, JSON.stringify(job));
137
+ await pl.exec();
138
+ },
139
+ async getStatus(jobId) {
140
+ const val = await redis.get((0, channels_js_1.jobKey)(jobId));
141
+ return val ? JSON.parse(val) : null;
142
+ },
143
+ async publishDone(jobId, result) {
144
+ const json = JSON.stringify(result);
145
+ const pl = redis.pipeline();
146
+ pl.publish((0, channels_js_1.jobDoneChannel)(jobId), json);
147
+ pl.lpush((0, channels_js_1.jobDoneQueueKey)(jobId), json);
148
+ pl.expire((0, channels_js_1.jobDoneQueueKey)(jobId), channels_js_1.TTL.JOB_SECONDS);
149
+ await pl.exec();
150
+ },
151
+ },
152
+ // ── token ─────────────────────────────────────────────────────────────────
153
+ token: {
154
+ async getMaster() {
155
+ const val = await redis.get(MASTER_TOKEN_KEY);
156
+ if (val === null)
157
+ throw new Error("cc-wire: master token not set");
158
+ return val;
159
+ },
160
+ async setMaster(token) {
161
+ await redis.set(MASTER_TOKEN_KEY, token);
162
+ },
163
+ },
164
+ _redis: redis,
165
+ };
166
+ }
@@ -11,11 +11,25 @@
11
11
  * All values match the exact strings used in the source repos as of 2026-05.
12
12
  */
13
13
  import type { NotificationPayload } from "./types.js";
14
+ /**
15
+ * Root directory (relative to HOME) where cc-discord checks out per-namespace
16
+ * workspace clones: `~/cc-discord-workspace/{namespace}`.
17
+ */
18
+ export declare const CC_DISCORD_WORKSPACE_ROOT = "cc-discord-workspace";
19
+ /**
20
+ * Directory name (relative to HOME) of the money-brain repo used by cc-tg
21
+ * for its dedicated session: `~/money-brain`.
22
+ */
23
+ export declare const CC_TG_WORKSPACE = "money-brain";
14
24
  /** Redis Stream written by cc-agent on every job status change. */
15
25
  export declare const EVENT_STREAM = "cca:event-stream";
16
26
  /** Consumer group name used by the coordinator to read from EVENT_STREAM. */
17
27
  export declare const COORDINATOR_GROUP = "coordinator";
18
- /** SET — canonical registry of meta-agent namespaces. */
28
+ /**
29
+ * SET — canonical registry of meta-agent namespaces.
30
+ * @deprecated cc-discord now maintains its own namespace registry.
31
+ * This key is no longer written by the cc-suite; kept for migration only.
32
+ */
19
33
  export declare const META_AGENTS_INDEX = "cca:meta:agents:index";
20
34
  /** SET — index of saved profile names. */
21
35
  export declare const PROFILES_INDEX = "cca:profiles:index";
@@ -86,10 +100,43 @@ export declare const chatIncomingChannel: (namespace: string) => string;
86
100
  export declare const chatOutgoingChannel: (namespace: string) => string;
87
101
  /** STRING (JSON) — MetaAgentInfo state, TTL 30 days. */
88
102
  export declare const metaKey: (namespace: string) => string;
89
- /** LIST — input queue for a meta-agent (RPUSH by cc-tg, RPOP by cc-agent). */
103
+ /**
104
+ * LIST — input queue for a meta-agent (RPUSH by cc-tg, RPOP by cc-agent).
105
+ * @deprecated Use `discordMetaInputKey(ns)` — cc-discord now owns namespace sessions directly.
106
+ */
90
107
  export declare const metaInputKey: (namespace: string) => string;
91
- /** STRING (JSON) — live meta-agent status (typing, tool, etc.), TTL 7 days. */
108
+ /**
109
+ * STRING (JSON) — live meta-agent status (typing, tool, etc.), TTL 7 days.
110
+ * @deprecated Use `discordMetaStatusKey(ns)` — cc-discord now owns namespace sessions directly.
111
+ */
92
112
  export declare const metaAgentStatusKey: (namespace: string) => string;
113
+ /** LIST — input queue for a cc-discord-managed namespace session (RPUSH/RPOP). */
114
+ export declare const discordMetaInputKey: (namespace: string) => string;
115
+ /** STRING (JSON) — live status for a cc-discord-managed namespace session, TTL 7 days. */
116
+ export declare const discordMetaStatusKey: (namespace: string) => string;
117
+ /** CHANNEL — cc-discord → UI outgoing chat messages (pub/sub). */
118
+ export declare const discordChatOutgoing: (namespace: string) => string;
119
+ /** LIST — cc-discord chat history (LPUSH capped at 500, LIFO). */
120
+ export declare const discordChatLog: (namespace: string) => string;
121
+ /** CHANNEL — UI/Discord → cc-discord incoming chat messages (pub/sub). */
122
+ export declare const discordChatIncoming: (namespace: string) => string;
123
+ /**
124
+ * CHANNEL + LIST — job-completion notifications for a Discord namespace.
125
+ *
126
+ * Same dual-purpose pattern as `notifyChannel`/`notifyListKey`: PUBLISH by
127
+ * coordinator (pub/sub) and RPUSH/RPOP delivery queue; Redis pub/sub and list
128
+ * namespaces are independent so the dual use is safe.
129
+ */
130
+ export declare const discordNotify: (namespace: string) => string;
131
+ /** CHANNEL — cc-tg → UI outgoing chat messages (pub/sub). */
132
+ export declare const tgChatOutgoing: () => string;
133
+ /** CHANNEL — UI/Telegram → cc-tg incoming chat messages (pub/sub). */
134
+ export declare const tgChatIncoming: () => string;
135
+ /**
136
+ * CHANNEL + LIST — job-completion notifications for the cc-tg session.
137
+ * Same dual-purpose pattern (pub/sub + RPOP poll fallback).
138
+ */
139
+ export declare const tgNotify: () => string;
93
140
  /** LIST — learnings for a namespace (LPUSH capped at 50, LIFO), TTL 90 days. */
94
141
  export declare const learningsKey: (namespace: string) => string;
95
142
  /** STRING (JSON array) — cron job definitions for a namespace. */
@@ -1 +1 @@
1
- {"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../src/channels.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../src/channels.ts"],"names":[],"mappings":"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"}
@@ -10,12 +10,27 @@
10
10
  *
11
11
  * All values match the exact strings used in the source repos as of 2026-05.
12
12
  */
13
+ // ─── Service Ownership Constants ─────────────────────────────────────────────
14
+ /**
15
+ * Root directory (relative to HOME) where cc-discord checks out per-namespace
16
+ * workspace clones: `~/cc-discord-workspace/{namespace}`.
17
+ */
18
+ export const CC_DISCORD_WORKSPACE_ROOT = "cc-discord-workspace";
19
+ /**
20
+ * Directory name (relative to HOME) of the money-brain repo used by cc-tg
21
+ * for its dedicated session: `~/money-brain`.
22
+ */
23
+ export const CC_TG_WORKSPACE = "money-brain";
13
24
  // ─── Static Keys ─────────────────────────────────────────────────────────────
14
25
  /** Redis Stream written by cc-agent on every job status change. */
15
26
  export const EVENT_STREAM = "cca:event-stream";
16
27
  /** Consumer group name used by the coordinator to read from EVENT_STREAM. */
17
28
  export const COORDINATOR_GROUP = "coordinator";
18
- /** SET — canonical registry of meta-agent namespaces. */
29
+ /**
30
+ * SET — canonical registry of meta-agent namespaces.
31
+ * @deprecated cc-discord now maintains its own namespace registry.
32
+ * This key is no longer written by the cc-suite; kept for migration only.
33
+ */
19
34
  export const META_AGENTS_INDEX = "cca:meta:agents:index";
20
35
  /** SET — index of saved profile names. */
21
36
  export const PROFILES_INDEX = "cca:profiles:index";
@@ -96,10 +111,52 @@ export const chatOutgoingChannel = (namespace) => `cca:chat:outgoing:${namespace
96
111
  // ─── Meta-Agent Keys (dynamic) ───────────────────────────────────────────────
97
112
  /** STRING (JSON) — MetaAgentInfo state, TTL 30 days. */
98
113
  export const metaKey = (namespace) => `cca:meta:${namespace}`;
99
- /** LIST — input queue for a meta-agent (RPUSH by cc-tg, RPOP by cc-agent). */
114
+ /**
115
+ * LIST — input queue for a meta-agent (RPUSH by cc-tg, RPOP by cc-agent).
116
+ * @deprecated Use `discordMetaInputKey(ns)` — cc-discord now owns namespace sessions directly.
117
+ */
100
118
  export const metaInputKey = (namespace) => `cca:meta:${namespace}:input`;
101
- /** STRING (JSON) — live meta-agent status (typing, tool, etc.), TTL 7 days. */
119
+ /**
120
+ * STRING (JSON) — live meta-agent status (typing, tool, etc.), TTL 7 days.
121
+ * @deprecated Use `discordMetaStatusKey(ns)` — cc-discord now owns namespace sessions directly.
122
+ */
102
123
  export const metaAgentStatusKey = (namespace) => `cca:meta-agent:status:${namespace}`;
124
+ // ─── cc-discord Keys (dynamic) ───────────────────────────────────────────────
125
+ //
126
+ // cc-discord owns all namespace-scoped Claude sessions. It reads from the
127
+ // meta input queue, writes status, and publishes/subscribes to chat/notify
128
+ // channels — all under the "cca:discord:" prefix to avoid collisions with
129
+ // the old cc-agent-owned keys.
130
+ /** LIST — input queue for a cc-discord-managed namespace session (RPUSH/RPOP). */
131
+ export const discordMetaInputKey = (namespace) => `cca:discord:meta:${namespace}:input`;
132
+ /** STRING (JSON) — live status for a cc-discord-managed namespace session, TTL 7 days. */
133
+ export const discordMetaStatusKey = (namespace) => `cca:discord:meta:${namespace}:status`;
134
+ /** CHANNEL — cc-discord → UI outgoing chat messages (pub/sub). */
135
+ export const discordChatOutgoing = (namespace) => `cca:discord:chat:outgoing:${namespace}`;
136
+ /** LIST — cc-discord chat history (LPUSH capped at 500, LIFO). */
137
+ export const discordChatLog = (namespace) => `cca:discord:chat:log:${namespace}`;
138
+ /** CHANNEL — UI/Discord → cc-discord incoming chat messages (pub/sub). */
139
+ export const discordChatIncoming = (namespace) => `cca:discord:chat:incoming:${namespace}`;
140
+ /**
141
+ * CHANNEL + LIST — job-completion notifications for a Discord namespace.
142
+ *
143
+ * Same dual-purpose pattern as `notifyChannel`/`notifyListKey`: PUBLISH by
144
+ * coordinator (pub/sub) and RPUSH/RPOP delivery queue; Redis pub/sub and list
145
+ * namespaces are independent so the dual use is safe.
146
+ */
147
+ export const discordNotify = (namespace) => `cca:discord:notify:${namespace}`;
148
+ // ─── cc-tg Keys (static) ─────────────────────────────────────────────────────
149
+ //
150
+ // cc-tg owns a single dedicated money-brain session with no namespace scoping.
151
+ /** CHANNEL — cc-tg → UI outgoing chat messages (pub/sub). */
152
+ export const tgChatOutgoing = () => "cca:tg:chat:outgoing";
153
+ /** CHANNEL — UI/Telegram → cc-tg incoming chat messages (pub/sub). */
154
+ export const tgChatIncoming = () => "cca:tg:chat:incoming";
155
+ /**
156
+ * CHANNEL + LIST — job-completion notifications for the cc-tg session.
157
+ * Same dual-purpose pattern (pub/sub + RPOP poll fallback).
158
+ */
159
+ export const tgNotify = () => "cca:tg:notify";
103
160
  // ─── Learnings Keys (dynamic) ─────────────────────────────────────────────────
104
161
  /** LIST — learnings for a namespace (LPUSH capped at 50, LIFO), TTL 90 days. */
105
162
  export const learningsKey = (namespace) => `cca:learnings:${namespace}`;
@@ -1 +1 @@
1
- {"version":3,"file":"channels.js","sourceRoot":"","sources":["../../src/channels.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"channels.js","sourceRoot":"","sources":["../../src/channels.ts"],"names":[],"mappings":"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"}
@@ -8,4 +8,5 @@
8
8
  */
9
9
  export * from "./channels.js";
10
10
  export * from "./types.js";
11
+ export * from "./runtime.js";
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
package/dist/esm/index.js CHANGED
@@ -8,4 +8,5 @@
8
8
  */
9
9
  export * from "./channels.js";
10
10
  export * from "./types.js";
11
+ export * from "./runtime.js";
11
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * cc-wire runtime — `createCcWire(redis)`
3
+ *
4
+ * The single entry point for all Redis I/O across the cc-suite.
5
+ * Services import this factory and call typed methods; they never
6
+ * write raw Redis commands or import key builders directly.
7
+ */
8
+ import type { Redis } from "ioredis";
9
+ import type { ChatMessage, MetaAgentStatus, NotificationPayload, SpawnParams } from "./types.js";
10
+ export interface DiscordApi {
11
+ /** RPUSH message to the input queue for a namespace session. */
12
+ enqueue(ns: string, msg: ChatMessage): Promise<void>;
13
+ /** RPOP next message from the input queue; null when empty. */
14
+ dequeue(ns: string): Promise<ChatMessage | null>;
15
+ /**
16
+ * Pipeline: PUBLISH to outgoing channel + LPUSH to chat log + LTRIM.
17
+ * Subscribers on the channel receive the message live; the log persists it.
18
+ */
19
+ publishOutgoing(ns: string, msg: ChatMessage): Promise<void>;
20
+ /** Subscribe to outgoing messages for a namespace. Uses an internal duplicate connection. */
21
+ subscribeOutgoing(ns: string, cb: (msg: ChatMessage) => void): void;
22
+ /** SET session status with 7-day TTL. */
23
+ setStatus(ns: string, status: MetaAgentStatus): Promise<void>;
24
+ /** GET session status; null when key is absent or expired. */
25
+ getStatus(ns: string): Promise<MetaAgentStatus | null>;
26
+ /** LPUSH message to chat log + LTRIM to 500. */
27
+ writeChatLog(ns: string, msg: ChatMessage): Promise<void>;
28
+ /** LRANGE chat log, reversed to chronological order. Default limit 50. */
29
+ getChatLog(ns: string, limit?: number): Promise<ChatMessage[]>;
30
+ /** PUBLISH notify channel + RPUSH delivery list + log. */
31
+ notify(ns: string, payload: NotificationPayload): Promise<void>;
32
+ /** RPOP from notify delivery list; null when empty. */
33
+ pollNotify(ns: string): Promise<NotificationPayload | null>;
34
+ /** Register a Discord channel → namespace mapping. */
35
+ registerChannel(channelId: string, ns: string, repoUrl: string): Promise<void>;
36
+ /** Look up a channel registration; null if not found. */
37
+ getChannel(channelId: string): Promise<{
38
+ namespace: string;
39
+ repoUrl: string;
40
+ } | null>;
41
+ /** List all registered channel mappings. */
42
+ listChannels(): Promise<Array<{
43
+ channelId: string;
44
+ namespace: string;
45
+ repoUrl: string;
46
+ }>>;
47
+ }
48
+ export interface TgApi {
49
+ /** Pipeline: PUBLISH to outgoing channel + LPUSH log + LTRIM. */
50
+ publishOutgoing(msg: ChatMessage): Promise<void>;
51
+ /** Subscribe to outgoing messages. Uses an internal duplicate connection. */
52
+ subscribeOutgoing(cb: (msg: ChatMessage) => void): void;
53
+ /** PUBLISH notify channel + RPUSH delivery list + log. */
54
+ notify(payload: NotificationPayload): Promise<void>;
55
+ /** RPOP from notify delivery list; null when empty. */
56
+ pollNotify(): Promise<NotificationPayload | null>;
57
+ }
58
+ export interface JobsApi {
59
+ /** LPUSH job to spawn queue and write initial job record. */
60
+ enqueue(job: SpawnParams & {
61
+ id: string;
62
+ }): Promise<void>;
63
+ /** GET job record; null when job does not exist. */
64
+ getStatus(jobId: string): Promise<unknown>;
65
+ /** PUBLISH job-done channel + LPUSH to done queue. */
66
+ publishDone(jobId: string, result: unknown): Promise<void>;
67
+ }
68
+ export interface TokenApi {
69
+ /** GET master token; throws if not set. */
70
+ getMaster(): Promise<string>;
71
+ /** SET master token (no TTL). */
72
+ setMaster(token: string): Promise<void>;
73
+ }
74
+ export interface CcWire {
75
+ /** cc-discord: per-namespace session management. */
76
+ discord: DiscordApi;
77
+ /** cc-tg: single money-brain session. */
78
+ tg: TgApi;
79
+ /** cc-agent: job queue. */
80
+ jobs: JobsApi;
81
+ /** Master token (shared across services). */
82
+ token: TokenApi;
83
+ /**
84
+ * Raw redis client escape hatch — for migration only.
85
+ * @internal
86
+ */
87
+ _redis: Redis;
88
+ }
89
+ export declare function createCcWire(redis: Redis): CcWire;
90
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,164 @@
1
+ import { discordMetaInputKey, discordMetaStatusKey, discordChatOutgoing, discordChatLog, discordNotify, tgChatOutgoing, tgNotify, jobKey, jobDoneChannel, jobDoneQueueKey, CAP, TTL, } from "./channels.js";
2
+ // ─── Private key helpers (not exported) ──────────────────────────────────────
3
+ const channelHashKey = (channelId) => `cca:discord:channel:${channelId}`;
4
+ const CHANNELS_SET = "cca:discord:channels:index";
5
+ const discordNotifyLogKey = (ns) => `cca:discord:notify-log:${ns}`;
6
+ const TG_NOTIFY_LOG = "cca:tg:notify-log";
7
+ const SPAWN_QUEUE = "cca:spawn:queue";
8
+ const MASTER_TOKEN_KEY = "cca:token:master";
9
+ // ─── Factory ──────────────────────────────────────────────────────────────────
10
+ export function createCcWire(redis) {
11
+ return {
12
+ // ── discord ──────────────────────────────────────────────────────────────
13
+ discord: {
14
+ async enqueue(ns, msg) {
15
+ await redis.rpush(discordMetaInputKey(ns), JSON.stringify(msg));
16
+ },
17
+ async dequeue(ns) {
18
+ const val = await redis.rpop(discordMetaInputKey(ns));
19
+ return val ? JSON.parse(val) : null;
20
+ },
21
+ async publishOutgoing(ns, msg) {
22
+ const json = JSON.stringify(msg);
23
+ const pl = redis.pipeline();
24
+ pl.publish(discordChatOutgoing(ns), json);
25
+ pl.lpush(discordChatLog(ns), json);
26
+ pl.ltrim(discordChatLog(ns), 0, CAP.CHAT_LOG - 1);
27
+ await pl.exec();
28
+ },
29
+ subscribeOutgoing(ns, cb) {
30
+ const sub = redis.duplicate();
31
+ sub.subscribe(discordChatOutgoing(ns));
32
+ sub.on("message", (channel, message) => {
33
+ if (channel === discordChatOutgoing(ns)) {
34
+ cb(JSON.parse(message));
35
+ }
36
+ });
37
+ },
38
+ async setStatus(ns, status) {
39
+ await redis.set(discordMetaStatusKey(ns), JSON.stringify(status), "EX", TTL.JOB_SECONDS);
40
+ },
41
+ async getStatus(ns) {
42
+ const val = await redis.get(discordMetaStatusKey(ns));
43
+ return val ? JSON.parse(val) : null;
44
+ },
45
+ async writeChatLog(ns, msg) {
46
+ const pl = redis.pipeline();
47
+ pl.lpush(discordChatLog(ns), JSON.stringify(msg));
48
+ pl.ltrim(discordChatLog(ns), 0, CAP.CHAT_LOG - 1);
49
+ await pl.exec();
50
+ },
51
+ async getChatLog(ns, limit = 50) {
52
+ const items = await redis.lrange(discordChatLog(ns), 0, limit - 1);
53
+ return items
54
+ .map((i) => JSON.parse(i))
55
+ .reverse();
56
+ },
57
+ async notify(ns, payload) {
58
+ const json = JSON.stringify(payload);
59
+ const pl = redis.pipeline();
60
+ pl.publish(discordNotify(ns), json);
61
+ pl.rpush(discordNotify(ns), json);
62
+ pl.lpush(discordNotifyLogKey(ns), json);
63
+ pl.ltrim(discordNotifyLogKey(ns), 0, CAP.NOTIFY_LOG - 1);
64
+ await pl.exec();
65
+ },
66
+ async pollNotify(ns) {
67
+ const val = await redis.rpop(discordNotify(ns));
68
+ return val ? JSON.parse(val) : null;
69
+ },
70
+ async registerChannel(channelId, ns, repoUrl) {
71
+ const pl = redis.pipeline();
72
+ pl.hset(channelHashKey(channelId), { namespace: ns, repoUrl });
73
+ pl.sadd(CHANNELS_SET, channelId);
74
+ await pl.exec();
75
+ },
76
+ async getChannel(channelId) {
77
+ const data = await redis.hgetall(channelHashKey(channelId));
78
+ if (!data || !data["namespace"])
79
+ return null;
80
+ return { namespace: data["namespace"], repoUrl: data["repoUrl"] ?? "" };
81
+ },
82
+ async listChannels() {
83
+ const ids = await redis.smembers(CHANNELS_SET);
84
+ const rows = await Promise.all(ids.map(async (channelId) => {
85
+ const data = await redis.hgetall(channelHashKey(channelId));
86
+ if (!data || !data["namespace"])
87
+ return null;
88
+ return {
89
+ channelId,
90
+ namespace: data["namespace"],
91
+ repoUrl: data["repoUrl"] ?? "",
92
+ };
93
+ }));
94
+ return rows.filter((r) => r !== null);
95
+ },
96
+ },
97
+ // ── tg ───────────────────────────────────────────────────────────────────
98
+ tg: {
99
+ async publishOutgoing(msg) {
100
+ const json = JSON.stringify(msg);
101
+ const pl = redis.pipeline();
102
+ pl.publish(tgChatOutgoing(), json);
103
+ pl.lpush("cca:tg:chat:log", json);
104
+ pl.ltrim("cca:tg:chat:log", 0, CAP.CHAT_LOG - 1);
105
+ await pl.exec();
106
+ },
107
+ subscribeOutgoing(cb) {
108
+ const sub = redis.duplicate();
109
+ sub.subscribe(tgChatOutgoing());
110
+ sub.on("message", (_channel, message) => {
111
+ cb(JSON.parse(message));
112
+ });
113
+ },
114
+ async notify(payload) {
115
+ const json = JSON.stringify(payload);
116
+ const pl = redis.pipeline();
117
+ pl.publish(tgNotify(), json);
118
+ pl.rpush(tgNotify(), json);
119
+ pl.lpush(TG_NOTIFY_LOG, json);
120
+ pl.ltrim(TG_NOTIFY_LOG, 0, CAP.NOTIFY_LOG - 1);
121
+ await pl.exec();
122
+ },
123
+ async pollNotify() {
124
+ const val = await redis.rpop(tgNotify());
125
+ return val ? JSON.parse(val) : null;
126
+ },
127
+ },
128
+ // ── jobs ─────────────────────────────────────────────────────────────────
129
+ jobs: {
130
+ async enqueue(job) {
131
+ const pl = redis.pipeline();
132
+ pl.set(jobKey(job.id), JSON.stringify({ ...job, status: "pending" }), "EX", TTL.JOB_SECONDS);
133
+ pl.lpush(SPAWN_QUEUE, JSON.stringify(job));
134
+ await pl.exec();
135
+ },
136
+ async getStatus(jobId) {
137
+ const val = await redis.get(jobKey(jobId));
138
+ return val ? JSON.parse(val) : null;
139
+ },
140
+ async publishDone(jobId, result) {
141
+ const json = JSON.stringify(result);
142
+ const pl = redis.pipeline();
143
+ pl.publish(jobDoneChannel(jobId), json);
144
+ pl.lpush(jobDoneQueueKey(jobId), json);
145
+ pl.expire(jobDoneQueueKey(jobId), TTL.JOB_SECONDS);
146
+ await pl.exec();
147
+ },
148
+ },
149
+ // ── token ─────────────────────────────────────────────────────────────────
150
+ token: {
151
+ async getMaster() {
152
+ const val = await redis.get(MASTER_TOKEN_KEY);
153
+ if (val === null)
154
+ throw new Error("cc-wire: master token not set");
155
+ return val;
156
+ },
157
+ async setMaster(token) {
158
+ await redis.set(MASTER_TOKEN_KEY, token);
159
+ },
160
+ },
161
+ _redis: redis,
162
+ };
163
+ }
164
+ //# sourceMappingURL=runtime.js.map