cc-claw 0.20.8 → 0.20.10

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 +68 -28
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -33,7 +33,7 @@ var VERSION;
33
33
  var init_version = __esm({
34
34
  "src/version.ts"() {
35
35
  "use strict";
36
- VERSION = true ? "0.20.8" : (() => {
36
+ VERSION = true ? "0.20.10" : (() => {
37
37
  try {
38
38
  return JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
39
39
  } catch {
@@ -19089,27 +19089,26 @@ async function sendHeartbeatKeyboard(chatId, channel, messageId) {
19089
19089
  const lastBeat = config2?.lastBeatAt ?? "never";
19090
19090
  lines.push(`Last beat: ${lastBeat}`);
19091
19091
  const buttons = [];
19092
- const toggleRow = [
19092
+ buttons.push([
19093
19093
  { label: `${enabled ? "\u2713 " : ""}On`, data: "hb:on", ...enabled ? { style: "success" } : {} },
19094
19094
  { label: `${!enabled ? "\u2713 " : ""}Off`, data: "hb:off", ...!enabled ? { style: "danger" } : {} },
19095
19095
  { label: "\u25B6 Run Now", data: "hb:run", style: "primary" }
19096
- ];
19097
- buttons.push(toggleRow);
19096
+ ]);
19098
19097
  const presets = [15, 30, 60, 120];
19099
- const intervalRow = presets.map((m) => ({
19098
+ buttons.push(presets.map((m) => ({
19100
19099
  label: `${m === intervalMin ? "\u2713 " : ""}${m} min`,
19101
19100
  data: `hb:interval:${m}`,
19102
19101
  ...m === intervalMin ? { style: "primary" } : {}
19103
- }));
19104
- buttons.push(intervalRow);
19102
+ })));
19105
19103
  const available = getAvailableBackendIds();
19104
+ buttons.push([{ label: "\u2699\uFE0F Main Engine", data: "hb:noop" }]);
19106
19105
  const backendRow = available.map((bid) => ({
19107
19106
  label: `${config2?.backend === bid ? "\u2713 " : ""}${capitalize(bid)}`,
19108
19107
  data: `hb:backend:${bid}`,
19109
19108
  ...config2?.backend === bid ? { style: "primary" } : {}
19110
19109
  }));
19111
19110
  if (config2?.backend) {
19112
- backendRow.push({ label: "Reset", data: "hb:backend:default" });
19111
+ backendRow.push({ label: "\u2715", data: "hb:backend:default", style: "danger" });
19113
19112
  }
19114
19113
  buttons.push(backendRow);
19115
19114
  const targetBackend = config2?.backend ?? getBackend(chatId) ?? "claude";
@@ -19117,42 +19116,47 @@ async function sendHeartbeatKeyboard(chatId, channel, messageId) {
19117
19116
  const adapter = getAdapter(targetBackend);
19118
19117
  const models = Object.entries(adapter.availableModels);
19119
19118
  if (models.length > 0) {
19120
- const modelRow = models.slice(0, 4).map(([key, info]) => ({
19121
- label: `${config2?.model === key ? "\u2713 " : ""}${info.label}`,
19119
+ const modelRow = models.slice(0, 4).map(([key]) => ({
19120
+ label: `${config2?.model === key ? "\u2713 " : ""}${shortModelName(key)}`,
19122
19121
  data: `hb:model:${key}`,
19123
19122
  ...config2?.model === key ? { style: "primary" } : {}
19124
19123
  }));
19125
19124
  if (config2?.model) {
19126
- modelRow.push({ label: "Reset", data: "hb:model:default" });
19125
+ modelRow.push({ label: "\u2715", data: "hb:model:default", style: "danger" });
19127
19126
  }
19128
19127
  buttons.push(modelRow);
19129
19128
  }
19130
19129
  } catch {
19131
19130
  }
19131
+ const fbCandidates = available.filter((bid) => !fallbacks.some((f) => f.backend === bid) && bid !== config2?.backend);
19132
+ if (fallbacks.length > 0 || fbCandidates.length > 0) {
19133
+ buttons.push([{ label: "\u{1F504} Fallback Chain", data: "hb:noop" }]);
19134
+ }
19132
19135
  if (fallbacks.length > 0) {
19133
- const fbRow = [
19134
- { label: `\u{1F504} Fallbacks: ${fallbacks.map((f) => capitalize(f.backend)).join(" \u2192 ")}`, data: "hb:noop" },
19135
- { label: "Clear", data: "hb:fb:clear", style: "danger" }
19136
- ];
19137
- buttons.push(fbRow);
19136
+ buttons.push([
19137
+ { label: fallbacks.map((f) => {
19138
+ const name = capitalize(f.backend);
19139
+ return f.model ? `${name} (${shortModelName(f.model)})` : name;
19140
+ }).join(" \u2192 "), data: "hb:noop" },
19141
+ { label: "Clear All", data: "hb:fb:clear", style: "danger" }
19142
+ ]);
19138
19143
  }
19139
- const fbAddRow = available.filter((bid) => !fallbacks.some((f) => f.backend === bid) && bid !== config2?.backend).slice(0, 4).map((bid) => ({
19140
- label: `+ ${capitalize(bid)}`,
19141
- data: `hb:fb:add:${bid}`
19142
- }));
19143
- if (fbAddRow.length > 0) {
19144
- buttons.push(fbAddRow);
19144
+ if (fbCandidates.length > 0) {
19145
+ buttons.push(fbCandidates.slice(0, 4).map((bid) => ({
19146
+ label: `+ ${capitalize(bid)}`,
19147
+ data: `hb:fb:add:${bid}`
19148
+ })));
19145
19149
  }
19146
- const configRow = [
19150
+ const optionsRow = [
19147
19151
  { label: `\u{1F4AD} Thinking: ${thinkingDisplay}`, data: "hb:thinking" }
19148
19152
  ];
19149
19153
  if (watches.length > 0) {
19150
- configRow.push({ label: `\u{1F441} Watches (${watches.length})`, data: "hb:watches" });
19154
+ optionsRow.push({ label: `\u{1F441} Watches (${watches.length})`, data: "hb:watches" });
19151
19155
  } else {
19152
- configRow.push({ label: "+ Add Watch", data: "hb:addwatch" });
19156
+ optionsRow.push({ label: "+ Add Watch", data: "hb:addwatch" });
19153
19157
  }
19154
- buttons.push(configRow);
19155
- buttons.push([{ label: `Active Hours: ${activeStart}-${activeEnd} (use /heartbeat hours)`, data: "hb:noop" }]);
19158
+ buttons.push(optionsRow);
19159
+ buttons.push([{ label: `\u23F0 ${activeStart}\u2013${activeEnd} (use /heartbeat hours)`, data: "hb:noop" }]);
19156
19160
  await sendOrEditKeyboard(chatId, channel, messageId, lines.join("\n"), buttons);
19157
19161
  }
19158
19162
  async function sendForgetPicker(chatId, channel, page, messageId) {
@@ -24326,13 +24330,49 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
24326
24330
  await channel.sendText(chatId, "Use /watch to manage awareness tasks.\n\nExamples:\n /watch add Check my email for urgent messages\n /watch add Check if Ollama is running\n /watch list\n /watch remove 1", { parseMode: "plain" });
24327
24331
  } else if (rest.startsWith("fb:add:")) {
24328
24332
  const bid = rest.slice(7);
24333
+ try {
24334
+ const adapter = getAdapter(bid);
24335
+ const models = Object.entries(adapter.availableModels);
24336
+ const rows = [
24337
+ [{ label: `Select model for ${capitalize(bid)} fallback:`, data: "hb:noop" }],
24338
+ [{ label: "Default", data: `hb:fb:pick:${bid}:default`, style: "primary" }]
24339
+ ];
24340
+ if (models.length > 0) {
24341
+ rows.push(models.slice(0, 4).map(([key]) => ({
24342
+ label: shortModelName(key),
24343
+ data: `hb:fb:pick:${bid}:${key}`
24344
+ })));
24345
+ }
24346
+ rows.push([{ label: "\u2190 Back", data: "hb:fb:back" }]);
24347
+ await sendOrEditKeyboard(
24348
+ chatId,
24349
+ channel,
24350
+ messageId,
24351
+ `Pick a model for the ${capitalize(bid)} fallback:`,
24352
+ rows
24353
+ );
24354
+ } catch {
24355
+ const config2 = getHeartbeatConfig(chatId);
24356
+ const current = parseHeartbeatFallbacks(config2?.fallbacks ?? null);
24357
+ if (!current.some((f) => f.backend === bid)) {
24358
+ current.push({ backend: bid });
24359
+ updateHeartbeatField(chatId, "fallbacks", JSON.stringify(current));
24360
+ }
24361
+ await sendHeartbeatKeyboard(chatId, channel, messageId);
24362
+ }
24363
+ } else if (rest.startsWith("fb:pick:")) {
24364
+ const parts = rest.slice(8).split(":");
24365
+ const bid = parts[0];
24366
+ const model2 = parts.slice(1).join(":");
24329
24367
  const config2 = getHeartbeatConfig(chatId);
24330
24368
  const current = parseHeartbeatFallbacks(config2?.fallbacks ?? null);
24331
24369
  if (!current.some((f) => f.backend === bid)) {
24332
- current.push({ backend: bid });
24370
+ current.push(model2 === "default" ? { backend: bid } : { backend: bid, model: model2 });
24333
24371
  updateHeartbeatField(chatId, "fallbacks", JSON.stringify(current));
24334
24372
  }
24335
24373
  await sendHeartbeatKeyboard(chatId, channel, messageId);
24374
+ } else if (rest === "fb:back") {
24375
+ await sendHeartbeatKeyboard(chatId, channel, messageId);
24336
24376
  } else if (rest === "fb:clear") {
24337
24377
  updateHeartbeatField(chatId, "fallbacks", null);
24338
24378
  await sendHeartbeatKeyboard(chatId, channel, messageId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-claw",
3
- "version": "0.20.8",
3
+ "version": "0.20.10",
4
4
  "description": "CC-Claw: Personal AI assistant on Telegram — multi-backend (Claude, Gemini, Codex, Cursor), sub-agent orchestration, MCP management",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",