cc-claw 0.19.3 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1203 -94
- 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.1" : (() => {
|
|
37
37
|
try {
|
|
38
38
|
return JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
39
39
|
} catch {
|
|
@@ -1774,6 +1774,12 @@ function initSchema(db3) {
|
|
|
1774
1774
|
value INTEGER NOT NULL DEFAULT 0
|
|
1775
1775
|
);
|
|
1776
1776
|
`);
|
|
1777
|
+
db3.exec(`
|
|
1778
|
+
CREATE TABLE IF NOT EXISTS chat_skill_suggestions (
|
|
1779
|
+
chat_id TEXT PRIMARY KEY,
|
|
1780
|
+
value INTEGER NOT NULL DEFAULT 1
|
|
1781
|
+
);
|
|
1782
|
+
`);
|
|
1777
1783
|
db3.exec(`
|
|
1778
1784
|
CREATE TABLE IF NOT EXISTS chat_session_log (
|
|
1779
1785
|
chat_id TEXT PRIMARY KEY,
|
|
@@ -2543,6 +2549,7 @@ __export(chat_settings_exports, {
|
|
|
2543
2549
|
getRecentBookmarks: () => getRecentBookmarks,
|
|
2544
2550
|
getSessionLogEnabled: () => getSessionLogEnabled,
|
|
2545
2551
|
getShowThinkingUi: () => getShowThinkingUi,
|
|
2552
|
+
getSkillSuggestionsEnabled: () => getSkillSuggestionsEnabled,
|
|
2546
2553
|
getSummarizer: () => getSummarizer,
|
|
2547
2554
|
getThinkingLevel: () => getThinkingLevel,
|
|
2548
2555
|
getToolsMap: () => getToolsMap,
|
|
@@ -2559,6 +2566,7 @@ __export(chat_settings_exports, {
|
|
|
2559
2566
|
setModel: () => setModel,
|
|
2560
2567
|
setSessionLogEnabled: () => setSessionLogEnabled,
|
|
2561
2568
|
setShowThinkingUi: () => setShowThinkingUi,
|
|
2569
|
+
setSkillSuggestionsEnabled: () => setSkillSuggestionsEnabled,
|
|
2562
2570
|
setSummarizer: () => setSummarizer,
|
|
2563
2571
|
setThinkingLevel: () => setThinkingLevel,
|
|
2564
2572
|
setVerboseLevel: () => setVerboseLevel,
|
|
@@ -2686,6 +2694,19 @@ function toggleShowThinkingUi(chatId) {
|
|
|
2686
2694
|
setShowThinkingUi(chatId, next);
|
|
2687
2695
|
return next;
|
|
2688
2696
|
}
|
|
2697
|
+
function getSkillSuggestionsEnabled(chatId) {
|
|
2698
|
+
const row = getDb().prepare(
|
|
2699
|
+
"SELECT value FROM chat_skill_suggestions WHERE chat_id = ?"
|
|
2700
|
+
).get(chatId);
|
|
2701
|
+
return (row?.value ?? 1) === 1;
|
|
2702
|
+
}
|
|
2703
|
+
function setSkillSuggestionsEnabled(chatId, enabled) {
|
|
2704
|
+
getDb().prepare(`
|
|
2705
|
+
INSERT INTO chat_skill_suggestions (chat_id, value)
|
|
2706
|
+
VALUES (?, ?)
|
|
2707
|
+
ON CONFLICT(chat_id) DO UPDATE SET value = ?
|
|
2708
|
+
`).run(chatId, enabled ? 1 : 0, enabled ? 1 : 0);
|
|
2709
|
+
}
|
|
2689
2710
|
function getMode(chatId) {
|
|
2690
2711
|
const row = getDb().prepare(
|
|
2691
2712
|
"SELECT mode FROM chat_mode WHERE chat_id = ?"
|
|
@@ -3677,6 +3698,9 @@ function setGeminiSlotEnabled(id, enabled) {
|
|
|
3677
3698
|
function reorderGeminiSlot(id, priority) {
|
|
3678
3699
|
getDb().prepare("UPDATE gemini_credentials SET priority = ? WHERE id = ?").run(priority, id);
|
|
3679
3700
|
}
|
|
3701
|
+
function renameGeminiSlot(id, label2) {
|
|
3702
|
+
return getDb().prepare("UPDATE gemini_credentials SET label = ? WHERE id = ?").run(label2, id).changes > 0;
|
|
3703
|
+
}
|
|
3680
3704
|
function getGeminiRotationMode() {
|
|
3681
3705
|
const row = getDb().prepare("SELECT value FROM meta WHERE key = 'gemini_rotation_mode'").get();
|
|
3682
3706
|
return row?.value ?? "all";
|
|
@@ -3775,6 +3799,9 @@ function setBackendSlotEnabled(id, enabled) {
|
|
|
3775
3799
|
function reorderBackendSlot(id, priority) {
|
|
3776
3800
|
getDb().prepare("UPDATE backend_credentials SET priority = ? WHERE id = ?").run(priority, id);
|
|
3777
3801
|
}
|
|
3802
|
+
function renameBackendSlot(id, label2) {
|
|
3803
|
+
return getDb().prepare("UPDATE backend_credentials SET label = ? WHERE id = ?").run(label2, id).changes > 0;
|
|
3804
|
+
}
|
|
3778
3805
|
function reenableBackendSlot(slotId) {
|
|
3779
3806
|
getDb().prepare(`
|
|
3780
3807
|
UPDATE backend_credentials
|
|
@@ -3891,6 +3918,7 @@ __export(store_exports5, {
|
|
|
3891
3918
|
getSessionSummaries: () => getSessionSummaries,
|
|
3892
3919
|
getSessionSummariesWithoutEmbeddings: () => getSessionSummariesWithoutEmbeddings,
|
|
3893
3920
|
getShowThinkingUi: () => getShowThinkingUi,
|
|
3921
|
+
getSkillSuggestionsEnabled: () => getSkillSuggestionsEnabled,
|
|
3894
3922
|
getSummarizer: () => getSummarizer,
|
|
3895
3923
|
getThinkingLevel: () => getThinkingLevel,
|
|
3896
3924
|
getToolsMap: () => getToolsMap,
|
|
@@ -3923,6 +3951,8 @@ __export(store_exports5, {
|
|
|
3923
3951
|
removeGeminiSlot: () => removeGeminiSlot,
|
|
3924
3952
|
removeHeartbeatWatch: () => removeHeartbeatWatch,
|
|
3925
3953
|
removePendingEscalation: () => removePendingEscalation,
|
|
3954
|
+
renameBackendSlot: () => renameBackendSlot,
|
|
3955
|
+
renameGeminiSlot: () => renameGeminiSlot,
|
|
3926
3956
|
reorderBackendSlot: () => reorderBackendSlot,
|
|
3927
3957
|
reorderGeminiSlot: () => reorderGeminiSlot,
|
|
3928
3958
|
resetJobFailures: () => resetJobFailures,
|
|
@@ -3957,6 +3987,7 @@ __export(store_exports5, {
|
|
|
3957
3987
|
setSessionLogEnabled: () => setSessionLogEnabled,
|
|
3958
3988
|
setSessionStartedAt: () => setSessionStartedAt,
|
|
3959
3989
|
setShowThinkingUi: () => setShowThinkingUi,
|
|
3990
|
+
setSkillSuggestionsEnabled: () => setSkillSuggestionsEnabled,
|
|
3960
3991
|
setSummarizer: () => setSummarizer,
|
|
3961
3992
|
setThinkingLevel: () => setThinkingLevel,
|
|
3962
3993
|
setVerboseLevel: () => setVerboseLevel,
|
|
@@ -6540,8 +6571,8 @@ var init_ndjson = __esm({
|
|
|
6540
6571
|
|
|
6541
6572
|
// src/memory/inject.ts
|
|
6542
6573
|
function getTopK(query) {
|
|
6543
|
-
const
|
|
6544
|
-
const scale =
|
|
6574
|
+
const wordCount2 = query.split(/\s+/).length;
|
|
6575
|
+
const scale = wordCount2 <= 3 ? 0.5 : wordCount2 <= 8 ? 0.75 : 1;
|
|
6545
6576
|
return {
|
|
6546
6577
|
vectorK: Math.max(5, Math.round(BASE_VECTOR_TOP_K * scale)),
|
|
6547
6578
|
ftsK: Math.max(5, Math.round(BASE_FTS_TOP_K * scale))
|
|
@@ -7094,7 +7125,7 @@ function searchContext(userMessage) {
|
|
|
7094
7125
|
}
|
|
7095
7126
|
return null;
|
|
7096
7127
|
}
|
|
7097
|
-
async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permMode, responseStyle, agentMode, sideQuestContext, planningDirective) {
|
|
7128
|
+
async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permMode, responseStyle, agentMode, sideQuestContext, planningDirective, chatContext) {
|
|
7098
7129
|
const sections = [];
|
|
7099
7130
|
if (planningDirective) {
|
|
7100
7131
|
sections.push(planningDirective);
|
|
@@ -7113,6 +7144,19 @@ async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permM
|
|
|
7113
7144
|
sections.push("[Response Style]\nYou should be detailed and thorough in your responses. Explain concepts fully and provide comprehensive answers.");
|
|
7114
7145
|
}
|
|
7115
7146
|
}
|
|
7147
|
+
if (chatId && tier !== "slim") {
|
|
7148
|
+
const parts = [`Chat ID: ${chatId}`];
|
|
7149
|
+
if (chatContext?.chatTitle) parts.push(`Group: ${chatContext.chatTitle}`);
|
|
7150
|
+
if (chatContext?.threadId) parts.push(`Forum topic thread: ${chatContext.threadId}`);
|
|
7151
|
+
try {
|
|
7152
|
+
const { getAllChatAliases: getAllChatAliases3 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
7153
|
+
const match = getAllChatAliases3().find((a) => a.chatId === chatId);
|
|
7154
|
+
if (match) parts.push(`Alias: ${match.alias}`);
|
|
7155
|
+
} catch {
|
|
7156
|
+
}
|
|
7157
|
+
sections.push(`[Current chat]
|
|
7158
|
+
${parts.join("\n")}`);
|
|
7159
|
+
}
|
|
7116
7160
|
if (tier === "full") {
|
|
7117
7161
|
const ctx = searchContext(userMessage);
|
|
7118
7162
|
if (ctx) {
|
|
@@ -9325,6 +9369,19 @@ var init_agent_log = __esm({
|
|
|
9325
9369
|
});
|
|
9326
9370
|
|
|
9327
9371
|
// src/agents/orchestrator.ts
|
|
9372
|
+
var orchestrator_exports = {};
|
|
9373
|
+
__export(orchestrator_exports, {
|
|
9374
|
+
cancelAgent: () => cancelAgent,
|
|
9375
|
+
cancelAllAgents: () => cancelAllAgents,
|
|
9376
|
+
diagnoseSpawnError: () => diagnoseSpawnError,
|
|
9377
|
+
getActiveProcessCount: () => getActiveProcessCount,
|
|
9378
|
+
getOrCreateOrchestration: () => getOrCreateOrchestration,
|
|
9379
|
+
getRunningAgentCount: () => getRunningAgentCount,
|
|
9380
|
+
initOrchestrator: () => initOrchestrator,
|
|
9381
|
+
setNotifyCallback: () => setNotifyCallback,
|
|
9382
|
+
shutdownOrchestrator: () => shutdownOrchestrator,
|
|
9383
|
+
spawnSubAgent: () => spawnSubAgent
|
|
9384
|
+
});
|
|
9328
9385
|
import { existsSync as existsSync10 } from "fs";
|
|
9329
9386
|
async function withRunnerLock(runnerId, fn) {
|
|
9330
9387
|
const prev = runnerLocks.get(runnerId) ?? Promise.resolve();
|
|
@@ -9964,6 +10021,9 @@ function cancelAllAgents(chatId, reason = "user_cancelled") {
|
|
|
9964
10021
|
updateOrchestrationStatus(db3, orch.id, "abandoned");
|
|
9965
10022
|
return count;
|
|
9966
10023
|
}
|
|
10024
|
+
function getActiveProcessCount() {
|
|
10025
|
+
return activeProcesses.size;
|
|
10026
|
+
}
|
|
9967
10027
|
function shutdownOrchestrator() {
|
|
9968
10028
|
for (const [agentId, proc] of activeProcesses) {
|
|
9969
10029
|
try {
|
|
@@ -12503,12 +12563,12 @@ var init_evolve = __esm({
|
|
|
12503
12563
|
const body = JSON.parse(await readBody(req));
|
|
12504
12564
|
const { setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
12505
12565
|
const { existsSync: fileExists, readFileSync: fileRead } = await import("fs");
|
|
12506
|
-
const { join:
|
|
12566
|
+
const { join: join36 } = await import("path");
|
|
12507
12567
|
const { CC_CLAW_HOME: home } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
12508
12568
|
const chatId = resolveChatId(body);
|
|
12509
12569
|
if (!chatId) return jsonResponse(res, { error: "No chatId provided and ALLOWED_CHAT_ID is not set" }, 400);
|
|
12510
|
-
const soulPath =
|
|
12511
|
-
const userPath =
|
|
12570
|
+
const soulPath = join36(home, "identity/SOUL.md");
|
|
12571
|
+
const userPath = join36(home, "identity/USER.md");
|
|
12512
12572
|
const soul = fileExists(soulPath) ? fileRead(soulPath, "utf-8") : "";
|
|
12513
12573
|
const user = fileExists(userPath) ? fileRead(userPath, "utf-8") : "";
|
|
12514
12574
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
@@ -12867,9 +12927,9 @@ function matchPatterns(message, patterns, signalType) {
|
|
|
12867
12927
|
return matches;
|
|
12868
12928
|
}
|
|
12869
12929
|
function classifySignals(userMessage, _agentResponse) {
|
|
12870
|
-
const
|
|
12930
|
+
const wordCount2 = userMessage.trim().split(/\s+/).filter(Boolean).length;
|
|
12871
12931
|
const results = [];
|
|
12872
|
-
if (
|
|
12932
|
+
if (wordCount2 >= 3) {
|
|
12873
12933
|
for (const m of matchPatterns(userMessage, CORRECTION_PATTERNS, "correction")) {
|
|
12874
12934
|
results.push({ ...m, source: "auto_detect" });
|
|
12875
12935
|
}
|
|
@@ -13549,12 +13609,12 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
13549
13609
|
const adapter = backend2 ? getAdapter(backend2) : getAdapterForChat(settingsChat);
|
|
13550
13610
|
const mode = permMode ?? getMode(settingsChat);
|
|
13551
13611
|
const responseStyle = getResponseStyle(settingsChat);
|
|
13552
|
-
const thinkingLevel = getThinkingLevel(settingsChat);
|
|
13612
|
+
const thinkingLevel = opts?.thinkingLevel ?? getThinkingLevel(settingsChat);
|
|
13553
13613
|
const resolvedCwd = cwd ?? WORKSPACE_PATH;
|
|
13554
13614
|
const tier = bootstrapTier ?? "full";
|
|
13555
13615
|
const effectiveAgentMode = optsAgentMode ?? getAgentMode(settingsChat);
|
|
13556
13616
|
const sideQuestCtx = settingsSourceChatId ? { parentChatId: settingsSourceChatId, actualChatId: chatId } : void 0;
|
|
13557
|
-
const fullPrompt = await assembleBootstrapPrompt(userMessage, tier, settingsChat, mode, responseStyle, effectiveAgentMode, sideQuestCtx, planningDirective);
|
|
13617
|
+
const fullPrompt = await assembleBootstrapPrompt(userMessage, tier, settingsChat, mode, responseStyle, effectiveAgentMode, sideQuestCtx, planningDirective, opts?.chatContext);
|
|
13558
13618
|
if (adapter.streamDirect) {
|
|
13559
13619
|
const resolvedModel2 = model2 ?? adapter.defaultModel;
|
|
13560
13620
|
const abortController = new AbortController();
|
|
@@ -16451,8 +16511,8 @@ async function mp3ToOgg(mp3Buffer) {
|
|
|
16451
16511
|
const id = crypto.randomUUID();
|
|
16452
16512
|
const tmpMp3 = `/tmp/cc-claw-tts-${id}.mp3`;
|
|
16453
16513
|
const tmpOgg = `/tmp/cc-claw-tts-${id}.ogg`;
|
|
16454
|
-
const { writeFile:
|
|
16455
|
-
await
|
|
16514
|
+
const { writeFile: writeFile6 } = await import("fs/promises");
|
|
16515
|
+
await writeFile6(tmpMp3, mp3Buffer);
|
|
16456
16516
|
await execFileAsync2("ffmpeg", ["-y", "-i", tmpMp3, "-c:a", "libopus", "-b:a", "64k", tmpOgg]);
|
|
16457
16517
|
const oggBuffer = await readFile2(tmpOgg);
|
|
16458
16518
|
unlink(tmpMp3).catch((err) => {
|
|
@@ -19227,10 +19287,10 @@ async function handleEvolveCallback(chatId, data, channel) {
|
|
|
19227
19287
|
const current = getReflectionStatus2(getDb(), chatId);
|
|
19228
19288
|
if (current === "frozen") {
|
|
19229
19289
|
const { readFileSync: readFileSync28, existsSync: existsSync56 } = await import("fs");
|
|
19230
|
-
const { join:
|
|
19290
|
+
const { join: join36 } = await import("path");
|
|
19231
19291
|
const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
19232
|
-
const soulPath =
|
|
19233
|
-
const userPath =
|
|
19292
|
+
const soulPath = join36(CC_CLAW_HOME3, "identity/SOUL.md");
|
|
19293
|
+
const userPath = join36(CC_CLAW_HOME3, "identity/USER.md");
|
|
19234
19294
|
const soul = existsSync56(soulPath) ? readFileSync28(soulPath, "utf-8") : "";
|
|
19235
19295
|
const user = existsSync56(userPath) ? readFileSync28(userPath, "utf-8") : "";
|
|
19236
19296
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
@@ -20580,6 +20640,133 @@ var init_optimize = __esm({
|
|
|
20580
20640
|
}
|
|
20581
20641
|
});
|
|
20582
20642
|
|
|
20643
|
+
// src/council/types.ts
|
|
20644
|
+
var COUNCIL_MIN_PARTICIPANTS, COUNCIL_MAX_ROUNDS, COUNCIL_WIZARD_TIMEOUT_MS;
|
|
20645
|
+
var init_types4 = __esm({
|
|
20646
|
+
"src/council/types.ts"() {
|
|
20647
|
+
"use strict";
|
|
20648
|
+
COUNCIL_MIN_PARTICIPANTS = 2;
|
|
20649
|
+
COUNCIL_MAX_ROUNDS = 3;
|
|
20650
|
+
COUNCIL_WIZARD_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
20651
|
+
}
|
|
20652
|
+
});
|
|
20653
|
+
|
|
20654
|
+
// src/council/wizard.ts
|
|
20655
|
+
var wizard_exports = {};
|
|
20656
|
+
__export(wizard_exports, {
|
|
20657
|
+
buildSelectKeyboard: () => buildSelectKeyboard,
|
|
20658
|
+
cancelCouncil: () => cancelCouncil,
|
|
20659
|
+
getCouncilState: () => getCouncilState,
|
|
20660
|
+
hasPendingCouncil: () => hasPendingCouncil,
|
|
20661
|
+
setCouncilQuestion: () => setCouncilQuestion,
|
|
20662
|
+
startCouncilWizard: () => startCouncilWizard,
|
|
20663
|
+
toggleParticipant: () => toggleParticipant
|
|
20664
|
+
});
|
|
20665
|
+
function resetCouncilTimeout(chatId) {
|
|
20666
|
+
const existing = councilTimers.get(chatId);
|
|
20667
|
+
if (existing) clearTimeout(existing);
|
|
20668
|
+
councilTimers.set(chatId, setTimeout(() => {
|
|
20669
|
+
pendingCouncils.delete(chatId);
|
|
20670
|
+
councilTimers.delete(chatId);
|
|
20671
|
+
log(`[council] Auto-cancelled stale council wizard for chat ${chatId}`);
|
|
20672
|
+
}, COUNCIL_WIZARD_TIMEOUT_MS));
|
|
20673
|
+
}
|
|
20674
|
+
function startCouncilWizard(chatId) {
|
|
20675
|
+
if (pendingCouncils.has(chatId)) {
|
|
20676
|
+
cancelCouncil(chatId);
|
|
20677
|
+
}
|
|
20678
|
+
pendingCouncils.set(chatId, {
|
|
20679
|
+
step: "select",
|
|
20680
|
+
selected: /* @__PURE__ */ new Map()
|
|
20681
|
+
});
|
|
20682
|
+
resetCouncilTimeout(chatId);
|
|
20683
|
+
}
|
|
20684
|
+
function hasPendingCouncil(chatId) {
|
|
20685
|
+
return pendingCouncils.has(chatId);
|
|
20686
|
+
}
|
|
20687
|
+
function getCouncilState(chatId) {
|
|
20688
|
+
return pendingCouncils.get(chatId);
|
|
20689
|
+
}
|
|
20690
|
+
function cancelCouncil(chatId) {
|
|
20691
|
+
pendingCouncils.delete(chatId);
|
|
20692
|
+
const timer = councilTimers.get(chatId);
|
|
20693
|
+
if (timer) {
|
|
20694
|
+
clearTimeout(timer);
|
|
20695
|
+
councilTimers.delete(chatId);
|
|
20696
|
+
}
|
|
20697
|
+
}
|
|
20698
|
+
function toggleParticipant(chatId, backend2, model2, label2) {
|
|
20699
|
+
const state = pendingCouncils.get(chatId);
|
|
20700
|
+
if (!state) return;
|
|
20701
|
+
resetCouncilTimeout(chatId);
|
|
20702
|
+
const key = `${backend2}:${model2}`;
|
|
20703
|
+
if (state.selected.has(key)) {
|
|
20704
|
+
state.selected.delete(key);
|
|
20705
|
+
} else {
|
|
20706
|
+
state.selected.set(key, { backend: backend2, model: model2, label: label2 });
|
|
20707
|
+
}
|
|
20708
|
+
}
|
|
20709
|
+
function setCouncilQuestion(chatId, question) {
|
|
20710
|
+
const state = pendingCouncils.get(chatId);
|
|
20711
|
+
if (!state) return { error: "No active council wizard." };
|
|
20712
|
+
resetCouncilTimeout(chatId);
|
|
20713
|
+
if (state.selected.size < COUNCIL_MIN_PARTICIPANTS) {
|
|
20714
|
+
return { error: `Select at least ${COUNCIL_MIN_PARTICIPANTS} models before starting.` };
|
|
20715
|
+
}
|
|
20716
|
+
state.question = question;
|
|
20717
|
+
state.step = "running";
|
|
20718
|
+
return {};
|
|
20719
|
+
}
|
|
20720
|
+
function buildSelectKeyboard(chatId) {
|
|
20721
|
+
const state = pendingCouncils.get(chatId);
|
|
20722
|
+
if (!state) {
|
|
20723
|
+
return { text: "No active council wizard.", buttons: [] };
|
|
20724
|
+
}
|
|
20725
|
+
const adapters2 = getAvailableAdapters();
|
|
20726
|
+
const buttons = [];
|
|
20727
|
+
for (const adapter of adapters2) {
|
|
20728
|
+
for (const [modelId, modelInfo] of Object.entries(adapter.availableModels)) {
|
|
20729
|
+
const key = `${adapter.id}:${modelId}`;
|
|
20730
|
+
const isSelected = state.selected.has(key);
|
|
20731
|
+
const checkmark = isSelected ? "\u2713 " : " ";
|
|
20732
|
+
const row = [{
|
|
20733
|
+
label: `${checkmark}${modelInfo.label}`,
|
|
20734
|
+
data: `council:toggle:${adapter.id}:${modelId}:${modelInfo.label}`,
|
|
20735
|
+
...isSelected ? { style: "success" } : {}
|
|
20736
|
+
}];
|
|
20737
|
+
buttons.push(row);
|
|
20738
|
+
}
|
|
20739
|
+
}
|
|
20740
|
+
const count = state.selected.size;
|
|
20741
|
+
const canStart = count >= COUNCIL_MIN_PARTICIPANTS;
|
|
20742
|
+
buttons.push([
|
|
20743
|
+
{
|
|
20744
|
+
label: canStart ? `\u25B6 Start Council (${count} models)` : `\u25B6 Start Council (${count} models)`,
|
|
20745
|
+
data: canStart ? "council:start" : "council:noop",
|
|
20746
|
+
...canStart ? {} : {}
|
|
20747
|
+
},
|
|
20748
|
+
{
|
|
20749
|
+
label: "\u2715 Cancel",
|
|
20750
|
+
data: "council:cancel"
|
|
20751
|
+
}
|
|
20752
|
+
]);
|
|
20753
|
+
return {
|
|
20754
|
+
text: `Select models for the council debate (${count} selected):`,
|
|
20755
|
+
buttons
|
|
20756
|
+
};
|
|
20757
|
+
}
|
|
20758
|
+
var pendingCouncils, councilTimers;
|
|
20759
|
+
var init_wizard2 = __esm({
|
|
20760
|
+
"src/council/wizard.ts"() {
|
|
20761
|
+
"use strict";
|
|
20762
|
+
init_types4();
|
|
20763
|
+
init_backends();
|
|
20764
|
+
init_log();
|
|
20765
|
+
pendingCouncils = /* @__PURE__ */ new Map();
|
|
20766
|
+
councilTimers = /* @__PURE__ */ new Map();
|
|
20767
|
+
}
|
|
20768
|
+
});
|
|
20769
|
+
|
|
20583
20770
|
// src/router/command-handlers.ts
|
|
20584
20771
|
import { readFile as readFile6 } from "fs/promises";
|
|
20585
20772
|
async function handleStopCommand(chatId, commandArgs, msg, channel) {
|
|
@@ -21186,6 +21373,12 @@ async function handleModelCommand(chatId, commandArgs, msg, channel) {
|
|
|
21186
21373
|
...id === current ? { style: "primary" } : {}
|
|
21187
21374
|
}];
|
|
21188
21375
|
});
|
|
21376
|
+
const isAuto = getModel(chatId) === "auto";
|
|
21377
|
+
buttons.unshift([{
|
|
21378
|
+
label: `${isAuto ? "\u2713 " : ""}\u{1F916} Auto (smart routing)`,
|
|
21379
|
+
data: "model:auto",
|
|
21380
|
+
...isAuto ? { style: "primary" } : {}
|
|
21381
|
+
}]);
|
|
21189
21382
|
await channel.sendKeyboard(chatId, `Models for ${adapter.displayName}:`, buttons);
|
|
21190
21383
|
} else {
|
|
21191
21384
|
const lines = Object.entries(models).map(
|
|
@@ -22095,6 +22288,20 @@ async function handleCronCommand(chatId, commandArgs, msg, channel) {
|
|
|
22095
22288
|
await startWizard(chatId, commandArgs, channel);
|
|
22096
22289
|
}
|
|
22097
22290
|
}
|
|
22291
|
+
async function handleCouncilCommand(chatId, commandArgs, msg, channel) {
|
|
22292
|
+
if (process.env.DASHBOARD_ENABLED !== "1") {
|
|
22293
|
+
await channel.sendText(chatId, "Council requires DASHBOARD_ENABLED=1 (uses the agent orchestrator).", { parseMode: "plain" });
|
|
22294
|
+
return;
|
|
22295
|
+
}
|
|
22296
|
+
const { startCouncilWizard: startCouncilWizard2, buildSelectKeyboard: buildSelectKeyboard2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
|
|
22297
|
+
startCouncilWizard2(chatId);
|
|
22298
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
22299
|
+
const { text, buttons } = buildSelectKeyboard2(chatId);
|
|
22300
|
+
await channel.sendKeyboard(chatId, text, buttons);
|
|
22301
|
+
} else {
|
|
22302
|
+
await channel.sendText(chatId, "Council requires Telegram (needs inline keyboards).", { parseMode: "plain" });
|
|
22303
|
+
}
|
|
22304
|
+
}
|
|
22098
22305
|
var init_command_handlers = __esm({
|
|
22099
22306
|
"src/router/command-handlers.ts"() {
|
|
22100
22307
|
"use strict";
|
|
@@ -22303,6 +22510,10 @@ async function handleCommand(msg, channel) {
|
|
|
22303
22510
|
case "intent":
|
|
22304
22511
|
await handleIntentCommand(chatId, commandArgs, msg, channel);
|
|
22305
22512
|
break;
|
|
22513
|
+
case "council":
|
|
22514
|
+
case "debate":
|
|
22515
|
+
await handleCouncilCommand(chatId, commandArgs, msg, channel);
|
|
22516
|
+
break;
|
|
22306
22517
|
case "evolve":
|
|
22307
22518
|
await handleEvolveCommandWrapper(chatId, commandArgs, msg, channel);
|
|
22308
22519
|
break;
|
|
@@ -22345,6 +22556,120 @@ var init_commands = __esm({
|
|
|
22345
22556
|
}
|
|
22346
22557
|
});
|
|
22347
22558
|
|
|
22559
|
+
// src/skills/auto-create.ts
|
|
22560
|
+
var auto_create_exports = {};
|
|
22561
|
+
__export(auto_create_exports, {
|
|
22562
|
+
buildSkillExtractionPrompt: () => buildSkillExtractionPrompt,
|
|
22563
|
+
clearPendingDraft: () => clearPendingDraft,
|
|
22564
|
+
getPendingDraft: () => getPendingDraft,
|
|
22565
|
+
isSkillWorthy: () => isSkillWorthy,
|
|
22566
|
+
parseExtractedSkill: () => parseExtractedSkill,
|
|
22567
|
+
saveSkill: () => saveSkill,
|
|
22568
|
+
storePendingDraft: () => storePendingDraft
|
|
22569
|
+
});
|
|
22570
|
+
import { join as join25 } from "path";
|
|
22571
|
+
import { writeFile as writeFile4, mkdir as mkdir3 } from "fs/promises";
|
|
22572
|
+
function isSkillWorthy(signals) {
|
|
22573
|
+
const { toolUseCount, tokenOutput, elapsedMs, userMessage } = signals;
|
|
22574
|
+
if (toolUseCount < 8) return false;
|
|
22575
|
+
const supplementary = [
|
|
22576
|
+
tokenOutput >= 3e3,
|
|
22577
|
+
// substantial output
|
|
22578
|
+
elapsedMs >= 45e3
|
|
22579
|
+
// took real effort (45s+)
|
|
22580
|
+
].filter(Boolean).length;
|
|
22581
|
+
if (supplementary < 1) return false;
|
|
22582
|
+
const words = userMessage.split(/\s+/).length;
|
|
22583
|
+
if (words < 5) return false;
|
|
22584
|
+
log(`[auto-skill] Skill-worthy: tools=${toolUseCount}, tokens=${tokenOutput}, elapsed=${elapsedMs}ms`);
|
|
22585
|
+
return true;
|
|
22586
|
+
}
|
|
22587
|
+
function buildSkillExtractionPrompt(userMessage, assistantResponse) {
|
|
22588
|
+
const cappedResponse = assistantResponse.length > 8e3 ? assistantResponse.slice(0, 8e3) + "\n\n[...truncated...]" : assistantResponse;
|
|
22589
|
+
return [
|
|
22590
|
+
"You are a skill extraction assistant. Analyze the following completed task and create a reusable SKILL.md file.",
|
|
22591
|
+
"",
|
|
22592
|
+
"A skill is a set of instructions that an AI agent can follow to accomplish a similar task in the future.",
|
|
22593
|
+
"Focus on the PROCESS and APPROACH, not the specific details of this particular task.",
|
|
22594
|
+
"",
|
|
22595
|
+
"## Completed Task",
|
|
22596
|
+
"",
|
|
22597
|
+
`**User request:** ${userMessage}`,
|
|
22598
|
+
"",
|
|
22599
|
+
`**Assistant response:**`,
|
|
22600
|
+
cappedResponse,
|
|
22601
|
+
"",
|
|
22602
|
+
"## Output Format",
|
|
22603
|
+
"",
|
|
22604
|
+
"Output ONLY the SKILL.md content with this exact format:",
|
|
22605
|
+
"",
|
|
22606
|
+
"```",
|
|
22607
|
+
"---",
|
|
22608
|
+
'name: "skill-name-in-kebab-case"',
|
|
22609
|
+
'description: "What this skill does and when to use it"',
|
|
22610
|
+
"---",
|
|
22611
|
+
"",
|
|
22612
|
+
"## [Skill Title]",
|
|
22613
|
+
"",
|
|
22614
|
+
"[Step-by-step instructions for accomplishing this type of task]",
|
|
22615
|
+
"[Include decision points, best practices, and common pitfalls]",
|
|
22616
|
+
"[Keep it general enough to be reusable, specific enough to be helpful]",
|
|
22617
|
+
"```",
|
|
22618
|
+
"",
|
|
22619
|
+
"Rules:",
|
|
22620
|
+
"- The skill name should be descriptive and kebab-case",
|
|
22621
|
+
"- The description should explain WHAT it does AND WHEN to use it",
|
|
22622
|
+
"- Instructions should be general (not tied to specific file names or projects)",
|
|
22623
|
+
"- Include any important caveats or prerequisites",
|
|
22624
|
+
"- Keep it under 100 lines"
|
|
22625
|
+
].join("\n");
|
|
22626
|
+
}
|
|
22627
|
+
function parseExtractedSkill(llmResponse) {
|
|
22628
|
+
let content = llmResponse;
|
|
22629
|
+
const fenceMatch = llmResponse.match(/```(?:markdown|md)?\s*\n([\s\S]*?)```/);
|
|
22630
|
+
if (fenceMatch) content = fenceMatch[1].trim();
|
|
22631
|
+
const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
22632
|
+
if (!fmMatch) {
|
|
22633
|
+
warn("[auto-skill] No frontmatter found in extracted skill");
|
|
22634
|
+
return null;
|
|
22635
|
+
}
|
|
22636
|
+
const nameMatch = fmMatch[1].match(/^name:\s*["']?([^"'\n]+)["']?\s*$/m);
|
|
22637
|
+
if (!nameMatch) {
|
|
22638
|
+
warn("[auto-skill] No name field in skill frontmatter");
|
|
22639
|
+
return null;
|
|
22640
|
+
}
|
|
22641
|
+
const name = nameMatch[1].trim().toLowerCase().replace(/\s+/g, "-");
|
|
22642
|
+
return { name, content };
|
|
22643
|
+
}
|
|
22644
|
+
async function saveSkill(name, content) {
|
|
22645
|
+
const dir = join25(SKILLS_PATH, name);
|
|
22646
|
+
await mkdir3(dir, { recursive: true });
|
|
22647
|
+
const filePath = join25(dir, "SKILL.md");
|
|
22648
|
+
await writeFile4(filePath, content, "utf-8");
|
|
22649
|
+
invalidateSkillCache();
|
|
22650
|
+
log(`[auto-skill] Saved skill "${name}" to ${filePath}`);
|
|
22651
|
+
return { path: filePath };
|
|
22652
|
+
}
|
|
22653
|
+
function storePendingDraft(chatId, draft) {
|
|
22654
|
+
pendingDrafts.set(chatId, draft);
|
|
22655
|
+
}
|
|
22656
|
+
function getPendingDraft(chatId) {
|
|
22657
|
+
return pendingDrafts.get(chatId);
|
|
22658
|
+
}
|
|
22659
|
+
function clearPendingDraft(chatId) {
|
|
22660
|
+
pendingDrafts.delete(chatId);
|
|
22661
|
+
}
|
|
22662
|
+
var pendingDrafts;
|
|
22663
|
+
var init_auto_create = __esm({
|
|
22664
|
+
"src/skills/auto-create.ts"() {
|
|
22665
|
+
"use strict";
|
|
22666
|
+
init_paths();
|
|
22667
|
+
init_discover();
|
|
22668
|
+
init_log();
|
|
22669
|
+
pendingDrafts = /* @__PURE__ */ new Map();
|
|
22670
|
+
}
|
|
22671
|
+
});
|
|
22672
|
+
|
|
22348
22673
|
// src/router/callbacks.ts
|
|
22349
22674
|
import { readFile as readFile7 } from "fs/promises";
|
|
22350
22675
|
async function handleCallback(chatId, data, channel, messageId) {
|
|
@@ -22404,6 +22729,12 @@ async function handleCallback(chatId, data, channel, messageId) {
|
|
|
22404
22729
|
await channel.sendText(chatId, `Using ${adapter.displayName} with default model. Ready!`, { parseMode: "plain" });
|
|
22405
22730
|
} else if (data.startsWith("model:")) {
|
|
22406
22731
|
const chosen = data.slice(6);
|
|
22732
|
+
if (chosen === "auto") {
|
|
22733
|
+
setModel(chatId, "auto");
|
|
22734
|
+
clearThinkingLevel(chatId);
|
|
22735
|
+
await channel.sendText(chatId, "\u{1F916} Smart routing enabled \u2014 model and thinking level will be chosen per message based on complexity.", { parseMode: "plain" });
|
|
22736
|
+
return;
|
|
22737
|
+
}
|
|
22407
22738
|
let adapter;
|
|
22408
22739
|
try {
|
|
22409
22740
|
adapter = getAdapterForChat(chatId);
|
|
@@ -23043,6 +23374,47 @@ ${rotationNote}`, { parseMode: "html" });
|
|
|
23043
23374
|
} else if (data.startsWith("reflect:")) {
|
|
23044
23375
|
await handleReflectCallback(chatId, data, channel);
|
|
23045
23376
|
return;
|
|
23377
|
+
} else if (data.startsWith("council:")) {
|
|
23378
|
+
const parts = data.split(":");
|
|
23379
|
+
const action = parts[1];
|
|
23380
|
+
if (action === "toggle") {
|
|
23381
|
+
const backend2 = parts[2];
|
|
23382
|
+
const model2 = parts[3];
|
|
23383
|
+
const label2 = parts.slice(4).join(":");
|
|
23384
|
+
const { toggleParticipant: toggleParticipant2, buildSelectKeyboard: buildSelectKeyboard2, hasPendingCouncil: hasPendingCouncil2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
|
|
23385
|
+
if (!hasPendingCouncil2(chatId)) {
|
|
23386
|
+
await channel.sendText(chatId, "No council wizard active. Use /council to start.", { parseMode: "plain" });
|
|
23387
|
+
return;
|
|
23388
|
+
}
|
|
23389
|
+
toggleParticipant2(chatId, backend2, model2, label2);
|
|
23390
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
23391
|
+
const { text, buttons } = buildSelectKeyboard2(chatId);
|
|
23392
|
+
await channel.sendKeyboard(chatId, text, buttons);
|
|
23393
|
+
}
|
|
23394
|
+
return;
|
|
23395
|
+
}
|
|
23396
|
+
if (action === "start") {
|
|
23397
|
+
const { getCouncilState: getCouncilState2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
|
|
23398
|
+
const state = getCouncilState2(chatId);
|
|
23399
|
+
if (!state || state.selected.size < 2) {
|
|
23400
|
+
await channel.sendText(chatId, "Select at least 2 models first.", { parseMode: "plain" });
|
|
23401
|
+
return;
|
|
23402
|
+
}
|
|
23403
|
+
state.step = "question";
|
|
23404
|
+
const names = [...state.selected.values()].map((p) => p.label).join(", ");
|
|
23405
|
+
await channel.sendText(chatId, `\u{1F3DB}\uFE0F Council members: ${names}
|
|
23406
|
+
|
|
23407
|
+
Now type the question you want them to debate.`, { parseMode: "plain" });
|
|
23408
|
+
return;
|
|
23409
|
+
}
|
|
23410
|
+
if (action === "cancel") {
|
|
23411
|
+
const { cancelCouncil: cancelCouncil2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
|
|
23412
|
+
cancelCouncil2(chatId);
|
|
23413
|
+
await channel.sendText(chatId, "Council cancelled.", { parseMode: "plain" });
|
|
23414
|
+
return;
|
|
23415
|
+
}
|
|
23416
|
+
if (action === "noop") return;
|
|
23417
|
+
return;
|
|
23046
23418
|
} else if (data.startsWith("opt:")) {
|
|
23047
23419
|
await handleOptimizeCallback(chatId, data, channel);
|
|
23048
23420
|
return;
|
|
@@ -23322,6 +23694,45 @@ Example: /limits ${bid} daily 500000`, { parseMode: "plain" });
|
|
|
23322
23694
|
const page = parseInt(data.slice(12), 10);
|
|
23323
23695
|
const skills2 = await discoverAllSkills();
|
|
23324
23696
|
await sendSkillsPage(chatId, channel, skills2, page, messageId);
|
|
23697
|
+
} else if (data === "skill:extract") {
|
|
23698
|
+
const { getPendingDraft: getPendingDraft2, clearPendingDraft: clearPendingDraft2, buildSkillExtractionPrompt: buildSkillExtractionPrompt2, parseExtractedSkill: parseExtractedSkill2, saveSkill: saveSkill2 } = await Promise.resolve().then(() => (init_auto_create(), auto_create_exports));
|
|
23699
|
+
const draft = getPendingDraft2(chatId);
|
|
23700
|
+
if (!draft) {
|
|
23701
|
+
await channel.sendText(chatId, "No pending skill draft.", { parseMode: "plain" });
|
|
23702
|
+
return;
|
|
23703
|
+
}
|
|
23704
|
+
await channel.sendText(chatId, "\u{1F50D} Extracting skill from conversation...", { parseMode: "plain" });
|
|
23705
|
+
await channel.sendTyping?.(chatId);
|
|
23706
|
+
try {
|
|
23707
|
+
const { askAgent: askAgent3 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
23708
|
+
const extractionPrompt = buildSkillExtractionPrompt2(draft.userMessage, draft.assistantResponse);
|
|
23709
|
+
const extractionResponse = await askAgent3(chatId, extractionPrompt, {
|
|
23710
|
+
bootstrapTier: "slim",
|
|
23711
|
+
maxTurns: 1,
|
|
23712
|
+
timeoutMs: 3e4
|
|
23713
|
+
});
|
|
23714
|
+
const parsed = parseExtractedSkill2(extractionResponse.text);
|
|
23715
|
+
if (parsed) {
|
|
23716
|
+
const { path } = await saveSkill2(parsed.name, parsed.content);
|
|
23717
|
+
clearPendingDraft2(chatId);
|
|
23718
|
+
await channel.sendText(chatId, `\u2705 Skill "${parsed.name}" saved.
|
|
23719
|
+
Path: ${path}
|
|
23720
|
+
|
|
23721
|
+
Use /skills to see all available skills.`, { parseMode: "plain" });
|
|
23722
|
+
} else {
|
|
23723
|
+
clearPendingDraft2(chatId);
|
|
23724
|
+
await channel.sendText(chatId, "Could not extract a well-formed skill from this conversation. Try /remember to save key steps manually.", { parseMode: "plain" });
|
|
23725
|
+
}
|
|
23726
|
+
} catch (e) {
|
|
23727
|
+
clearPendingDraft2(chatId);
|
|
23728
|
+
await channel.sendText(chatId, `Skill extraction failed: ${e.message}`, { parseMode: "plain" });
|
|
23729
|
+
}
|
|
23730
|
+
return;
|
|
23731
|
+
} else if (data === "skill:discard") {
|
|
23732
|
+
const { clearPendingDraft: clearPendingDraft2 } = await Promise.resolve().then(() => (init_auto_create(), auto_create_exports));
|
|
23733
|
+
clearPendingDraft2(chatId);
|
|
23734
|
+
if (messageId) await replaceWithText("\u{1F44C} Noted.");
|
|
23735
|
+
return;
|
|
23325
23736
|
} else if (data.startsWith("skill:")) {
|
|
23326
23737
|
const parts = data.slice(6).split(":");
|
|
23327
23738
|
let skillName;
|
|
@@ -23396,6 +23807,399 @@ var init_callbacks = __esm({
|
|
|
23396
23807
|
}
|
|
23397
23808
|
});
|
|
23398
23809
|
|
|
23810
|
+
// src/channels/thread-wrapper.ts
|
|
23811
|
+
var thread_wrapper_exports = {};
|
|
23812
|
+
__export(thread_wrapper_exports, {
|
|
23813
|
+
withThread: () => withThread
|
|
23814
|
+
});
|
|
23815
|
+
function withThread(channel, threadId) {
|
|
23816
|
+
return {
|
|
23817
|
+
get name() {
|
|
23818
|
+
return channel.name;
|
|
23819
|
+
},
|
|
23820
|
+
start: channel.start.bind(channel),
|
|
23821
|
+
stop: channel.stop.bind(channel),
|
|
23822
|
+
getCapabilities: channel.getCapabilities.bind(channel),
|
|
23823
|
+
downloadFile: channel.downloadFile.bind(channel),
|
|
23824
|
+
isAuthorized: channel.isAuthorized.bind(channel),
|
|
23825
|
+
sendText(chatId, text, opts) {
|
|
23826
|
+
return channel.sendText(chatId, text, { ...opts, threadId: opts?.threadId ?? threadId });
|
|
23827
|
+
},
|
|
23828
|
+
sendVoice(chatId, audioBuffer, fileName) {
|
|
23829
|
+
return channel.sendVoice(chatId, audioBuffer, fileName, threadId);
|
|
23830
|
+
},
|
|
23831
|
+
sendFile(chatId, buffer, fileName, mimeType) {
|
|
23832
|
+
return channel.sendFile(chatId, buffer, fileName, mimeType, threadId);
|
|
23833
|
+
},
|
|
23834
|
+
sendTyping: channel.sendTyping ? (chatId) => channel.sendTyping(chatId, threadId) : void 0,
|
|
23835
|
+
sendKeyboard: channel.sendKeyboard ? (chatId, text, buttons) => channel.sendKeyboard(chatId, text, buttons, threadId) : void 0,
|
|
23836
|
+
sendTextReturningId: channel.sendTextReturningId ? (chatId, text, parseMode) => channel.sendTextReturningId(chatId, text, parseMode, threadId) : void 0,
|
|
23837
|
+
// These operate on existing messages — no threadId needed
|
|
23838
|
+
editText: channel.editText?.bind(channel),
|
|
23839
|
+
editKeyboard: channel.editKeyboard?.bind(channel),
|
|
23840
|
+
reactToMessage: channel.reactToMessage?.bind(channel)
|
|
23841
|
+
};
|
|
23842
|
+
}
|
|
23843
|
+
var init_thread_wrapper = __esm({
|
|
23844
|
+
"src/channels/thread-wrapper.ts"() {
|
|
23845
|
+
"use strict";
|
|
23846
|
+
}
|
|
23847
|
+
});
|
|
23848
|
+
|
|
23849
|
+
// src/intent/complexity.ts
|
|
23850
|
+
var complexity_exports = {};
|
|
23851
|
+
__export(complexity_exports, {
|
|
23852
|
+
classifyComplexity: () => classifyComplexity
|
|
23853
|
+
});
|
|
23854
|
+
function wordCount(text) {
|
|
23855
|
+
return text.trim().split(/\s+/).filter(Boolean).length;
|
|
23856
|
+
}
|
|
23857
|
+
function classifyComplexity(text) {
|
|
23858
|
+
const trimmed = text.trim();
|
|
23859
|
+
const lower = trimmed.toLowerCase();
|
|
23860
|
+
const words = wordCount(trimmed);
|
|
23861
|
+
if (TRIVIAL_EXACT.has(lower)) {
|
|
23862
|
+
log(`[complexity] "${lower}" -> trivial (exact match)`);
|
|
23863
|
+
return "trivial";
|
|
23864
|
+
}
|
|
23865
|
+
if (trimmed.length <= 4 && /^[\p{Emoji}\s]+$/u.test(trimmed)) {
|
|
23866
|
+
log(`[complexity] "${trimmed}" -> trivial (emoji-only)`);
|
|
23867
|
+
return "trivial";
|
|
23868
|
+
}
|
|
23869
|
+
if (COMPLEX_SIGNALS.test(trimmed) && (words > 15 || trimmed.length > 200)) {
|
|
23870
|
+
log(`[complexity] "${trimmed.slice(0, 40)}..." -> complex (signal words + length)`);
|
|
23871
|
+
return "complex";
|
|
23872
|
+
}
|
|
23873
|
+
if (MUTATION_VERBS.test(trimmed)) {
|
|
23874
|
+
const tier = words > 30 || trimmed.length > 300 ? "complex" : "moderate";
|
|
23875
|
+
log(`[complexity] "${trimmed.slice(0, 40)}..." -> ${tier} (mutation verb)`);
|
|
23876
|
+
return tier;
|
|
23877
|
+
}
|
|
23878
|
+
for (const pattern of CODE_PATTERNS) {
|
|
23879
|
+
if (pattern.test(trimmed)) {
|
|
23880
|
+
const tier = words > 30 || trimmed.length > 300 ? "complex" : "moderate";
|
|
23881
|
+
log(`[complexity] "${trimmed.slice(0, 40)}..." -> ${tier} (code pattern)`);
|
|
23882
|
+
return tier;
|
|
23883
|
+
}
|
|
23884
|
+
}
|
|
23885
|
+
if (trimmed.length > 200 || words > 25) {
|
|
23886
|
+
const tier = words > 30 || trimmed.length > 300 ? "complex" : "moderate";
|
|
23887
|
+
log(`[complexity] "${trimmed.slice(0, 40)}..." -> ${tier} (long message)`);
|
|
23888
|
+
return tier;
|
|
23889
|
+
}
|
|
23890
|
+
for (const pattern of QUESTION_PATTERNS) {
|
|
23891
|
+
if (pattern.test(trimmed)) {
|
|
23892
|
+
log(`[complexity] "${trimmed.slice(0, 40)}..." -> simple (question)`);
|
|
23893
|
+
return "simple";
|
|
23894
|
+
}
|
|
23895
|
+
}
|
|
23896
|
+
log(`[complexity] "${trimmed.slice(0, 40)}..." -> moderate (default)`);
|
|
23897
|
+
return "moderate";
|
|
23898
|
+
}
|
|
23899
|
+
var TRIVIAL_EXACT, COMPLEX_SIGNALS, MUTATION_VERBS, CODE_PATTERNS, QUESTION_PATTERNS;
|
|
23900
|
+
var init_complexity = __esm({
|
|
23901
|
+
"src/intent/complexity.ts"() {
|
|
23902
|
+
"use strict";
|
|
23903
|
+
init_log();
|
|
23904
|
+
TRIVIAL_EXACT = /* @__PURE__ */ new Set([
|
|
23905
|
+
"hey",
|
|
23906
|
+
"hi",
|
|
23907
|
+
"hello",
|
|
23908
|
+
"yo",
|
|
23909
|
+
"sup",
|
|
23910
|
+
"howdy",
|
|
23911
|
+
"hiya",
|
|
23912
|
+
"thanks",
|
|
23913
|
+
"thank you",
|
|
23914
|
+
"thx",
|
|
23915
|
+
"ty",
|
|
23916
|
+
"thank u",
|
|
23917
|
+
"ok",
|
|
23918
|
+
"okay",
|
|
23919
|
+
"k",
|
|
23920
|
+
"kk",
|
|
23921
|
+
"cool",
|
|
23922
|
+
"nice",
|
|
23923
|
+
"great",
|
|
23924
|
+
"awesome",
|
|
23925
|
+
"perfect",
|
|
23926
|
+
"good morning",
|
|
23927
|
+
"good night",
|
|
23928
|
+
"good evening",
|
|
23929
|
+
"gm",
|
|
23930
|
+
"gn",
|
|
23931
|
+
"bye",
|
|
23932
|
+
"goodbye",
|
|
23933
|
+
"later",
|
|
23934
|
+
"see ya",
|
|
23935
|
+
"cya",
|
|
23936
|
+
"lol",
|
|
23937
|
+
"lmao",
|
|
23938
|
+
"haha",
|
|
23939
|
+
"heh",
|
|
23940
|
+
"np",
|
|
23941
|
+
"no problem",
|
|
23942
|
+
"no worries",
|
|
23943
|
+
"nw",
|
|
23944
|
+
"got it",
|
|
23945
|
+
"understood",
|
|
23946
|
+
"roger",
|
|
23947
|
+
"copy",
|
|
23948
|
+
"good",
|
|
23949
|
+
"fine",
|
|
23950
|
+
"alright",
|
|
23951
|
+
"sure",
|
|
23952
|
+
"yes",
|
|
23953
|
+
"no",
|
|
23954
|
+
"yep",
|
|
23955
|
+
"nope",
|
|
23956
|
+
"yeah",
|
|
23957
|
+
"nah"
|
|
23958
|
+
]);
|
|
23959
|
+
COMPLEX_SIGNALS = /\b(architect|design|research|plan|strategy|migration|microservice|distributed|end-to-end|trade-offs|pros\s+and\s+cons)\b/i;
|
|
23960
|
+
MUTATION_VERBS = /\b(fix|create|build|deploy|refactor|implement|write|add|update|edit|test|debug)\b/i;
|
|
23961
|
+
CODE_PATTERNS = [
|
|
23962
|
+
/```/,
|
|
23963
|
+
// code blocks
|
|
23964
|
+
/\.[a-z]{1,5}\b/,
|
|
23965
|
+
// file extensions (.ts, .py, .json)
|
|
23966
|
+
/[/\\][\w.-]+/
|
|
23967
|
+
// file paths (/src/foo, .\bar)
|
|
23968
|
+
];
|
|
23969
|
+
QUESTION_PATTERNS = [
|
|
23970
|
+
/^(?:what|which|where|when|why|how)\b/i,
|
|
23971
|
+
/^(?:show|tell|list|explain)\b/i,
|
|
23972
|
+
/^(?:is|are)\b/i
|
|
23973
|
+
];
|
|
23974
|
+
}
|
|
23975
|
+
});
|
|
23976
|
+
|
|
23977
|
+
// src/intent/auto-route.ts
|
|
23978
|
+
var auto_route_exports = {};
|
|
23979
|
+
__export(auto_route_exports, {
|
|
23980
|
+
resolveAutoRoute: () => resolveAutoRoute
|
|
23981
|
+
});
|
|
23982
|
+
function tieredModels(adapter) {
|
|
23983
|
+
const modelIds = Object.keys(adapter.availableModels);
|
|
23984
|
+
if (modelIds.length <= 1) {
|
|
23985
|
+
const only = modelIds[0] ?? adapter.defaultModel;
|
|
23986
|
+
return { cheap: only, mid: only, best: only };
|
|
23987
|
+
}
|
|
23988
|
+
const pricingEntries = modelIds.filter((id) => adapter.pricing[id]).map((id) => ({ id, out: adapter.pricing[id].out }));
|
|
23989
|
+
if (pricingEntries.length >= 2) {
|
|
23990
|
+
pricingEntries.sort((a, b) => a.out - b.out);
|
|
23991
|
+
const cheap = pricingEntries[0].id;
|
|
23992
|
+
const best = pricingEntries[pricingEntries.length - 1].id;
|
|
23993
|
+
const midIdx = Math.floor(pricingEntries.length / 2);
|
|
23994
|
+
const mid = pricingEntries.length === 2 ? pricingEntries[1].id : pricingEntries[midIdx].id;
|
|
23995
|
+
return { cheap, mid, best };
|
|
23996
|
+
}
|
|
23997
|
+
return {
|
|
23998
|
+
cheap: adapter.summarizerModel,
|
|
23999
|
+
mid: adapter.defaultModel,
|
|
24000
|
+
best: modelIds[0]
|
|
24001
|
+
};
|
|
24002
|
+
}
|
|
24003
|
+
function pickThinking(model2, adapter, desired) {
|
|
24004
|
+
const info = adapter.availableModels[model2];
|
|
24005
|
+
if (!info || info.thinking !== "adjustable") {
|
|
24006
|
+
return "auto";
|
|
24007
|
+
}
|
|
24008
|
+
const levels = info.thinkingLevels;
|
|
24009
|
+
if (!levels || levels.length === 0) {
|
|
24010
|
+
return "auto";
|
|
24011
|
+
}
|
|
24012
|
+
if (levels.includes(desired)) {
|
|
24013
|
+
return desired;
|
|
24014
|
+
}
|
|
24015
|
+
const desiredIdx = THINKING_ORDER.indexOf(desired);
|
|
24016
|
+
if (desiredIdx === -1) return levels[0];
|
|
24017
|
+
let closest = levels[0];
|
|
24018
|
+
let closestDist = Infinity;
|
|
24019
|
+
for (const lvl of levels) {
|
|
24020
|
+
const idx = THINKING_ORDER.indexOf(lvl);
|
|
24021
|
+
if (idx === -1) continue;
|
|
24022
|
+
const dist = Math.abs(idx - desiredIdx);
|
|
24023
|
+
if (dist < closestDist) {
|
|
24024
|
+
closestDist = dist;
|
|
24025
|
+
closest = lvl;
|
|
24026
|
+
}
|
|
24027
|
+
}
|
|
24028
|
+
return closest;
|
|
24029
|
+
}
|
|
24030
|
+
function resolveAutoRoute(tier, adapter) {
|
|
24031
|
+
const models = tieredModels(adapter);
|
|
24032
|
+
const mapping = TIER_MAP[tier];
|
|
24033
|
+
const model2 = models[mapping.tier];
|
|
24034
|
+
const thinkingLevel = pickThinking(model2, adapter, mapping.thinking);
|
|
24035
|
+
log(
|
|
24036
|
+
`[auto-route] ${tier} -> ${model2} (${mapping.tier}), thinking=${thinkingLevel} [${adapter.id}]`
|
|
24037
|
+
);
|
|
24038
|
+
return { model: model2, thinkingLevel };
|
|
24039
|
+
}
|
|
24040
|
+
var THINKING_ORDER, TIER_MAP;
|
|
24041
|
+
var init_auto_route = __esm({
|
|
24042
|
+
"src/intent/auto-route.ts"() {
|
|
24043
|
+
"use strict";
|
|
24044
|
+
init_log();
|
|
24045
|
+
THINKING_ORDER = ["off", "low", "medium", "high", "extra_high"];
|
|
24046
|
+
TIER_MAP = {
|
|
24047
|
+
trivial: { tier: "cheap", thinking: "off" },
|
|
24048
|
+
simple: { tier: "cheap", thinking: "low" },
|
|
24049
|
+
moderate: { tier: "mid", thinking: "medium" },
|
|
24050
|
+
complex: { tier: "best", thinking: "high" }
|
|
24051
|
+
};
|
|
24052
|
+
}
|
|
24053
|
+
});
|
|
24054
|
+
|
|
24055
|
+
// src/council/executor.ts
|
|
24056
|
+
var executor_exports = {};
|
|
24057
|
+
__export(executor_exports, {
|
|
24058
|
+
anonymizeSubmissions: () => anonymizeSubmissions,
|
|
24059
|
+
buildRoundPrompt: () => buildRoundPrompt,
|
|
24060
|
+
executeCouncil: () => executeCouncil,
|
|
24061
|
+
waitForAgent: () => waitForAgent
|
|
24062
|
+
});
|
|
24063
|
+
function anonymizeSubmissions(submissions) {
|
|
24064
|
+
const entries = [...submissions.entries()].map(([, response]) => response);
|
|
24065
|
+
for (let i = entries.length - 1; i > 0; i--) {
|
|
24066
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
24067
|
+
[entries[i], entries[j]] = [entries[j], entries[i]];
|
|
24068
|
+
}
|
|
24069
|
+
const labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
24070
|
+
return entries.map((response, idx) => ({
|
|
24071
|
+
label: `Participant ${labels[idx] ?? String(idx + 1)}`,
|
|
24072
|
+
response
|
|
24073
|
+
}));
|
|
24074
|
+
}
|
|
24075
|
+
function buildRoundPrompt(question, roundNumber, priorSubmissions) {
|
|
24076
|
+
if (roundNumber === 1 || !priorSubmissions?.length) {
|
|
24077
|
+
return [
|
|
24078
|
+
"You are participating in a council debate. Provide your best answer to the following question.",
|
|
24079
|
+
"",
|
|
24080
|
+
`Question: ${question}`
|
|
24081
|
+
].join("\n");
|
|
24082
|
+
}
|
|
24083
|
+
const submissionBlock = priorSubmissions.map((s) => `--- ${s.label} ---
|
|
24084
|
+
${s.response}`).join("\n\n");
|
|
24085
|
+
return [
|
|
24086
|
+
"You are participating in a council debate (round " + roundNumber + ").",
|
|
24087
|
+
"Review the positions below, address any disagreements, and refine your answer.",
|
|
24088
|
+
"Evaluate each position on merit only. You do NOT know which model produced which submission.",
|
|
24089
|
+
"",
|
|
24090
|
+
`Question: ${question}`,
|
|
24091
|
+
"",
|
|
24092
|
+
"Previous submissions:",
|
|
24093
|
+
submissionBlock
|
|
24094
|
+
].join("\n");
|
|
24095
|
+
}
|
|
24096
|
+
async function waitForAgent(agentId, maxWaitMs = 3e5) {
|
|
24097
|
+
const { getAgent: getAgent3 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
24098
|
+
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
24099
|
+
const db3 = getDb2();
|
|
24100
|
+
const deadline = Date.now() + maxWaitMs;
|
|
24101
|
+
const terminalStatuses = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
24102
|
+
while (Date.now() < deadline) {
|
|
24103
|
+
const agent = getAgent3(db3, agentId);
|
|
24104
|
+
if (!agent) {
|
|
24105
|
+
return { resultSummary: null, tokenInput: 0, tokenOutput: 0, status: "not_found" };
|
|
24106
|
+
}
|
|
24107
|
+
if (terminalStatuses.has(agent.status)) {
|
|
24108
|
+
return {
|
|
24109
|
+
resultSummary: agent.resultSummary,
|
|
24110
|
+
tokenInput: agent.tokenInput,
|
|
24111
|
+
tokenOutput: agent.tokenOutput,
|
|
24112
|
+
status: agent.status
|
|
24113
|
+
};
|
|
24114
|
+
}
|
|
24115
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
24116
|
+
}
|
|
24117
|
+
return { resultSummary: null, tokenInput: 0, tokenOutput: 0, status: "timeout" };
|
|
24118
|
+
}
|
|
24119
|
+
function checkConvergence(submissions) {
|
|
24120
|
+
const wordSets = [...submissions.values()].map((text) => {
|
|
24121
|
+
const words = text.toLowerCase().replace(/[^a-z0-9\s]/g, "").split(/\s+/).filter((w) => w.length > 3);
|
|
24122
|
+
return new Set(words);
|
|
24123
|
+
});
|
|
24124
|
+
if (wordSets.length < 2) return true;
|
|
24125
|
+
for (let i = 0; i < wordSets.length; i++) {
|
|
24126
|
+
for (let j = i + 1; j < wordSets.length; j++) {
|
|
24127
|
+
const a = wordSets[i];
|
|
24128
|
+
const b = wordSets[j];
|
|
24129
|
+
const intersection = new Set([...a].filter((w) => b.has(w)));
|
|
24130
|
+
const union = /* @__PURE__ */ new Set([...a, ...b]);
|
|
24131
|
+
if (union.size === 0) continue;
|
|
24132
|
+
const overlap = intersection.size / union.size;
|
|
24133
|
+
if (overlap < 0.6) return false;
|
|
24134
|
+
}
|
|
24135
|
+
}
|
|
24136
|
+
return true;
|
|
24137
|
+
}
|
|
24138
|
+
async function executeCouncil(chatId, participants, question, onProgress) {
|
|
24139
|
+
const { spawnSubAgent: spawnSubAgent2 } = await Promise.resolve().then(() => (init_orchestrator(), orchestrator_exports));
|
|
24140
|
+
const startTime = Date.now();
|
|
24141
|
+
const rounds = [];
|
|
24142
|
+
const totalTokens = { input: 0, output: 0 };
|
|
24143
|
+
let lastAnonymized = [];
|
|
24144
|
+
for (let round = 1; round <= COUNCIL_MAX_ROUNDS; round++) {
|
|
24145
|
+
onProgress?.(`Round ${round}/${COUNCIL_MAX_ROUNDS}: spawning ${participants.length} agents...`);
|
|
24146
|
+
const prompt = buildRoundPrompt(question, round, round > 1 ? lastAnonymized : void 0);
|
|
24147
|
+
const submissions = /* @__PURE__ */ new Map();
|
|
24148
|
+
const spawnPromises = participants.map(async (p) => {
|
|
24149
|
+
const key = `${p.backend}:${p.model}`;
|
|
24150
|
+
const { agentId } = await spawnSubAgent2(chatId, {
|
|
24151
|
+
runner: p.backend,
|
|
24152
|
+
task: prompt,
|
|
24153
|
+
name: `council-${p.label}-r${round}`,
|
|
24154
|
+
model: p.model,
|
|
24155
|
+
permMode: "readonly",
|
|
24156
|
+
role: "worker"
|
|
24157
|
+
});
|
|
24158
|
+
return { key, agentId };
|
|
24159
|
+
});
|
|
24160
|
+
const spawned = await Promise.all(spawnPromises);
|
|
24161
|
+
const resultPromises = spawned.map(async ({ key, agentId }) => {
|
|
24162
|
+
const result = await waitForAgent(agentId);
|
|
24163
|
+
totalTokens.input += result.tokenInput;
|
|
24164
|
+
totalTokens.output += result.tokenOutput;
|
|
24165
|
+
if (result.resultSummary) {
|
|
24166
|
+
submissions.set(key, result.resultSummary);
|
|
24167
|
+
} else {
|
|
24168
|
+
submissions.set(key, "(No response)");
|
|
24169
|
+
}
|
|
24170
|
+
});
|
|
24171
|
+
await Promise.all(resultPromises);
|
|
24172
|
+
rounds.push({ roundNumber: round, submissions });
|
|
24173
|
+
lastAnonymized = anonymizeSubmissions(submissions);
|
|
24174
|
+
onProgress?.(`Round ${round} complete: ${submissions.size} responses collected.`);
|
|
24175
|
+
if (round >= 2 && checkConvergence(submissions)) {
|
|
24176
|
+
log(`[council] Convergence reached after round ${round}`);
|
|
24177
|
+
onProgress?.(`Convergence reached after round ${round}.`);
|
|
24178
|
+
break;
|
|
24179
|
+
}
|
|
24180
|
+
}
|
|
24181
|
+
const finalParts = lastAnonymized.map(
|
|
24182
|
+
(s) => `### ${s.label}
|
|
24183
|
+
${s.response}`
|
|
24184
|
+
);
|
|
24185
|
+
const finalAnswer = finalParts.join("\n\n");
|
|
24186
|
+
const elapsedMs = Date.now() - startTime;
|
|
24187
|
+
return {
|
|
24188
|
+
rounds,
|
|
24189
|
+
finalAnswer,
|
|
24190
|
+
participants,
|
|
24191
|
+
totalTokens,
|
|
24192
|
+
elapsedMs
|
|
24193
|
+
};
|
|
24194
|
+
}
|
|
24195
|
+
var init_executor = __esm({
|
|
24196
|
+
"src/council/executor.ts"() {
|
|
24197
|
+
"use strict";
|
|
24198
|
+
init_types4();
|
|
24199
|
+
init_log();
|
|
24200
|
+
}
|
|
24201
|
+
});
|
|
24202
|
+
|
|
23399
24203
|
// src/router.ts
|
|
23400
24204
|
var router_exports = {};
|
|
23401
24205
|
__export(router_exports, {
|
|
@@ -23432,6 +24236,10 @@ __export(router_exports, {
|
|
|
23432
24236
|
});
|
|
23433
24237
|
async function handleMessage(msg, channel) {
|
|
23434
24238
|
const { chatId } = msg;
|
|
24239
|
+
if (msg.threadId) {
|
|
24240
|
+
const { withThread: withThread2 } = await Promise.resolve().then(() => (init_thread_wrapper(), thread_wrapper_exports));
|
|
24241
|
+
channel = withThread2(channel, msg.threadId);
|
|
24242
|
+
}
|
|
23435
24243
|
if (msg.messageId && typeof channel.reactToMessage === "function" && msg.type !== "text" && msg.type !== "command") {
|
|
23436
24244
|
channel.reactToMessage(chatId, msg.messageId, pickReactionEmoji(msg)).catch(() => {
|
|
23437
24245
|
});
|
|
@@ -23509,6 +24317,20 @@ async function handleText(msg, channel) {
|
|
|
23509
24317
|
return;
|
|
23510
24318
|
}
|
|
23511
24319
|
const model2 = resolveModel(chatId);
|
|
24320
|
+
let autoRouted = false;
|
|
24321
|
+
let effectiveModel = model2;
|
|
24322
|
+
let effectiveThinking;
|
|
24323
|
+
if (model2 === "auto") {
|
|
24324
|
+
const { classifyComplexity: classifyComplexity2 } = await Promise.resolve().then(() => (init_complexity(), complexity_exports));
|
|
24325
|
+
const { resolveAutoRoute: resolveAutoRoute2 } = await Promise.resolve().then(() => (init_auto_route(), auto_route_exports));
|
|
24326
|
+
const adapter = getAdapterForChat(chatId);
|
|
24327
|
+
const tier = classifyComplexity2(text);
|
|
24328
|
+
const route = resolveAutoRoute2(tier, adapter);
|
|
24329
|
+
effectiveModel = route.model;
|
|
24330
|
+
effectiveThinking = route.thinkingLevel;
|
|
24331
|
+
autoRouted = true;
|
|
24332
|
+
log(`[router] Auto-route: "${text.slice(0, 40)}..." -> ${tier} -> model=${effectiveModel}, thinking=${effectiveThinking}`);
|
|
24333
|
+
}
|
|
23512
24334
|
const backendId = settings.getBackend() ?? "claude";
|
|
23513
24335
|
const limitMsg = checkBackendLimits(backendId);
|
|
23514
24336
|
if (limitMsg) {
|
|
@@ -23632,6 +24454,43 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
23632
24454
|
return;
|
|
23633
24455
|
}
|
|
23634
24456
|
}
|
|
24457
|
+
{
|
|
24458
|
+
const { hasPendingCouncil: hasPendingCouncil2, getCouncilState: getCouncilState2, setCouncilQuestion: setCouncilQuestion2, cancelCouncil: cancelCouncil2 } = await Promise.resolve().then(() => (init_wizard2(), wizard_exports));
|
|
24459
|
+
if (hasPendingCouncil2(chatId)) {
|
|
24460
|
+
const state = getCouncilState2(chatId);
|
|
24461
|
+
if (state?.step === "question") {
|
|
24462
|
+
const result = setCouncilQuestion2(chatId, text);
|
|
24463
|
+
if (result.error) {
|
|
24464
|
+
await channel.sendText(chatId, result.error, { parseMode: "plain" });
|
|
24465
|
+
return;
|
|
24466
|
+
}
|
|
24467
|
+
const participants = [...state.selected.values()];
|
|
24468
|
+
const question = state.question;
|
|
24469
|
+
cancelCouncil2(chatId);
|
|
24470
|
+
await channel.sendText(chatId, `\u{1F3DB}\uFE0F Council convened \u2014 ${participants.length} models, up to 3 rounds.
|
|
24471
|
+
|
|
24472
|
+
Debating: "${question.slice(0, 100)}${question.length > 100 ? "\u2026" : ""}"`, { parseMode: "plain" });
|
|
24473
|
+
await channel.sendTyping?.(chatId);
|
|
24474
|
+
try {
|
|
24475
|
+
const { executeCouncil: executeCouncil2 } = await Promise.resolve().then(() => (init_executor(), executor_exports));
|
|
24476
|
+
const councilResult = await executeCouncil2(
|
|
24477
|
+
chatId,
|
|
24478
|
+
participants,
|
|
24479
|
+
question,
|
|
24480
|
+
(msg2) => {
|
|
24481
|
+
channel.sendText(chatId, msg2, { parseMode: "plain" }).catch(() => {
|
|
24482
|
+
});
|
|
24483
|
+
}
|
|
24484
|
+
);
|
|
24485
|
+
await sendResponse(chatId, channel, councilResult.finalAnswer, msg.messageId);
|
|
24486
|
+
} catch (e) {
|
|
24487
|
+
const errMsg = e.message ?? String(e);
|
|
24488
|
+
await channel.sendText(chatId, `Council failed: ${errMsg}`, { parseMode: "plain" });
|
|
24489
|
+
}
|
|
24490
|
+
return;
|
|
24491
|
+
}
|
|
24492
|
+
}
|
|
24493
|
+
}
|
|
23635
24494
|
if (isChatBusy(chatId) && !bypassBusyCheck.delete(chatId)) {
|
|
23636
24495
|
if (typeof channel.sendKeyboard === "function") {
|
|
23637
24496
|
pendingInterrupts.set(chatId, { msg, channel });
|
|
@@ -23741,6 +24600,7 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
23741
24600
|
liveStatus = ls.liveStatus;
|
|
23742
24601
|
const baseCb = tVerbose !== "off" ? ls.toolCb : void 0;
|
|
23743
24602
|
tToolCb = async (toolName, input, result) => {
|
|
24603
|
+
if (result === void 0) toolUseCount++;
|
|
23744
24604
|
if (baseCb) await baseCb(toolName, input, result);
|
|
23745
24605
|
if (sessionLog) {
|
|
23746
24606
|
if (result === void 0) {
|
|
@@ -23756,6 +24616,7 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
23756
24616
|
}
|
|
23757
24617
|
} else if (sessionLog) {
|
|
23758
24618
|
tToolCb = async (toolName, input, result) => {
|
|
24619
|
+
if (result === void 0) toolUseCount++;
|
|
23759
24620
|
if (result === void 0) {
|
|
23760
24621
|
sessionLog.logToolStart(toolName, input);
|
|
23761
24622
|
} else {
|
|
@@ -23763,15 +24624,18 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
23763
24624
|
}
|
|
23764
24625
|
};
|
|
23765
24626
|
}
|
|
24627
|
+
let toolUseCount = 0;
|
|
23766
24628
|
const sigT0 = Date.now();
|
|
23767
24629
|
const response = await askAgent(chatId, cleanText || text, {
|
|
23768
24630
|
cwd: settings.getCwd(),
|
|
23769
|
-
model:
|
|
24631
|
+
model: effectiveModel,
|
|
23770
24632
|
permMode: tMode,
|
|
23771
24633
|
onToolAction: tToolCb,
|
|
23772
24634
|
bootstrapTier,
|
|
23773
24635
|
maxTurns,
|
|
23774
24636
|
agentMode: effectiveAgentMode,
|
|
24637
|
+
...effectiveThinking ? { thinkingLevel: effectiveThinking } : {},
|
|
24638
|
+
chatContext: { chatTitle: msg.chatTitle, threadId: msg.threadId },
|
|
23775
24639
|
onThinking: liveStatus || sessionLog ? (chunk) => {
|
|
23776
24640
|
if (liveStatus) liveStatus.addThinking(chunk);
|
|
23777
24641
|
if (sessionLog) sessionLog.logThinking(chunk);
|
|
@@ -23821,7 +24685,7 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
23821
24685
|
const sigEnabled = settings.getModelSignature();
|
|
23822
24686
|
if (sigEnabled === "on" && responseText && !responseText.startsWith("(No response")) {
|
|
23823
24687
|
const adapter2 = getAdapterForChat(chatId);
|
|
23824
|
-
const modelId = response.resolvedModel ??
|
|
24688
|
+
const modelId = response.resolvedModel ?? effectiveModel ?? adapter2.defaultModel;
|
|
23825
24689
|
const thinking2 = settings.getThinkingLevel() || "auto";
|
|
23826
24690
|
const shortModel = formatModelShort(modelId);
|
|
23827
24691
|
let slotTag = "";
|
|
@@ -23876,6 +24740,42 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
23876
24740
|
} catch (e) {
|
|
23877
24741
|
log(`[reflection] Signal detection error: ${e}`);
|
|
23878
24742
|
}
|
|
24743
|
+
try {
|
|
24744
|
+
const { getSkillSuggestionsEnabled: getSkillSuggestionsEnabled2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
24745
|
+
if (intent === "agentic" && toolUseCount > 0 && getSkillSuggestionsEnabled2(chatId)) {
|
|
24746
|
+
const { isSkillWorthy: isSkillWorthy2 } = await Promise.resolve().then(() => (init_auto_create(), auto_create_exports));
|
|
24747
|
+
const signals = {
|
|
24748
|
+
toolUseCount,
|
|
24749
|
+
tokenOutput: response.usage?.output ?? 0,
|
|
24750
|
+
elapsedMs,
|
|
24751
|
+
userMessage: cleanText || text
|
|
24752
|
+
};
|
|
24753
|
+
if (isSkillWorthy2(signals) && typeof channel.sendKeyboard === "function") {
|
|
24754
|
+
const { storePendingDraft: storePendingDraft2 } = await Promise.resolve().then(() => (init_auto_create(), auto_create_exports));
|
|
24755
|
+
const taskSummary = (cleanText || text).slice(0, 120) + ((cleanText || text).length > 120 ? "\u2026" : "");
|
|
24756
|
+
storePendingDraft2(chatId, {
|
|
24757
|
+
name: "",
|
|
24758
|
+
content: "",
|
|
24759
|
+
userMessage: cleanText || text,
|
|
24760
|
+
assistantResponse: response.text
|
|
24761
|
+
});
|
|
24762
|
+
await channel.sendKeyboard(
|
|
24763
|
+
chatId,
|
|
24764
|
+
`\u{1F4A1} That looked like a reusable workflow:
|
|
24765
|
+
|
|
24766
|
+
"${taskSummary}"
|
|
24767
|
+
|
|
24768
|
+
Want me to extract it as a reusable skill? (${toolUseCount} tools used, ${elapsedSec}s)`,
|
|
24769
|
+
[[
|
|
24770
|
+
{ label: "\u2705 Extract Skill", data: "skill:extract", style: "success" },
|
|
24771
|
+
{ label: "\u2715 No thanks", data: "skill:discard" }
|
|
24772
|
+
]]
|
|
24773
|
+
);
|
|
24774
|
+
}
|
|
24775
|
+
}
|
|
24776
|
+
} catch (e) {
|
|
24777
|
+
log(`[auto-skill] Evaluation error: ${e}`);
|
|
24778
|
+
}
|
|
23879
24779
|
} catch (err) {
|
|
23880
24780
|
error("[router] Error:", err);
|
|
23881
24781
|
const errMsg = errorMessage(err);
|
|
@@ -24368,7 +25268,7 @@ var init_cron = __esm({
|
|
|
24368
25268
|
});
|
|
24369
25269
|
|
|
24370
25270
|
// src/agents/runners/wrap-backend.ts
|
|
24371
|
-
import { join as
|
|
25271
|
+
import { join as join26 } from "path";
|
|
24372
25272
|
function buildMcpCommands(backendId) {
|
|
24373
25273
|
const exe = backendId === BACKEND.CURSOR ? "agent" : backendId;
|
|
24374
25274
|
return {
|
|
@@ -24462,7 +25362,7 @@ function wrapBackendAdapter(adapter) {
|
|
|
24462
25362
|
const configPath = writeMcpConfigFile(server);
|
|
24463
25363
|
return ["--mcp-config", configPath];
|
|
24464
25364
|
},
|
|
24465
|
-
getSkillPath: () =>
|
|
25365
|
+
getSkillPath: () => join26(SKILLS_PATH, `agent-${adapter.id}.md`)
|
|
24466
25366
|
};
|
|
24467
25367
|
}
|
|
24468
25368
|
var BACKEND_CAPABILITIES;
|
|
@@ -24515,7 +25415,7 @@ var init_wrap_backend = __esm({
|
|
|
24515
25415
|
|
|
24516
25416
|
// src/agents/runners/config-loader.ts
|
|
24517
25417
|
import { readFileSync as readFileSync14, readdirSync as readdirSync14, existsSync as existsSync23, mkdirSync as mkdirSync10, watchFile, unwatchFile } from "fs";
|
|
24518
|
-
import { join as
|
|
25418
|
+
import { join as join27 } from "path";
|
|
24519
25419
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
24520
25420
|
function resolveExecutable2(config2) {
|
|
24521
25421
|
if (existsSync23(config2.executable)) return config2.executable;
|
|
@@ -24651,7 +25551,7 @@ function configToRunner(config2) {
|
|
|
24651
25551
|
prepareMcpInjection() {
|
|
24652
25552
|
return [];
|
|
24653
25553
|
},
|
|
24654
|
-
getSkillPath: () =>
|
|
25554
|
+
getSkillPath: () => join27(SKILLS_PATH, `agent-${config2.id}.md`)
|
|
24655
25555
|
};
|
|
24656
25556
|
}
|
|
24657
25557
|
function loadRunnerConfig(filePath) {
|
|
@@ -24671,7 +25571,7 @@ function loadAllRunnerConfigs() {
|
|
|
24671
25571
|
const files = readdirSync14(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
24672
25572
|
const configs = [];
|
|
24673
25573
|
for (const file of files) {
|
|
24674
|
-
const config2 = loadRunnerConfig(
|
|
25574
|
+
const config2 = loadRunnerConfig(join27(RUNNERS_PATH, file));
|
|
24675
25575
|
if (config2) configs.push(config2);
|
|
24676
25576
|
}
|
|
24677
25577
|
return configs;
|
|
@@ -24701,7 +25601,7 @@ function watchRunnerConfigs(onChange) {
|
|
|
24701
25601
|
}
|
|
24702
25602
|
const files = readdirSync14(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
24703
25603
|
for (const file of files) {
|
|
24704
|
-
const fullPath =
|
|
25604
|
+
const fullPath = join27(RUNNERS_PATH, file);
|
|
24705
25605
|
if (watchedFiles.has(fullPath)) continue;
|
|
24706
25606
|
watchedFiles.add(fullPath);
|
|
24707
25607
|
watchFile(fullPath, { interval: 5e3 }, () => {
|
|
@@ -25321,9 +26221,11 @@ var init_telegram2 = __esm({
|
|
|
25321
26221
|
async stop() {
|
|
25322
26222
|
await this.bot.stop();
|
|
25323
26223
|
}
|
|
25324
|
-
async sendTyping(chatId) {
|
|
26224
|
+
async sendTyping(chatId, threadId) {
|
|
25325
26225
|
try {
|
|
25326
|
-
await this.bot.api.sendChatAction(numericChatId(chatId), "typing"
|
|
26226
|
+
await this.bot.api.sendChatAction(numericChatId(chatId), "typing", {
|
|
26227
|
+
...threadId ? { message_thread_id: threadId } : {}
|
|
26228
|
+
});
|
|
25327
26229
|
} catch {
|
|
25328
26230
|
}
|
|
25329
26231
|
}
|
|
@@ -25370,21 +26272,23 @@ var init_telegram2 = __esm({
|
|
|
25370
26272
|
}
|
|
25371
26273
|
}
|
|
25372
26274
|
}
|
|
25373
|
-
async sendVoice(chatId, audioBuffer, fileName) {
|
|
26275
|
+
async sendVoice(chatId, audioBuffer, fileName, threadId) {
|
|
25374
26276
|
await withRetry(
|
|
25375
26277
|
"sendVoice",
|
|
25376
26278
|
() => this.bot.api.sendVoice(
|
|
25377
26279
|
numericChatId(chatId),
|
|
25378
|
-
new InputFile(audioBuffer, fileName ?? "response.ogg")
|
|
26280
|
+
new InputFile(audioBuffer, fileName ?? "response.ogg"),
|
|
26281
|
+
{ ...threadId ? { message_thread_id: threadId } : {} }
|
|
25379
26282
|
)
|
|
25380
26283
|
);
|
|
25381
26284
|
}
|
|
25382
|
-
async sendFile(chatId, buffer, fileName) {
|
|
26285
|
+
async sendFile(chatId, buffer, fileName, _mimeType, threadId) {
|
|
25383
26286
|
await withRetry(
|
|
25384
26287
|
"sendFile",
|
|
25385
26288
|
() => this.bot.api.sendDocument(
|
|
25386
26289
|
numericChatId(chatId),
|
|
25387
|
-
new InputFile(buffer, fileName)
|
|
26290
|
+
new InputFile(buffer, fileName),
|
|
26291
|
+
{ ...threadId ? { message_thread_id: threadId } : {} }
|
|
25388
26292
|
)
|
|
25389
26293
|
);
|
|
25390
26294
|
}
|
|
@@ -25394,10 +26298,11 @@ var init_telegram2 = __esm({
|
|
|
25394
26298
|
const response = await fetch(fileUrl);
|
|
25395
26299
|
return Buffer.from(await response.arrayBuffer());
|
|
25396
26300
|
}
|
|
25397
|
-
async sendTextReturningId(chatId, text, parseMode) {
|
|
26301
|
+
async sendTextReturningId(chatId, text, parseMode, threadId) {
|
|
25398
26302
|
try {
|
|
25399
26303
|
const formatted = sanitizeForTelegram(parseMode === "html" ? text : parseMode === "plain" ? text : formatForTelegram(text));
|
|
25400
|
-
const
|
|
26304
|
+
const threadOpts = threadId ? { message_thread_id: threadId } : {};
|
|
26305
|
+
const opts = parseMode === "plain" ? { ...threadOpts } : { parse_mode: "HTML", ...threadOpts };
|
|
25401
26306
|
const msg = await withRetry(
|
|
25402
26307
|
"sendTextReturningId",
|
|
25403
26308
|
() => this.bot.api.sendMessage(numericChatId(chatId), formatted, opts)
|
|
@@ -25485,7 +26390,7 @@ var init_telegram2 = __esm({
|
|
|
25485
26390
|
onReaction(handler) {
|
|
25486
26391
|
this.reactionHandlers.push(handler);
|
|
25487
26392
|
}
|
|
25488
|
-
async sendKeyboard(chatId, text, buttons) {
|
|
26393
|
+
async sendKeyboard(chatId, text, buttons, threadId) {
|
|
25489
26394
|
const keyboard = new InlineKeyboard();
|
|
25490
26395
|
for (const row of buttons) {
|
|
25491
26396
|
for (const btn of row) {
|
|
@@ -25499,12 +26404,14 @@ var init_telegram2 = __esm({
|
|
|
25499
26404
|
const MAX_KEYBOARD_TEXT = 4e3;
|
|
25500
26405
|
const safeText = text.length > MAX_KEYBOARD_TEXT ? text.slice(0, MAX_KEYBOARD_TEXT) + "\n\n\u2026(truncated)" : text;
|
|
25501
26406
|
const formatted = sanitizeForTelegram(formatForTelegram(safeText));
|
|
26407
|
+
const threadOpts = threadId ? { message_thread_id: threadId } : {};
|
|
25502
26408
|
try {
|
|
25503
26409
|
const msg = await withRetry(
|
|
25504
26410
|
"sendKeyboard",
|
|
25505
26411
|
() => this.bot.api.sendMessage(numericChatId(chatId), formatted, {
|
|
25506
26412
|
parse_mode: "HTML",
|
|
25507
|
-
reply_markup: keyboard
|
|
26413
|
+
reply_markup: keyboard,
|
|
26414
|
+
...threadOpts
|
|
25508
26415
|
})
|
|
25509
26416
|
);
|
|
25510
26417
|
return msg.message_id.toString();
|
|
@@ -25519,7 +26426,8 @@ var init_telegram2 = __esm({
|
|
|
25519
26426
|
const retryMsg = await withRetry(
|
|
25520
26427
|
"sendKeyboard:plain",
|
|
25521
26428
|
() => this.bot.api.sendMessage(numericChatId(chatId), escaped, {
|
|
25522
|
-
reply_markup: keyboard
|
|
26429
|
+
reply_markup: keyboard,
|
|
26430
|
+
...threadOpts
|
|
25523
26431
|
})
|
|
25524
26432
|
);
|
|
25525
26433
|
return retryMsg.message_id.toString();
|
|
@@ -25532,7 +26440,7 @@ var init_telegram2 = __esm({
|
|
|
25532
26440
|
if (plainText.trim()) {
|
|
25533
26441
|
await withRetry(
|
|
25534
26442
|
"sendKeyboard:text-rescue",
|
|
25535
|
-
() => this.bot.api.sendMessage(numericChatId(chatId), plainText, {})
|
|
26443
|
+
() => this.bot.api.sendMessage(numericChatId(chatId), plainText, { ...threadOpts })
|
|
25536
26444
|
);
|
|
25537
26445
|
}
|
|
25538
26446
|
} catch {
|
|
@@ -25541,7 +26449,8 @@ var init_telegram2 = __esm({
|
|
|
25541
26449
|
const fallbackMsg = await withRetry(
|
|
25542
26450
|
"sendKeyboard:fallback",
|
|
25543
26451
|
() => this.bot.api.sendMessage(numericChatId(chatId), "\u2B06\uFE0F (see above for details)", {
|
|
25544
|
-
reply_markup: keyboard
|
|
26452
|
+
reply_markup: keyboard,
|
|
26453
|
+
...threadOpts
|
|
25545
26454
|
})
|
|
25546
26455
|
);
|
|
25547
26456
|
return fallbackMsg.message_id.toString();
|
|
@@ -25633,6 +26542,7 @@ var init_telegram2 = __esm({
|
|
|
25633
26542
|
const fwdOrigin = ctx.message?.forward_origin;
|
|
25634
26543
|
const fwdFromChat = ctx.message?.forward_from_chat;
|
|
25635
26544
|
const forwardedFrom = fwdOrigin?.chat?.title ?? fwdOrigin?.sender_chat?.title ?? fwdOrigin?.sender_user?.first_name ?? fwdOrigin?.sender_user_name ?? fwdFromChat?.title ?? void 0;
|
|
26545
|
+
const threadId = ctx.message?.message_thread_id;
|
|
25636
26546
|
if (ctx.message?.voice) {
|
|
25637
26547
|
return {
|
|
25638
26548
|
chatId,
|
|
@@ -25646,6 +26556,7 @@ var init_telegram2 = __esm({
|
|
|
25646
26556
|
chatTitle,
|
|
25647
26557
|
replyToText,
|
|
25648
26558
|
forwardedFrom,
|
|
26559
|
+
threadId,
|
|
25649
26560
|
raw: ctx
|
|
25650
26561
|
};
|
|
25651
26562
|
}
|
|
@@ -25665,6 +26576,7 @@ var init_telegram2 = __esm({
|
|
|
25665
26576
|
chatTitle,
|
|
25666
26577
|
replyToText,
|
|
25667
26578
|
forwardedFrom,
|
|
26579
|
+
threadId,
|
|
25668
26580
|
raw: ctx
|
|
25669
26581
|
};
|
|
25670
26582
|
}
|
|
@@ -25682,6 +26594,7 @@ var init_telegram2 = __esm({
|
|
|
25682
26594
|
chatTitle,
|
|
25683
26595
|
replyToText,
|
|
25684
26596
|
forwardedFrom,
|
|
26597
|
+
threadId,
|
|
25685
26598
|
raw: ctx
|
|
25686
26599
|
};
|
|
25687
26600
|
}
|
|
@@ -25708,6 +26621,7 @@ var init_telegram2 = __esm({
|
|
|
25708
26621
|
chatTitle,
|
|
25709
26622
|
replyToText,
|
|
25710
26623
|
forwardedFrom,
|
|
26624
|
+
threadId,
|
|
25711
26625
|
raw: ctx
|
|
25712
26626
|
};
|
|
25713
26627
|
}
|
|
@@ -25729,6 +26643,7 @@ var init_telegram2 = __esm({
|
|
|
25729
26643
|
chatTitle,
|
|
25730
26644
|
replyToText,
|
|
25731
26645
|
forwardedFrom,
|
|
26646
|
+
threadId,
|
|
25732
26647
|
raw: ctx
|
|
25733
26648
|
};
|
|
25734
26649
|
}
|
|
@@ -25742,6 +26657,7 @@ var init_telegram2 = __esm({
|
|
|
25742
26657
|
chatTitle,
|
|
25743
26658
|
replyToText,
|
|
25744
26659
|
forwardedFrom,
|
|
26660
|
+
threadId,
|
|
25745
26661
|
raw: ctx
|
|
25746
26662
|
};
|
|
25747
26663
|
}
|
|
@@ -25753,8 +26669,8 @@ var init_telegram2 = __esm({
|
|
|
25753
26669
|
|
|
25754
26670
|
// src/skills/bootstrap.ts
|
|
25755
26671
|
import { existsSync as existsSync24 } from "fs";
|
|
25756
|
-
import { readdir as readdir5, readFile as readFile8, writeFile as
|
|
25757
|
-
import { join as
|
|
26672
|
+
import { readdir as readdir5, readFile as readFile8, writeFile as writeFile5, copyFile } from "fs/promises";
|
|
26673
|
+
import { join as join28, dirname as dirname5 } from "path";
|
|
25758
26674
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
25759
26675
|
async function copyAgentManifestSkills() {
|
|
25760
26676
|
if (!existsSync24(PKG_SKILLS)) return;
|
|
@@ -25762,8 +26678,8 @@ async function copyAgentManifestSkills() {
|
|
|
25762
26678
|
const entries = await readdir5(PKG_SKILLS, { withFileTypes: true });
|
|
25763
26679
|
for (const entry of entries) {
|
|
25764
26680
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
25765
|
-
const src =
|
|
25766
|
-
const dest =
|
|
26681
|
+
const src = join28(PKG_SKILLS, entry.name);
|
|
26682
|
+
const dest = join28(SKILLS_PATH, entry.name);
|
|
25767
26683
|
if (existsSync24(dest)) continue;
|
|
25768
26684
|
await copyFile(src, dest);
|
|
25769
26685
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
@@ -25774,7 +26690,7 @@ async function copyAgentManifestSkills() {
|
|
|
25774
26690
|
}
|
|
25775
26691
|
async function bootstrapSkills() {
|
|
25776
26692
|
await copyAgentManifestSkills();
|
|
25777
|
-
const usmDir =
|
|
26693
|
+
const usmDir = join28(SKILLS_PATH, USM_DIR_NAME);
|
|
25778
26694
|
if (existsSync24(usmDir)) return;
|
|
25779
26695
|
try {
|
|
25780
26696
|
const entries = await readdir5(SKILLS_PATH);
|
|
@@ -25798,7 +26714,7 @@ async function bootstrapSkills() {
|
|
|
25798
26714
|
}
|
|
25799
26715
|
}
|
|
25800
26716
|
async function patchUsmForCcClaw(usmDir) {
|
|
25801
|
-
const skillPath =
|
|
26717
|
+
const skillPath = join28(usmDir, "SKILL.md");
|
|
25802
26718
|
if (!existsSync24(skillPath)) return;
|
|
25803
26719
|
try {
|
|
25804
26720
|
let content = await readFile8(skillPath, "utf-8");
|
|
@@ -25827,7 +26743,7 @@ async function patchUsmForCcClaw(usmDir) {
|
|
|
25827
26743
|
}
|
|
25828
26744
|
}
|
|
25829
26745
|
if (patched) {
|
|
25830
|
-
await
|
|
26746
|
+
await writeFile5(skillPath, content, "utf-8");
|
|
25831
26747
|
log("[skills] Patched USM SKILL.md with CC-Claw support");
|
|
25832
26748
|
}
|
|
25833
26749
|
} catch (err) {
|
|
@@ -25844,8 +26760,8 @@ var init_bootstrap = __esm({
|
|
|
25844
26760
|
USM_REPO = "jacob-bd/universal-skills-manager";
|
|
25845
26761
|
USM_DIR_NAME = "universal-skills-manager";
|
|
25846
26762
|
CC_CLAW_ECOSYSTEM_PATCH = `| **CC-Claw** | \`~/.cc-claw/workspace/skills/\` | N/A (daemon, no project scope) |`;
|
|
25847
|
-
PKG_ROOT =
|
|
25848
|
-
PKG_SKILLS =
|
|
26763
|
+
PKG_ROOT = join28(dirname5(fileURLToPath2(import.meta.url)), "..", "..");
|
|
26764
|
+
PKG_SKILLS = join28(PKG_ROOT, "skills");
|
|
25849
26765
|
}
|
|
25850
26766
|
});
|
|
25851
26767
|
|
|
@@ -26068,7 +26984,7 @@ __export(ai_skill_exports, {
|
|
|
26068
26984
|
installAiSkill: () => installAiSkill
|
|
26069
26985
|
});
|
|
26070
26986
|
import { existsSync as existsSync25, writeFileSync as writeFileSync8, mkdirSync as mkdirSync11 } from "fs";
|
|
26071
|
-
import { join as
|
|
26987
|
+
import { join as join29 } from "path";
|
|
26072
26988
|
import { homedir as homedir9 } from "os";
|
|
26073
26989
|
function generateAiSkill() {
|
|
26074
26990
|
const version = VERSION;
|
|
@@ -26488,8 +27404,8 @@ function installAiSkill() {
|
|
|
26488
27404
|
const failed = [];
|
|
26489
27405
|
for (const [backend2, dirs] of Object.entries(BACKEND_SKILL_DIRS2)) {
|
|
26490
27406
|
for (const dir of dirs) {
|
|
26491
|
-
const skillDir =
|
|
26492
|
-
const skillPath =
|
|
27407
|
+
const skillDir = join29(dir, "cc-claw-cli");
|
|
27408
|
+
const skillPath = join29(skillDir, "SKILL.md");
|
|
26493
27409
|
try {
|
|
26494
27410
|
mkdirSync11(skillDir, { recursive: true });
|
|
26495
27411
|
writeFileSync8(skillPath, skill, "utf-8");
|
|
@@ -26508,11 +27424,11 @@ var init_ai_skill = __esm({
|
|
|
26508
27424
|
init_paths();
|
|
26509
27425
|
init_version();
|
|
26510
27426
|
BACKEND_SKILL_DIRS2 = {
|
|
26511
|
-
"cc-claw": [
|
|
26512
|
-
claude: [
|
|
26513
|
-
gemini: [
|
|
26514
|
-
codex: [
|
|
26515
|
-
cursor: [
|
|
27427
|
+
"cc-claw": [join29(homedir9(), ".cc-claw", "workspace", "skills")],
|
|
27428
|
+
claude: [join29(homedir9(), ".claude", "skills")],
|
|
27429
|
+
gemini: [join29(homedir9(), ".gemini", "skills")],
|
|
27430
|
+
codex: [join29(homedir9(), ".agents", "skills")],
|
|
27431
|
+
cursor: [join29(homedir9(), ".cursor", "skills"), join29(homedir9(), ".cursor", "skills-cursor")]
|
|
26516
27432
|
};
|
|
26517
27433
|
}
|
|
26518
27434
|
});
|
|
@@ -26523,17 +27439,17 @@ __export(index_exports, {
|
|
|
26523
27439
|
main: () => main
|
|
26524
27440
|
});
|
|
26525
27441
|
import { mkdirSync as mkdirSync12, existsSync as existsSync26, renameSync as renameSync2, statSync as statSync8, readFileSync as readFileSync16 } from "fs";
|
|
26526
|
-
import { join as
|
|
27442
|
+
import { join as join30 } from "path";
|
|
26527
27443
|
import dotenv from "dotenv";
|
|
26528
27444
|
function migrateLayout() {
|
|
26529
27445
|
const moves = [
|
|
26530
|
-
[
|
|
26531
|
-
[
|
|
26532
|
-
[
|
|
26533
|
-
[
|
|
26534
|
-
[
|
|
26535
|
-
[
|
|
26536
|
-
[
|
|
27446
|
+
[join30(CC_CLAW_HOME, "cc-claw.db"), join30(DATA_PATH, "cc-claw.db")],
|
|
27447
|
+
[join30(CC_CLAW_HOME, "cc-claw.db-shm"), join30(DATA_PATH, "cc-claw.db-shm")],
|
|
27448
|
+
[join30(CC_CLAW_HOME, "cc-claw.db-wal"), join30(DATA_PATH, "cc-claw.db-wal")],
|
|
27449
|
+
[join30(CC_CLAW_HOME, "cc-claw.log"), join30(LOGS_PATH, "cc-claw.log")],
|
|
27450
|
+
[join30(CC_CLAW_HOME, "cc-claw.log.1"), join30(LOGS_PATH, "cc-claw.log.1")],
|
|
27451
|
+
[join30(CC_CLAW_HOME, "cc-claw.error.log"), join30(LOGS_PATH, "cc-claw.error.log")],
|
|
27452
|
+
[join30(CC_CLAW_HOME, "cc-claw.error.log.1"), join30(LOGS_PATH, "cc-claw.error.log.1")]
|
|
26537
27453
|
];
|
|
26538
27454
|
for (const [from, to] of moves) {
|
|
26539
27455
|
if (existsSync26(from) && !existsSync26(to)) {
|
|
@@ -26713,10 +27629,10 @@ async function main() {
|
|
|
26713
27629
|
try {
|
|
26714
27630
|
const { generateAiSkill: generateAiSkill2 } = await Promise.resolve().then(() => (init_ai_skill(), ai_skill_exports));
|
|
26715
27631
|
const { writeFileSync: writeFileSync13, mkdirSync: mkdirSync19 } = await import("fs");
|
|
26716
|
-
const { join:
|
|
26717
|
-
const skillDir =
|
|
27632
|
+
const { join: join36 } = await import("path");
|
|
27633
|
+
const skillDir = join36(SKILLS_PATH, "cc-claw-cli");
|
|
26718
27634
|
mkdirSync19(skillDir, { recursive: true });
|
|
26719
|
-
writeFileSync13(
|
|
27635
|
+
writeFileSync13(join36(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
|
|
26720
27636
|
log("[cc-claw] AI skill updated");
|
|
26721
27637
|
} catch {
|
|
26722
27638
|
}
|
|
@@ -26947,7 +27863,7 @@ __export(service_exports2, {
|
|
|
26947
27863
|
import { existsSync as existsSync28, mkdirSync as mkdirSync13, writeFileSync as writeFileSync9, unlinkSync as unlinkSync8 } from "fs";
|
|
26948
27864
|
import { execFileSync as execFileSync3, execSync as execSync4 } from "child_process";
|
|
26949
27865
|
import { homedir as homedir10, platform } from "os";
|
|
26950
|
-
import { join as
|
|
27866
|
+
import { join as join31, dirname as dirname6 } from "path";
|
|
26951
27867
|
function xmlEscape(s) {
|
|
26952
27868
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
26953
27869
|
}
|
|
@@ -26965,14 +27881,14 @@ function getPathDirs() {
|
|
|
26965
27881
|
const home = homedir10();
|
|
26966
27882
|
const dirs = /* @__PURE__ */ new Set([
|
|
26967
27883
|
nodeBin,
|
|
26968
|
-
|
|
27884
|
+
join31(home, ".local", "bin"),
|
|
26969
27885
|
"/usr/local/bin",
|
|
26970
27886
|
"/usr/bin",
|
|
26971
27887
|
"/bin"
|
|
26972
27888
|
]);
|
|
26973
27889
|
try {
|
|
26974
27890
|
const prefix = execSync4("npm config get prefix", { encoding: "utf-8" }).trim();
|
|
26975
|
-
if (prefix) dirs.add(
|
|
27891
|
+
if (prefix) dirs.add(join31(prefix, "bin"));
|
|
26976
27892
|
} catch {
|
|
26977
27893
|
}
|
|
26978
27894
|
return [...dirs].join(":");
|
|
@@ -27155,7 +28071,7 @@ function statusLinux() {
|
|
|
27155
28071
|
}
|
|
27156
28072
|
}
|
|
27157
28073
|
function installService() {
|
|
27158
|
-
if (!existsSync28(
|
|
28074
|
+
if (!existsSync28(join31(CC_CLAW_HOME, ".env"))) {
|
|
27159
28075
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
27160
28076
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
27161
28077
|
process.exitCode = 1;
|
|
@@ -27184,9 +28100,9 @@ var init_service2 = __esm({
|
|
|
27184
28100
|
"use strict";
|
|
27185
28101
|
init_paths();
|
|
27186
28102
|
PLIST_LABEL = "com.cc-claw";
|
|
27187
|
-
PLIST_PATH =
|
|
27188
|
-
SYSTEMD_DIR =
|
|
27189
|
-
UNIT_PATH =
|
|
28103
|
+
PLIST_PATH = join31(homedir10(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
28104
|
+
SYSTEMD_DIR = join31(homedir10(), ".config", "systemd", "user");
|
|
28105
|
+
UNIT_PATH = join31(SYSTEMD_DIR, "cc-claw.service");
|
|
27190
28106
|
}
|
|
27191
28107
|
});
|
|
27192
28108
|
|
|
@@ -28086,12 +29002,14 @@ __export(gemini_exports, {
|
|
|
28086
29002
|
geminiDisable: () => geminiDisable,
|
|
28087
29003
|
geminiEnable: () => geminiEnable,
|
|
28088
29004
|
geminiList: () => geminiList,
|
|
29005
|
+
geminiRelogin: () => geminiRelogin,
|
|
28089
29006
|
geminiRemove: () => geminiRemove,
|
|
29007
|
+
geminiRename: () => geminiRename,
|
|
28090
29008
|
geminiReorder: () => geminiReorder,
|
|
28091
29009
|
geminiRotation: () => geminiRotation
|
|
28092
29010
|
});
|
|
28093
29011
|
import { existsSync as existsSync33, mkdirSync as mkdirSync14, writeFileSync as writeFileSync10, readFileSync as readFileSync23, chmodSync } from "fs";
|
|
28094
|
-
import { join as
|
|
29012
|
+
import { join as join32 } from "path";
|
|
28095
29013
|
import { createInterface as createInterface8 } from "readline";
|
|
28096
29014
|
function requireDb() {
|
|
28097
29015
|
if (!existsSync33(DB_PATH)) {
|
|
@@ -28119,7 +29037,7 @@ async function resolveSlotId(idOrLabel) {
|
|
|
28119
29037
|
function resolveOAuthEmail(configHome) {
|
|
28120
29038
|
if (!configHome) return null;
|
|
28121
29039
|
try {
|
|
28122
|
-
const accountsPath =
|
|
29040
|
+
const accountsPath = join32(configHome, ".gemini", "google_accounts.json");
|
|
28123
29041
|
if (!existsSync33(accountsPath)) return null;
|
|
28124
29042
|
const accounts = JSON.parse(readFileSync23(accountsPath, "utf-8"));
|
|
28125
29043
|
return accounts.active || null;
|
|
@@ -28203,14 +29121,14 @@ async function geminiAddKey(globalOpts, opts) {
|
|
|
28203
29121
|
}
|
|
28204
29122
|
async function geminiAddAccount(globalOpts, opts) {
|
|
28205
29123
|
await requireWriteDb();
|
|
28206
|
-
const slotsDir =
|
|
29124
|
+
const slotsDir = join32(CC_CLAW_HOME, "gemini-slots");
|
|
28207
29125
|
if (!existsSync33(slotsDir)) mkdirSync14(slotsDir, { recursive: true });
|
|
28208
29126
|
const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
28209
29127
|
const tempId = Date.now();
|
|
28210
|
-
const slotDir =
|
|
29128
|
+
const slotDir = join32(slotsDir, `slot-${tempId}`);
|
|
28211
29129
|
mkdirSync14(slotDir, { recursive: true, mode: 448 });
|
|
28212
|
-
mkdirSync14(
|
|
28213
|
-
writeFileSync10(
|
|
29130
|
+
mkdirSync14(join32(slotDir, ".gemini"), { recursive: true });
|
|
29131
|
+
writeFileSync10(join32(slotDir, ".gemini", "settings.json"), JSON.stringify({
|
|
28214
29132
|
security: { auth: { selectedType: "oauth-personal" } }
|
|
28215
29133
|
}, null, 2));
|
|
28216
29134
|
console.log("");
|
|
@@ -28227,7 +29145,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
28227
29145
|
});
|
|
28228
29146
|
} catch {
|
|
28229
29147
|
}
|
|
28230
|
-
const oauthPath =
|
|
29148
|
+
const oauthPath = join32(slotDir, ".gemini", "oauth_creds.json");
|
|
28231
29149
|
if (!existsSync33(oauthPath)) {
|
|
28232
29150
|
console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
|
|
28233
29151
|
console.log(" The slot directory is preserved at: " + slotDir);
|
|
@@ -28236,7 +29154,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
28236
29154
|
}
|
|
28237
29155
|
let accountEmail = "unknown";
|
|
28238
29156
|
try {
|
|
28239
|
-
const accounts = JSON.parse(__require("fs").readFileSync(
|
|
29157
|
+
const accounts = JSON.parse(__require("fs").readFileSync(join32(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
|
|
28240
29158
|
accountEmail = accounts.active || accountEmail;
|
|
28241
29159
|
} catch {
|
|
28242
29160
|
}
|
|
@@ -28311,6 +29229,92 @@ async function geminiReorder(globalOpts, idOrLabel, priority) {
|
|
|
28311
29229
|
() => success(`Slot "${idOrLabel}" (#${slotId}) priority set to ${priority}`)
|
|
28312
29230
|
);
|
|
28313
29231
|
}
|
|
29232
|
+
async function geminiRename(globalOpts, idOrLabel, newLabel) {
|
|
29233
|
+
await requireWriteDb();
|
|
29234
|
+
const slotId = await resolveSlotId(idOrLabel);
|
|
29235
|
+
if (!slotId) {
|
|
29236
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29237
|
+
return;
|
|
29238
|
+
}
|
|
29239
|
+
const { renameGeminiSlot: renameGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29240
|
+
const updated = renameGeminiSlot2(slotId, newLabel);
|
|
29241
|
+
if (updated) {
|
|
29242
|
+
output({ id: slotId, label: newLabel }, () => success(`Renamed slot #${slotId} \u2192 "${newLabel}"`));
|
|
29243
|
+
} else {
|
|
29244
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29245
|
+
}
|
|
29246
|
+
}
|
|
29247
|
+
async function geminiRelogin(globalOpts, idOrLabel) {
|
|
29248
|
+
await requireWriteDb();
|
|
29249
|
+
const slotId = await resolveSlotId(idOrLabel);
|
|
29250
|
+
if (!slotId) {
|
|
29251
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29252
|
+
return;
|
|
29253
|
+
}
|
|
29254
|
+
const { getGeminiSlots: getGeminiSlots2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29255
|
+
const slot = getGeminiSlots2().find((s) => s.id === slotId);
|
|
29256
|
+
if (!slot) {
|
|
29257
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29258
|
+
return;
|
|
29259
|
+
}
|
|
29260
|
+
if (slot.slotType !== "oauth") {
|
|
29261
|
+
outputError("NOT_OAUTH", `Slot "${idOrLabel}" is an API key slot \u2014 re-login only works for OAuth slots.`);
|
|
29262
|
+
return;
|
|
29263
|
+
}
|
|
29264
|
+
if (!slot.configHome) {
|
|
29265
|
+
outputError("NO_CONFIG", `Slot "${idOrLabel}" has no config directory \u2014 cannot re-login.`);
|
|
29266
|
+
return;
|
|
29267
|
+
}
|
|
29268
|
+
const settingsPath = join32(slot.configHome, ".gemini", "settings.json");
|
|
29269
|
+
if (!existsSync33(settingsPath)) {
|
|
29270
|
+
mkdirSync14(join32(slot.configHome, ".gemini"), { recursive: true });
|
|
29271
|
+
writeFileSync10(settingsPath, JSON.stringify({
|
|
29272
|
+
security: { auth: { selectedType: "oauth-personal" } }
|
|
29273
|
+
}, null, 2));
|
|
29274
|
+
}
|
|
29275
|
+
console.log("");
|
|
29276
|
+
console.log(` Re-authenticating Gemini slot "${slot.label || `#${slot.id}`}"...`);
|
|
29277
|
+
console.log(" Sign in with the same Google account when prompted.");
|
|
29278
|
+
console.log(" After sign-in, type /quit to return here.");
|
|
29279
|
+
console.log("");
|
|
29280
|
+
const { execSync: execSync6 } = await import("child_process");
|
|
29281
|
+
try {
|
|
29282
|
+
execSync6(`gemini`, {
|
|
29283
|
+
stdio: "inherit",
|
|
29284
|
+
env: {
|
|
29285
|
+
...process.env,
|
|
29286
|
+
GEMINI_CLI_HOME: slot.configHome,
|
|
29287
|
+
GEMINI_API_KEY: void 0,
|
|
29288
|
+
GOOGLE_API_KEY: void 0
|
|
29289
|
+
},
|
|
29290
|
+
cwd: slot.configHome
|
|
29291
|
+
});
|
|
29292
|
+
} catch {
|
|
29293
|
+
}
|
|
29294
|
+
const oauthPath = join32(slot.configHome, ".gemini", "oauth_creds.json");
|
|
29295
|
+
if (!existsSync33(oauthPath)) {
|
|
29296
|
+
console.log(error2("\n Re-login failed \u2014 no OAuth credentials found."));
|
|
29297
|
+
console.log(` Try again: cc-claw gemini re-login ${idOrLabel}
|
|
29298
|
+
`);
|
|
29299
|
+
process.exit(1);
|
|
29300
|
+
}
|
|
29301
|
+
const { setGeminiSlotEnabled: setGeminiSlotEnabled2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29302
|
+
setGeminiSlotEnabled2(slotId, true);
|
|
29303
|
+
let accountEmail = slot.label;
|
|
29304
|
+
try {
|
|
29305
|
+
const accounts = JSON.parse(readFileSync23(join32(slot.configHome, ".gemini", "google_accounts.json"), "utf-8"));
|
|
29306
|
+
if (accounts.active) accountEmail = accounts.active;
|
|
29307
|
+
} catch {
|
|
29308
|
+
}
|
|
29309
|
+
if (accountEmail && accountEmail !== slot.label) {
|
|
29310
|
+
const { renameGeminiSlot: renameGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29311
|
+
renameGeminiSlot2(slotId, accountEmail);
|
|
29312
|
+
}
|
|
29313
|
+
output(
|
|
29314
|
+
{ id: slotId, label: accountEmail, refreshed: true },
|
|
29315
|
+
() => success(`Re-authenticated Gemini slot #${slotId} (${accountEmail})`)
|
|
29316
|
+
);
|
|
29317
|
+
}
|
|
28314
29318
|
async function geminiRotation(globalOpts, mode) {
|
|
28315
29319
|
const validModes = ["off", "all", "accounts", "keys"];
|
|
28316
29320
|
if (!mode) {
|
|
@@ -28351,12 +29355,14 @@ __export(backend_cmd_factory_exports, {
|
|
|
28351
29355
|
makeEnable: () => makeEnable,
|
|
28352
29356
|
makeList: () => makeList,
|
|
28353
29357
|
makeRefresh: () => makeRefresh,
|
|
29358
|
+
makeRelogin: () => makeRelogin,
|
|
28354
29359
|
makeRemove: () => makeRemove,
|
|
29360
|
+
makeRename: () => makeRename,
|
|
28355
29361
|
makeReorder: () => makeReorder,
|
|
28356
29362
|
registerBackendSlotCommands: () => registerBackendSlotCommands
|
|
28357
29363
|
});
|
|
28358
29364
|
import { existsSync as existsSync34, mkdirSync as mkdirSync15, readFileSync as readFileSync24 } from "fs";
|
|
28359
|
-
import { join as
|
|
29365
|
+
import { join as join33 } from "path";
|
|
28360
29366
|
import { createInterface as createInterface9 } from "readline";
|
|
28361
29367
|
function requireDb2() {
|
|
28362
29368
|
if (!existsSync34(DB_PATH)) {
|
|
@@ -28448,10 +29454,10 @@ function makeAddAccount(backend2, displayName) {
|
|
|
28448
29454
|
process.exit(1);
|
|
28449
29455
|
}
|
|
28450
29456
|
await requireWriteDb2();
|
|
28451
|
-
const slotsDir =
|
|
29457
|
+
const slotsDir = join33(CC_CLAW_HOME, config2.slotsSubdir);
|
|
28452
29458
|
if (!existsSync34(slotsDir)) mkdirSync15(slotsDir, { recursive: true });
|
|
28453
29459
|
const tempId = Date.now();
|
|
28454
|
-
const slotDir =
|
|
29460
|
+
const slotDir = join33(slotsDir, `slot-${tempId}`);
|
|
28455
29461
|
mkdirSync15(slotDir, { recursive: true, mode: 448 });
|
|
28456
29462
|
if (config2.preSetup) config2.preSetup(slotDir);
|
|
28457
29463
|
console.log("");
|
|
@@ -28562,6 +29568,88 @@ function makeReorder(backend2, _displayName) {
|
|
|
28562
29568
|
);
|
|
28563
29569
|
};
|
|
28564
29570
|
}
|
|
29571
|
+
function makeRename(backend2, _displayName) {
|
|
29572
|
+
return async function rename(_globalOpts, idOrLabel, newLabel) {
|
|
29573
|
+
await requireWriteDb2();
|
|
29574
|
+
const slotId = await resolveSlotId2(backend2, idOrLabel);
|
|
29575
|
+
if (!slotId) {
|
|
29576
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29577
|
+
return;
|
|
29578
|
+
}
|
|
29579
|
+
const { renameBackendSlot: renameBackendSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29580
|
+
const updated = renameBackendSlot2(slotId, newLabel);
|
|
29581
|
+
if (updated) {
|
|
29582
|
+
output({ id: slotId, label: newLabel }, () => success(`Renamed slot #${slotId} \u2192 "${newLabel}"`));
|
|
29583
|
+
} else {
|
|
29584
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29585
|
+
}
|
|
29586
|
+
};
|
|
29587
|
+
}
|
|
29588
|
+
function makeRelogin(backend2, displayName) {
|
|
29589
|
+
return async function relogin(_globalOpts, idOrLabel) {
|
|
29590
|
+
const config2 = ADD_ACCOUNT_CONFIGS[backend2];
|
|
29591
|
+
if (!config2) {
|
|
29592
|
+
outputError("UNSUPPORTED", `re-login is not supported for ${displayName}. Only OAuth/subscription slots can be re-logged.`);
|
|
29593
|
+
process.exit(1);
|
|
29594
|
+
}
|
|
29595
|
+
await requireWriteDb2();
|
|
29596
|
+
const slotId = await resolveSlotId2(backend2, idOrLabel);
|
|
29597
|
+
if (!slotId) {
|
|
29598
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29599
|
+
return;
|
|
29600
|
+
}
|
|
29601
|
+
const { getBackendSlots: getBackendSlots2, reenableBackendSlot: reenableBackendSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29602
|
+
const slot = getBackendSlots2(backend2).find((s) => s.id === slotId);
|
|
29603
|
+
if (!slot) {
|
|
29604
|
+
outputError("NOT_FOUND", `Slot "${idOrLabel}" not found.`);
|
|
29605
|
+
return;
|
|
29606
|
+
}
|
|
29607
|
+
if (slot.slotType !== "oauth") {
|
|
29608
|
+
outputError("NOT_OAUTH", `Slot "${idOrLabel}" is an API key slot \u2014 re-login only works for OAuth/subscription slots.`);
|
|
29609
|
+
return;
|
|
29610
|
+
}
|
|
29611
|
+
if (!slot.configHome) {
|
|
29612
|
+
outputError("NO_CONFIG", `Slot "${idOrLabel}" has no config directory \u2014 cannot re-login.`);
|
|
29613
|
+
return;
|
|
29614
|
+
}
|
|
29615
|
+
if (config2.preSetup) config2.preSetup(slot.configHome);
|
|
29616
|
+
console.log("");
|
|
29617
|
+
console.log(` Re-authenticating ${displayName} slot "${slot.label || `#${slot.id}`}"...`);
|
|
29618
|
+
console.log(` Sign in with the same account when the browser opens.`);
|
|
29619
|
+
console.log("");
|
|
29620
|
+
const { execSync: execSync6 } = await import("child_process");
|
|
29621
|
+
const loginEnv = {
|
|
29622
|
+
...process.env,
|
|
29623
|
+
[config2.envKey]: config2.envValue(slot.configHome),
|
|
29624
|
+
...config2.envOverrides
|
|
29625
|
+
};
|
|
29626
|
+
try {
|
|
29627
|
+
execSync6(config2.loginCommand.join(" "), {
|
|
29628
|
+
stdio: "inherit",
|
|
29629
|
+
env: loginEnv,
|
|
29630
|
+
cwd: slot.configHome
|
|
29631
|
+
});
|
|
29632
|
+
} catch {
|
|
29633
|
+
}
|
|
29634
|
+
if (!config2.verifyCredentials(slot.configHome)) {
|
|
29635
|
+
console.log(error2(`
|
|
29636
|
+
Re-login failed \u2014 no credentials found.`));
|
|
29637
|
+
console.log(` Try again: cc-claw ${backend2} re-login ${idOrLabel}
|
|
29638
|
+
`);
|
|
29639
|
+
process.exit(1);
|
|
29640
|
+
}
|
|
29641
|
+
reenableBackendSlot2(slotId);
|
|
29642
|
+
const newLabel = config2.extractLabel(slot.configHome);
|
|
29643
|
+
if (newLabel && newLabel !== slot.label && newLabel !== "subscription") {
|
|
29644
|
+
const { renameBackendSlot: renameBackendSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
29645
|
+
renameBackendSlot2(slotId, newLabel);
|
|
29646
|
+
}
|
|
29647
|
+
output(
|
|
29648
|
+
{ id: slotId, label: newLabel || slot.label, refreshed: true },
|
|
29649
|
+
() => success(`Re-authenticated ${displayName} slot #${slotId} (${newLabel || slot.label})`)
|
|
29650
|
+
);
|
|
29651
|
+
};
|
|
29652
|
+
}
|
|
28565
29653
|
function makeRefresh(backend2, displayName) {
|
|
28566
29654
|
return async function refresh(_globalOpts) {
|
|
28567
29655
|
await requireWriteDb2();
|
|
@@ -28620,11 +29708,11 @@ var init_backend_cmd_factory = __esm({
|
|
|
28620
29708
|
envValue: (slotDir) => slotDir,
|
|
28621
29709
|
envOverrides: { ANTHROPIC_API_KEY: void 0 },
|
|
28622
29710
|
preSetup: (slotDir) => {
|
|
28623
|
-
mkdirSync15(
|
|
29711
|
+
mkdirSync15(join33(slotDir, ".claude"), { recursive: true });
|
|
28624
29712
|
},
|
|
28625
29713
|
verifyCredentials: (slotDir) => {
|
|
28626
|
-
const claudeJson =
|
|
28627
|
-
const claudeJsonNested =
|
|
29714
|
+
const claudeJson = join33(slotDir, ".claude.json");
|
|
29715
|
+
const claudeJsonNested = join33(slotDir, ".claude", ".claude.json");
|
|
28628
29716
|
if (existsSync34(claudeJson)) {
|
|
28629
29717
|
try {
|
|
28630
29718
|
const data = JSON.parse(readFileSync24(claudeJson, "utf-8"));
|
|
@@ -28656,7 +29744,7 @@ var init_backend_cmd_factory = __esm({
|
|
|
28656
29744
|
} catch {
|
|
28657
29745
|
}
|
|
28658
29746
|
try {
|
|
28659
|
-
const claudeJson =
|
|
29747
|
+
const claudeJson = join33(slotDir, ".claude.json");
|
|
28660
29748
|
if (existsSync34(claudeJson)) {
|
|
28661
29749
|
const data = JSON.parse(readFileSync24(claudeJson, "utf-8"));
|
|
28662
29750
|
if (data.oauthAccount?.emailAddress) return data.oauthAccount.emailAddress;
|
|
@@ -28673,11 +29761,11 @@ var init_backend_cmd_factory = __esm({
|
|
|
28673
29761
|
envValue: (slotDir) => slotDir,
|
|
28674
29762
|
envOverrides: { OPENAI_API_KEY: void 0 },
|
|
28675
29763
|
verifyCredentials: (slotDir) => {
|
|
28676
|
-
return existsSync34(
|
|
29764
|
+
return existsSync34(join33(slotDir, "auth.json"));
|
|
28677
29765
|
},
|
|
28678
29766
|
extractLabel: (slotDir) => {
|
|
28679
29767
|
try {
|
|
28680
|
-
const authData = JSON.parse(readFileSync24(
|
|
29768
|
+
const authData = JSON.parse(readFileSync24(join33(slotDir, "auth.json"), "utf-8"));
|
|
28681
29769
|
if (authData.email) return authData.email;
|
|
28682
29770
|
if (authData.account_name) return authData.account_name;
|
|
28683
29771
|
if (authData.user?.email) return authData.user.email;
|
|
@@ -31041,7 +32129,7 @@ __export(completion_exports, {
|
|
|
31041
32129
|
completionCommand: () => completionCommand
|
|
31042
32130
|
});
|
|
31043
32131
|
import { writeFileSync as writeFileSync11, mkdirSync as mkdirSync17 } from "fs";
|
|
31044
|
-
import { join as
|
|
32132
|
+
import { join as join34 } from "path";
|
|
31045
32133
|
import { homedir as homedir11 } from "os";
|
|
31046
32134
|
async function completionCommand(opts) {
|
|
31047
32135
|
const shell = opts.shell ?? detectShell();
|
|
@@ -31057,10 +32145,10 @@ async function completionCommand(opts) {
|
|
|
31057
32145
|
process.exit(1);
|
|
31058
32146
|
}
|
|
31059
32147
|
if (opts.install) {
|
|
31060
|
-
const dir =
|
|
32148
|
+
const dir = join34(homedir11(), ".config", "cc-claw", "completions");
|
|
31061
32149
|
mkdirSync17(dir, { recursive: true });
|
|
31062
32150
|
const filename = shell === "zsh" ? "_cc-claw" : shell === "fish" ? "cc-claw.fish" : "cc-claw.bash";
|
|
31063
|
-
const filepath =
|
|
32151
|
+
const filepath = join34(dir, filename);
|
|
31064
32152
|
writeFileSync11(filepath, script, "utf-8");
|
|
31065
32153
|
console.log(`\u2713 Completion script written to ${filepath}
|
|
31066
32154
|
`);
|
|
@@ -31710,7 +32798,7 @@ var setup_exports = {};
|
|
|
31710
32798
|
import { existsSync as existsSync55, writeFileSync as writeFileSync12, readFileSync as readFileSync27, copyFileSync as copyFileSync4, mkdirSync as mkdirSync18, statSync as statSync12 } from "fs";
|
|
31711
32799
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
31712
32800
|
import { createInterface as createInterface11 } from "readline";
|
|
31713
|
-
import { join as
|
|
32801
|
+
import { join as join35 } from "path";
|
|
31714
32802
|
function divider2() {
|
|
31715
32803
|
console.log(dim("\u2500".repeat(55)));
|
|
31716
32804
|
}
|
|
@@ -31798,7 +32886,7 @@ async function setup() {
|
|
|
31798
32886
|
if (match) env[match[1].trim()] = match[2].trim();
|
|
31799
32887
|
}
|
|
31800
32888
|
}
|
|
31801
|
-
const cwdDb =
|
|
32889
|
+
const cwdDb = join35(process.cwd(), "cc-claw.db");
|
|
31802
32890
|
if (existsSync55(cwdDb) && !existsSync55(DB_PATH)) {
|
|
31803
32891
|
const { size } = statSync12(cwdDb);
|
|
31804
32892
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
@@ -32188,6 +33276,14 @@ gemini.command("reorder <id-or-label> <priority>").description("Set slot priorit
|
|
|
32188
33276
|
const { geminiReorder: geminiReorder2 } = await Promise.resolve().then(() => (init_gemini2(), gemini_exports));
|
|
32189
33277
|
await geminiReorder2(program.opts(), id, priority);
|
|
32190
33278
|
});
|
|
33279
|
+
gemini.command("rename <id-or-label> <new-label>").description("Rename a credential slot").action(async (id, newLabel) => {
|
|
33280
|
+
const { geminiRename: geminiRename2 } = await Promise.resolve().then(() => (init_gemini2(), gemini_exports));
|
|
33281
|
+
await geminiRename2(program.opts(), id, newLabel);
|
|
33282
|
+
});
|
|
33283
|
+
gemini.command("re-login <id-or-label>").alias("relogin").description("Re-authenticate an OAuth slot (refreshes expired token in-place)").action(async (id) => {
|
|
33284
|
+
const { geminiRelogin: geminiRelogin2 } = await Promise.resolve().then(() => (init_gemini2(), gemini_exports));
|
|
33285
|
+
await geminiRelogin2(program.opts(), id);
|
|
33286
|
+
});
|
|
32191
33287
|
gemini.command("rotation [mode]").description("Get or set rotation mode (off, all, accounts, keys)").action(async (mode) => {
|
|
32192
33288
|
const { geminiRotation: geminiRotation2 } = await Promise.resolve().then(() => (init_gemini2(), gemini_exports));
|
|
32193
33289
|
await geminiRotation2(program.opts(), mode);
|
|
@@ -32226,6 +33322,14 @@ function registerUnifiedSlotCommands(parentCmd, backendId, displayName) {
|
|
|
32226
33322
|
const { makeRefresh: makeRefresh2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
32227
33323
|
await makeRefresh2(backendId, displayName)(program.opts());
|
|
32228
33324
|
});
|
|
33325
|
+
cmd.command("rename <id-or-label> <new-label>").description("Rename a credential slot").action(async (id, newLabel) => {
|
|
33326
|
+
const { makeRename: makeRename2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
33327
|
+
await makeRename2(backendId, displayName)(program.opts(), id, newLabel);
|
|
33328
|
+
});
|
|
33329
|
+
cmd.command("re-login <id-or-label>").alias("relogin").description("Re-authenticate an OAuth/subscription slot (refreshes expired token in-place)").action(async (id) => {
|
|
33330
|
+
const { makeRelogin: makeRelogin2 } = await Promise.resolve().then(() => (init_backend_cmd_factory(), backend_cmd_factory_exports));
|
|
33331
|
+
await makeRelogin2(backendId, displayName)(program.opts(), id);
|
|
33332
|
+
});
|
|
32229
33333
|
}
|
|
32230
33334
|
registerUnifiedSlotCommands(program, "claude", "Claude");
|
|
32231
33335
|
registerUnifiedSlotCommands(program, "codex", "Codex");
|
|
@@ -32653,6 +33757,11 @@ optimize.command("skills").description("List available CC-Claw skills").action(a
|
|
|
32653
33757
|
const { optimizeSkills: optimizeSkills2 } = await Promise.resolve().then(() => (init_optimize2(), optimize_exports));
|
|
32654
33758
|
await optimizeSkills2();
|
|
32655
33759
|
});
|
|
33760
|
+
program.command("council").alias("debate").description("Multi-model council debate (Telegram interactive)").action(async () => {
|
|
33761
|
+
console.log("Council is an interactive Telegram command.");
|
|
33762
|
+
console.log("Use /council in Telegram to start a multi-model debate wizard.");
|
|
33763
|
+
console.log("Select 2+ models, pose a question, and they debate anonymously for up to 3 rounds.");
|
|
33764
|
+
});
|
|
32656
33765
|
program.command("start", { hidden: true }).description("Run the bot in the foreground (use 'service start' for background daemon)").action(async () => {
|
|
32657
33766
|
await Promise.resolve().then(() => (init_index(), index_exports));
|
|
32658
33767
|
});
|