cc-claw 0.19.3 → 0.20.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.
- package/dist/cli.js +1156 -92
- 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.
|
|
36
|
+
VERSION = true ? "0.20.0" : (() => {
|
|
37
37
|
try {
|
|
38
38
|
return JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
39
39
|
} catch {
|
|
@@ -3677,6 +3677,9 @@ function setGeminiSlotEnabled(id, enabled) {
|
|
|
3677
3677
|
function reorderGeminiSlot(id, priority) {
|
|
3678
3678
|
getDb().prepare("UPDATE gemini_credentials SET priority = ? WHERE id = ?").run(priority, id);
|
|
3679
3679
|
}
|
|
3680
|
+
function renameGeminiSlot(id, label2) {
|
|
3681
|
+
return getDb().prepare("UPDATE gemini_credentials SET label = ? WHERE id = ?").run(label2, id).changes > 0;
|
|
3682
|
+
}
|
|
3680
3683
|
function getGeminiRotationMode() {
|
|
3681
3684
|
const row = getDb().prepare("SELECT value FROM meta WHERE key = 'gemini_rotation_mode'").get();
|
|
3682
3685
|
return row?.value ?? "all";
|
|
@@ -3775,6 +3778,9 @@ function setBackendSlotEnabled(id, enabled) {
|
|
|
3775
3778
|
function reorderBackendSlot(id, priority) {
|
|
3776
3779
|
getDb().prepare("UPDATE backend_credentials SET priority = ? WHERE id = ?").run(priority, id);
|
|
3777
3780
|
}
|
|
3781
|
+
function renameBackendSlot(id, label2) {
|
|
3782
|
+
return getDb().prepare("UPDATE backend_credentials SET label = ? WHERE id = ?").run(label2, id).changes > 0;
|
|
3783
|
+
}
|
|
3778
3784
|
function reenableBackendSlot(slotId) {
|
|
3779
3785
|
getDb().prepare(`
|
|
3780
3786
|
UPDATE backend_credentials
|
|
@@ -3923,6 +3929,8 @@ __export(store_exports5, {
|
|
|
3923
3929
|
removeGeminiSlot: () => removeGeminiSlot,
|
|
3924
3930
|
removeHeartbeatWatch: () => removeHeartbeatWatch,
|
|
3925
3931
|
removePendingEscalation: () => removePendingEscalation,
|
|
3932
|
+
renameBackendSlot: () => renameBackendSlot,
|
|
3933
|
+
renameGeminiSlot: () => renameGeminiSlot,
|
|
3926
3934
|
reorderBackendSlot: () => reorderBackendSlot,
|
|
3927
3935
|
reorderGeminiSlot: () => reorderGeminiSlot,
|
|
3928
3936
|
resetJobFailures: () => resetJobFailures,
|
|
@@ -6540,8 +6548,8 @@ var init_ndjson = __esm({
|
|
|
6540
6548
|
|
|
6541
6549
|
// src/memory/inject.ts
|
|
6542
6550
|
function getTopK(query) {
|
|
6543
|
-
const
|
|
6544
|
-
const scale =
|
|
6551
|
+
const wordCount2 = query.split(/\s+/).length;
|
|
6552
|
+
const scale = wordCount2 <= 3 ? 0.5 : wordCount2 <= 8 ? 0.75 : 1;
|
|
6545
6553
|
return {
|
|
6546
6554
|
vectorK: Math.max(5, Math.round(BASE_VECTOR_TOP_K * scale)),
|
|
6547
6555
|
ftsK: Math.max(5, Math.round(BASE_FTS_TOP_K * scale))
|
|
@@ -9325,6 +9333,19 @@ var init_agent_log = __esm({
|
|
|
9325
9333
|
});
|
|
9326
9334
|
|
|
9327
9335
|
// src/agents/orchestrator.ts
|
|
9336
|
+
var orchestrator_exports = {};
|
|
9337
|
+
__export(orchestrator_exports, {
|
|
9338
|
+
cancelAgent: () => cancelAgent,
|
|
9339
|
+
cancelAllAgents: () => cancelAllAgents,
|
|
9340
|
+
diagnoseSpawnError: () => diagnoseSpawnError,
|
|
9341
|
+
getActiveProcessCount: () => getActiveProcessCount,
|
|
9342
|
+
getOrCreateOrchestration: () => getOrCreateOrchestration,
|
|
9343
|
+
getRunningAgentCount: () => getRunningAgentCount,
|
|
9344
|
+
initOrchestrator: () => initOrchestrator,
|
|
9345
|
+
setNotifyCallback: () => setNotifyCallback,
|
|
9346
|
+
shutdownOrchestrator: () => shutdownOrchestrator,
|
|
9347
|
+
spawnSubAgent: () => spawnSubAgent
|
|
9348
|
+
});
|
|
9328
9349
|
import { existsSync as existsSync10 } from "fs";
|
|
9329
9350
|
async function withRunnerLock(runnerId, fn) {
|
|
9330
9351
|
const prev = runnerLocks.get(runnerId) ?? Promise.resolve();
|
|
@@ -9964,6 +9985,9 @@ function cancelAllAgents(chatId, reason = "user_cancelled") {
|
|
|
9964
9985
|
updateOrchestrationStatus(db3, orch.id, "abandoned");
|
|
9965
9986
|
return count;
|
|
9966
9987
|
}
|
|
9988
|
+
function getActiveProcessCount() {
|
|
9989
|
+
return activeProcesses.size;
|
|
9990
|
+
}
|
|
9967
9991
|
function shutdownOrchestrator() {
|
|
9968
9992
|
for (const [agentId, proc] of activeProcesses) {
|
|
9969
9993
|
try {
|
|
@@ -12503,12 +12527,12 @@ var init_evolve = __esm({
|
|
|
12503
12527
|
const body = JSON.parse(await readBody(req));
|
|
12504
12528
|
const { setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
12505
12529
|
const { existsSync: fileExists, readFileSync: fileRead } = await import("fs");
|
|
12506
|
-
const { join:
|
|
12530
|
+
const { join: join36 } = await import("path");
|
|
12507
12531
|
const { CC_CLAW_HOME: home } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
12508
12532
|
const chatId = resolveChatId(body);
|
|
12509
12533
|
if (!chatId) return jsonResponse(res, { error: "No chatId provided and ALLOWED_CHAT_ID is not set" }, 400);
|
|
12510
|
-
const soulPath =
|
|
12511
|
-
const userPath =
|
|
12534
|
+
const soulPath = join36(home, "identity/SOUL.md");
|
|
12535
|
+
const userPath = join36(home, "identity/USER.md");
|
|
12512
12536
|
const soul = fileExists(soulPath) ? fileRead(soulPath, "utf-8") : "";
|
|
12513
12537
|
const user = fileExists(userPath) ? fileRead(userPath, "utf-8") : "";
|
|
12514
12538
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
@@ -12867,9 +12891,9 @@ function matchPatterns(message, patterns, signalType) {
|
|
|
12867
12891
|
return matches;
|
|
12868
12892
|
}
|
|
12869
12893
|
function classifySignals(userMessage, _agentResponse) {
|
|
12870
|
-
const
|
|
12894
|
+
const wordCount2 = userMessage.trim().split(/\s+/).filter(Boolean).length;
|
|
12871
12895
|
const results = [];
|
|
12872
|
-
if (
|
|
12896
|
+
if (wordCount2 >= 3) {
|
|
12873
12897
|
for (const m of matchPatterns(userMessage, CORRECTION_PATTERNS, "correction")) {
|
|
12874
12898
|
results.push({ ...m, source: "auto_detect" });
|
|
12875
12899
|
}
|
|
@@ -13549,7 +13573,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
13549
13573
|
const adapter = backend2 ? getAdapter(backend2) : getAdapterForChat(settingsChat);
|
|
13550
13574
|
const mode = permMode ?? getMode(settingsChat);
|
|
13551
13575
|
const responseStyle = getResponseStyle(settingsChat);
|
|
13552
|
-
const thinkingLevel = getThinkingLevel(settingsChat);
|
|
13576
|
+
const thinkingLevel = opts?.thinkingLevel ?? getThinkingLevel(settingsChat);
|
|
13553
13577
|
const resolvedCwd = cwd ?? WORKSPACE_PATH;
|
|
13554
13578
|
const tier = bootstrapTier ?? "full";
|
|
13555
13579
|
const effectiveAgentMode = optsAgentMode ?? getAgentMode(settingsChat);
|
|
@@ -16451,8 +16475,8 @@ async function mp3ToOgg(mp3Buffer) {
|
|
|
16451
16475
|
const id = crypto.randomUUID();
|
|
16452
16476
|
const tmpMp3 = `/tmp/cc-claw-tts-${id}.mp3`;
|
|
16453
16477
|
const tmpOgg = `/tmp/cc-claw-tts-${id}.ogg`;
|
|
16454
|
-
const { writeFile:
|
|
16455
|
-
await
|
|
16478
|
+
const { writeFile: writeFile6 } = await import("fs/promises");
|
|
16479
|
+
await writeFile6(tmpMp3, mp3Buffer);
|
|
16456
16480
|
await execFileAsync2("ffmpeg", ["-y", "-i", tmpMp3, "-c:a", "libopus", "-b:a", "64k", tmpOgg]);
|
|
16457
16481
|
const oggBuffer = await readFile2(tmpOgg);
|
|
16458
16482
|
unlink(tmpMp3).catch((err) => {
|
|
@@ -19227,10 +19251,10 @@ async function handleEvolveCallback(chatId, data, channel) {
|
|
|
19227
19251
|
const current = getReflectionStatus2(getDb(), chatId);
|
|
19228
19252
|
if (current === "frozen") {
|
|
19229
19253
|
const { readFileSync: readFileSync28, existsSync: existsSync56 } = await import("fs");
|
|
19230
|
-
const { join:
|
|
19254
|
+
const { join: join36 } = await import("path");
|
|
19231
19255
|
const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
19232
|
-
const soulPath =
|
|
19233
|
-
const userPath =
|
|
19256
|
+
const soulPath = join36(CC_CLAW_HOME3, "identity/SOUL.md");
|
|
19257
|
+
const userPath = join36(CC_CLAW_HOME3, "identity/USER.md");
|
|
19234
19258
|
const soul = existsSync56(soulPath) ? readFileSync28(soulPath, "utf-8") : "";
|
|
19235
19259
|
const user = existsSync56(userPath) ? readFileSync28(userPath, "utf-8") : "";
|
|
19236
19260
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
@@ -20580,6 +20604,133 @@ var init_optimize = __esm({
|
|
|
20580
20604
|
}
|
|
20581
20605
|
});
|
|
20582
20606
|
|
|
20607
|
+
// src/council/types.ts
|
|
20608
|
+
var COUNCIL_MIN_PARTICIPANTS, COUNCIL_MAX_ROUNDS, COUNCIL_WIZARD_TIMEOUT_MS;
|
|
20609
|
+
var init_types4 = __esm({
|
|
20610
|
+
"src/council/types.ts"() {
|
|
20611
|
+
"use strict";
|
|
20612
|
+
COUNCIL_MIN_PARTICIPANTS = 2;
|
|
20613
|
+
COUNCIL_MAX_ROUNDS = 3;
|
|
20614
|
+
COUNCIL_WIZARD_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
20615
|
+
}
|
|
20616
|
+
});
|
|
20617
|
+
|
|
20618
|
+
// src/council/wizard.ts
|
|
20619
|
+
var wizard_exports = {};
|
|
20620
|
+
__export(wizard_exports, {
|
|
20621
|
+
buildSelectKeyboard: () => buildSelectKeyboard,
|
|
20622
|
+
cancelCouncil: () => cancelCouncil,
|
|
20623
|
+
getCouncilState: () => getCouncilState,
|
|
20624
|
+
hasPendingCouncil: () => hasPendingCouncil,
|
|
20625
|
+
setCouncilQuestion: () => setCouncilQuestion,
|
|
20626
|
+
startCouncilWizard: () => startCouncilWizard,
|
|
20627
|
+
toggleParticipant: () => toggleParticipant
|
|
20628
|
+
});
|
|
20629
|
+
function resetCouncilTimeout(chatId) {
|
|
20630
|
+
const existing = councilTimers.get(chatId);
|
|
20631
|
+
if (existing) clearTimeout(existing);
|
|
20632
|
+
councilTimers.set(chatId, setTimeout(() => {
|
|
20633
|
+
pendingCouncils.delete(chatId);
|
|
20634
|
+
councilTimers.delete(chatId);
|
|
20635
|
+
log(`[council] Auto-cancelled stale council wizard for chat ${chatId}`);
|
|
20636
|
+
}, COUNCIL_WIZARD_TIMEOUT_MS));
|
|
20637
|
+
}
|
|
20638
|
+
function startCouncilWizard(chatId) {
|
|
20639
|
+
if (pendingCouncils.has(chatId)) {
|
|
20640
|
+
cancelCouncil(chatId);
|
|
20641
|
+
}
|
|
20642
|
+
pendingCouncils.set(chatId, {
|
|
20643
|
+
step: "select",
|
|
20644
|
+
selected: /* @__PURE__ */ new Map()
|
|
20645
|
+
});
|
|
20646
|
+
resetCouncilTimeout(chatId);
|
|
20647
|
+
}
|
|
20648
|
+
function hasPendingCouncil(chatId) {
|
|
20649
|
+
return pendingCouncils.has(chatId);
|
|
20650
|
+
}
|
|
20651
|
+
function getCouncilState(chatId) {
|
|
20652
|
+
return pendingCouncils.get(chatId);
|
|
20653
|
+
}
|
|
20654
|
+
function cancelCouncil(chatId) {
|
|
20655
|
+
pendingCouncils.delete(chatId);
|
|
20656
|
+
const timer = councilTimers.get(chatId);
|
|
20657
|
+
if (timer) {
|
|
20658
|
+
clearTimeout(timer);
|
|
20659
|
+
councilTimers.delete(chatId);
|
|
20660
|
+
}
|
|
20661
|
+
}
|
|
20662
|
+
function toggleParticipant(chatId, backend2, model2, label2) {
|
|
20663
|
+
const state = pendingCouncils.get(chatId);
|
|
20664
|
+
if (!state) return;
|
|
20665
|
+
resetCouncilTimeout(chatId);
|
|
20666
|
+
const key = `${backend2}:${model2}`;
|
|
20667
|
+
if (state.selected.has(key)) {
|
|
20668
|
+
state.selected.delete(key);
|
|
20669
|
+
} else {
|
|
20670
|
+
state.selected.set(key, { backend: backend2, model: model2, label: label2 });
|
|
20671
|
+
}
|
|
20672
|
+
}
|
|
20673
|
+
function setCouncilQuestion(chatId, question) {
|
|
20674
|
+
const state = pendingCouncils.get(chatId);
|
|
20675
|
+
if (!state) return { error: "No active council wizard." };
|
|
20676
|
+
resetCouncilTimeout(chatId);
|
|
20677
|
+
if (state.selected.size < COUNCIL_MIN_PARTICIPANTS) {
|
|
20678
|
+
return { error: `Select at least ${COUNCIL_MIN_PARTICIPANTS} models before starting.` };
|
|
20679
|
+
}
|
|
20680
|
+
state.question = question;
|
|
20681
|
+
state.step = "running";
|
|
20682
|
+
return {};
|
|
20683
|
+
}
|
|
20684
|
+
function buildSelectKeyboard(chatId) {
|
|
20685
|
+
const state = pendingCouncils.get(chatId);
|
|
20686
|
+
if (!state) {
|
|
20687
|
+
return { text: "No active council wizard.", buttons: [] };
|
|
20688
|
+
}
|
|
20689
|
+
const adapters2 = getAvailableAdapters();
|
|
20690
|
+
const buttons = [];
|
|
20691
|
+
for (const adapter of adapters2) {
|
|
20692
|
+
for (const [modelId, modelInfo] of Object.entries(adapter.availableModels)) {
|
|
20693
|
+
const key = `${adapter.id}:${modelId}`;
|
|
20694
|
+
const isSelected = state.selected.has(key);
|
|
20695
|
+
const checkmark = isSelected ? "\u2713 " : " ";
|
|
20696
|
+
const row = [{
|
|
20697
|
+
label: `${checkmark}${modelInfo.label}`,
|
|
20698
|
+
data: `council:toggle:${adapter.id}:${modelId}:${modelInfo.label}`,
|
|
20699
|
+
...isSelected ? { style: "success" } : {}
|
|
20700
|
+
}];
|
|
20701
|
+
buttons.push(row);
|
|
20702
|
+
}
|
|
20703
|
+
}
|
|
20704
|
+
const count = state.selected.size;
|
|
20705
|
+
const canStart = count >= COUNCIL_MIN_PARTICIPANTS;
|
|
20706
|
+
buttons.push([
|
|
20707
|
+
{
|
|
20708
|
+
label: canStart ? `\u25B6 Start Council (${count} models)` : `\u25B6 Start Council (${count} models)`,
|
|
20709
|
+
data: canStart ? "council:start" : "council:noop",
|
|
20710
|
+
...canStart ? {} : {}
|
|
20711
|
+
},
|
|
20712
|
+
{
|
|
20713
|
+
label: "\u2715 Cancel",
|
|
20714
|
+
data: "council:cancel"
|
|
20715
|
+
}
|
|
20716
|
+
]);
|
|
20717
|
+
return {
|
|
20718
|
+
text: `Select models for the council debate (${count} selected):`,
|
|
20719
|
+
buttons
|
|
20720
|
+
};
|
|
20721
|
+
}
|
|
20722
|
+
var pendingCouncils, councilTimers;
|
|
20723
|
+
var init_wizard2 = __esm({
|
|
20724
|
+
"src/council/wizard.ts"() {
|
|
20725
|
+
"use strict";
|
|
20726
|
+
init_types4();
|
|
20727
|
+
init_backends();
|
|
20728
|
+
init_log();
|
|
20729
|
+
pendingCouncils = /* @__PURE__ */ new Map();
|
|
20730
|
+
councilTimers = /* @__PURE__ */ new Map();
|
|
20731
|
+
}
|
|
20732
|
+
});
|
|
20733
|
+
|
|
20583
20734
|
// src/router/command-handlers.ts
|
|
20584
20735
|
import { readFile as readFile6 } from "fs/promises";
|
|
20585
20736
|
async function handleStopCommand(chatId, commandArgs, msg, channel) {
|
|
@@ -21186,6 +21337,12 @@ async function handleModelCommand(chatId, commandArgs, msg, channel) {
|
|
|
21186
21337
|
...id === current ? { style: "primary" } : {}
|
|
21187
21338
|
}];
|
|
21188
21339
|
});
|
|
21340
|
+
const isAuto = getModel(chatId) === "auto";
|
|
21341
|
+
buttons.unshift([{
|
|
21342
|
+
label: `${isAuto ? "\u2713 " : ""}\u{1F916} Auto (smart routing)`,
|
|
21343
|
+
data: "model:auto",
|
|
21344
|
+
...isAuto ? { style: "primary" } : {}
|
|
21345
|
+
}]);
|
|
21189
21346
|
await channel.sendKeyboard(chatId, `Models for ${adapter.displayName}:`, buttons);
|
|
21190
21347
|
} else {
|
|
21191
21348
|
const lines = Object.entries(models).map(
|
|
@@ -22095,6 +22252,20 @@ async function handleCronCommand(chatId, commandArgs, msg, channel) {
|
|
|
22095
22252
|
await startWizard(chatId, commandArgs, channel);
|
|
22096
22253
|
}
|
|
22097
22254
|
}
|
|
22255
|
+
async function handleCouncilCommand(chatId, commandArgs, msg, channel) {
|
|
22256
|
+
if (process.env.DASHBOARD_ENABLED !== "1") {
|
|
22257
|
+
await channel.sendText(chatId, "Council requires DASHBOARD_ENABLED=1 (uses the agent orchestrator).", { parseMode: "plain" });
|
|
22258
|
+
return;
|
|
22259
|
+
}
|
|
22260
|
+
const { startCouncilWizard: startCouncilWizard2, buildSelectKeyboard: buildSelectKeyboard2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
|
|
22261
|
+
startCouncilWizard2(chatId);
|
|
22262
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
22263
|
+
const { text, buttons } = buildSelectKeyboard2(chatId);
|
|
22264
|
+
await channel.sendKeyboard(chatId, text, buttons);
|
|
22265
|
+
} else {
|
|
22266
|
+
await channel.sendText(chatId, "Council requires Telegram (needs inline keyboards).", { parseMode: "plain" });
|
|
22267
|
+
}
|
|
22268
|
+
}
|
|
22098
22269
|
var init_command_handlers = __esm({
|
|
22099
22270
|
"src/router/command-handlers.ts"() {
|
|
22100
22271
|
"use strict";
|
|
@@ -22303,6 +22474,10 @@ async function handleCommand(msg, channel) {
|
|
|
22303
22474
|
case "intent":
|
|
22304
22475
|
await handleIntentCommand(chatId, commandArgs, msg, channel);
|
|
22305
22476
|
break;
|
|
22477
|
+
case "council":
|
|
22478
|
+
case "debate":
|
|
22479
|
+
await handleCouncilCommand(chatId, commandArgs, msg, channel);
|
|
22480
|
+
break;
|
|
22306
22481
|
case "evolve":
|
|
22307
22482
|
await handleEvolveCommandWrapper(chatId, commandArgs, msg, channel);
|
|
22308
22483
|
break;
|
|
@@ -22345,6 +22520,118 @@ var init_commands = __esm({
|
|
|
22345
22520
|
}
|
|
22346
22521
|
});
|
|
22347
22522
|
|
|
22523
|
+
// src/skills/auto-create.ts
|
|
22524
|
+
var auto_create_exports = {};
|
|
22525
|
+
__export(auto_create_exports, {
|
|
22526
|
+
buildSkillExtractionPrompt: () => buildSkillExtractionPrompt,
|
|
22527
|
+
clearPendingDraft: () => clearPendingDraft,
|
|
22528
|
+
getPendingDraft: () => getPendingDraft,
|
|
22529
|
+
isSkillWorthy: () => isSkillWorthy,
|
|
22530
|
+
parseExtractedSkill: () => parseExtractedSkill,
|
|
22531
|
+
saveSkill: () => saveSkill,
|
|
22532
|
+
storePendingDraft: () => storePendingDraft
|
|
22533
|
+
});
|
|
22534
|
+
import { join as join25 } from "path";
|
|
22535
|
+
import { writeFile as writeFile4, mkdir as mkdir3 } from "fs/promises";
|
|
22536
|
+
function isSkillWorthy(signals) {
|
|
22537
|
+
const { toolUseCount, tokenOutput, elapsedMs, userMessage } = signals;
|
|
22538
|
+
if (toolUseCount < 3) return false;
|
|
22539
|
+
const supplementary = [
|
|
22540
|
+
tokenOutput >= 1500,
|
|
22541
|
+
elapsedMs >= 2e4
|
|
22542
|
+
].filter(Boolean).length;
|
|
22543
|
+
if (supplementary < 1) return false;
|
|
22544
|
+
const words = userMessage.split(/\s+/).length;
|
|
22545
|
+
if (words < 5) return false;
|
|
22546
|
+
log(`[auto-skill] Skill-worthy: tools=${toolUseCount}, tokens=${tokenOutput}, elapsed=${elapsedMs}ms`);
|
|
22547
|
+
return true;
|
|
22548
|
+
}
|
|
22549
|
+
function buildSkillExtractionPrompt(userMessage, assistantResponse) {
|
|
22550
|
+
const cappedResponse = assistantResponse.length > 8e3 ? assistantResponse.slice(0, 8e3) + "\n\n[...truncated...]" : assistantResponse;
|
|
22551
|
+
return [
|
|
22552
|
+
"You are a skill extraction assistant. Analyze the following completed task and create a reusable SKILL.md file.",
|
|
22553
|
+
"",
|
|
22554
|
+
"A skill is a set of instructions that an AI agent can follow to accomplish a similar task in the future.",
|
|
22555
|
+
"Focus on the PROCESS and APPROACH, not the specific details of this particular task.",
|
|
22556
|
+
"",
|
|
22557
|
+
"## Completed Task",
|
|
22558
|
+
"",
|
|
22559
|
+
`**User request:** ${userMessage}`,
|
|
22560
|
+
"",
|
|
22561
|
+
`**Assistant response:**`,
|
|
22562
|
+
cappedResponse,
|
|
22563
|
+
"",
|
|
22564
|
+
"## Output Format",
|
|
22565
|
+
"",
|
|
22566
|
+
"Output ONLY the SKILL.md content with this exact format:",
|
|
22567
|
+
"",
|
|
22568
|
+
"```",
|
|
22569
|
+
"---",
|
|
22570
|
+
'name: "skill-name-in-kebab-case"',
|
|
22571
|
+
'description: "What this skill does and when to use it"',
|
|
22572
|
+
"---",
|
|
22573
|
+
"",
|
|
22574
|
+
"## [Skill Title]",
|
|
22575
|
+
"",
|
|
22576
|
+
"[Step-by-step instructions for accomplishing this type of task]",
|
|
22577
|
+
"[Include decision points, best practices, and common pitfalls]",
|
|
22578
|
+
"[Keep it general enough to be reusable, specific enough to be helpful]",
|
|
22579
|
+
"```",
|
|
22580
|
+
"",
|
|
22581
|
+
"Rules:",
|
|
22582
|
+
"- The skill name should be descriptive and kebab-case",
|
|
22583
|
+
"- The description should explain WHAT it does AND WHEN to use it",
|
|
22584
|
+
"- Instructions should be general (not tied to specific file names or projects)",
|
|
22585
|
+
"- Include any important caveats or prerequisites",
|
|
22586
|
+
"- Keep it under 100 lines"
|
|
22587
|
+
].join("\n");
|
|
22588
|
+
}
|
|
22589
|
+
function parseExtractedSkill(llmResponse) {
|
|
22590
|
+
let content = llmResponse;
|
|
22591
|
+
const fenceMatch = llmResponse.match(/```(?:markdown|md)?\s*\n([\s\S]*?)```/);
|
|
22592
|
+
if (fenceMatch) content = fenceMatch[1].trim();
|
|
22593
|
+
const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
22594
|
+
if (!fmMatch) {
|
|
22595
|
+
warn("[auto-skill] No frontmatter found in extracted skill");
|
|
22596
|
+
return null;
|
|
22597
|
+
}
|
|
22598
|
+
const nameMatch = fmMatch[1].match(/^name:\s*["']?([^"'\n]+)["']?\s*$/m);
|
|
22599
|
+
if (!nameMatch) {
|
|
22600
|
+
warn("[auto-skill] No name field in skill frontmatter");
|
|
22601
|
+
return null;
|
|
22602
|
+
}
|
|
22603
|
+
const name = nameMatch[1].trim().toLowerCase().replace(/\s+/g, "-");
|
|
22604
|
+
return { name, content };
|
|
22605
|
+
}
|
|
22606
|
+
async function saveSkill(name, content) {
|
|
22607
|
+
const dir = join25(SKILLS_PATH, name);
|
|
22608
|
+
await mkdir3(dir, { recursive: true });
|
|
22609
|
+
const filePath = join25(dir, "SKILL.md");
|
|
22610
|
+
await writeFile4(filePath, content, "utf-8");
|
|
22611
|
+
invalidateSkillCache();
|
|
22612
|
+
log(`[auto-skill] Saved skill "${name}" to ${filePath}`);
|
|
22613
|
+
return { path: filePath };
|
|
22614
|
+
}
|
|
22615
|
+
function storePendingDraft(chatId, draft) {
|
|
22616
|
+
pendingDrafts.set(chatId, draft);
|
|
22617
|
+
}
|
|
22618
|
+
function getPendingDraft(chatId) {
|
|
22619
|
+
return pendingDrafts.get(chatId);
|
|
22620
|
+
}
|
|
22621
|
+
function clearPendingDraft(chatId) {
|
|
22622
|
+
pendingDrafts.delete(chatId);
|
|
22623
|
+
}
|
|
22624
|
+
var pendingDrafts;
|
|
22625
|
+
var init_auto_create = __esm({
|
|
22626
|
+
"src/skills/auto-create.ts"() {
|
|
22627
|
+
"use strict";
|
|
22628
|
+
init_paths();
|
|
22629
|
+
init_discover();
|
|
22630
|
+
init_log();
|
|
22631
|
+
pendingDrafts = /* @__PURE__ */ new Map();
|
|
22632
|
+
}
|
|
22633
|
+
});
|
|
22634
|
+
|
|
22348
22635
|
// src/router/callbacks.ts
|
|
22349
22636
|
import { readFile as readFile7 } from "fs/promises";
|
|
22350
22637
|
async function handleCallback(chatId, data, channel, messageId) {
|
|
@@ -22404,6 +22691,12 @@ async function handleCallback(chatId, data, channel, messageId) {
|
|
|
22404
22691
|
await channel.sendText(chatId, `Using ${adapter.displayName} with default model. Ready!`, { parseMode: "plain" });
|
|
22405
22692
|
} else if (data.startsWith("model:")) {
|
|
22406
22693
|
const chosen = data.slice(6);
|
|
22694
|
+
if (chosen === "auto") {
|
|
22695
|
+
setModel(chatId, "auto");
|
|
22696
|
+
clearThinkingLevel(chatId);
|
|
22697
|
+
await channel.sendText(chatId, "\u{1F916} Smart routing enabled \u2014 model and thinking level will be chosen per message based on complexity.", { parseMode: "plain" });
|
|
22698
|
+
return;
|
|
22699
|
+
}
|
|
22407
22700
|
let adapter;
|
|
22408
22701
|
try {
|
|
22409
22702
|
adapter = getAdapterForChat(chatId);
|
|
@@ -23043,6 +23336,47 @@ ${rotationNote}`, { parseMode: "html" });
|
|
|
23043
23336
|
} else if (data.startsWith("reflect:")) {
|
|
23044
23337
|
await handleReflectCallback(chatId, data, channel);
|
|
23045
23338
|
return;
|
|
23339
|
+
} else if (data.startsWith("council:")) {
|
|
23340
|
+
const parts = data.split(":");
|
|
23341
|
+
const action = parts[1];
|
|
23342
|
+
if (action === "toggle") {
|
|
23343
|
+
const backend2 = parts[2];
|
|
23344
|
+
const model2 = parts[3];
|
|
23345
|
+
const label2 = parts.slice(4).join(":");
|
|
23346
|
+
const { toggleParticipant: toggleParticipant2, buildSelectKeyboard: buildSelectKeyboard2, hasPendingCouncil: hasPendingCouncil2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
|
|
23347
|
+
if (!hasPendingCouncil2(chatId)) {
|
|
23348
|
+
await channel.sendText(chatId, "No council wizard active. Use /council to start.", { parseMode: "plain" });
|
|
23349
|
+
return;
|
|
23350
|
+
}
|
|
23351
|
+
toggleParticipant2(chatId, backend2, model2, label2);
|
|
23352
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
23353
|
+
const { text, buttons } = buildSelectKeyboard2(chatId);
|
|
23354
|
+
await channel.sendKeyboard(chatId, text, buttons);
|
|
23355
|
+
}
|
|
23356
|
+
return;
|
|
23357
|
+
}
|
|
23358
|
+
if (action === "start") {
|
|
23359
|
+
const { getCouncilState: getCouncilState2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
|
|
23360
|
+
const state = getCouncilState2(chatId);
|
|
23361
|
+
if (!state || state.selected.size < 2) {
|
|
23362
|
+
await channel.sendText(chatId, "Select at least 2 models first.", { parseMode: "plain" });
|
|
23363
|
+
return;
|
|
23364
|
+
}
|
|
23365
|
+
state.step = "question";
|
|
23366
|
+
const names = [...state.selected.values()].map((p) => p.label).join(", ");
|
|
23367
|
+
await channel.sendText(chatId, `\u{1F3DB}\uFE0F Council members: ${names}
|
|
23368
|
+
|
|
23369
|
+
Now type the question you want them to debate.`, { parseMode: "plain" });
|
|
23370
|
+
return;
|
|
23371
|
+
}
|
|
23372
|
+
if (action === "cancel") {
|
|
23373
|
+
const { cancelCouncil: cancelCouncil2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
|
|
23374
|
+
cancelCouncil2(chatId);
|
|
23375
|
+
await channel.sendText(chatId, "Council cancelled.", { parseMode: "plain" });
|
|
23376
|
+
return;
|
|
23377
|
+
}
|
|
23378
|
+
if (action === "noop") return;
|
|
23379
|
+
return;
|
|
23046
23380
|
} else if (data.startsWith("opt:")) {
|
|
23047
23381
|
await handleOptimizeCallback(chatId, data, channel);
|
|
23048
23382
|
return;
|
|
@@ -23322,6 +23656,45 @@ Example: /limits ${bid} daily 500000`, { parseMode: "plain" });
|
|
|
23322
23656
|
const page = parseInt(data.slice(12), 10);
|
|
23323
23657
|
const skills2 = await discoverAllSkills();
|
|
23324
23658
|
await sendSkillsPage(chatId, channel, skills2, page, messageId);
|
|
23659
|
+
} else if (data === "skill:extract") {
|
|
23660
|
+
const { getPendingDraft: getPendingDraft2, clearPendingDraft: clearPendingDraft2, buildSkillExtractionPrompt: buildSkillExtractionPrompt2, parseExtractedSkill: parseExtractedSkill2, saveSkill: saveSkill2 } = await Promise.resolve().then(() => (init_auto_create(), auto_create_exports));
|
|
23661
|
+
const draft = getPendingDraft2(chatId);
|
|
23662
|
+
if (!draft) {
|
|
23663
|
+
await channel.sendText(chatId, "No pending skill draft.", { parseMode: "plain" });
|
|
23664
|
+
return;
|
|
23665
|
+
}
|
|
23666
|
+
await channel.sendText(chatId, "\u{1F50D} Extracting skill from conversation...", { parseMode: "plain" });
|
|
23667
|
+
await channel.sendTyping?.(chatId);
|
|
23668
|
+
try {
|
|
23669
|
+
const { askAgent: askAgent3 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
23670
|
+
const extractionPrompt = buildSkillExtractionPrompt2(draft.userMessage, draft.assistantResponse);
|
|
23671
|
+
const extractionResponse = await askAgent3(chatId, extractionPrompt, {
|
|
23672
|
+
bootstrapTier: "slim",
|
|
23673
|
+
maxTurns: 1,
|
|
23674
|
+
timeoutMs: 3e4
|
|
23675
|
+
});
|
|
23676
|
+
const parsed = parseExtractedSkill2(extractionResponse.text);
|
|
23677
|
+
if (parsed) {
|
|
23678
|
+
const { path } = await saveSkill2(parsed.name, parsed.content);
|
|
23679
|
+
clearPendingDraft2(chatId);
|
|
23680
|
+
await channel.sendText(chatId, `\u2705 Skill "${parsed.name}" saved.
|
|
23681
|
+
Path: ${path}
|
|
23682
|
+
|
|
23683
|
+
Use /skills to see all available skills.`, { parseMode: "plain" });
|
|
23684
|
+
} else {
|
|
23685
|
+
clearPendingDraft2(chatId);
|
|
23686
|
+
await channel.sendText(chatId, "Could not extract a well-formed skill from this conversation. Try /remember to save key steps manually.", { parseMode: "plain" });
|
|
23687
|
+
}
|
|
23688
|
+
} catch (e) {
|
|
23689
|
+
clearPendingDraft2(chatId);
|
|
23690
|
+
await channel.sendText(chatId, `Skill extraction failed: ${e.message}`, { parseMode: "plain" });
|
|
23691
|
+
}
|
|
23692
|
+
return;
|
|
23693
|
+
} else if (data === "skill:discard") {
|
|
23694
|
+
const { clearPendingDraft: clearPendingDraft2 } = await Promise.resolve().then(() => (init_auto_create(), auto_create_exports));
|
|
23695
|
+
clearPendingDraft2(chatId);
|
|
23696
|
+
await channel.sendText(chatId, "Skill draft discarded.", { parseMode: "plain" });
|
|
23697
|
+
return;
|
|
23325
23698
|
} else if (data.startsWith("skill:")) {
|
|
23326
23699
|
const parts = data.slice(6).split(":");
|
|
23327
23700
|
let skillName;
|
|
@@ -23396,6 +23769,399 @@ var init_callbacks = __esm({
|
|
|
23396
23769
|
}
|
|
23397
23770
|
});
|
|
23398
23771
|
|
|
23772
|
+
// src/channels/thread-wrapper.ts
|
|
23773
|
+
var thread_wrapper_exports = {};
|
|
23774
|
+
__export(thread_wrapper_exports, {
|
|
23775
|
+
withThread: () => withThread
|
|
23776
|
+
});
|
|
23777
|
+
function withThread(channel, threadId) {
|
|
23778
|
+
return {
|
|
23779
|
+
get name() {
|
|
23780
|
+
return channel.name;
|
|
23781
|
+
},
|
|
23782
|
+
start: channel.start.bind(channel),
|
|
23783
|
+
stop: channel.stop.bind(channel),
|
|
23784
|
+
getCapabilities: channel.getCapabilities.bind(channel),
|
|
23785
|
+
downloadFile: channel.downloadFile.bind(channel),
|
|
23786
|
+
isAuthorized: channel.isAuthorized.bind(channel),
|
|
23787
|
+
sendText(chatId, text, opts) {
|
|
23788
|
+
return channel.sendText(chatId, text, { ...opts, threadId: opts?.threadId ?? threadId });
|
|
23789
|
+
},
|
|
23790
|
+
sendVoice(chatId, audioBuffer, fileName) {
|
|
23791
|
+
return channel.sendVoice(chatId, audioBuffer, fileName, threadId);
|
|
23792
|
+
},
|
|
23793
|
+
sendFile(chatId, buffer, fileName, mimeType) {
|
|
23794
|
+
return channel.sendFile(chatId, buffer, fileName, mimeType, threadId);
|
|
23795
|
+
},
|
|
23796
|
+
sendTyping: channel.sendTyping ? (chatId) => channel.sendTyping(chatId, threadId) : void 0,
|
|
23797
|
+
sendKeyboard: channel.sendKeyboard ? (chatId, text, buttons) => channel.sendKeyboard(chatId, text, buttons, threadId) : void 0,
|
|
23798
|
+
sendTextReturningId: channel.sendTextReturningId ? (chatId, text, parseMode) => channel.sendTextReturningId(chatId, text, parseMode, threadId) : void 0,
|
|
23799
|
+
// These operate on existing messages — no threadId needed
|
|
23800
|
+
editText: channel.editText?.bind(channel),
|
|
23801
|
+
editKeyboard: channel.editKeyboard?.bind(channel),
|
|
23802
|
+
reactToMessage: channel.reactToMessage?.bind(channel)
|
|
23803
|
+
};
|
|
23804
|
+
}
|
|
23805
|
+
var init_thread_wrapper = __esm({
|
|
23806
|
+
"src/channels/thread-wrapper.ts"() {
|
|
23807
|
+
"use strict";
|
|
23808
|
+
}
|
|
23809
|
+
});
|
|
23810
|
+
|
|
23811
|
+
// src/intent/complexity.ts
|
|
23812
|
+
var complexity_exports = {};
|
|
23813
|
+
__export(complexity_exports, {
|
|
23814
|
+
classifyComplexity: () => classifyComplexity
|
|
23815
|
+
});
|
|
23816
|
+
function wordCount(text) {
|
|
23817
|
+
return text.trim().split(/\s+/).filter(Boolean).length;
|
|
23818
|
+
}
|
|
23819
|
+
function classifyComplexity(text) {
|
|
23820
|
+
const trimmed = text.trim();
|
|
23821
|
+
const lower = trimmed.toLowerCase();
|
|
23822
|
+
const words = wordCount(trimmed);
|
|
23823
|
+
if (TRIVIAL_EXACT.has(lower)) {
|
|
23824
|
+
log(`[complexity] "${lower}" -> trivial (exact match)`);
|
|
23825
|
+
return "trivial";
|
|
23826
|
+
}
|
|
23827
|
+
if (trimmed.length <= 4 && /^[\p{Emoji}\s]+$/u.test(trimmed)) {
|
|
23828
|
+
log(`[complexity] "${trimmed}" -> trivial (emoji-only)`);
|
|
23829
|
+
return "trivial";
|
|
23830
|
+
}
|
|
23831
|
+
if (COMPLEX_SIGNALS.test(trimmed) && (words > 15 || trimmed.length > 200)) {
|
|
23832
|
+
log(`[complexity] "${trimmed.slice(0, 40)}..." -> complex (signal words + length)`);
|
|
23833
|
+
return "complex";
|
|
23834
|
+
}
|
|
23835
|
+
if (MUTATION_VERBS.test(trimmed)) {
|
|
23836
|
+
const tier = words > 30 || trimmed.length > 300 ? "complex" : "moderate";
|
|
23837
|
+
log(`[complexity] "${trimmed.slice(0, 40)}..." -> ${tier} (mutation verb)`);
|
|
23838
|
+
return tier;
|
|
23839
|
+
}
|
|
23840
|
+
for (const pattern of CODE_PATTERNS) {
|
|
23841
|
+
if (pattern.test(trimmed)) {
|
|
23842
|
+
const tier = words > 30 || trimmed.length > 300 ? "complex" : "moderate";
|
|
23843
|
+
log(`[complexity] "${trimmed.slice(0, 40)}..." -> ${tier} (code pattern)`);
|
|
23844
|
+
return tier;
|
|
23845
|
+
}
|
|
23846
|
+
}
|
|
23847
|
+
if (trimmed.length > 200 || words > 25) {
|
|
23848
|
+
const tier = words > 30 || trimmed.length > 300 ? "complex" : "moderate";
|
|
23849
|
+
log(`[complexity] "${trimmed.slice(0, 40)}..." -> ${tier} (long message)`);
|
|
23850
|
+
return tier;
|
|
23851
|
+
}
|
|
23852
|
+
for (const pattern of QUESTION_PATTERNS) {
|
|
23853
|
+
if (pattern.test(trimmed)) {
|
|
23854
|
+
log(`[complexity] "${trimmed.slice(0, 40)}..." -> simple (question)`);
|
|
23855
|
+
return "simple";
|
|
23856
|
+
}
|
|
23857
|
+
}
|
|
23858
|
+
log(`[complexity] "${trimmed.slice(0, 40)}..." -> moderate (default)`);
|
|
23859
|
+
return "moderate";
|
|
23860
|
+
}
|
|
23861
|
+
var TRIVIAL_EXACT, COMPLEX_SIGNALS, MUTATION_VERBS, CODE_PATTERNS, QUESTION_PATTERNS;
|
|
23862
|
+
var init_complexity = __esm({
|
|
23863
|
+
"src/intent/complexity.ts"() {
|
|
23864
|
+
"use strict";
|
|
23865
|
+
init_log();
|
|
23866
|
+
TRIVIAL_EXACT = /* @__PURE__ */ new Set([
|
|
23867
|
+
"hey",
|
|
23868
|
+
"hi",
|
|
23869
|
+
"hello",
|
|
23870
|
+
"yo",
|
|
23871
|
+
"sup",
|
|
23872
|
+
"howdy",
|
|
23873
|
+
"hiya",
|
|
23874
|
+
"thanks",
|
|
23875
|
+
"thank you",
|
|
23876
|
+
"thx",
|
|
23877
|
+
"ty",
|
|
23878
|
+
"thank u",
|
|
23879
|
+
"ok",
|
|
23880
|
+
"okay",
|
|
23881
|
+
"k",
|
|
23882
|
+
"kk",
|
|
23883
|
+
"cool",
|
|
23884
|
+
"nice",
|
|
23885
|
+
"great",
|
|
23886
|
+
"awesome",
|
|
23887
|
+
"perfect",
|
|
23888
|
+
"good morning",
|
|
23889
|
+
"good night",
|
|
23890
|
+
"good evening",
|
|
23891
|
+
"gm",
|
|
23892
|
+
"gn",
|
|
23893
|
+
"bye",
|
|
23894
|
+
"goodbye",
|
|
23895
|
+
"later",
|
|
23896
|
+
"see ya",
|
|
23897
|
+
"cya",
|
|
23898
|
+
"lol",
|
|
23899
|
+
"lmao",
|
|
23900
|
+
"haha",
|
|
23901
|
+
"heh",
|
|
23902
|
+
"np",
|
|
23903
|
+
"no problem",
|
|
23904
|
+
"no worries",
|
|
23905
|
+
"nw",
|
|
23906
|
+
"got it",
|
|
23907
|
+
"understood",
|
|
23908
|
+
"roger",
|
|
23909
|
+
"copy",
|
|
23910
|
+
"good",
|
|
23911
|
+
"fine",
|
|
23912
|
+
"alright",
|
|
23913
|
+
"sure",
|
|
23914
|
+
"yes",
|
|
23915
|
+
"no",
|
|
23916
|
+
"yep",
|
|
23917
|
+
"nope",
|
|
23918
|
+
"yeah",
|
|
23919
|
+
"nah"
|
|
23920
|
+
]);
|
|
23921
|
+
COMPLEX_SIGNALS = /\b(architect|design|research|plan|strategy|migration|microservice|distributed|end-to-end|trade-offs|pros\s+and\s+cons)\b/i;
|
|
23922
|
+
MUTATION_VERBS = /\b(fix|create|build|deploy|refactor|implement|write|add|update|edit|test|debug)\b/i;
|
|
23923
|
+
CODE_PATTERNS = [
|
|
23924
|
+
/```/,
|
|
23925
|
+
// code blocks
|
|
23926
|
+
/\.[a-z]{1,5}\b/,
|
|
23927
|
+
// file extensions (.ts, .py, .json)
|
|
23928
|
+
/[/\\][\w.-]+/
|
|
23929
|
+
// file paths (/src/foo, .\bar)
|
|
23930
|
+
];
|
|
23931
|
+
QUESTION_PATTERNS = [
|
|
23932
|
+
/^(?:what|which|where|when|why|how)\b/i,
|
|
23933
|
+
/^(?:show|tell|list|explain)\b/i,
|
|
23934
|
+
/^(?:is|are)\b/i
|
|
23935
|
+
];
|
|
23936
|
+
}
|
|
23937
|
+
});
|
|
23938
|
+
|
|
23939
|
+
// src/intent/auto-route.ts
|
|
23940
|
+
var auto_route_exports = {};
|
|
23941
|
+
__export(auto_route_exports, {
|
|
23942
|
+
resolveAutoRoute: () => resolveAutoRoute
|
|
23943
|
+
});
|
|
23944
|
+
function tieredModels(adapter) {
|
|
23945
|
+
const modelIds = Object.keys(adapter.availableModels);
|
|
23946
|
+
if (modelIds.length <= 1) {
|
|
23947
|
+
const only = modelIds[0] ?? adapter.defaultModel;
|
|
23948
|
+
return { cheap: only, mid: only, best: only };
|
|
23949
|
+
}
|
|
23950
|
+
const pricingEntries = modelIds.filter((id) => adapter.pricing[id]).map((id) => ({ id, out: adapter.pricing[id].out }));
|
|
23951
|
+
if (pricingEntries.length >= 2) {
|
|
23952
|
+
pricingEntries.sort((a, b) => a.out - b.out);
|
|
23953
|
+
const cheap = pricingEntries[0].id;
|
|
23954
|
+
const best = pricingEntries[pricingEntries.length - 1].id;
|
|
23955
|
+
const midIdx = Math.floor(pricingEntries.length / 2);
|
|
23956
|
+
const mid = pricingEntries.length === 2 ? pricingEntries[1].id : pricingEntries[midIdx].id;
|
|
23957
|
+
return { cheap, mid, best };
|
|
23958
|
+
}
|
|
23959
|
+
return {
|
|
23960
|
+
cheap: adapter.summarizerModel,
|
|
23961
|
+
mid: adapter.defaultModel,
|
|
23962
|
+
best: modelIds[0]
|
|
23963
|
+
};
|
|
23964
|
+
}
|
|
23965
|
+
function pickThinking(model2, adapter, desired) {
|
|
23966
|
+
const info = adapter.availableModels[model2];
|
|
23967
|
+
if (!info || info.thinking !== "adjustable") {
|
|
23968
|
+
return "auto";
|
|
23969
|
+
}
|
|
23970
|
+
const levels = info.thinkingLevels;
|
|
23971
|
+
if (!levels || levels.length === 0) {
|
|
23972
|
+
return "auto";
|
|
23973
|
+
}
|
|
23974
|
+
if (levels.includes(desired)) {
|
|
23975
|
+
return desired;
|
|
23976
|
+
}
|
|
23977
|
+
const desiredIdx = THINKING_ORDER.indexOf(desired);
|
|
23978
|
+
if (desiredIdx === -1) return levels[0];
|
|
23979
|
+
let closest = levels[0];
|
|
23980
|
+
let closestDist = Infinity;
|
|
23981
|
+
for (const lvl of levels) {
|
|
23982
|
+
const idx = THINKING_ORDER.indexOf(lvl);
|
|
23983
|
+
if (idx === -1) continue;
|
|
23984
|
+
const dist = Math.abs(idx - desiredIdx);
|
|
23985
|
+
if (dist < closestDist) {
|
|
23986
|
+
closestDist = dist;
|
|
23987
|
+
closest = lvl;
|
|
23988
|
+
}
|
|
23989
|
+
}
|
|
23990
|
+
return closest;
|
|
23991
|
+
}
|
|
23992
|
+
function resolveAutoRoute(tier, adapter) {
|
|
23993
|
+
const models = tieredModels(adapter);
|
|
23994
|
+
const mapping = TIER_MAP[tier];
|
|
23995
|
+
const model2 = models[mapping.tier];
|
|
23996
|
+
const thinkingLevel = pickThinking(model2, adapter, mapping.thinking);
|
|
23997
|
+
log(
|
|
23998
|
+
`[auto-route] ${tier} -> ${model2} (${mapping.tier}), thinking=${thinkingLevel} [${adapter.id}]`
|
|
23999
|
+
);
|
|
24000
|
+
return { model: model2, thinkingLevel };
|
|
24001
|
+
}
|
|
24002
|
+
var THINKING_ORDER, TIER_MAP;
|
|
24003
|
+
var init_auto_route = __esm({
|
|
24004
|
+
"src/intent/auto-route.ts"() {
|
|
24005
|
+
"use strict";
|
|
24006
|
+
init_log();
|
|
24007
|
+
THINKING_ORDER = ["off", "low", "medium", "high", "extra_high"];
|
|
24008
|
+
TIER_MAP = {
|
|
24009
|
+
trivial: { tier: "cheap", thinking: "off" },
|
|
24010
|
+
simple: { tier: "cheap", thinking: "low" },
|
|
24011
|
+
moderate: { tier: "mid", thinking: "medium" },
|
|
24012
|
+
complex: { tier: "best", thinking: "high" }
|
|
24013
|
+
};
|
|
24014
|
+
}
|
|
24015
|
+
});
|
|
24016
|
+
|
|
24017
|
+
// src/council/executor.ts
|
|
24018
|
+
var executor_exports = {};
|
|
24019
|
+
__export(executor_exports, {
|
|
24020
|
+
anonymizeSubmissions: () => anonymizeSubmissions,
|
|
24021
|
+
buildRoundPrompt: () => buildRoundPrompt,
|
|
24022
|
+
executeCouncil: () => executeCouncil,
|
|
24023
|
+
waitForAgent: () => waitForAgent
|
|
24024
|
+
});
|
|
24025
|
+
function anonymizeSubmissions(submissions) {
|
|
24026
|
+
const entries = [...submissions.entries()].map(([, response]) => response);
|
|
24027
|
+
for (let i = entries.length - 1; i > 0; i--) {
|
|
24028
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
24029
|
+
[entries[i], entries[j]] = [entries[j], entries[i]];
|
|
24030
|
+
}
|
|
24031
|
+
const labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
24032
|
+
return entries.map((response, idx) => ({
|
|
24033
|
+
label: `Participant ${labels[idx] ?? String(idx + 1)}`,
|
|
24034
|
+
response
|
|
24035
|
+
}));
|
|
24036
|
+
}
|
|
24037
|
+
function buildRoundPrompt(question, roundNumber, priorSubmissions) {
|
|
24038
|
+
if (roundNumber === 1 || !priorSubmissions?.length) {
|
|
24039
|
+
return [
|
|
24040
|
+
"You are participating in a council debate. Provide your best answer to the following question.",
|
|
24041
|
+
"",
|
|
24042
|
+
`Question: ${question}`
|
|
24043
|
+
].join("\n");
|
|
24044
|
+
}
|
|
24045
|
+
const submissionBlock = priorSubmissions.map((s) => `--- ${s.label} ---
|
|
24046
|
+
${s.response}`).join("\n\n");
|
|
24047
|
+
return [
|
|
24048
|
+
"You are participating in a council debate (round " + roundNumber + ").",
|
|
24049
|
+
"Review the positions below, address any disagreements, and refine your answer.",
|
|
24050
|
+
"Evaluate each position on merit only. You do NOT know which model produced which submission.",
|
|
24051
|
+
"",
|
|
24052
|
+
`Question: ${question}`,
|
|
24053
|
+
"",
|
|
24054
|
+
"Previous submissions:",
|
|
24055
|
+
submissionBlock
|
|
24056
|
+
].join("\n");
|
|
24057
|
+
}
|
|
24058
|
+
async function waitForAgent(agentId, maxWaitMs = 3e5) {
|
|
24059
|
+
const { getAgent: getAgent3 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
24060
|
+
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
24061
|
+
const db3 = getDb2();
|
|
24062
|
+
const deadline = Date.now() + maxWaitMs;
|
|
24063
|
+
const terminalStatuses = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
24064
|
+
while (Date.now() < deadline) {
|
|
24065
|
+
const agent = getAgent3(db3, agentId);
|
|
24066
|
+
if (!agent) {
|
|
24067
|
+
return { resultSummary: null, tokenInput: 0, tokenOutput: 0, status: "not_found" };
|
|
24068
|
+
}
|
|
24069
|
+
if (terminalStatuses.has(agent.status)) {
|
|
24070
|
+
return {
|
|
24071
|
+
resultSummary: agent.resultSummary,
|
|
24072
|
+
tokenInput: agent.tokenInput,
|
|
24073
|
+
tokenOutput: agent.tokenOutput,
|
|
24074
|
+
status: agent.status
|
|
24075
|
+
};
|
|
24076
|
+
}
|
|
24077
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
24078
|
+
}
|
|
24079
|
+
return { resultSummary: null, tokenInput: 0, tokenOutput: 0, status: "timeout" };
|
|
24080
|
+
}
|
|
24081
|
+
function checkConvergence(submissions) {
|
|
24082
|
+
const wordSets = [...submissions.values()].map((text) => {
|
|
24083
|
+
const words = text.toLowerCase().replace(/[^a-z0-9\s]/g, "").split(/\s+/).filter((w) => w.length > 3);
|
|
24084
|
+
return new Set(words);
|
|
24085
|
+
});
|
|
24086
|
+
if (wordSets.length < 2) return true;
|
|
24087
|
+
for (let i = 0; i < wordSets.length; i++) {
|
|
24088
|
+
for (let j = i + 1; j < wordSets.length; j++) {
|
|
24089
|
+
const a = wordSets[i];
|
|
24090
|
+
const b = wordSets[j];
|
|
24091
|
+
const intersection = new Set([...a].filter((w) => b.has(w)));
|
|
24092
|
+
const union = /* @__PURE__ */ new Set([...a, ...b]);
|
|
24093
|
+
if (union.size === 0) continue;
|
|
24094
|
+
const overlap = intersection.size / union.size;
|
|
24095
|
+
if (overlap < 0.6) return false;
|
|
24096
|
+
}
|
|
24097
|
+
}
|
|
24098
|
+
return true;
|
|
24099
|
+
}
|
|
24100
|
+
async function executeCouncil(chatId, participants, question, onProgress) {
|
|
24101
|
+
const { spawnSubAgent: spawnSubAgent2 } = await Promise.resolve().then(() => (init_orchestrator(), orchestrator_exports));
|
|
24102
|
+
const startTime = Date.now();
|
|
24103
|
+
const rounds = [];
|
|
24104
|
+
const totalTokens = { input: 0, output: 0 };
|
|
24105
|
+
let lastAnonymized = [];
|
|
24106
|
+
for (let round = 1; round <= COUNCIL_MAX_ROUNDS; round++) {
|
|
24107
|
+
onProgress?.(`Round ${round}/${COUNCIL_MAX_ROUNDS}: spawning ${participants.length} agents...`);
|
|
24108
|
+
const prompt = buildRoundPrompt(question, round, round > 1 ? lastAnonymized : void 0);
|
|
24109
|
+
const submissions = /* @__PURE__ */ new Map();
|
|
24110
|
+
const spawnPromises = participants.map(async (p) => {
|
|
24111
|
+
const key = `${p.backend}:${p.model}`;
|
|
24112
|
+
const { agentId } = await spawnSubAgent2(chatId, {
|
|
24113
|
+
runner: p.backend,
|
|
24114
|
+
task: prompt,
|
|
24115
|
+
name: `council-${p.label}-r${round}`,
|
|
24116
|
+
model: p.model,
|
|
24117
|
+
permMode: "readonly",
|
|
24118
|
+
role: "worker"
|
|
24119
|
+
});
|
|
24120
|
+
return { key, agentId };
|
|
24121
|
+
});
|
|
24122
|
+
const spawned = await Promise.all(spawnPromises);
|
|
24123
|
+
const resultPromises = spawned.map(async ({ key, agentId }) => {
|
|
24124
|
+
const result = await waitForAgent(agentId);
|
|
24125
|
+
totalTokens.input += result.tokenInput;
|
|
24126
|
+
totalTokens.output += result.tokenOutput;
|
|
24127
|
+
if (result.resultSummary) {
|
|
24128
|
+
submissions.set(key, result.resultSummary);
|
|
24129
|
+
} else {
|
|
24130
|
+
submissions.set(key, "(No response)");
|
|
24131
|
+
}
|
|
24132
|
+
});
|
|
24133
|
+
await Promise.all(resultPromises);
|
|
24134
|
+
rounds.push({ roundNumber: round, submissions });
|
|
24135
|
+
lastAnonymized = anonymizeSubmissions(submissions);
|
|
24136
|
+
onProgress?.(`Round ${round} complete: ${submissions.size} responses collected.`);
|
|
24137
|
+
if (round >= 2 && checkConvergence(submissions)) {
|
|
24138
|
+
log(`[council] Convergence reached after round ${round}`);
|
|
24139
|
+
onProgress?.(`Convergence reached after round ${round}.`);
|
|
24140
|
+
break;
|
|
24141
|
+
}
|
|
24142
|
+
}
|
|
24143
|
+
const finalParts = lastAnonymized.map(
|
|
24144
|
+
(s) => `### ${s.label}
|
|
24145
|
+
${s.response}`
|
|
24146
|
+
);
|
|
24147
|
+
const finalAnswer = finalParts.join("\n\n");
|
|
24148
|
+
const elapsedMs = Date.now() - startTime;
|
|
24149
|
+
return {
|
|
24150
|
+
rounds,
|
|
24151
|
+
finalAnswer,
|
|
24152
|
+
participants,
|
|
24153
|
+
totalTokens,
|
|
24154
|
+
elapsedMs
|
|
24155
|
+
};
|
|
24156
|
+
}
|
|
24157
|
+
var init_executor = __esm({
|
|
24158
|
+
"src/council/executor.ts"() {
|
|
24159
|
+
"use strict";
|
|
24160
|
+
init_types4();
|
|
24161
|
+
init_log();
|
|
24162
|
+
}
|
|
24163
|
+
});
|
|
24164
|
+
|
|
23399
24165
|
// src/router.ts
|
|
23400
24166
|
var router_exports = {};
|
|
23401
24167
|
__export(router_exports, {
|
|
@@ -23432,6 +24198,10 @@ __export(router_exports, {
|
|
|
23432
24198
|
});
|
|
23433
24199
|
async function handleMessage(msg, channel) {
|
|
23434
24200
|
const { chatId } = msg;
|
|
24201
|
+
if (msg.threadId) {
|
|
24202
|
+
const { withThread: withThread2 } = await Promise.resolve().then(() => (init_thread_wrapper(), thread_wrapper_exports));
|
|
24203
|
+
channel = withThread2(channel, msg.threadId);
|
|
24204
|
+
}
|
|
23435
24205
|
if (msg.messageId && typeof channel.reactToMessage === "function" && msg.type !== "text" && msg.type !== "command") {
|
|
23436
24206
|
channel.reactToMessage(chatId, msg.messageId, pickReactionEmoji(msg)).catch(() => {
|
|
23437
24207
|
});
|
|
@@ -23509,6 +24279,20 @@ async function handleText(msg, channel) {
|
|
|
23509
24279
|
return;
|
|
23510
24280
|
}
|
|
23511
24281
|
const model2 = resolveModel(chatId);
|
|
24282
|
+
let autoRouted = false;
|
|
24283
|
+
let effectiveModel = model2;
|
|
24284
|
+
let effectiveThinking;
|
|
24285
|
+
if (model2 === "auto") {
|
|
24286
|
+
const { classifyComplexity: classifyComplexity2 } = await Promise.resolve().then(() => (init_complexity(), complexity_exports));
|
|
24287
|
+
const { resolveAutoRoute: resolveAutoRoute2 } = await Promise.resolve().then(() => (init_auto_route(), auto_route_exports));
|
|
24288
|
+
const adapter = getAdapterForChat(chatId);
|
|
24289
|
+
const tier = classifyComplexity2(text);
|
|
24290
|
+
const route = resolveAutoRoute2(tier, adapter);
|
|
24291
|
+
effectiveModel = route.model;
|
|
24292
|
+
effectiveThinking = route.thinkingLevel;
|
|
24293
|
+
autoRouted = true;
|
|
24294
|
+
log(`[router] Auto-route: "${text.slice(0, 40)}..." -> ${tier} -> model=${effectiveModel}, thinking=${effectiveThinking}`);
|
|
24295
|
+
}
|
|
23512
24296
|
const backendId = settings.getBackend() ?? "claude";
|
|
23513
24297
|
const limitMsg = checkBackendLimits(backendId);
|
|
23514
24298
|
if (limitMsg) {
|
|
@@ -23632,6 +24416,43 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
23632
24416
|
return;
|
|
23633
24417
|
}
|
|
23634
24418
|
}
|
|
24419
|
+
{
|
|
24420
|
+
const { hasPendingCouncil: hasPendingCouncil2, getCouncilState: getCouncilState2, setCouncilQuestion: setCouncilQuestion2, cancelCouncil: cancelCouncil2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
|
|
24421
|
+
if (hasPendingCouncil2(chatId)) {
|
|
24422
|
+
const state = getCouncilState2(chatId);
|
|
24423
|
+
if (state?.step === "question") {
|
|
24424
|
+
const result = setCouncilQuestion2(chatId, text);
|
|
24425
|
+
if (result.error) {
|
|
24426
|
+
await channel.sendText(chatId, result.error, { parseMode: "plain" });
|
|
24427
|
+
return;
|
|
24428
|
+
}
|
|
24429
|
+
const participants = [...state.selected.values()];
|
|
24430
|
+
const question = state.question;
|
|
24431
|
+
cancelCouncil2(chatId);
|
|
24432
|
+
await channel.sendText(chatId, `\u{1F3DB}\uFE0F Council convened \u2014 ${participants.length} models, up to 3 rounds.
|
|
24433
|
+
|
|
24434
|
+
Debating: "${question.slice(0, 100)}${question.length > 100 ? "\u2026" : ""}"`, { parseMode: "plain" });
|
|
24435
|
+
await channel.sendTyping?.(chatId);
|
|
24436
|
+
try {
|
|
24437
|
+
const { executeCouncil: executeCouncil2 } = await Promise.resolve().then(() => (init_executor(), executor_exports));
|
|
24438
|
+
const councilResult = await executeCouncil2(
|
|
24439
|
+
chatId,
|
|
24440
|
+
participants,
|
|
24441
|
+
question,
|
|
24442
|
+
(msg2) => {
|
|
24443
|
+
channel.sendText(chatId, msg2, { parseMode: "plain" }).catch(() => {
|
|
24444
|
+
});
|
|
24445
|
+
}
|
|
24446
|
+
);
|
|
24447
|
+
await sendResponse(chatId, channel, councilResult.finalAnswer, msg.messageId);
|
|
24448
|
+
} catch (e) {
|
|
24449
|
+
const errMsg = e.message ?? String(e);
|
|
24450
|
+
await channel.sendText(chatId, `Council failed: ${errMsg}`, { parseMode: "plain" });
|
|
24451
|
+
}
|
|
24452
|
+
return;
|
|
24453
|
+
}
|
|
24454
|
+
}
|
|
24455
|
+
}
|
|
23635
24456
|
if (isChatBusy(chatId) && !bypassBusyCheck.delete(chatId)) {
|
|
23636
24457
|
if (typeof channel.sendKeyboard === "function") {
|
|
23637
24458
|
pendingInterrupts.set(chatId, { msg, channel });
|
|
@@ -23741,6 +24562,7 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
23741
24562
|
liveStatus = ls.liveStatus;
|
|
23742
24563
|
const baseCb = tVerbose !== "off" ? ls.toolCb : void 0;
|
|
23743
24564
|
tToolCb = async (toolName, input, result) => {
|
|
24565
|
+
if (result === void 0) toolUseCount++;
|
|
23744
24566
|
if (baseCb) await baseCb(toolName, input, result);
|
|
23745
24567
|
if (sessionLog) {
|
|
23746
24568
|
if (result === void 0) {
|
|
@@ -23756,6 +24578,7 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
23756
24578
|
}
|
|
23757
24579
|
} else if (sessionLog) {
|
|
23758
24580
|
tToolCb = async (toolName, input, result) => {
|
|
24581
|
+
if (result === void 0) toolUseCount++;
|
|
23759
24582
|
if (result === void 0) {
|
|
23760
24583
|
sessionLog.logToolStart(toolName, input);
|
|
23761
24584
|
} else {
|
|
@@ -23763,15 +24586,17 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
23763
24586
|
}
|
|
23764
24587
|
};
|
|
23765
24588
|
}
|
|
24589
|
+
let toolUseCount = 0;
|
|
23766
24590
|
const sigT0 = Date.now();
|
|
23767
24591
|
const response = await askAgent(chatId, cleanText || text, {
|
|
23768
24592
|
cwd: settings.getCwd(),
|
|
23769
|
-
model:
|
|
24593
|
+
model: effectiveModel,
|
|
23770
24594
|
permMode: tMode,
|
|
23771
24595
|
onToolAction: tToolCb,
|
|
23772
24596
|
bootstrapTier,
|
|
23773
24597
|
maxTurns,
|
|
23774
24598
|
agentMode: effectiveAgentMode,
|
|
24599
|
+
...effectiveThinking ? { thinkingLevel: effectiveThinking } : {},
|
|
23775
24600
|
onThinking: liveStatus || sessionLog ? (chunk) => {
|
|
23776
24601
|
if (liveStatus) liveStatus.addThinking(chunk);
|
|
23777
24602
|
if (sessionLog) sessionLog.logThinking(chunk);
|
|
@@ -23821,7 +24646,7 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
23821
24646
|
const sigEnabled = settings.getModelSignature();
|
|
23822
24647
|
if (sigEnabled === "on" && responseText && !responseText.startsWith("(No response")) {
|
|
23823
24648
|
const adapter2 = getAdapterForChat(chatId);
|
|
23824
|
-
const modelId = response.resolvedModel ??
|
|
24649
|
+
const modelId = response.resolvedModel ?? effectiveModel ?? adapter2.defaultModel;
|
|
23825
24650
|
const thinking2 = settings.getThinkingLevel() || "auto";
|
|
23826
24651
|
const shortModel = formatModelShort(modelId);
|
|
23827
24652
|
let slotTag = "";
|
|
@@ -23876,6 +24701,36 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
23876
24701
|
} catch (e) {
|
|
23877
24702
|
log(`[reflection] Signal detection error: ${e}`);
|
|
23878
24703
|
}
|
|
24704
|
+
try {
|
|
24705
|
+
if (intent === "agentic" && toolUseCount > 0) {
|
|
24706
|
+
const { isSkillWorthy: isSkillWorthy2 } = await Promise.resolve().then(() => (init_auto_create(), auto_create_exports));
|
|
24707
|
+
const signals = {
|
|
24708
|
+
toolUseCount,
|
|
24709
|
+
tokenOutput: response.usage?.output ?? 0,
|
|
24710
|
+
elapsedMs,
|
|
24711
|
+
userMessage: cleanText || text
|
|
24712
|
+
};
|
|
24713
|
+
if (isSkillWorthy2(signals) && typeof channel.sendKeyboard === "function") {
|
|
24714
|
+
const { storePendingDraft: storePendingDraft2 } = await Promise.resolve().then(() => (init_auto_create(), auto_create_exports));
|
|
24715
|
+
storePendingDraft2(chatId, {
|
|
24716
|
+
name: "",
|
|
24717
|
+
content: "",
|
|
24718
|
+
userMessage: cleanText || text,
|
|
24719
|
+
assistantResponse: response.text
|
|
24720
|
+
});
|
|
24721
|
+
await channel.sendKeyboard(
|
|
24722
|
+
chatId,
|
|
24723
|
+
"\u{1F4A1} That looked like a reusable workflow. Want me to extract it as a skill?",
|
|
24724
|
+
[[
|
|
24725
|
+
{ label: "\u2705 Extract Skill", data: "skill:extract", style: "success" },
|
|
24726
|
+
{ label: "\u2715 No thanks", data: "skill:discard" }
|
|
24727
|
+
]]
|
|
24728
|
+
);
|
|
24729
|
+
}
|
|
24730
|
+
}
|
|
24731
|
+
} catch (e) {
|
|
24732
|
+
log(`[auto-skill] Evaluation error: ${e}`);
|
|
24733
|
+
}
|
|
23879
24734
|
} catch (err) {
|
|
23880
24735
|
error("[router] Error:", err);
|
|
23881
24736
|
const errMsg = errorMessage(err);
|
|
@@ -24368,7 +25223,7 @@ var init_cron = __esm({
|
|
|
24368
25223
|
});
|
|
24369
25224
|
|
|
24370
25225
|
// src/agents/runners/wrap-backend.ts
|
|
24371
|
-
import { join as
|
|
25226
|
+
import { join as join26 } from "path";
|
|
24372
25227
|
function buildMcpCommands(backendId) {
|
|
24373
25228
|
const exe = backendId === BACKEND.CURSOR ? "agent" : backendId;
|
|
24374
25229
|
return {
|
|
@@ -24462,7 +25317,7 @@ function wrapBackendAdapter(adapter) {
|
|
|
24462
25317
|
const configPath = writeMcpConfigFile(server);
|
|
24463
25318
|
return ["--mcp-config", configPath];
|
|
24464
25319
|
},
|
|
24465
|
-
getSkillPath: () =>
|
|
25320
|
+
getSkillPath: () => join26(SKILLS_PATH, `agent-${adapter.id}.md`)
|
|
24466
25321
|
};
|
|
24467
25322
|
}
|
|
24468
25323
|
var BACKEND_CAPABILITIES;
|
|
@@ -24515,7 +25370,7 @@ var init_wrap_backend = __esm({
|
|
|
24515
25370
|
|
|
24516
25371
|
// src/agents/runners/config-loader.ts
|
|
24517
25372
|
import { readFileSync as readFileSync14, readdirSync as readdirSync14, existsSync as existsSync23, mkdirSync as mkdirSync10, watchFile, unwatchFile } from "fs";
|
|
24518
|
-
import { join as
|
|
25373
|
+
import { join as join27 } from "path";
|
|
24519
25374
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
24520
25375
|
function resolveExecutable2(config2) {
|
|
24521
25376
|
if (existsSync23(config2.executable)) return config2.executable;
|
|
@@ -24651,7 +25506,7 @@ function configToRunner(config2) {
|
|
|
24651
25506
|
prepareMcpInjection() {
|
|
24652
25507
|
return [];
|
|
24653
25508
|
},
|
|
24654
|
-
getSkillPath: () =>
|
|
25509
|
+
getSkillPath: () => join27(SKILLS_PATH, `agent-${config2.id}.md`)
|
|
24655
25510
|
};
|
|
24656
25511
|
}
|
|
24657
25512
|
function loadRunnerConfig(filePath) {
|
|
@@ -24671,7 +25526,7 @@ function loadAllRunnerConfigs() {
|
|
|
24671
25526
|
const files = readdirSync14(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
24672
25527
|
const configs = [];
|
|
24673
25528
|
for (const file of files) {
|
|
24674
|
-
const config2 = loadRunnerConfig(
|
|
25529
|
+
const config2 = loadRunnerConfig(join27(RUNNERS_PATH, file));
|
|
24675
25530
|
if (config2) configs.push(config2);
|
|
24676
25531
|
}
|
|
24677
25532
|
return configs;
|
|
@@ -24701,7 +25556,7 @@ function watchRunnerConfigs(onChange) {
|
|
|
24701
25556
|
}
|
|
24702
25557
|
const files = readdirSync14(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
24703
25558
|
for (const file of files) {
|
|
24704
|
-
const fullPath =
|
|
25559
|
+
const fullPath = join27(RUNNERS_PATH, file);
|
|
24705
25560
|
if (watchedFiles.has(fullPath)) continue;
|
|
24706
25561
|
watchedFiles.add(fullPath);
|
|
24707
25562
|
watchFile(fullPath, { interval: 5e3 }, () => {
|
|
@@ -25321,9 +26176,11 @@ var init_telegram2 = __esm({
|
|
|
25321
26176
|
async stop() {
|
|
25322
26177
|
await this.bot.stop();
|
|
25323
26178
|
}
|
|
25324
|
-
async sendTyping(chatId) {
|
|
26179
|
+
async sendTyping(chatId, threadId) {
|
|
25325
26180
|
try {
|
|
25326
|
-
await this.bot.api.sendChatAction(numericChatId(chatId), "typing"
|
|
26181
|
+
await this.bot.api.sendChatAction(numericChatId(chatId), "typing", {
|
|
26182
|
+
...threadId ? { message_thread_id: threadId } : {}
|
|
26183
|
+
});
|
|
25327
26184
|
} catch {
|
|
25328
26185
|
}
|
|
25329
26186
|
}
|
|
@@ -25370,21 +26227,23 @@ var init_telegram2 = __esm({
|
|
|
25370
26227
|
}
|
|
25371
26228
|
}
|
|
25372
26229
|
}
|
|
25373
|
-
async sendVoice(chatId, audioBuffer, fileName) {
|
|
26230
|
+
async sendVoice(chatId, audioBuffer, fileName, threadId) {
|
|
25374
26231
|
await withRetry(
|
|
25375
26232
|
"sendVoice",
|
|
25376
26233
|
() => this.bot.api.sendVoice(
|
|
25377
26234
|
numericChatId(chatId),
|
|
25378
|
-
new InputFile(audioBuffer, fileName ?? "response.ogg")
|
|
26235
|
+
new InputFile(audioBuffer, fileName ?? "response.ogg"),
|
|
26236
|
+
{ ...threadId ? { message_thread_id: threadId } : {} }
|
|
25379
26237
|
)
|
|
25380
26238
|
);
|
|
25381
26239
|
}
|
|
25382
|
-
async sendFile(chatId, buffer, fileName) {
|
|
26240
|
+
async sendFile(chatId, buffer, fileName, _mimeType, threadId) {
|
|
25383
26241
|
await withRetry(
|
|
25384
26242
|
"sendFile",
|
|
25385
26243
|
() => this.bot.api.sendDocument(
|
|
25386
26244
|
numericChatId(chatId),
|
|
25387
|
-
new InputFile(buffer, fileName)
|
|
26245
|
+
new InputFile(buffer, fileName),
|
|
26246
|
+
{ ...threadId ? { message_thread_id: threadId } : {} }
|
|
25388
26247
|
)
|
|
25389
26248
|
);
|
|
25390
26249
|
}
|
|
@@ -25394,10 +26253,11 @@ var init_telegram2 = __esm({
|
|
|
25394
26253
|
const response = await fetch(fileUrl);
|
|
25395
26254
|
return Buffer.from(await response.arrayBuffer());
|
|
25396
26255
|
}
|
|
25397
|
-
async sendTextReturningId(chatId, text, parseMode) {
|
|
26256
|
+
async sendTextReturningId(chatId, text, parseMode, threadId) {
|
|
25398
26257
|
try {
|
|
25399
26258
|
const formatted = sanitizeForTelegram(parseMode === "html" ? text : parseMode === "plain" ? text : formatForTelegram(text));
|
|
25400
|
-
const
|
|
26259
|
+
const threadOpts = threadId ? { message_thread_id: threadId } : {};
|
|
26260
|
+
const opts = parseMode === "plain" ? { ...threadOpts } : { parse_mode: "HTML", ...threadOpts };
|
|
25401
26261
|
const msg = await withRetry(
|
|
25402
26262
|
"sendTextReturningId",
|
|
25403
26263
|
() => this.bot.api.sendMessage(numericChatId(chatId), formatted, opts)
|
|
@@ -25485,7 +26345,7 @@ var init_telegram2 = __esm({
|
|
|
25485
26345
|
onReaction(handler) {
|
|
25486
26346
|
this.reactionHandlers.push(handler);
|
|
25487
26347
|
}
|
|
25488
|
-
async sendKeyboard(chatId, text, buttons) {
|
|
26348
|
+
async sendKeyboard(chatId, text, buttons, threadId) {
|
|
25489
26349
|
const keyboard = new InlineKeyboard();
|
|
25490
26350
|
for (const row of buttons) {
|
|
25491
26351
|
for (const btn of row) {
|
|
@@ -25499,12 +26359,14 @@ var init_telegram2 = __esm({
|
|
|
25499
26359
|
const MAX_KEYBOARD_TEXT = 4e3;
|
|
25500
26360
|
const safeText = text.length > MAX_KEYBOARD_TEXT ? text.slice(0, MAX_KEYBOARD_TEXT) + "\n\n\u2026(truncated)" : text;
|
|
25501
26361
|
const formatted = sanitizeForTelegram(formatForTelegram(safeText));
|
|
26362
|
+
const threadOpts = threadId ? { message_thread_id: threadId } : {};
|
|
25502
26363
|
try {
|
|
25503
26364
|
const msg = await withRetry(
|
|
25504
26365
|
"sendKeyboard",
|
|
25505
26366
|
() => this.bot.api.sendMessage(numericChatId(chatId), formatted, {
|
|
25506
26367
|
parse_mode: "HTML",
|
|
25507
|
-
reply_markup: keyboard
|
|
26368
|
+
reply_markup: keyboard,
|
|
26369
|
+
...threadOpts
|
|
25508
26370
|
})
|
|
25509
26371
|
);
|
|
25510
26372
|
return msg.message_id.toString();
|
|
@@ -25519,7 +26381,8 @@ var init_telegram2 = __esm({
|
|
|
25519
26381
|
const retryMsg = await withRetry(
|
|
25520
26382
|
"sendKeyboard:plain",
|
|
25521
26383
|
() => this.bot.api.sendMessage(numericChatId(chatId), escaped, {
|
|
25522
|
-
reply_markup: keyboard
|
|
26384
|
+
reply_markup: keyboard,
|
|
26385
|
+
...threadOpts
|
|
25523
26386
|
})
|
|
25524
26387
|
);
|
|
25525
26388
|
return retryMsg.message_id.toString();
|
|
@@ -25532,7 +26395,7 @@ var init_telegram2 = __esm({
|
|
|
25532
26395
|
if (plainText.trim()) {
|
|
25533
26396
|
await withRetry(
|
|
25534
26397
|
"sendKeyboard:text-rescue",
|
|
25535
|
-
() => this.bot.api.sendMessage(numericChatId(chatId), plainText, {})
|
|
26398
|
+
() => this.bot.api.sendMessage(numericChatId(chatId), plainText, { ...threadOpts })
|
|
25536
26399
|
);
|
|
25537
26400
|
}
|
|
25538
26401
|
} catch {
|
|
@@ -25541,7 +26404,8 @@ var init_telegram2 = __esm({
|
|
|
25541
26404
|
const fallbackMsg = await withRetry(
|
|
25542
26405
|
"sendKeyboard:fallback",
|
|
25543
26406
|
() => this.bot.api.sendMessage(numericChatId(chatId), "\u2B06\uFE0F (see above for details)", {
|
|
25544
|
-
reply_markup: keyboard
|
|
26407
|
+
reply_markup: keyboard,
|
|
26408
|
+
...threadOpts
|
|
25545
26409
|
})
|
|
25546
26410
|
);
|
|
25547
26411
|
return fallbackMsg.message_id.toString();
|
|
@@ -25633,6 +26497,7 @@ var init_telegram2 = __esm({
|
|
|
25633
26497
|
const fwdOrigin = ctx.message?.forward_origin;
|
|
25634
26498
|
const fwdFromChat = ctx.message?.forward_from_chat;
|
|
25635
26499
|
const forwardedFrom = fwdOrigin?.chat?.title ?? fwdOrigin?.sender_chat?.title ?? fwdOrigin?.sender_user?.first_name ?? fwdOrigin?.sender_user_name ?? fwdFromChat?.title ?? void 0;
|
|
26500
|
+
const threadId = ctx.message?.message_thread_id;
|
|
25636
26501
|
if (ctx.message?.voice) {
|
|
25637
26502
|
return {
|
|
25638
26503
|
chatId,
|
|
@@ -25646,6 +26511,7 @@ var init_telegram2 = __esm({
|
|
|
25646
26511
|
chatTitle,
|
|
25647
26512
|
replyToText,
|
|
25648
26513
|
forwardedFrom,
|
|
26514
|
+
threadId,
|
|
25649
26515
|
raw: ctx
|
|
25650
26516
|
};
|
|
25651
26517
|
}
|
|
@@ -25665,6 +26531,7 @@ var init_telegram2 = __esm({
|
|
|
25665
26531
|
chatTitle,
|
|
25666
26532
|
replyToText,
|
|
25667
26533
|
forwardedFrom,
|
|
26534
|
+
threadId,
|
|
25668
26535
|
raw: ctx
|
|
25669
26536
|
};
|
|
25670
26537
|
}
|
|
@@ -25682,6 +26549,7 @@ var init_telegram2 = __esm({
|
|
|
25682
26549
|
chatTitle,
|
|
25683
26550
|
replyToText,
|
|
25684
26551
|
forwardedFrom,
|
|
26552
|
+
threadId,
|
|
25685
26553
|
raw: ctx
|
|
25686
26554
|
};
|
|
25687
26555
|
}
|
|
@@ -25708,6 +26576,7 @@ var init_telegram2 = __esm({
|
|
|
25708
26576
|
chatTitle,
|
|
25709
26577
|
replyToText,
|
|
25710
26578
|
forwardedFrom,
|
|
26579
|
+
threadId,
|
|
25711
26580
|
raw: ctx
|
|
25712
26581
|
};
|
|
25713
26582
|
}
|
|
@@ -25729,6 +26598,7 @@ var init_telegram2 = __esm({
|
|
|
25729
26598
|
chatTitle,
|
|
25730
26599
|
replyToText,
|
|
25731
26600
|
forwardedFrom,
|
|
26601
|
+
threadId,
|
|
25732
26602
|
raw: ctx
|
|
25733
26603
|
};
|
|
25734
26604
|
}
|
|
@@ -25742,6 +26612,7 @@ var init_telegram2 = __esm({
|
|
|
25742
26612
|
chatTitle,
|
|
25743
26613
|
replyToText,
|
|
25744
26614
|
forwardedFrom,
|
|
26615
|
+
threadId,
|
|
25745
26616
|
raw: ctx
|
|
25746
26617
|
};
|
|
25747
26618
|
}
|
|
@@ -25753,8 +26624,8 @@ var init_telegram2 = __esm({
|
|
|
25753
26624
|
|
|
25754
26625
|
// src/skills/bootstrap.ts
|
|
25755
26626
|
import { existsSync as existsSync24 } from "fs";
|
|
25756
|
-
import { readdir as readdir5, readFile as readFile8, writeFile as
|
|
25757
|
-
import { join as
|
|
26627
|
+
import { readdir as readdir5, readFile as readFile8, writeFile as writeFile5, copyFile } from "fs/promises";
|
|
26628
|
+
import { join as join28, dirname as dirname5 } from "path";
|
|
25758
26629
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
25759
26630
|
async function copyAgentManifestSkills() {
|
|
25760
26631
|
if (!existsSync24(PKG_SKILLS)) return;
|
|
@@ -25762,8 +26633,8 @@ async function copyAgentManifestSkills() {
|
|
|
25762
26633
|
const entries = await readdir5(PKG_SKILLS, { withFileTypes: true });
|
|
25763
26634
|
for (const entry of entries) {
|
|
25764
26635
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
25765
|
-
const src =
|
|
25766
|
-
const dest =
|
|
26636
|
+
const src = join28(PKG_SKILLS, entry.name);
|
|
26637
|
+
const dest = join28(SKILLS_PATH, entry.name);
|
|
25767
26638
|
if (existsSync24(dest)) continue;
|
|
25768
26639
|
await copyFile(src, dest);
|
|
25769
26640
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
@@ -25774,7 +26645,7 @@ async function copyAgentManifestSkills() {
|
|
|
25774
26645
|
}
|
|
25775
26646
|
async function bootstrapSkills() {
|
|
25776
26647
|
await copyAgentManifestSkills();
|
|
25777
|
-
const usmDir =
|
|
26648
|
+
const usmDir = join28(SKILLS_PATH, USM_DIR_NAME);
|
|
25778
26649
|
if (existsSync24(usmDir)) return;
|
|
25779
26650
|
try {
|
|
25780
26651
|
const entries = await readdir5(SKILLS_PATH);
|
|
@@ -25798,7 +26669,7 @@ async function bootstrapSkills() {
|
|
|
25798
26669
|
}
|
|
25799
26670
|
}
|
|
25800
26671
|
async function patchUsmForCcClaw(usmDir) {
|
|
25801
|
-
const skillPath =
|
|
26672
|
+
const skillPath = join28(usmDir, "SKILL.md");
|
|
25802
26673
|
if (!existsSync24(skillPath)) return;
|
|
25803
26674
|
try {
|
|
25804
26675
|
let content = await readFile8(skillPath, "utf-8");
|
|
@@ -25827,7 +26698,7 @@ async function patchUsmForCcClaw(usmDir) {
|
|
|
25827
26698
|
}
|
|
25828
26699
|
}
|
|
25829
26700
|
if (patched) {
|
|
25830
|
-
await
|
|
26701
|
+
await writeFile5(skillPath, content, "utf-8");
|
|
25831
26702
|
log("[skills] Patched USM SKILL.md with CC-Claw support");
|
|
25832
26703
|
}
|
|
25833
26704
|
} catch (err) {
|
|
@@ -25844,8 +26715,8 @@ var init_bootstrap = __esm({
|
|
|
25844
26715
|
USM_REPO = "jacob-bd/universal-skills-manager";
|
|
25845
26716
|
USM_DIR_NAME = "universal-skills-manager";
|
|
25846
26717
|
CC_CLAW_ECOSYSTEM_PATCH = `| **CC-Claw** | \`~/.cc-claw/workspace/skills/\` | N/A (daemon, no project scope) |`;
|
|
25847
|
-
PKG_ROOT =
|
|
25848
|
-
PKG_SKILLS =
|
|
26718
|
+
PKG_ROOT = join28(dirname5(fileURLToPath2(import.meta.url)), "..", "..");
|
|
26719
|
+
PKG_SKILLS = join28(PKG_ROOT, "skills");
|
|
25849
26720
|
}
|
|
25850
26721
|
});
|
|
25851
26722
|
|
|
@@ -26068,7 +26939,7 @@ __export(ai_skill_exports, {
|
|
|
26068
26939
|
installAiSkill: () => installAiSkill
|
|
26069
26940
|
});
|
|
26070
26941
|
import { existsSync as existsSync25, writeFileSync as writeFileSync8, mkdirSync as mkdirSync11 } from "fs";
|
|
26071
|
-
import { join as
|
|
26942
|
+
import { join as join29 } from "path";
|
|
26072
26943
|
import { homedir as homedir9 } from "os";
|
|
26073
26944
|
function generateAiSkill() {
|
|
26074
26945
|
const version = VERSION;
|
|
@@ -26488,8 +27359,8 @@ function installAiSkill() {
|
|
|
26488
27359
|
const failed = [];
|
|
26489
27360
|
for (const [backend2, dirs] of Object.entries(BACKEND_SKILL_DIRS2)) {
|
|
26490
27361
|
for (const dir of dirs) {
|
|
26491
|
-
const skillDir =
|
|
26492
|
-
const skillPath =
|
|
27362
|
+
const skillDir = join29(dir, "cc-claw-cli");
|
|
27363
|
+
const skillPath = join29(skillDir, "SKILL.md");
|
|
26493
27364
|
try {
|
|
26494
27365
|
mkdirSync11(skillDir, { recursive: true });
|
|
26495
27366
|
writeFileSync8(skillPath, skill, "utf-8");
|
|
@@ -26508,11 +27379,11 @@ var init_ai_skill = __esm({
|
|
|
26508
27379
|
init_paths();
|
|
26509
27380
|
init_version();
|
|
26510
27381
|
BACKEND_SKILL_DIRS2 = {
|
|
26511
|
-
"cc-claw": [
|
|
26512
|
-
claude: [
|
|
26513
|
-
gemini: [
|
|
26514
|
-
codex: [
|
|
26515
|
-
cursor: [
|
|
27382
|
+
"cc-claw": [join29(homedir9(), ".cc-claw", "workspace", "skills")],
|
|
27383
|
+
claude: [join29(homedir9(), ".claude", "skills")],
|
|
27384
|
+
gemini: [join29(homedir9(), ".gemini", "skills")],
|
|
27385
|
+
codex: [join29(homedir9(), ".agents", "skills")],
|
|
27386
|
+
cursor: [join29(homedir9(), ".cursor", "skills"), join29(homedir9(), ".cursor", "skills-cursor")]
|
|
26516
27387
|
};
|
|
26517
27388
|
}
|
|
26518
27389
|
});
|
|
@@ -26523,17 +27394,17 @@ __export(index_exports, {
|
|
|
26523
27394
|
main: () => main
|
|
26524
27395
|
});
|
|
26525
27396
|
import { mkdirSync as mkdirSync12, existsSync as existsSync26, renameSync as renameSync2, statSync as statSync8, readFileSync as readFileSync16 } from "fs";
|
|
26526
|
-
import { join as
|
|
27397
|
+
import { join as join30 } from "path";
|
|
26527
27398
|
import dotenv from "dotenv";
|
|
26528
27399
|
function migrateLayout() {
|
|
26529
27400
|
const moves = [
|
|
26530
|
-
[
|
|
26531
|
-
[
|
|
26532
|
-
[
|
|
26533
|
-
[
|
|
26534
|
-
[
|
|
26535
|
-
[
|
|
26536
|
-
[
|
|
27401
|
+
[join30(CC_CLAW_HOME, "cc-claw.db"), join30(DATA_PATH, "cc-claw.db")],
|
|
27402
|
+
[join30(CC_CLAW_HOME, "cc-claw.db-shm"), join30(DATA_PATH, "cc-claw.db-shm")],
|
|
27403
|
+
[join30(CC_CLAW_HOME, "cc-claw.db-wal"), join30(DATA_PATH, "cc-claw.db-wal")],
|
|
27404
|
+
[join30(CC_CLAW_HOME, "cc-claw.log"), join30(LOGS_PATH, "cc-claw.log")],
|
|
27405
|
+
[join30(CC_CLAW_HOME, "cc-claw.log.1"), join30(LOGS_PATH, "cc-claw.log.1")],
|
|
27406
|
+
[join30(CC_CLAW_HOME, "cc-claw.error.log"), join30(LOGS_PATH, "cc-claw.error.log")],
|
|
27407
|
+
[join30(CC_CLAW_HOME, "cc-claw.error.log.1"), join30(LOGS_PATH, "cc-claw.error.log.1")]
|
|
26537
27408
|
];
|
|
26538
27409
|
for (const [from, to] of moves) {
|
|
26539
27410
|
if (existsSync26(from) && !existsSync26(to)) {
|
|
@@ -26713,10 +27584,10 @@ async function main() {
|
|
|
26713
27584
|
try {
|
|
26714
27585
|
const { generateAiSkill: generateAiSkill2 } = await Promise.resolve().then(() => (init_ai_skill(), ai_skill_exports));
|
|
26715
27586
|
const { writeFileSync: writeFileSync13, mkdirSync: mkdirSync19 } = await import("fs");
|
|
26716
|
-
const { join:
|
|
26717
|
-
const skillDir =
|
|
27587
|
+
const { join: join36 } = await import("path");
|
|
27588
|
+
const skillDir = join36(SKILLS_PATH, "cc-claw-cli");
|
|
26718
27589
|
mkdirSync19(skillDir, { recursive: true });
|
|
26719
|
-
writeFileSync13(
|
|
27590
|
+
writeFileSync13(join36(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
|
|
26720
27591
|
log("[cc-claw] AI skill updated");
|
|
26721
27592
|
} catch {
|
|
26722
27593
|
}
|
|
@@ -26947,7 +27818,7 @@ __export(service_exports2, {
|
|
|
26947
27818
|
import { existsSync as existsSync28, mkdirSync as mkdirSync13, writeFileSync as writeFileSync9, unlinkSync as unlinkSync8 } from "fs";
|
|
26948
27819
|
import { execFileSync as execFileSync3, execSync as execSync4 } from "child_process";
|
|
26949
27820
|
import { homedir as homedir10, platform } from "os";
|
|
26950
|
-
import { join as
|
|
27821
|
+
import { join as join31, dirname as dirname6 } from "path";
|
|
26951
27822
|
function xmlEscape(s) {
|
|
26952
27823
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
26953
27824
|
}
|
|
@@ -26965,14 +27836,14 @@ function getPathDirs() {
|
|
|
26965
27836
|
const home = homedir10();
|
|
26966
27837
|
const dirs = /* @__PURE__ */ new Set([
|
|
26967
27838
|
nodeBin,
|
|
26968
|
-
|
|
27839
|
+
join31(home, ".local", "bin"),
|
|
26969
27840
|
"/usr/local/bin",
|
|
26970
27841
|
"/usr/bin",
|
|
26971
27842
|
"/bin"
|
|
26972
27843
|
]);
|
|
26973
27844
|
try {
|
|
26974
27845
|
const prefix = execSync4("npm config get prefix", { encoding: "utf-8" }).trim();
|
|
26975
|
-
if (prefix) dirs.add(
|
|
27846
|
+
if (prefix) dirs.add(join31(prefix, "bin"));
|
|
26976
27847
|
} catch {
|
|
26977
27848
|
}
|
|
26978
27849
|
return [...dirs].join(":");
|
|
@@ -27155,7 +28026,7 @@ function statusLinux() {
|
|
|
27155
28026
|
}
|
|
27156
28027
|
}
|
|
27157
28028
|
function installService() {
|
|
27158
|
-
if (!existsSync28(
|
|
28029
|
+
if (!existsSync28(join31(CC_CLAW_HOME, ".env"))) {
|
|
27159
28030
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
27160
28031
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
27161
28032
|
process.exitCode = 1;
|
|
@@ -27184,9 +28055,9 @@ var init_service2 = __esm({
|
|
|
27184
28055
|
"use strict";
|
|
27185
28056
|
init_paths();
|
|
27186
28057
|
PLIST_LABEL = "com.cc-claw";
|
|
27187
|
-
PLIST_PATH =
|
|
27188
|
-
SYSTEMD_DIR =
|
|
27189
|
-
UNIT_PATH =
|
|
28058
|
+
PLIST_PATH = join31(homedir10(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
28059
|
+
SYSTEMD_DIR = join31(homedir10(), ".config", "systemd", "user");
|
|
28060
|
+
UNIT_PATH = join31(SYSTEMD_DIR, "cc-claw.service");
|
|
27190
28061
|
}
|
|
27191
28062
|
});
|
|
27192
28063
|
|
|
@@ -28086,12 +28957,14 @@ __export(gemini_exports, {
|
|
|
28086
28957
|
geminiDisable: () => geminiDisable,
|
|
28087
28958
|
geminiEnable: () => geminiEnable,
|
|
28088
28959
|
geminiList: () => geminiList,
|
|
28960
|
+
geminiRelogin: () => geminiRelogin,
|
|
28089
28961
|
geminiRemove: () => geminiRemove,
|
|
28962
|
+
geminiRename: () => geminiRename,
|
|
28090
28963
|
geminiReorder: () => geminiReorder,
|
|
28091
28964
|
geminiRotation: () => geminiRotation
|
|
28092
28965
|
});
|
|
28093
28966
|
import { existsSync as existsSync33, mkdirSync as mkdirSync14, writeFileSync as writeFileSync10, readFileSync as readFileSync23, chmodSync } from "fs";
|
|
28094
|
-
import { join as
|
|
28967
|
+
import { join as join32 } from "path";
|
|
28095
28968
|
import { createInterface as createInterface8 } from "readline";
|
|
28096
28969
|
function requireDb() {
|
|
28097
28970
|
if (!existsSync33(DB_PATH)) {
|
|
@@ -28119,7 +28992,7 @@ async function resolveSlotId(idOrLabel) {
|
|
|
28119
28992
|
function resolveOAuthEmail(configHome) {
|
|
28120
28993
|
if (!configHome) return null;
|
|
28121
28994
|
try {
|
|
28122
|
-
const accountsPath =
|
|
28995
|
+
const accountsPath = join32(configHome, ".gemini", "google_accounts.json");
|
|
28123
28996
|
if (!existsSync33(accountsPath)) return null;
|
|
28124
28997
|
const accounts = JSON.parse(readFileSync23(accountsPath, "utf-8"));
|
|
28125
28998
|
return accounts.active || null;
|
|
@@ -28203,14 +29076,14 @@ async function geminiAddKey(globalOpts, opts) {
|
|
|
28203
29076
|
}
|
|
28204
29077
|
async function geminiAddAccount(globalOpts, opts) {
|
|
28205
29078
|
await requireWriteDb();
|
|
28206
|
-
const slotsDir =
|
|
29079
|
+
const slotsDir = join32(CC_CLAW_HOME, "gemini-slots");
|
|
28207
29080
|
if (!existsSync33(slotsDir)) mkdirSync14(slotsDir, { recursive: true });
|
|
28208
29081
|
const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
28209
29082
|
const tempId = Date.now();
|
|
28210
|
-
const slotDir =
|
|
29083
|
+
const slotDir = join32(slotsDir, `slot-${tempId}`);
|
|
28211
29084
|
mkdirSync14(slotDir, { recursive: true, mode: 448 });
|
|
28212
|
-
mkdirSync14(
|
|
28213
|
-
writeFileSync10(
|
|
29085
|
+
mkdirSync14(join32(slotDir, ".gemini"), { recursive: true });
|
|
29086
|
+
writeFileSync10(join32(slotDir, ".gemini", "settings.json"), JSON.stringify({
|
|
28214
29087
|
security: { auth: { selectedType: "oauth-personal" } }
|
|
28215
29088
|
}, null, 2));
|
|
28216
29089
|
console.log("");
|
|
@@ -28227,7 +29100,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
28227
29100
|
});
|
|
28228
29101
|
} catch {
|
|
28229
29102
|
}
|
|
28230
|
-
const oauthPath =
|
|
29103
|
+
const oauthPath = join32(slotDir, ".gemini", "oauth_creds.json");
|
|
28231
29104
|
if (!existsSync33(oauthPath)) {
|
|
28232
29105
|
console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
|
|
28233
29106
|
console.log(" The slot directory is preserved at: " + slotDir);
|
|
@@ -28236,7 +29109,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
28236
29109
|
}
|
|
28237
29110
|
let accountEmail = "unknown";
|
|
28238
29111
|
try {
|
|
28239
|
-
const accounts = JSON.parse(__require("fs").readFileSync(
|
|
29112
|
+
const accounts = JSON.parse(__require("fs").readFileSync(join32(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
|
|
28240
29113
|
accountEmail = accounts.active || accountEmail;
|
|
28241
29114
|
} catch {
|
|
28242
29115
|
}
|
|
@@ -28311,6 +29184,92 @@ async function geminiReorder(globalOpts, idOrLabel, priority) {
|
|
|
28311
29184
|
() => success(`Slot "${idOrLabel}" (#${slotId}) priority set to ${priority}`)
|
|
28312
29185
|
);
|
|
28313
29186
|
}
|
|
29187
|
+
async function geminiRename(globalOpts, idOrLabel, newLabel) {
|
|
29188
|
+
await requireWriteDb();
|
|
29189
|
+
const slotId = await resolveSlotId(idOrLabel);
|
|
29190
|
+
if (!slotId) {
|
|
29191
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29192
|
+
return;
|
|
29193
|
+
}
|
|
29194
|
+
const { renameGeminiSlot: renameGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29195
|
+
const updated = renameGeminiSlot2(slotId, newLabel);
|
|
29196
|
+
if (updated) {
|
|
29197
|
+
output({ id: slotId, label: newLabel }, () => success(`Renamed slot #${slotId} \u2192 "${newLabel}"`));
|
|
29198
|
+
} else {
|
|
29199
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29200
|
+
}
|
|
29201
|
+
}
|
|
29202
|
+
async function geminiRelogin(globalOpts, idOrLabel) {
|
|
29203
|
+
await requireWriteDb();
|
|
29204
|
+
const slotId = await resolveSlotId(idOrLabel);
|
|
29205
|
+
if (!slotId) {
|
|
29206
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29207
|
+
return;
|
|
29208
|
+
}
|
|
29209
|
+
const { getGeminiSlots: getGeminiSlots2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29210
|
+
const slot = getGeminiSlots2().find((s) => s.id === slotId);
|
|
29211
|
+
if (!slot) {
|
|
29212
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29213
|
+
return;
|
|
29214
|
+
}
|
|
29215
|
+
if (slot.slotType !== "oauth") {
|
|
29216
|
+
outputError("NOT_OAUTH", `Slot "${idOrLabel}" is an API key slot \u2014 re-login only works for OAuth slots.`);
|
|
29217
|
+
return;
|
|
29218
|
+
}
|
|
29219
|
+
if (!slot.configHome) {
|
|
29220
|
+
outputError("NO_CONFIG", `Slot "${idOrLabel}" has no config directory \u2014 cannot re-login.`);
|
|
29221
|
+
return;
|
|
29222
|
+
}
|
|
29223
|
+
const settingsPath = join32(slot.configHome, ".gemini", "settings.json");
|
|
29224
|
+
if (!existsSync33(settingsPath)) {
|
|
29225
|
+
mkdirSync14(join32(slot.configHome, ".gemini"), { recursive: true });
|
|
29226
|
+
writeFileSync10(settingsPath, JSON.stringify({
|
|
29227
|
+
security: { auth: { selectedType: "oauth-personal" } }
|
|
29228
|
+
}, null, 2));
|
|
29229
|
+
}
|
|
29230
|
+
console.log("");
|
|
29231
|
+
console.log(` Re-authenticating Gemini slot "${slot.label || `#${slot.id}`}"...`);
|
|
29232
|
+
console.log(" Sign in with the same Google account when prompted.");
|
|
29233
|
+
console.log(" After sign-in, type /quit to return here.");
|
|
29234
|
+
console.log("");
|
|
29235
|
+
const { execSync: execSync6 } = await import("child_process");
|
|
29236
|
+
try {
|
|
29237
|
+
execSync6(`gemini`, {
|
|
29238
|
+
stdio: "inherit",
|
|
29239
|
+
env: {
|
|
29240
|
+
...process.env,
|
|
29241
|
+
GEMINI_CLI_HOME: slot.configHome,
|
|
29242
|
+
GEMINI_API_KEY: void 0,
|
|
29243
|
+
GOOGLE_API_KEY: void 0
|
|
29244
|
+
},
|
|
29245
|
+
cwd: slot.configHome
|
|
29246
|
+
});
|
|
29247
|
+
} catch {
|
|
29248
|
+
}
|
|
29249
|
+
const oauthPath = join32(slot.configHome, ".gemini", "oauth_creds.json");
|
|
29250
|
+
if (!existsSync33(oauthPath)) {
|
|
29251
|
+
console.log(error2("\n Re-login failed \u2014 no OAuth credentials found."));
|
|
29252
|
+
console.log(` Try again: cc-claw gemini re-login ${idOrLabel}
|
|
29253
|
+
`);
|
|
29254
|
+
process.exit(1);
|
|
29255
|
+
}
|
|
29256
|
+
const { setGeminiSlotEnabled: setGeminiSlotEnabled2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29257
|
+
setGeminiSlotEnabled2(slotId, true);
|
|
29258
|
+
let accountEmail = slot.label;
|
|
29259
|
+
try {
|
|
29260
|
+
const accounts = JSON.parse(readFileSync23(join32(slot.configHome, ".gemini", "google_accounts.json"), "utf-8"));
|
|
29261
|
+
if (accounts.active) accountEmail = accounts.active;
|
|
29262
|
+
} catch {
|
|
29263
|
+
}
|
|
29264
|
+
if (accountEmail && accountEmail !== slot.label) {
|
|
29265
|
+
const { renameGeminiSlot: renameGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29266
|
+
renameGeminiSlot2(slotId, accountEmail);
|
|
29267
|
+
}
|
|
29268
|
+
output(
|
|
29269
|
+
{ id: slotId, label: accountEmail, refreshed: true },
|
|
29270
|
+
() => success(`Re-authenticated Gemini slot #${slotId} (${accountEmail})`)
|
|
29271
|
+
);
|
|
29272
|
+
}
|
|
28314
29273
|
async function geminiRotation(globalOpts, mode) {
|
|
28315
29274
|
const validModes = ["off", "all", "accounts", "keys"];
|
|
28316
29275
|
if (!mode) {
|
|
@@ -28351,12 +29310,14 @@ __export(backend_cmd_factory_exports, {
|
|
|
28351
29310
|
makeEnable: () => makeEnable,
|
|
28352
29311
|
makeList: () => makeList,
|
|
28353
29312
|
makeRefresh: () => makeRefresh,
|
|
29313
|
+
makeRelogin: () => makeRelogin,
|
|
28354
29314
|
makeRemove: () => makeRemove,
|
|
29315
|
+
makeRename: () => makeRename,
|
|
28355
29316
|
makeReorder: () => makeReorder,
|
|
28356
29317
|
registerBackendSlotCommands: () => registerBackendSlotCommands
|
|
28357
29318
|
});
|
|
28358
29319
|
import { existsSync as existsSync34, mkdirSync as mkdirSync15, readFileSync as readFileSync24 } from "fs";
|
|
28359
|
-
import { join as
|
|
29320
|
+
import { join as join33 } from "path";
|
|
28360
29321
|
import { createInterface as createInterface9 } from "readline";
|
|
28361
29322
|
function requireDb2() {
|
|
28362
29323
|
if (!existsSync34(DB_PATH)) {
|
|
@@ -28448,10 +29409,10 @@ function makeAddAccount(backend2, displayName) {
|
|
|
28448
29409
|
process.exit(1);
|
|
28449
29410
|
}
|
|
28450
29411
|
await requireWriteDb2();
|
|
28451
|
-
const slotsDir =
|
|
29412
|
+
const slotsDir = join33(CC_CLAW_HOME, config2.slotsSubdir);
|
|
28452
29413
|
if (!existsSync34(slotsDir)) mkdirSync15(slotsDir, { recursive: true });
|
|
28453
29414
|
const tempId = Date.now();
|
|
28454
|
-
const slotDir =
|
|
29415
|
+
const slotDir = join33(slotsDir, `slot-${tempId}`);
|
|
28455
29416
|
mkdirSync15(slotDir, { recursive: true, mode: 448 });
|
|
28456
29417
|
if (config2.preSetup) config2.preSetup(slotDir);
|
|
28457
29418
|
console.log("");
|
|
@@ -28562,6 +29523,88 @@ function makeReorder(backend2, _displayName) {
|
|
|
28562
29523
|
);
|
|
28563
29524
|
};
|
|
28564
29525
|
}
|
|
29526
|
+
function makeRename(backend2, _displayName) {
|
|
29527
|
+
return async function rename(_globalOpts, idOrLabel, newLabel) {
|
|
29528
|
+
await requireWriteDb2();
|
|
29529
|
+
const slotId = await resolveSlotId2(backend2, idOrLabel);
|
|
29530
|
+
if (!slotId) {
|
|
29531
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29532
|
+
return;
|
|
29533
|
+
}
|
|
29534
|
+
const { renameBackendSlot: renameBackendSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29535
|
+
const updated = renameBackendSlot2(slotId, newLabel);
|
|
29536
|
+
if (updated) {
|
|
29537
|
+
output({ id: slotId, label: newLabel }, () => success(`Renamed slot #${slotId} \u2192 "${newLabel}"`));
|
|
29538
|
+
} else {
|
|
29539
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29540
|
+
}
|
|
29541
|
+
};
|
|
29542
|
+
}
|
|
29543
|
+
function makeRelogin(backend2, displayName) {
|
|
29544
|
+
return async function relogin(_globalOpts, idOrLabel) {
|
|
29545
|
+
const config2 = ADD_ACCOUNT_CONFIGS[backend2];
|
|
29546
|
+
if (!config2) {
|
|
29547
|
+
outputError("UNSUPPORTED", `re-login is not supported for ${displayName}. Only OAuth/subscription slots can be re-logged.`);
|
|
29548
|
+
process.exit(1);
|
|
29549
|
+
}
|
|
29550
|
+
await requireWriteDb2();
|
|
29551
|
+
const slotId = await resolveSlotId2(backend2, idOrLabel);
|
|
29552
|
+
if (!slotId) {
|
|
29553
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29554
|
+
return;
|
|
29555
|
+
}
|
|
29556
|
+
const { getBackendSlots: getBackendSlots2, reenableBackendSlot: reenableBackendSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29557
|
+
const slot = getBackendSlots2(backend2).find((s) => s.id === slotId);
|
|
29558
|
+
if (!slot) {
|
|
29559
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29560
|
+
return;
|
|
29561
|
+
}
|
|
29562
|
+
if (slot.slotType !== "oauth") {
|
|
29563
|
+
outputError("NOT_OAUTH", `Slot "${idOrLabel}" is an API key slot \u2014 re-login only works for OAuth/subscription slots.`);
|
|
29564
|
+
return;
|
|
29565
|
+
}
|
|
29566
|
+
if (!slot.configHome) {
|
|
29567
|
+
outputError("NO_CONFIG", `Slot "${idOrLabel}" has no config directory \u2014 cannot re-login.`);
|
|
29568
|
+
return;
|
|
29569
|
+
}
|
|
29570
|
+
if (config2.preSetup) config2.preSetup(slot.configHome);
|
|
29571
|
+
console.log("");
|
|
29572
|
+
console.log(` Re-authenticating ${displayName} slot "${slot.label || `#${slot.id}`}"...`);
|
|
29573
|
+
console.log(` Sign in with the same account when the browser opens.`);
|
|
29574
|
+
console.log("");
|
|
29575
|
+
const { execSync: execSync6 } = await import("child_process");
|
|
29576
|
+
const loginEnv = {
|
|
29577
|
+
...process.env,
|
|
29578
|
+
[config2.envKey]: config2.envValue(slot.configHome),
|
|
29579
|
+
...config2.envOverrides
|
|
29580
|
+
};
|
|
29581
|
+
try {
|
|
29582
|
+
execSync6(config2.loginCommand.join(" "), {
|
|
29583
|
+
stdio: "inherit",
|
|
29584
|
+
env: loginEnv,
|
|
29585
|
+
cwd: slot.configHome
|
|
29586
|
+
});
|
|
29587
|
+
} catch {
|
|
29588
|
+
}
|
|
29589
|
+
if (!config2.verifyCredentials(slot.configHome)) {
|
|
29590
|
+
console.log(error2(`
|
|
29591
|
+
Re-login failed \u2014 no credentials found.`));
|
|
29592
|
+
console.log(` Try again: cc-claw ${backend2} re-login ${idOrLabel}
|
|
29593
|
+
`);
|
|
29594
|
+
process.exit(1);
|
|
29595
|
+
}
|
|
29596
|
+
reenableBackendSlot2(slotId);
|
|
29597
|
+
const newLabel = config2.extractLabel(slot.configHome);
|
|
29598
|
+
if (newLabel && newLabel !== slot.label && newLabel !== "subscription") {
|
|
29599
|
+
const { renameBackendSlot: renameBackendSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29600
|
+
renameBackendSlot2(slotId, newLabel);
|
|
29601
|
+
}
|
|
29602
|
+
output(
|
|
29603
|
+
{ id: slotId, label: newLabel || slot.label, refreshed: true },
|
|
29604
|
+
() => success(`Re-authenticated ${displayName} slot #${slotId} (${newLabel || slot.label})`)
|
|
29605
|
+
);
|
|
29606
|
+
};
|
|
29607
|
+
}
|
|
28565
29608
|
function makeRefresh(backend2, displayName) {
|
|
28566
29609
|
return async function refresh(_globalOpts) {
|
|
28567
29610
|
await requireWriteDb2();
|
|
@@ -28620,11 +29663,11 @@ var init_backend_cmd_factory = __esm({
|
|
|
28620
29663
|
envValue: (slotDir) => slotDir,
|
|
28621
29664
|
envOverrides: { ANTHROPIC_API_KEY: void 0 },
|
|
28622
29665
|
preSetup: (slotDir) => {
|
|
28623
|
-
mkdirSync15(
|
|
29666
|
+
mkdirSync15(join33(slotDir, ".claude"), { recursive: true });
|
|
28624
29667
|
},
|
|
28625
29668
|
verifyCredentials: (slotDir) => {
|
|
28626
|
-
const claudeJson =
|
|
28627
|
-
const claudeJsonNested =
|
|
29669
|
+
const claudeJson = join33(slotDir, ".claude.json");
|
|
29670
|
+
const claudeJsonNested = join33(slotDir, ".claude", ".claude.json");
|
|
28628
29671
|
if (existsSync34(claudeJson)) {
|
|
28629
29672
|
try {
|
|
28630
29673
|
const data = JSON.parse(readFileSync24(claudeJson, "utf-8"));
|
|
@@ -28656,7 +29699,7 @@ var init_backend_cmd_factory = __esm({
|
|
|
28656
29699
|
} catch {
|
|
28657
29700
|
}
|
|
28658
29701
|
try {
|
|
28659
|
-
const claudeJson =
|
|
29702
|
+
const claudeJson = join33(slotDir, ".claude.json");
|
|
28660
29703
|
if (existsSync34(claudeJson)) {
|
|
28661
29704
|
const data = JSON.parse(readFileSync24(claudeJson, "utf-8"));
|
|
28662
29705
|
if (data.oauthAccount?.emailAddress) return data.oauthAccount.emailAddress;
|
|
@@ -28673,11 +29716,11 @@ var init_backend_cmd_factory = __esm({
|
|
|
28673
29716
|
envValue: (slotDir) => slotDir,
|
|
28674
29717
|
envOverrides: { OPENAI_API_KEY: void 0 },
|
|
28675
29718
|
verifyCredentials: (slotDir) => {
|
|
28676
|
-
return existsSync34(
|
|
29719
|
+
return existsSync34(join33(slotDir, "auth.json"));
|
|
28677
29720
|
},
|
|
28678
29721
|
extractLabel: (slotDir) => {
|
|
28679
29722
|
try {
|
|
28680
|
-
const authData = JSON.parse(readFileSync24(
|
|
29723
|
+
const authData = JSON.parse(readFileSync24(join33(slotDir, "auth.json"), "utf-8"));
|
|
28681
29724
|
if (authData.email) return authData.email;
|
|
28682
29725
|
if (authData.account_name) return authData.account_name;
|
|
28683
29726
|
if (authData.user?.email) return authData.user.email;
|
|
@@ -31041,7 +32084,7 @@ __export(completion_exports, {
|
|
|
31041
32084
|
completionCommand: () => completionCommand
|
|
31042
32085
|
});
|
|
31043
32086
|
import { writeFileSync as writeFileSync11, mkdirSync as mkdirSync17 } from "fs";
|
|
31044
|
-
import { join as
|
|
32087
|
+
import { join as join34 } from "path";
|
|
31045
32088
|
import { homedir as homedir11 } from "os";
|
|
31046
32089
|
async function completionCommand(opts) {
|
|
31047
32090
|
const shell = opts.shell ?? detectShell();
|
|
@@ -31057,10 +32100,10 @@ async function completionCommand(opts) {
|
|
|
31057
32100
|
process.exit(1);
|
|
31058
32101
|
}
|
|
31059
32102
|
if (opts.install) {
|
|
31060
|
-
const dir =
|
|
32103
|
+
const dir = join34(homedir11(), ".config", "cc-claw", "completions");
|
|
31061
32104
|
mkdirSync17(dir, { recursive: true });
|
|
31062
32105
|
const filename = shell === "zsh" ? "_cc-claw" : shell === "fish" ? "cc-claw.fish" : "cc-claw.bash";
|
|
31063
|
-
const filepath =
|
|
32106
|
+
const filepath = join34(dir, filename);
|
|
31064
32107
|
writeFileSync11(filepath, script, "utf-8");
|
|
31065
32108
|
console.log(`\u2713 Completion script written to ${filepath}
|
|
31066
32109
|
`);
|
|
@@ -31710,7 +32753,7 @@ var setup_exports = {};
|
|
|
31710
32753
|
import { existsSync as existsSync55, writeFileSync as writeFileSync12, readFileSync as readFileSync27, copyFileSync as copyFileSync4, mkdirSync as mkdirSync18, statSync as statSync12 } from "fs";
|
|
31711
32754
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
31712
32755
|
import { createInterface as createInterface11 } from "readline";
|
|
31713
|
-
import { join as
|
|
32756
|
+
import { join as join35 } from "path";
|
|
31714
32757
|
function divider2() {
|
|
31715
32758
|
console.log(dim("\u2500".repeat(55)));
|
|
31716
32759
|
}
|
|
@@ -31798,7 +32841,7 @@ async function setup() {
|
|
|
31798
32841
|
if (match) env[match[1].trim()] = match[2].trim();
|
|
31799
32842
|
}
|
|
31800
32843
|
}
|
|
31801
|
-
const cwdDb =
|
|
32844
|
+
const cwdDb = join35(process.cwd(), "cc-claw.db");
|
|
31802
32845
|
if (existsSync55(cwdDb) && !existsSync55(DB_PATH)) {
|
|
31803
32846
|
const { size } = statSync12(cwdDb);
|
|
31804
32847
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
@@ -32188,6 +33231,14 @@ gemini.command("reorder <id-or-label> <priority>").description("Set slot priorit
|
|
|
32188
33231
|
const { geminiReorder: geminiReorder2 } = await Promise.resolve().then(() => (init_gemini2(), gemini_exports));
|
|
32189
33232
|
await geminiReorder2(program.opts(), id, priority);
|
|
32190
33233
|
});
|
|
33234
|
+
gemini.command("rename <id-or-label> <new-label>").description("Rename a credential slot").action(async (id, newLabel) => {
|
|
33235
|
+
const { geminiRename: geminiRename2 } = await Promise.resolve().then(() => (init_gemini2(), gemini_exports));
|
|
33236
|
+
await geminiRename2(program.opts(), id, newLabel);
|
|
33237
|
+
});
|
|
33238
|
+
gemini.command("re-login <id-or-label>").alias("relogin").description("Re-authenticate an OAuth slot (refreshes expired token in-place)").action(async (id) => {
|
|
33239
|
+
const { geminiRelogin: geminiRelogin2 } = await Promise.resolve().then(() => (init_gemini2(), gemini_exports));
|
|
33240
|
+
await geminiRelogin2(program.opts(), id);
|
|
33241
|
+
});
|
|
32191
33242
|
gemini.command("rotation [mode]").description("Get or set rotation mode (off, all, accounts, keys)").action(async (mode) => {
|
|
32192
33243
|
const { geminiRotation: geminiRotation2 } = await Promise.resolve().then(() => (init_gemini2(), gemini_exports));
|
|
32193
33244
|
await geminiRotation2(program.opts(), mode);
|
|
@@ -32226,6 +33277,14 @@ function registerUnifiedSlotCommands(parentCmd, backendId, displayName) {
|
|
|
32226
33277
|
const { makeRefresh: makeRefresh2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
32227
33278
|
await makeRefresh2(backendId, displayName)(program.opts());
|
|
32228
33279
|
});
|
|
33280
|
+
cmd.command("rename <id-or-label> <new-label>").description("Rename a credential slot").action(async (id, newLabel) => {
|
|
33281
|
+
const { makeRename: makeRename2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
33282
|
+
await makeRename2(backendId, displayName)(program.opts(), id, newLabel);
|
|
33283
|
+
});
|
|
33284
|
+
cmd.command("re-login <id-or-label>").alias("relogin").description("Re-authenticate an OAuth/subscription slot (refreshes expired token in-place)").action(async (id) => {
|
|
33285
|
+
const { makeRelogin: makeRelogin2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
33286
|
+
await makeRelogin2(backendId, displayName)(program.opts(), id);
|
|
33287
|
+
});
|
|
32229
33288
|
}
|
|
32230
33289
|
registerUnifiedSlotCommands(program, "claude", "Claude");
|
|
32231
33290
|
registerUnifiedSlotCommands(program, "codex", "Codex");
|
|
@@ -32653,6 +33712,11 @@ optimize.command("skills").description("List available CC-Claw skills").action(a
|
|
|
32653
33712
|
const { optimizeSkills: optimizeSkills2 } = await Promise.resolve().then(() => (init_optimize2(), optimize_exports));
|
|
32654
33713
|
await optimizeSkills2();
|
|
32655
33714
|
});
|
|
33715
|
+
program.command("council").alias("debate").description("Multi-model council debate (Telegram interactive)").action(async () => {
|
|
33716
|
+
console.log("Council is an interactive Telegram command.");
|
|
33717
|
+
console.log("Use /council in Telegram to start a multi-model debate wizard.");
|
|
33718
|
+
console.log("Select 2+ models, pose a question, and they debate anonymously for up to 3 rounds.");
|
|
33719
|
+
});
|
|
32656
33720
|
program.command("start", { hidden: true }).description("Run the bot in the foreground (use 'service start' for background daemon)").action(async () => {
|
|
32657
33721
|
await Promise.resolve().then(() => (init_index(), index_exports));
|
|
32658
33722
|
});
|