cc-claw 0.20.15 → 0.20.16

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 +148 -10
  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.15" : (() => {
36
+ VERSION = true ? "0.20.16" : (() => {
37
37
  try {
38
38
  return JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
39
39
  } catch {
@@ -4150,6 +4150,11 @@ var init_store5 = __esm({
4150
4150
  });
4151
4151
 
4152
4152
  // src/backends/types.ts
4153
+ var types_exports = {};
4154
+ __export(types_exports, {
4155
+ BACKEND: () => BACKEND,
4156
+ isBackendId: () => isBackendId
4157
+ });
4153
4158
  function isBackendId(value) {
4154
4159
  return Object.values(BACKEND).includes(value);
4155
4160
  }
@@ -16087,6 +16092,17 @@ var init_types3 = __esm({
16087
16092
  });
16088
16093
 
16089
16094
  // src/scheduler/wizard.ts
16095
+ var wizard_exports = {};
16096
+ __export(wizard_exports, {
16097
+ cancelWizard: () => cancelWizard,
16098
+ getPendingJob: () => getPendingJob,
16099
+ handleWizardCallback: () => handleWizardCallback,
16100
+ handleWizardText: () => handleWizardText,
16101
+ hasPendingWizard: () => hasPendingWizard,
16102
+ resolveSlotLabel: () => resolveSlotLabel,
16103
+ startEditWizard: () => startEditWizard,
16104
+ startWizard: () => startWizard
16105
+ });
16090
16106
  function hasPendingWizard(chatId) {
16091
16107
  return pendingJobs.has(chatId);
16092
16108
  }
@@ -16107,6 +16123,9 @@ function resetWizardTimeout(chatId) {
16107
16123
  log(`[wizard] Auto-cancelled stale wizard for chat ${chatId}`);
16108
16124
  }, WIZARD_TIMEOUT_MS));
16109
16125
  }
16126
+ function getPendingJob(chatId) {
16127
+ return pendingJobs.get(chatId);
16128
+ }
16110
16129
  function parseNaturalLanguage(input) {
16111
16130
  const lower = input.toLowerCase();
16112
16131
  const minMatch = lower.match(/every\s+(\d+)\s+min/);
@@ -20100,6 +20119,7 @@ async function sendJobDetail(chatId, jobId, channel, messageId) {
20100
20119
  }
20101
20120
  actionRow1.push({ label: "Edit", data: `job:edit:${job.id}` });
20102
20121
  const actionRow2 = [
20122
+ { label: "\u{1F9EA} Test Model", data: `job:test:${job.id}` },
20103
20123
  { label: "View Runs", data: `job:runs:${job.id}`, style: "primary" }
20104
20124
  ];
20105
20125
  if (job.active) {
@@ -22159,8 +22179,8 @@ var init_types4 = __esm({
22159
22179
  });
22160
22180
 
22161
22181
  // src/council/wizard.ts
22162
- var wizard_exports = {};
22163
- __export(wizard_exports, {
22182
+ var wizard_exports2 = {};
22183
+ __export(wizard_exports2, {
22164
22184
  buildSelectKeyboard: () => buildSelectKeyboard,
22165
22185
  cancelCouncil: () => cancelCouncil,
22166
22186
  getCouncilState: () => getCouncilState,
@@ -24003,7 +24023,7 @@ async function handleCouncilCommand(chatId, commandArgs, msg, channel) {
24003
24023
  await channel.sendText(chatId, "Council requires DASHBOARD_ENABLED=1 (uses the agent orchestrator).", { parseMode: "plain" });
24004
24024
  return;
24005
24025
  }
24006
- const { startCouncilWizard: startCouncilWizard2, buildSelectKeyboard: buildSelectKeyboard2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
24026
+ const { startCouncilWizard: startCouncilWizard2, buildSelectKeyboard: buildSelectKeyboard2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports2));
24007
24027
  startCouncilWizard2(chatId);
24008
24028
  if (typeof channel.sendKeyboard === "function") {
24009
24029
  const { text, buttons } = buildSelectKeyboard2(chatId);
@@ -24604,12 +24624,99 @@ ${plan.originalMessage}`;
24604
24624
  } else if (data.startsWith("sched:")) {
24605
24625
  await handleWizardCallback(chatId, data, channel);
24606
24626
  } else if (data.startsWith("job:")) {
24627
+ async function showJobAccountPicker(cid, jobId, backend2, model2, thinking2, ch) {
24628
+ const isGemini = backend2 === "gemini";
24629
+ const slots = isGemini ? getGeminiSlots() : getBackendSlots(backend2);
24630
+ const enabledSlots = slots.filter((s) => s.enabled);
24631
+ if (enabledSlots.length === 0 || typeof ch.sendKeyboard !== "function") {
24632
+ const { updateJob: updateJobFields } = await Promise.resolve().then(() => (init_store5(), store_exports5));
24633
+ updateJobFields(jobId, { backend: backend2, model: model2, thinking: thinking2, credentialSlotId: null });
24634
+ const { getAdapter: getAdapter4 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
24635
+ const adapter = getAdapter4(backend2);
24636
+ await ch.sendText(cid, `Job #${jobId} updated: ${adapter.displayName} / ${model2} / ${thinking2}`, { parseMode: "plain" });
24637
+ await sendJobDetail(cid, jobId, ch);
24638
+ return;
24639
+ }
24640
+ const rows = [
24641
+ [{ label: "\u{1F504} Auto (rotate)", data: `job:setaccount:${jobId}:${backend2}:${model2}:${thinking2}:auto` }]
24642
+ ];
24643
+ for (const slot of enabledSlots) {
24644
+ const s = slot;
24645
+ const icon = s.slotType === "api_key" ? "\u{1F511}" : "\u{1F4E7}";
24646
+ const label2 = s.label || s.email || `Slot #${s.id}`;
24647
+ const type = s.slotType === "api_key" ? "API key" : "OAuth";
24648
+ rows.push([{ label: `${icon} ${label2} (${type})`, data: `job:setaccount:${jobId}:${backend2}:${model2}:${thinking2}:${s.id}` }]);
24649
+ }
24650
+ rows.push([{ label: "\u2190 Back", data: `job:editbackend:${jobId}` }]);
24651
+ await ch.sendKeyboard(cid, `Which account for Job #${jobId}?`, rows);
24652
+ }
24607
24653
  const rest = data.slice(4);
24608
24654
  if (rest === "back") {
24609
24655
  await sendJobsBoard(chatId, channel, 1);
24610
24656
  } else if (rest.startsWith("view:")) {
24611
24657
  const id = parseInt(rest.slice(5), 10);
24612
24658
  await sendJobDetail(chatId, id, channel, messageId);
24659
+ } else if (rest.startsWith("test:")) {
24660
+ const id = parseInt(rest.slice(5), 10);
24661
+ const { getJobById: getJob } = await Promise.resolve().then(() => (init_store5(), store_exports5));
24662
+ const testJob = getJob(id);
24663
+ if (!testJob) {
24664
+ await channel.sendText(chatId, `Job #${id} not found.`, { parseMode: "plain" });
24665
+ } else {
24666
+ await channel.sendText(chatId, `\u{1F9EA} Testing model: ${testJob.backend ?? "default"}/${testJob.model ?? "default"}...`, { parseMode: "plain" });
24667
+ try {
24668
+ const { askAgent: askAgent3 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
24669
+ const { BACKEND: BACKEND2 } = await Promise.resolve().then(() => (init_types(), types_exports));
24670
+ const { pinChatGeminiSlot: pinChatGeminiSlot4, pinChatBackendSlot: pinChatBackendSlot3 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
24671
+ const testChatId = `cron:test:${id}:${Date.now()}`;
24672
+ const backend2 = testJob.backend ?? "claude";
24673
+ if (testJob.credentialSlotId) {
24674
+ if (backend2 === BACKEND2.GEMINI) {
24675
+ pinChatGeminiSlot4(testChatId, testJob.credentialSlotId);
24676
+ } else {
24677
+ pinChatBackendSlot3(testChatId, backend2, testJob.credentialSlotId);
24678
+ }
24679
+ }
24680
+ const t0 = Date.now();
24681
+ const resp = await askAgent3(testChatId, 'Reply with exactly: "pong"', {
24682
+ backend: backend2,
24683
+ model: testJob.model ?? void 0,
24684
+ bootstrapTier: "chat",
24685
+ maxTurns: 1,
24686
+ timeoutMs: 3e4,
24687
+ permMode: "yolo"
24688
+ });
24689
+ const elapsed = ((Date.now() - t0) / 1e3).toFixed(1);
24690
+ const got = resp.text?.trim().slice(0, 100) || "(empty)";
24691
+ const { resolveSlotLabel: resolveSlotLabel2 } = await Promise.resolve().then(() => (init_wizard(), wizard_exports));
24692
+ const acct = resolveSlotLabel2(backend2, testJob.credentialSlotId);
24693
+ if (typeof channel.sendKeyboard === "function") {
24694
+ await channel.sendKeyboard(
24695
+ chatId,
24696
+ `\u2705 Model test passed (${elapsed}s)
24697
+
24698
+ Backend: ${backend2}
24699
+ Model: ${testJob.model ?? "default"}
24700
+ Account: ${acct}
24701
+ Response: "${got}"`,
24702
+ [[{ label: "\u2190 Back to Job", data: `job:view:${id}` }]]
24703
+ );
24704
+ }
24705
+ } catch (err) {
24706
+ const msg = err instanceof Error ? err.message : String(err);
24707
+ if (typeof channel.sendKeyboard === "function") {
24708
+ await channel.sendKeyboard(
24709
+ chatId,
24710
+ `\u274C Model test failed
24711
+
24712
+ ${msg.slice(0, 500)}`,
24713
+ [[{ label: "\u2190 Back to Job", data: `job:view:${id}` }]]
24714
+ );
24715
+ } else {
24716
+ await channel.sendText(chatId, `\u274C Model test failed: ${msg.slice(0, 300)}`, { parseMode: "plain" });
24717
+ }
24718
+ }
24719
+ }
24613
24720
  } else if (rest.startsWith("run:")) {
24614
24721
  const id = parseInt(rest.slice(4), 10);
24615
24722
  await channel.sendText(chatId, `Triggering job #${id}...`, { parseMode: "plain" });
@@ -24748,11 +24855,42 @@ What do you want to change?`,
24748
24855
  const id = parseInt(parts[0], 10);
24749
24856
  const backend2 = parts[1];
24750
24857
  const model2 = parts.slice(2).join(":");
24858
+ const { getAdapter: getAdapter4 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
24859
+ const adapter = getAdapter4(backend2);
24860
+ const modelInfo = adapter.availableModels[model2];
24861
+ if (modelInfo?.thinking === "adjustable" && modelInfo.thinkingLevels && typeof channel.sendKeyboard === "function") {
24862
+ const rows = modelInfo.thinkingLevels.map((level) => [{
24863
+ label: level === "auto" ? "Auto (default)" : level.replace("_", " ").replace(/\b\w/g, (c) => c.toUpperCase()),
24864
+ data: `job:setthinking:${id}:${backend2}:${model2}:${level}`
24865
+ }]);
24866
+ rows.push([{ label: "\u2190 Back", data: `job:setbackend:${id}:${backend2}` }]);
24867
+ await channel.sendKeyboard(chatId, `Thinking level for Job #${id}?`, rows);
24868
+ } else {
24869
+ await showJobAccountPicker(chatId, id, backend2, model2, "auto", channel);
24870
+ }
24871
+ } else if (rest.startsWith("setthinking:")) {
24872
+ const parts = rest.slice(12).split(":");
24873
+ const id = parseInt(parts[0], 10);
24874
+ const backend2 = parts[1];
24875
+ const model2 = parts[2];
24876
+ const thinking2 = parts[3] ?? "auto";
24877
+ await showJobAccountPicker(chatId, id, backend2, model2, thinking2, channel);
24878
+ } else if (rest.startsWith("setaccount:")) {
24879
+ const parts = rest.slice(11).split(":");
24880
+ const id = parseInt(parts[0], 10);
24881
+ const backend2 = parts[1];
24882
+ const model2 = parts[2];
24883
+ const thinking2 = parts[3];
24884
+ const slotVal = parts[4];
24885
+ const credentialSlotId = slotVal === "auto" ? null : parseInt(slotVal, 10);
24751
24886
  const { updateJob: updateJobFields } = await Promise.resolve().then(() => (init_store5(), store_exports5));
24752
- updateJobFields(id, { backend: backend2, model: model2 });
24887
+ updateJobFields(id, { backend: backend2, model: model2, thinking: thinking2, credentialSlotId });
24753
24888
  const { getAdapter: getAdapter4 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
24754
24889
  const adapter = getAdapter4(backend2);
24755
- await channel.sendText(chatId, `Job #${id} updated: ${adapter.displayName} / ${model2}`, { parseMode: "plain" });
24890
+ const { resolveSlotLabel: resolveSlotLabel2 } = await Promise.resolve().then(() => (init_wizard(), wizard_exports));
24891
+ const accountLabel = resolveSlotLabel2(backend2, credentialSlotId);
24892
+ await channel.sendText(chatId, `Job #${id} updated: ${adapter.displayName} / ${model2} / ${thinking2}
24893
+ Account: ${accountLabel}`, { parseMode: "plain" });
24756
24894
  await sendJobDetail(chatId, id, channel);
24757
24895
  } else if (rest.startsWith("edittimeout:")) {
24758
24896
  const id = parseInt(rest.slice(12), 10);
@@ -25089,7 +25227,7 @@ ${rotationNote}`, { parseMode: "html" });
25089
25227
  const { getAdapter: getAdapter4 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
25090
25228
  const toggleAdapter = getAdapter4(backend2);
25091
25229
  const label2 = toggleAdapter.availableModels[model2]?.label ?? model2;
25092
- const { toggleParticipant: toggleParticipant2, buildSelectKeyboard: buildSelectKeyboard2, hasPendingCouncil: hasPendingCouncil2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
25230
+ const { toggleParticipant: toggleParticipant2, buildSelectKeyboard: buildSelectKeyboard2, hasPendingCouncil: hasPendingCouncil2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports2));
25093
25231
  if (!hasPendingCouncil2(chatId)) {
25094
25232
  await channel.sendText(chatId, "No council wizard active. Use /council to start.", { parseMode: "plain" });
25095
25233
  return;
@@ -25102,7 +25240,7 @@ ${rotationNote}`, { parseMode: "html" });
25102
25240
  return;
25103
25241
  }
25104
25242
  if (action === "start") {
25105
- const { getCouncilState: getCouncilState2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
25243
+ const { getCouncilState: getCouncilState2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports2));
25106
25244
  const state = getCouncilState2(chatId);
25107
25245
  if (!state || state.selected.size < 2) {
25108
25246
  await channel.sendText(chatId, "Select at least 2 models first.", { parseMode: "plain" });
@@ -25116,7 +25254,7 @@ Now type the question you want them to debate.`, { parseMode: "plain" });
25116
25254
  return;
25117
25255
  }
25118
25256
  if (action === "cancel") {
25119
- const { cancelCouncil: cancelCouncil2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
25257
+ const { cancelCouncil: cancelCouncil2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports2));
25120
25258
  cancelCouncil2(chatId);
25121
25259
  await channel.sendText(chatId, "Council cancelled.", { parseMode: "plain" });
25122
25260
  return;
@@ -26282,7 +26420,7 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
26282
26420
  }
26283
26421
  }
26284
26422
  {
26285
- const { hasPendingCouncil: hasPendingCouncil2, getCouncilState: getCouncilState2, setCouncilQuestion: setCouncilQuestion2, cancelCouncil: cancelCouncil2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
26423
+ const { hasPendingCouncil: hasPendingCouncil2, getCouncilState: getCouncilState2, setCouncilQuestion: setCouncilQuestion2, cancelCouncil: cancelCouncil2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports2));
26286
26424
  if (hasPendingCouncil2(chatId)) {
26287
26425
  const state = getCouncilState2(chatId);
26288
26426
  if (state?.step === "question") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-claw",
3
- "version": "0.20.15",
3
+ "version": "0.20.16",
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",