@gonzih/cc-discord 0.1.1 → 0.1.3

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/bot.js CHANGED
@@ -13,8 +13,7 @@ import { formatForDiscord, splitLongMessage, stripAnsi } from "./formatter.js";
13
13
  import { getCurrentToken } from "./tokens.js";
14
14
  import { writeChatLog } from "./notifier.js";
15
15
  import { CronManager } from "./cron.js";
16
- import { parseRoutingTag, parseChannelCreateIntent, ensureMetaAgent, routeToMetaAgent } from "./router.js";
17
- import { metaAgentStatusKey } from "@gonzih/cc-wire";
16
+ import { parseChannelCreateIntent, ensureMetaAgent, routeToMetaAgent } from "./router.js";
18
17
  /** Convert a Discord snowflake string to a safe 53-bit integer for CronManager compatibility. */
19
18
  function snowflakeToInt(id) {
20
19
  // Discord snowflakes are up to 2^63, beyond Number.MAX_SAFE_INTEGER.
@@ -278,55 +277,6 @@ export class CcDiscordBot {
278
277
  }
279
278
  return;
280
279
  }
281
- // #tag / #org/repo routing — delegate to meta-agent
282
- if (this.redis) {
283
- const routing = parseRoutingTag(text);
284
- if (routing) {
285
- const channel = msg.channel;
286
- await channel.send(`→ #${routing.namespace}`).catch(() => { });
287
- this.writeChatMessage("user", "discord", text, effectiveChannelId);
288
- this.opts.registerRoutedChannelId?.(routing.namespace, effectiveChannelId);
289
- try {
290
- await ensureMetaAgent(routing.namespace, routing.repoUrl, (toolName, args) => this.callCcAgentTool(toolName, args ?? {}), this.redis);
291
- await routeToMetaAgent(routing.namespace, routing.strippedMessage, this.redis);
292
- }
293
- catch (err) {
294
- await channel.send(`Failed to route to #${routing.namespace}: ${err.message}`).catch(() => { });
295
- }
296
- return;
297
- }
298
- }
299
- // Channel name → meta-agent namespace routing
300
- if (this.redis) {
301
- const channelName = msg.channel.name ?? "";
302
- if (channelName && channelName !== "general") {
303
- // Check if a meta-agent is running for this channel name as namespace
304
- const ns = channelName.toLowerCase().replace(/[^a-z0-9-]/g, "-");
305
- try {
306
- const statusRaw = await this.redis.get(metaAgentStatusKey(ns));
307
- if (statusRaw) {
308
- const status = JSON.parse(statusRaw);
309
- if (status.status === "running" || status.status === "idle") {
310
- // Route to meta-agent
311
- const channel = msg.channel;
312
- await channel.send(`→ #${ns} (meta-agent)`).catch(() => { });
313
- this.writeChatMessage("user", "discord", text, effectiveChannelId);
314
- this.opts.registerRoutedChannelId?.(ns, effectiveChannelId);
315
- try {
316
- await routeToMetaAgent(ns, text, this.redis);
317
- }
318
- catch (err) {
319
- await channel.send(`Failed to route to #${ns}: ${err.message}`).catch(() => { });
320
- }
321
- return;
322
- }
323
- }
324
- }
325
- catch {
326
- // Redis error — fall through to local session
327
- }
328
- }
329
- }
330
280
  // Local Claude session
331
281
  const session = this.getOrCreateSession(effectiveChannelId, msg.channel);
332
282
  try {
package/dist/router.d.ts CHANGED
@@ -1,34 +1,9 @@
1
1
  /**
2
- * Routing helpers: hashtag meta-agent routing and channel-creation intent detection.
3
- *
4
- * Parses #tag or #org/repo tokens from Telegram messages and routes them to
5
- * the appropriate cc-agent meta-agent instead of the local Claude session.
6
- *
7
- * Tag formats:
8
- * #repo-name → namespace=repo-name, repo=https://github.com/{DEFAULT_GITHUB_ORG}/repo-name (null if DEFAULT_GITHUB_ORG unset)
9
- * #org/repo → namespace=repo, repo=https://github.com/org/repo
2
+ * Routing helpers: channel-creation intent detection and meta-agent routing.
10
3
  */
11
4
  import { Redis } from "ioredis";
12
- /** Callback type matching CcTgBot.callCcAgentTool */
5
+ /** Callback type matching CcDiscordBot.callCcAgentTool */
13
6
  export type CallToolFn = (toolName: string, args?: Record<string, unknown>) => Promise<string | null>;
14
- export interface RoutingTag {
15
- namespace: string;
16
- repoUrl: string;
17
- /** Original message with the tag token stripped and whitespace collapsed */
18
- strippedMessage: string;
19
- }
20
- /**
21
- * Parse the first #tag or #org/repo token from a message.
22
- * Returns null when no routing tag is present, or when the short #repo format is used
23
- * without DEFAULT_GITHUB_ORG being set (operators must configure this explicitly).
24
- *
25
- * Examples:
26
- * "#cc-agent fix the bug" → null if DEFAULT_GITHUB_ORG unset; { namespace: "cc-agent", repoUrl: "…/{org}/cc-agent", … } if set
27
- * "#gonzih/of-stack deploy it" → { namespace: "of-stack", repoUrl: "…/gonzih/of-stack", … }
28
- * "#org/repo do something" → { namespace: "repo", repoUrl: "…/org/repo", … }
29
- * "please help #of-stack with this" → null if DEFAULT_GITHUB_ORG unset
30
- */
31
- export declare function parseRoutingTag(text: string): RoutingTag | null;
32
7
  /**
33
8
  * Ensure a meta-agent for the given namespace is running.
34
9
  *
package/dist/router.js CHANGED
@@ -1,53 +1,8 @@
1
1
  /**
2
- * Routing helpers: hashtag meta-agent routing and channel-creation intent detection.
3
- *
4
- * Parses #tag or #org/repo tokens from Telegram messages and routes them to
5
- * the appropriate cc-agent meta-agent instead of the local Claude session.
6
- *
7
- * Tag formats:
8
- * #repo-name → namespace=repo-name, repo=https://github.com/{DEFAULT_GITHUB_ORG}/repo-name (null if DEFAULT_GITHUB_ORG unset)
9
- * #org/repo → namespace=repo, repo=https://github.com/org/repo
2
+ * Routing helpers: channel-creation intent detection and meta-agent routing.
10
3
  */
11
4
  import { execSync } from "child_process";
12
5
  import { metaAgentStatusKey, metaKey, metaInputKey } from "@gonzih/cc-wire";
13
- /**
14
- * Parse the first #tag or #org/repo token from a message.
15
- * Returns null when no routing tag is present, or when the short #repo format is used
16
- * without DEFAULT_GITHUB_ORG being set (operators must configure this explicitly).
17
- *
18
- * Examples:
19
- * "#cc-agent fix the bug" → null if DEFAULT_GITHUB_ORG unset; { namespace: "cc-agent", repoUrl: "…/{org}/cc-agent", … } if set
20
- * "#gonzih/of-stack deploy it" → { namespace: "of-stack", repoUrl: "…/gonzih/of-stack", … }
21
- * "#org/repo do something" → { namespace: "repo", repoUrl: "…/org/repo", … }
22
- * "please help #of-stack with this" → null if DEFAULT_GITHUB_ORG unset
23
- */
24
- export function parseRoutingTag(text) {
25
- const defaultOrg = process.env.DEFAULT_GITHUB_ORG;
26
- // Match #word or #org/repo — each segment: starts with alphanumeric, allows ._- inside
27
- const match = text.match(/#([a-zA-Z0-9][a-zA-Z0-9._-]*)(?:\/([a-zA-Z0-9][a-zA-Z0-9._-]*))?/);
28
- if (!match)
29
- return null;
30
- const fullMatch = match[0]; // e.g. "#gonzih/of-stack"
31
- const part1 = match[1]; // org-or-repo
32
- const part2 = match[2]; // repo (only present in #org/repo format)
33
- let namespace;
34
- let repoUrl;
35
- if (part2) {
36
- // #org/repo format
37
- namespace = part2;
38
- repoUrl = `https://github.com/${part1}/${part2}`;
39
- }
40
- else {
41
- // #repo format — requires DEFAULT_GITHUB_ORG; return null if unset
42
- if (!defaultOrg)
43
- return null;
44
- namespace = part1;
45
- repoUrl = `https://github.com/${defaultOrg}/${part1}`;
46
- }
47
- // Strip the matched tag token and collapse whitespace
48
- const strippedMessage = text.replace(fullMatch, "").replace(/\s+/g, " ").trim();
49
- return { namespace, repoUrl, strippedMessage };
50
- }
51
6
  /**
52
7
  * Ensure a meta-agent for the given namespace is running.
53
8
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gonzih/cc-discord",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Claude Code Discord bot — chat with Claude Code via Discord",
5
5
  "type": "module",
6
6
  "bin": {