cc-claw 0.7.0 → 0.7.1

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 (2) hide show
  1. package/dist/cli.js +52 -18
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -55,7 +55,7 @@ var VERSION;
55
55
  var init_version = __esm({
56
56
  "src/version.ts"() {
57
57
  "use strict";
58
- VERSION = true ? "0.7.0" : (() => {
58
+ VERSION = true ? "0.7.1" : (() => {
59
59
  try {
60
60
  return JSON.parse(readFileSync(join2(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
61
61
  } catch {
@@ -3919,6 +3919,16 @@ var init_loader = __esm({
3919
3919
  });
3920
3920
 
3921
3921
  // src/memory/session-log.ts
3922
+ var session_log_exports = {};
3923
+ __export(session_log_exports, {
3924
+ appendToLog: () => appendToLog,
3925
+ clearLog: () => clearLog,
3926
+ getCachedLog: () => getCachedLog,
3927
+ getLastMessageTimestamp: () => getLastMessageTimestamp,
3928
+ getLog: () => getLog,
3929
+ getLoggedChatIds: () => getLoggedChatIds,
3930
+ getMessagePairCount: () => getMessagePairCount
3931
+ });
3922
3932
  function appendToLog(chatId, userMessage, assistantResponse, backend2, model2, sessionId) {
3923
3933
  const now = Date.now();
3924
3934
  appendMessageLog(chatId, "user", userMessage, backend2 ?? null, model2 ?? null, sessionId ?? null);
@@ -3962,6 +3972,9 @@ function getLastMessageTimestamp(chatId) {
3962
3972
  const last = rows[rows.length - 1];
3963
3973
  return (/* @__PURE__ */ new Date(last.created_at + (last.created_at.includes("Z") ? "" : "Z"))).getTime();
3964
3974
  }
3975
+ function getCachedLog(chatId) {
3976
+ return cache.get(chatId) ?? [];
3977
+ }
3965
3978
  function getLoggedChatIds() {
3966
3979
  return getUnsummarizedChatIds();
3967
3980
  }
@@ -10645,7 +10658,7 @@ async function handleCommand(msg, channel) {
10645
10658
  case "help":
10646
10659
  await channel.sendText(
10647
10660
  chatId,
10648
- "Hey! I'm CC-Claw \u2014 your personal AI assistant on Telegram.\n\nI use AI coding CLIs (Claude, Gemini, Codex) as my brain. Just send me a message to get started.\n\nCommands:\n/backend [name] - Switch AI backend (or /claude /gemini /codex)\n/model - Switch model for active backend\n/gemini slot - Select Gemini credential (account/key)\n/summarizer - Configure session summarization model\n/status - Show session, model, backend, and usage\n/cost - Show estimated API cost (use /cost all for all-time)\n/usage - Show usage per backend with limits\n/limits - Configure usage limits per backend\n/newchat - Start a fresh conversation\n/summarize - Save session to memory (without resetting)\n/summarize all - Summarize all pending sessions (pre-restart)\n/cwd <path> - Set working directory\n/cwd - Show current working directory\n/memory - List stored memories\n/remember <text> - Save a memory\n/forget <keyword> - Remove a memory\n/voice - Toggle voice responses\n/voice_config - Configure voice provider and voice\n/imagine <prompt> - Generate an image (or /image)\n/cron <description> - Schedule a task (or /schedule)\n/cron - List scheduled jobs (or /jobs)\n/cron cancel <id> - Cancel a job\n/cron pause <id> - Pause a job\n/cron resume <id> - Resume a job\n/cron run <id> - Trigger a job now\n/cron runs [id] - View run history\n/cron edit <id> - Edit a job\n/cron health - Scheduler health\n/skills - List skills from all backends\n/skill-install <url> - Install a skill from GitHub\n/setup-profile - Set up your user profile\n/chats - List authorized chats and aliases\n/heartbeat - Proactive awareness (on/off/interval/hours)\n/history - List recent session summaries\n/stop - Cancel the current running task\n/tools - Configure which tools the agent can use\n/permissions - Switch permission mode (yolo/safe/plan)\n/verbose - Tool visibility (off/normal/verbose)\n/model_signature - Toggle model+thinking signature on responses\n/intent <msg> - Test intent classifier (chat vs agentic)\n/agents - List active sub-agents\n/agents mode [auto|native|claw] - Set agent mode (native vs orchestrated)\n/agents history - Native sub-agent activity (24h)\n/tasks - Show task board for current orchestration\n/stopagent <id> - Cancel a specific sub-agent\n/stopall - Cancel all sub-agents in this chat\n/runners - List registered CLI runners\n/mcps - List registered MCP servers\n/help - Show this message",
10661
+ "Hey! I'm CC-Claw \u2014 your personal AI assistant on Telegram.\n\nI use AI coding CLIs (Claude, Gemini, Codex) as my brain. Just send me a message to get started.\n\nCommands:\n/backend [name] - Switch AI backend (or /claude /gemini /codex)\n/model - Switch model for active backend\n/gemini_accounts - Manage Gemini credentials & rotation\n/summarizer - Configure session summarization model\n/status - Show session, model, backend, and usage\n/cost - Show estimated API cost (use /cost all for all-time)\n/usage - Show usage per backend with limits\n/limits - Configure usage limits per backend\n/newchat - Start a fresh conversation\n/summarize - Save session to memory (without resetting)\n/summarize all - Summarize all pending sessions (pre-restart)\n/cwd <path> - Set working directory\n/cwd - Show current working directory\n/memory - List stored memories\n/remember <text> - Save a memory\n/forget <keyword> - Remove a memory\n/voice - Toggle voice responses\n/voice_config - Configure voice provider and voice\n/imagine <prompt> - Generate an image (or /image)\n/cron <description> - Schedule a task (or /schedule)\n/cron - List scheduled jobs (or /jobs)\n/cron cancel <id> - Cancel a job\n/cron pause <id> - Pause a job\n/cron resume <id> - Resume a job\n/cron run <id> - Trigger a job now\n/cron runs [id] - View run history\n/cron edit <id> - Edit a job\n/cron health - Scheduler health\n/skills - List skills from all backends\n/skill-install <url> - Install a skill from GitHub\n/setup-profile - Set up your user profile\n/chats - List authorized chats and aliases\n/heartbeat - Proactive awareness (on/off/interval/hours)\n/history - List recent session summaries\n/stop - Cancel the current running task\n/tools - Configure which tools the agent can use\n/permissions - Switch permission mode (yolo/safe/plan)\n/verbose - Tool visibility (off/normal/verbose)\n/model_signature - Toggle model+thinking signature on responses\n/intent <msg> - Test intent classifier (chat vs agentic)\n/agents - List active sub-agents\n/agents mode [auto|native|claw] - Set agent mode (native vs orchestrated)\n/agents history - Native sub-agent activity (24h)\n/tasks - Show task board for current orchestration\n/stopagent <id> - Cancel a specific sub-agent\n/stopall - Cancel all sub-agents in this chat\n/runners - List registered CLI runners\n/mcps - List registered MCP servers\n/help - Show this message",
10649
10662
  "plain"
10650
10663
  );
10651
10664
  break;
@@ -12648,7 +12661,7 @@ async function doBackendSwitch(chatId, backendId, channel) {
12648
12661
  }
12649
12662
  if (summarized) {
12650
12663
  await channel.sendText(chatId, "\u{1F4BE} Context saved \u2014 session summarized to memory.", "plain");
12651
- } else if (pairCount > 0 && bridge) {
12664
+ } else if (bridge) {
12652
12665
  await channel.sendText(chatId, "\u{1F4AC} Context preserved.", "plain");
12653
12666
  }
12654
12667
  clearSession(chatId);
@@ -14072,22 +14085,16 @@ async function main() {
14072
14085
  initDatabase();
14073
14086
  pruneMessageLog(30, 2e3);
14074
14087
  bootstrapBuiltinMcps(getDb());
14075
- const SUMMARIZE_TIMEOUT_MS2 = 3e4;
14076
- try {
14077
- let timer;
14078
- const timeoutPromise = new Promise((_, reject) => {
14079
- timer = setTimeout(() => reject(new Error("timeout")), SUMMARIZE_TIMEOUT_MS2);
14088
+ let pendingSummarizeNotify = null;
14089
+ const { getLoggedChatIds: getLoggedChatIds2 } = await Promise.resolve().then(() => (init_session_log(), session_log_exports));
14090
+ const pendingCount = getLoggedChatIds2().length;
14091
+ if (pendingCount > 0) {
14092
+ summarizeAllPending().then(() => {
14093
+ log(`[cc-claw] Background summarization complete (${pendingCount} session(s))`);
14094
+ if (pendingSummarizeNotify) pendingSummarizeNotify();
14095
+ }).catch((err) => {
14096
+ log(`[cc-claw] Background summarization failed: ${err}`);
14080
14097
  });
14081
- try {
14082
- await Promise.race([
14083
- summarizeAllPending(),
14084
- timeoutPromise
14085
- ]);
14086
- } finally {
14087
- clearTimeout(timer);
14088
- }
14089
- } catch {
14090
- log("[cc-claw] Session summarization skipped (timeout or backend unavailable)");
14091
14098
  }
14092
14099
  setBootTime();
14093
14100
  log("[cc-claw] Database initialized (sessions preserved for resume)");
@@ -14100,6 +14107,17 @@ async function main() {
14100
14107
  }
14101
14108
  await channelRegistry.startAll(handleMessage);
14102
14109
  log("[cc-claw] Channels started");
14110
+ if (pendingCount > 0) {
14111
+ const primaryChatId = (process.env.ALLOWED_CHAT_ID ?? "").split(",")[0]?.trim();
14112
+ pendingSummarizeNotify = () => {
14113
+ if (primaryChatId) {
14114
+ for (const ch of channelRegistry.list()) {
14115
+ ch.sendText(primaryChatId, "\u{1F504} Restarted \u2014 your conversations were summarized and saved.", "plain").catch(() => {
14116
+ });
14117
+ }
14118
+ }
14119
+ };
14120
+ }
14103
14121
  const telegramChannel = channelRegistry.get("telegram");
14104
14122
  if (telegramChannel && typeof telegramChannel.onCallback === "function") {
14105
14123
  telegramChannel.onCallback(handleCallback);
@@ -15266,6 +15284,22 @@ async function geminiAddKey(globalOpts, opts) {
15266
15284
  outputError("EMPTY_KEY", "No key provided.");
15267
15285
  process.exit(1);
15268
15286
  }
15287
+ console.log(" Validating API key...");
15288
+ try {
15289
+ const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models?key=${encodeURIComponent(key.trim())}`);
15290
+ if (!res.ok) {
15291
+ const body = await res.text().catch(() => "");
15292
+ if (res.status === 400 || res.status === 403) {
15293
+ outputError("INVALID_KEY", `API key is invalid or unauthorized (HTTP ${res.status}).`);
15294
+ process.exit(1);
15295
+ }
15296
+ console.log(warning(` Warning: validation returned HTTP ${res.status} \u2014 saving anyway. ${body.slice(0, 100)}`));
15297
+ } else {
15298
+ console.log(success(" \u2713 API key is valid."));
15299
+ }
15300
+ } catch (err) {
15301
+ console.log(warning(` Warning: could not validate key (network error) \u2014 saving anyway.`));
15302
+ }
15269
15303
  const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store4(), store_exports3));
15270
15304
  const id = addGeminiSlot2({
15271
15305
  slotType: "api_key",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-claw",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "CC-Claw: Personal AI assistant on Telegram — multi-backend (Claude, Gemini, Codex), sub-agent orchestration, MCP management",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",