cueclaw 0.1.3 → 0.1.4
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/README.md +27 -27
- package/dist/{app-JK3HBFKZ.js → app-6SXWEUZZ.js} +20 -10
- package/dist/{chunk-X3WNTN5V.js → chunk-3HV3MHME.js} +45 -32
- package/dist/{chunk-HDUFGPCI.js → chunk-54BGF7G5.js} +51 -9
- package/dist/{chunk-25KI643G.js → chunk-5TV4LNC3.js} +6 -0
- package/dist/{chunk-KRNAXOQ4.js → chunk-FKKDQVRE.js} +2 -1
- package/dist/{chunk-JJUF2AJ5.js → chunk-HKZ6IN7X.js} +21 -5
- package/dist/{chunk-CXBDJQJJ.js → chunk-MEAAX2SW.js} +1 -1
- package/dist/cli.js +19 -19
- package/dist/{config-D5A5TNLZ.js → config-FYL6T5JP.js} +1 -1
- package/dist/{daemon-4DVXPT4O.js → daemon-Y5HIGH44.js} +4 -4
- package/dist/{executor-TMY6MGVY.js → executor-44MSZ76T.js} +3 -3
- package/dist/{service-AP5GEITC.js → service-Q7USNFFB.js} +2 -2
- package/dist/{setup-U2YKLOK6.js → setup-JK664Y2M.js} +2 -2
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -19,6 +19,32 @@
|
|
|
19
19
|
2. **Review** the generated execution plan (DAG)
|
|
20
20
|
3. **Confirm**, and CueClaw runs it in the background as a daemon
|
|
21
21
|
|
|
22
|
+
```
|
|
23
|
+
You: "Every day at 10am, scrape GitHub Trending for the top 10 projects,
|
|
24
|
+
summarize each with stars/language/description, and send the digest
|
|
25
|
+
to me on Telegram."
|
|
26
|
+
|
|
27
|
+
CueClaw:
|
|
28
|
+
┌─ Plan: GitHub Trending Digest ─────────────┐
|
|
29
|
+
│ Trigger: cron (0 10 * * *) │
|
|
30
|
+
│ │
|
|
31
|
+
│ 1. Fetch GitHub Trending page │
|
|
32
|
+
│ 2. Extract top 10 projects with metadata │
|
|
33
|
+
│ └─ depends on: step 1 │
|
|
34
|
+
│ 3. Generate formatted digest summary │
|
|
35
|
+
│ └─ depends on: step 2 │
|
|
36
|
+
│ 4. Send digest via Telegram │
|
|
37
|
+
│ └─ depends on: step 3 │
|
|
38
|
+
│ │
|
|
39
|
+
│ [Y] Confirm [M] Modify [N] Cancel │
|
|
40
|
+
└────────────────────────────────────────────┘
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### More Examples
|
|
44
|
+
|
|
45
|
+
<details>
|
|
46
|
+
<summary><b>X (Twitter) Auto Engage</b> — poll trigger, daily cron summary</summary>
|
|
47
|
+
|
|
22
48
|
```
|
|
23
49
|
You: "Every 30 minutes, check my X timeline for trending AI/LLM tweets,
|
|
24
50
|
reply with a professional but friendly tone, and post a daily
|
|
@@ -35,12 +61,10 @@ CueClaw:
|
|
|
35
61
|
│ └─ depends on: step 2 │
|
|
36
62
|
│ 4. Daily: compose & post trend summary │
|
|
37
63
|
│ └─ cron: 0 21 * * * │
|
|
38
|
-
│ │
|
|
39
|
-
│ [Y] Confirm [M] Modify [N] Cancel │
|
|
40
64
|
└────────────────────────────────────────────┘
|
|
41
65
|
```
|
|
42
66
|
|
|
43
|
-
|
|
67
|
+
</details>
|
|
44
68
|
|
|
45
69
|
<details>
|
|
46
70
|
<summary><b>GitHub Issue to Draft PR</b> — poll trigger, multi-step DAG</summary>
|
|
@@ -66,30 +90,6 @@ CueClaw:
|
|
|
66
90
|
|
|
67
91
|
</details>
|
|
68
92
|
|
|
69
|
-
<details>
|
|
70
|
-
<summary><b>GitHub Trending Daily Digest</b> — cron trigger, Telegram notification</summary>
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
You: "Every day at 10am, scrape GitHub Trending for the top 10 projects,
|
|
74
|
-
summarize each with stars/language/description, and send the digest
|
|
75
|
-
to me on Telegram."
|
|
76
|
-
|
|
77
|
-
CueClaw:
|
|
78
|
-
┌─ Plan: GitHub Trending Digest ─────────────┐
|
|
79
|
-
│ Trigger: cron (0 10 * * *) │
|
|
80
|
-
│ │
|
|
81
|
-
│ 1. Fetch GitHub Trending page │
|
|
82
|
-
│ 2. Extract top 10 projects with metadata │
|
|
83
|
-
│ └─ depends on: step 1 │
|
|
84
|
-
│ 3. Generate formatted digest summary │
|
|
85
|
-
│ └─ depends on: step 2 │
|
|
86
|
-
│ 4. Send digest via Telegram │
|
|
87
|
-
│ └─ depends on: step 3 │
|
|
88
|
-
└────────────────────────────────────────────┘
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
</details>
|
|
92
|
-
|
|
93
93
|
<details>
|
|
94
94
|
<summary><b>PR Review Loop</b> — interactive commands via poll trigger</summary>
|
|
95
95
|
|
|
@@ -6,14 +6,14 @@ import {
|
|
|
6
6
|
readPidFile,
|
|
7
7
|
removePidFile,
|
|
8
8
|
spawnDaemonProcess
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-54BGF7G5.js";
|
|
10
10
|
import {
|
|
11
11
|
getServiceStatus
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-MEAAX2SW.js";
|
|
13
13
|
import {
|
|
14
14
|
checkEnvironment,
|
|
15
15
|
validateAuth
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-FKKDQVRE.js";
|
|
17
17
|
import {
|
|
18
18
|
askQuestionTool,
|
|
19
19
|
buildPlannerSystemPrompt,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
} from "./chunk-DVQFSFIZ.js";
|
|
29
29
|
import {
|
|
30
30
|
executeWorkflow
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-3HV3MHME.js";
|
|
32
32
|
import {
|
|
33
33
|
deleteWorkflow,
|
|
34
34
|
getStepRunsByRunId,
|
|
@@ -38,14 +38,14 @@ import {
|
|
|
38
38
|
listWorkflows,
|
|
39
39
|
updateWorkflowPhase,
|
|
40
40
|
upsertWorkflow
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-HKZ6IN7X.js";
|
|
42
42
|
import {
|
|
43
43
|
cueclawHome,
|
|
44
44
|
loadConfig,
|
|
45
45
|
loadExistingConfig,
|
|
46
46
|
validateConfig,
|
|
47
47
|
writeConfig
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-5TV4LNC3.js";
|
|
49
49
|
import "./chunk-BVQG3WYO.js";
|
|
50
50
|
import {
|
|
51
51
|
isDev,
|
|
@@ -872,14 +872,15 @@ ${failedSteps.join("\n")}` : "";
|
|
|
872
872
|
}, []);
|
|
873
873
|
const handleCancel = useCallback4(() => {
|
|
874
874
|
if (workflow) {
|
|
875
|
-
rejectPlan(workflow);
|
|
875
|
+
const rejected = rejectPlan(workflow);
|
|
876
|
+
updateWorkflowPhase(db, workflow.id, rejected.phase);
|
|
876
877
|
}
|
|
877
878
|
if (plannerSessionRef.current) {
|
|
878
879
|
plannerSessionRef.current = null;
|
|
879
880
|
}
|
|
880
881
|
dispatch({ type: "SHOW_CHAT" });
|
|
881
882
|
dispatch({ type: "ADD_MESSAGE", message: { type: "assistant", text: "Plan cancelled." } });
|
|
882
|
-
}, [workflow]);
|
|
883
|
+
}, [workflow, db]);
|
|
883
884
|
const handleExecutionBack = useCallback4(() => {
|
|
884
885
|
dispatch({ type: "SHOW_CHAT" });
|
|
885
886
|
}, []);
|
|
@@ -1715,8 +1716,17 @@ function AppProvider({ cwd, skipOnboarding, children }) {
|
|
|
1715
1716
|
const stepRuns = latestRun ? getStepRunsByRunId(db, latestRun.id) : [];
|
|
1716
1717
|
dispatch({ type: "SHOW_DETAIL", workflow, runs, stepRuns });
|
|
1717
1718
|
}, [db]);
|
|
1718
|
-
const handleStatusStop = useCallback7((
|
|
1719
|
-
|
|
1719
|
+
const handleStatusStop = useCallback7((workflow) => {
|
|
1720
|
+
const controller = execution.abortMapRef.current.get(workflow.id);
|
|
1721
|
+
if (controller) {
|
|
1722
|
+
controller.abort();
|
|
1723
|
+
dispatch({ type: "ADD_MESSAGE", message: { type: "system", text: `Stopping workflow: ${workflow.name}` } });
|
|
1724
|
+
} else {
|
|
1725
|
+
dispatch({ type: "ADD_MESSAGE", message: { type: "warning", text: `Workflow "${workflow.name}" is not currently executing.` } });
|
|
1726
|
+
}
|
|
1727
|
+
const workflows = listWorkflows(db);
|
|
1728
|
+
dispatch({ type: "SHOW_STATUS", workflows });
|
|
1729
|
+
}, [db, execution.abortMapRef]);
|
|
1720
1730
|
const handleStatusDelete = useCallback7((workflow) => {
|
|
1721
1731
|
deleteWorkflow(db, workflow.id);
|
|
1722
1732
|
const updated = listWorkflows(db);
|
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
updateStepRunStatus,
|
|
5
5
|
updateWorkflowPhase,
|
|
6
6
|
updateWorkflowRunStatus
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HKZ6IN7X.js";
|
|
8
8
|
import {
|
|
9
9
|
cueclawHome,
|
|
10
10
|
getDefaultImage,
|
|
11
11
|
loadConfig
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-5TV4LNC3.js";
|
|
13
13
|
import {
|
|
14
14
|
ConfigError,
|
|
15
15
|
ExecutorError
|
|
@@ -538,11 +538,12 @@ function runAgent(opts) {
|
|
|
538
538
|
const resultPromise = (async () => {
|
|
539
539
|
const authToken = config.claude.executor.api_key ?? config.claude.api_key;
|
|
540
540
|
const baseUrl = config.claude.executor.base_url ?? config.claude.base_url;
|
|
541
|
-
const
|
|
542
|
-
|
|
543
|
-
process.env["ANTHROPIC_AUTH_TOKEN"] = authToken;
|
|
541
|
+
const stepEnv = { ...process.env };
|
|
542
|
+
if (authToken) stepEnv["ANTHROPIC_AUTH_TOKEN"] = authToken;
|
|
544
543
|
if (baseUrl !== "https://api.anthropic.com") {
|
|
545
|
-
|
|
544
|
+
stepEnv["ANTHROPIC_BASE_URL"] = baseUrl;
|
|
545
|
+
} else {
|
|
546
|
+
delete stepEnv["ANTHROPIC_BASE_URL"];
|
|
546
547
|
}
|
|
547
548
|
try {
|
|
548
549
|
const { query } = await import("@anthropic-ai/claude-agent-sdk");
|
|
@@ -564,7 +565,8 @@ function runAgent(opts) {
|
|
|
564
565
|
"WebFetch"
|
|
565
566
|
],
|
|
566
567
|
settingSources: ["project"],
|
|
567
|
-
permissionMode: permMode
|
|
568
|
+
permissionMode: permMode,
|
|
569
|
+
env: stepEnv
|
|
568
570
|
}
|
|
569
571
|
});
|
|
570
572
|
let sessionId;
|
|
@@ -605,10 +607,6 @@ function runAgent(opts) {
|
|
|
605
607
|
logger.error({ err, stepId: opts.stepId }, "Agent execution failed");
|
|
606
608
|
return { status: "failed", error: errorMsg };
|
|
607
609
|
} finally {
|
|
608
|
-
if (prevAuthToken !== void 0) process.env["ANTHROPIC_AUTH_TOKEN"] = prevAuthToken;
|
|
609
|
-
else delete process.env["ANTHROPIC_AUTH_TOKEN"];
|
|
610
|
-
if (prevBaseUrl !== void 0) process.env["ANTHROPIC_BASE_URL"] = prevBaseUrl;
|
|
611
|
-
else delete process.env["ANTHROPIC_BASE_URL"];
|
|
612
610
|
}
|
|
613
611
|
})();
|
|
614
612
|
return {
|
|
@@ -646,6 +644,12 @@ function updateSessionSdkId(db, sessionId, sdkSessionId) {
|
|
|
646
644
|
db.prepare("UPDATE sessions SET sdk_session_id = ?, last_used_at = ? WHERE id = ?").run(sdkSessionId, (/* @__PURE__ */ new Date()).toISOString(), sessionId);
|
|
647
645
|
logger.debug({ sessionId, sdkSessionId }, "Session SDK ID updated");
|
|
648
646
|
}
|
|
647
|
+
function cleanupStaleSessions(db, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
|
|
648
|
+
const cutoff = new Date(Date.now() - maxAgeMs).toISOString();
|
|
649
|
+
const result = db.prepare("DELETE FROM sessions WHERE is_active = 0 AND last_used_at < ?").run(cutoff);
|
|
650
|
+
logger.info({ deletedCount: result.changes, cutoff }, "Stale sessions cleaned up");
|
|
651
|
+
return result.changes;
|
|
652
|
+
}
|
|
649
653
|
|
|
650
654
|
// src/executor.ts
|
|
651
655
|
var STEP_REF_PATTERN = /\$steps\.([a-z0-9-]+)\.output/g;
|
|
@@ -690,7 +694,7 @@ function hasSkipMarker(inputs) {
|
|
|
690
694
|
}
|
|
691
695
|
return false;
|
|
692
696
|
}
|
|
693
|
-
async function executeStepOnce(step, resolvedInputs, runId, db, cwd, onProgress, execLogger) {
|
|
697
|
+
async function executeStepOnce(step, resolvedInputs, workflowId, runId, db, cwd, onProgress, execLogger) {
|
|
694
698
|
const stepRunId = `sr_${nanoid3()}`;
|
|
695
699
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
696
700
|
const stepRun = {
|
|
@@ -710,7 +714,7 @@ ${JSON.stringify(resolvedInputs, null, 2)}` : "";
|
|
|
710
714
|
const handle = runAgent({
|
|
711
715
|
prompt,
|
|
712
716
|
cwd,
|
|
713
|
-
workflowId
|
|
717
|
+
workflowId,
|
|
714
718
|
stepId: step.id,
|
|
715
719
|
runId,
|
|
716
720
|
onProgress: onProgress ? (msg) => onProgress(step.id, msg) : void 0
|
|
@@ -730,11 +734,11 @@ ${JSON.stringify(resolvedInputs, null, 2)}` : "";
|
|
|
730
734
|
}
|
|
731
735
|
return result;
|
|
732
736
|
}
|
|
733
|
-
async function executeStepWithRetry(step, resolvedInputs, runId, db, cwd, policy, onProgress, execLogger) {
|
|
737
|
+
async function executeStepWithRetry(step, resolvedInputs, workflowId, runId, db, cwd, policy, onProgress, execLogger) {
|
|
734
738
|
const maxRetries = policy.max_retries ?? 0;
|
|
735
739
|
let delay = policy.retry_delay_ms ?? 5e3;
|
|
736
740
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
737
|
-
const result = await executeStepOnce(step, resolvedInputs, runId, db, cwd, onProgress, execLogger);
|
|
741
|
+
const result = await executeStepOnce(step, resolvedInputs, workflowId, runId, db, cwd, onProgress, execLogger);
|
|
738
742
|
if (result.status !== "failed" || attempt === maxRetries) return result;
|
|
739
743
|
logger.info({ stepId: step.id, attempt, delay }, "Retrying step");
|
|
740
744
|
await new Promise((r) => setTimeout(r, delay));
|
|
@@ -813,6 +817,7 @@ async function executeWorkflow(opts) {
|
|
|
813
817
|
const result = await executeStepWithRetry(
|
|
814
818
|
step,
|
|
815
819
|
resolvedInputs,
|
|
820
|
+
workflow.id,
|
|
816
821
|
runId,
|
|
817
822
|
db,
|
|
818
823
|
cwd,
|
|
@@ -825,10 +830,25 @@ async function executeWorkflow(opts) {
|
|
|
825
830
|
);
|
|
826
831
|
for (const { stepId, result } of results) {
|
|
827
832
|
completed.set(stepId, result);
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
833
|
+
}
|
|
834
|
+
for (const { stepId, result } of results) {
|
|
835
|
+
if (result.status !== "failed") continue;
|
|
836
|
+
const policy = workflow.failure_policy.on_step_failure;
|
|
837
|
+
if (policy === "stop") {
|
|
838
|
+
execLogger.warn({ stepId, policy: "stop" }, "Stop policy triggered, skipping remaining steps");
|
|
839
|
+
for (const remainingId of remaining) {
|
|
840
|
+
completed.set(remainingId, { status: "skipped" });
|
|
841
|
+
const skipRunId = `sr_${nanoid3()}`;
|
|
842
|
+
insertStepRun(db, { id: skipRunId, run_id: runId, step_id: remainingId, status: "skipped" });
|
|
843
|
+
}
|
|
844
|
+
remaining.clear();
|
|
845
|
+
runFailed = true;
|
|
846
|
+
break;
|
|
847
|
+
}
|
|
848
|
+
if (policy === "ask_user" && onStepFailure) {
|
|
849
|
+
const decision = await onStepFailure(stepMap.get(stepId), result.error ?? "Unknown error");
|
|
850
|
+
execLogger.info({ stepId, decision }, "ask_user decision received");
|
|
851
|
+
if (decision === "stop") {
|
|
832
852
|
for (const remainingId of remaining) {
|
|
833
853
|
completed.set(remainingId, { status: "skipped" });
|
|
834
854
|
const skipRunId = `sr_${nanoid3()}`;
|
|
@@ -838,19 +858,11 @@ async function executeWorkflow(opts) {
|
|
|
838
858
|
runFailed = true;
|
|
839
859
|
break;
|
|
840
860
|
}
|
|
841
|
-
if (
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
completed.set(remainingId, { status: "skipped" });
|
|
847
|
-
const skipRunId = `sr_${nanoid3()}`;
|
|
848
|
-
insertStepRun(db, { id: skipRunId, run_id: runId, step_id: remainingId, status: "skipped" });
|
|
849
|
-
}
|
|
850
|
-
remaining.clear();
|
|
851
|
-
runFailed = true;
|
|
852
|
-
break;
|
|
853
|
-
}
|
|
861
|
+
if (decision === "retry") {
|
|
862
|
+
remaining.add(stepId);
|
|
863
|
+
completed.delete(stepId);
|
|
864
|
+
execLogger.info({ stepId }, "Re-queuing step for retry");
|
|
865
|
+
continue;
|
|
854
866
|
}
|
|
855
867
|
}
|
|
856
868
|
}
|
|
@@ -871,6 +883,7 @@ async function executeWorkflow(opts) {
|
|
|
871
883
|
}
|
|
872
884
|
|
|
873
885
|
export {
|
|
886
|
+
cleanupStaleSessions,
|
|
874
887
|
resolveValue,
|
|
875
888
|
resolveInputs,
|
|
876
889
|
executeWorkflow
|
|
@@ -8,8 +8,9 @@ import {
|
|
|
8
8
|
createAnthropicClient
|
|
9
9
|
} from "./chunk-DVQFSFIZ.js";
|
|
10
10
|
import {
|
|
11
|
+
cleanupStaleSessions,
|
|
11
12
|
executeWorkflow
|
|
12
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-3HV3MHME.js";
|
|
13
14
|
import {
|
|
14
15
|
getWorkflow,
|
|
15
16
|
initDb,
|
|
@@ -17,11 +18,11 @@ import {
|
|
|
17
18
|
listWorkflows,
|
|
18
19
|
updateWorkflowPhase,
|
|
19
20
|
upsertWorkflow
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-HKZ6IN7X.js";
|
|
21
22
|
import {
|
|
22
23
|
cueclawHome,
|
|
23
24
|
loadConfig
|
|
24
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-5TV4LNC3.js";
|
|
25
26
|
import {
|
|
26
27
|
logger
|
|
27
28
|
} from "./chunk-KBLMQZ3P.js";
|
|
@@ -36,6 +37,7 @@ var CONFIRMATION_TIMEOUT = 10 * 6e4;
|
|
|
36
37
|
var RATE_LIMIT_WINDOW = 6e4;
|
|
37
38
|
var RATE_LIMIT_MAX = 10;
|
|
38
39
|
var CLEANUP_INTERVAL = 5 * 6e4;
|
|
40
|
+
var ACTIVE_JID_TTL = 24 * 60 * 6e4;
|
|
39
41
|
var MessageRouter = class {
|
|
40
42
|
constructor(db, config, cwd) {
|
|
41
43
|
this.db = db;
|
|
@@ -45,6 +47,7 @@ var MessageRouter = class {
|
|
|
45
47
|
channels = /* @__PURE__ */ new Map();
|
|
46
48
|
pendingConfirmations = /* @__PURE__ */ new Map();
|
|
47
49
|
messageTimestamps = /* @__PURE__ */ new Map();
|
|
50
|
+
activeJids = /* @__PURE__ */ new Map();
|
|
48
51
|
cleanupTimer = null;
|
|
49
52
|
registerChannel(channel) {
|
|
50
53
|
this.channels.set(channel.name, channel);
|
|
@@ -58,6 +61,7 @@ var MessageRouter = class {
|
|
|
58
61
|
clearInterval(this.cleanupTimer);
|
|
59
62
|
this.cleanupTimer = null;
|
|
60
63
|
}
|
|
64
|
+
this.activeJids.clear();
|
|
61
65
|
}
|
|
62
66
|
/** Disconnect all registered channels */
|
|
63
67
|
async disconnectAll() {
|
|
@@ -65,16 +69,39 @@ var MessageRouter = class {
|
|
|
65
69
|
[...this.channels.values()].map((c) => c.disconnect())
|
|
66
70
|
);
|
|
67
71
|
}
|
|
68
|
-
/** Broadcast a notification to all
|
|
72
|
+
/** Broadcast a notification to all active users on connected channels */
|
|
69
73
|
broadcastNotification(message) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
const now = Date.now();
|
|
75
|
+
for (const [channelName, channel] of this.channels) {
|
|
76
|
+
if (!channel.isConnected()) continue;
|
|
77
|
+
const jids = this.activeJids.get(channelName);
|
|
78
|
+
const recipients = /* @__PURE__ */ new Set();
|
|
79
|
+
if (jids && jids.size > 0) {
|
|
80
|
+
for (const [jid, lastSeenAt] of jids) {
|
|
81
|
+
if (now - lastSeenAt <= ACTIVE_JID_TTL) recipients.add(jid);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (recipients.size === 0) {
|
|
85
|
+
for (const jid of this.getConfiguredRecipients(channelName)) {
|
|
86
|
+
recipients.add(jid);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (const jid of recipients) {
|
|
90
|
+
channel.sendMessage(jid, message).catch((err) => {
|
|
91
|
+
logger.error({ err, channel: channelName, jid }, "Failed to broadcast notification");
|
|
74
92
|
});
|
|
75
93
|
}
|
|
76
94
|
}
|
|
77
95
|
}
|
|
96
|
+
getConfiguredRecipients(channelName) {
|
|
97
|
+
if (channelName === "telegram") {
|
|
98
|
+
return this.config.telegram?.allowed_users ?? [];
|
|
99
|
+
}
|
|
100
|
+
if (channelName === "whatsapp") {
|
|
101
|
+
return this.config.whatsapp?.allowed_jids ?? [];
|
|
102
|
+
}
|
|
103
|
+
return [];
|
|
104
|
+
}
|
|
78
105
|
async handleInbound(channelName, chatJid, message) {
|
|
79
106
|
const channel = this.channels.get(channelName);
|
|
80
107
|
if (!channel) {
|
|
@@ -84,6 +111,8 @@ var MessageRouter = class {
|
|
|
84
111
|
const text = typeof message === "string" ? message : message.text;
|
|
85
112
|
const sender = typeof message === "string" ? void 0 : message.sender;
|
|
86
113
|
logger.debug({ channelName, chatJid }, "Inbound message received");
|
|
114
|
+
if (!this.activeJids.has(channelName)) this.activeJids.set(channelName, /* @__PURE__ */ new Map());
|
|
115
|
+
this.activeJids.get(channelName).set(chatJid, Date.now());
|
|
87
116
|
if (this.isRateLimited(chatJid)) {
|
|
88
117
|
logger.warn({ chatJid, channelName }, "Rate limit exceeded");
|
|
89
118
|
await channel.sendMessage(chatJid, "Rate limited, please wait before sending more messages.");
|
|
@@ -307,7 +336,8 @@ ${msg}`;
|
|
|
307
336
|
}
|
|
308
337
|
} else if (["no", "n", "cancel", "3"].includes(lower)) {
|
|
309
338
|
this.pendingConfirmations.delete(chatJid);
|
|
310
|
-
rejectPlan(pending.workflow);
|
|
339
|
+
const rejected = rejectPlan(pending.workflow);
|
|
340
|
+
updateWorkflowPhase(this.db, pending.workflowId, rejected.phase);
|
|
311
341
|
logger.info({ workflowId: pending.workflowId, chatJid }, "Workflow rejected via channel");
|
|
312
342
|
await channel.sendMessage(chatJid, "Plan cancelled.");
|
|
313
343
|
} else if (["modify", "m", "2"].includes(lower)) {
|
|
@@ -353,6 +383,16 @@ ${msg}`;
|
|
|
353
383
|
this.messageTimestamps.set(jid, recent);
|
|
354
384
|
}
|
|
355
385
|
}
|
|
386
|
+
for (const [channelName, jids] of this.activeJids) {
|
|
387
|
+
for (const [jid, lastSeenAt] of jids) {
|
|
388
|
+
if (now - lastSeenAt > ACTIVE_JID_TTL) {
|
|
389
|
+
jids.delete(jid);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (jids.size === 0) {
|
|
393
|
+
this.activeJids.delete(channelName);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
356
396
|
}
|
|
357
397
|
};
|
|
358
398
|
|
|
@@ -675,6 +715,8 @@ async function startDaemon() {
|
|
|
675
715
|
logger.error({ err }, "Failed to start Telegram channel");
|
|
676
716
|
}
|
|
677
717
|
}
|
|
718
|
+
const cleaned = cleanupStaleSessions(db);
|
|
719
|
+
if (cleaned > 0) logger.info({ cleaned }, "Cleaned up stale sessions");
|
|
678
720
|
await recoverRunningWorkflows(db, router);
|
|
679
721
|
logger.debug("Starting trigger loop and router");
|
|
680
722
|
const maxConcurrent = 5;
|
|
@@ -115,6 +115,12 @@ function loadConfig() {
|
|
|
115
115
|
merged.claude = merged.claude ?? {};
|
|
116
116
|
merged.claude.base_url = process.env["ANTHROPIC_BASE_URL"];
|
|
117
117
|
}
|
|
118
|
+
if (process.env["CUECLAW_MODEL"]) {
|
|
119
|
+
merged.claude = merged.claude ?? {};
|
|
120
|
+
const model = process.env["CUECLAW_MODEL"];
|
|
121
|
+
merged.claude.planner = { ...merged.claude.planner, model };
|
|
122
|
+
merged.claude.executor = { ...merged.claude.executor, model };
|
|
123
|
+
}
|
|
118
124
|
if (process.env["TELEGRAM_BOT_TOKEN"]) {
|
|
119
125
|
merged.telegram = merged.telegram ?? {};
|
|
120
126
|
merged.telegram.token = process.env["TELEGRAM_BOT_TOKEN"];
|
|
@@ -29,8 +29,9 @@ function checkEnvironment() {
|
|
|
29
29
|
async function validateAuth(config) {
|
|
30
30
|
try {
|
|
31
31
|
const client = createAnthropicClient(config);
|
|
32
|
+
const model = config.claude.planner.model ?? "claude-haiku-4-5-20251001";
|
|
32
33
|
await client.messages.create({
|
|
33
|
-
model
|
|
34
|
+
model,
|
|
34
35
|
max_tokens: 10,
|
|
35
36
|
messages: [{ role: "user", content: "ping" }]
|
|
36
37
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
cueclawHome
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5TV4LNC3.js";
|
|
4
4
|
|
|
5
5
|
// src/db.ts
|
|
6
6
|
import Database from "better-sqlite3";
|
|
@@ -166,8 +166,16 @@ function insertWorkflowRun(db, run) {
|
|
|
166
166
|
`).run(run.id, run.workflow_id, run.trigger_data, run.status, run.started_at, run.completed_at ?? null, run.error ?? null, run.duration_ms ?? null);
|
|
167
167
|
}
|
|
168
168
|
function updateWorkflowRunStatus(db, id, status, error) {
|
|
169
|
-
const
|
|
170
|
-
|
|
169
|
+
const now = /* @__PURE__ */ new Date();
|
|
170
|
+
const completedAt = status !== "running" ? now.toISOString() : null;
|
|
171
|
+
let durationMs = null;
|
|
172
|
+
if (completedAt) {
|
|
173
|
+
const row = db.prepare("SELECT started_at FROM workflow_runs WHERE id = ?").get(id);
|
|
174
|
+
if (row?.started_at) {
|
|
175
|
+
durationMs = now.getTime() - new Date(row.started_at).getTime();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
db.prepare("UPDATE workflow_runs SET status = ?, completed_at = ?, error = ?, duration_ms = ? WHERE id = ?").run(status, completedAt, error ?? null, durationMs, id);
|
|
171
179
|
}
|
|
172
180
|
function insertStepRun(db, stepRun) {
|
|
173
181
|
db.prepare(`
|
|
@@ -176,8 +184,16 @@ function insertStepRun(db, stepRun) {
|
|
|
176
184
|
`).run(stepRun.id, stepRun.run_id, stepRun.step_id, stepRun.status, stepRun.output_json ?? null, stepRun.error ?? null, stepRun.started_at ?? null, stepRun.completed_at ?? null, stepRun.duration_ms ?? null);
|
|
177
185
|
}
|
|
178
186
|
function updateStepRunStatus(db, id, status, output, error) {
|
|
179
|
-
const
|
|
180
|
-
|
|
187
|
+
const now = /* @__PURE__ */ new Date();
|
|
188
|
+
const completedAt = status === "succeeded" || status === "failed" || status === "skipped" ? now.toISOString() : null;
|
|
189
|
+
let durationMs = null;
|
|
190
|
+
if (completedAt) {
|
|
191
|
+
const row = db.prepare("SELECT started_at FROM step_runs WHERE id = ?").get(id);
|
|
192
|
+
if (row?.started_at) {
|
|
193
|
+
durationMs = now.getTime() - new Date(row.started_at).getTime();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
db.prepare("UPDATE step_runs SET status = ?, output_json = ?, error = ?, completed_at = ?, duration_ms = ? WHERE id = ?").run(status, output ?? null, error ?? null, completedAt, durationMs, id);
|
|
181
197
|
}
|
|
182
198
|
function getStepRunsByRunId(db, runId) {
|
|
183
199
|
return db.prepare("SELECT * FROM step_runs WHERE run_id = ?").all(runId);
|
package/dist/cli.js
CHANGED
|
@@ -8,13 +8,13 @@ import {
|
|
|
8
8
|
insertWorkflow,
|
|
9
9
|
listWorkflows,
|
|
10
10
|
updateWorkflowPhase
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-HKZ6IN7X.js";
|
|
12
12
|
import {
|
|
13
13
|
createDefaultConfig,
|
|
14
14
|
cueclawHome,
|
|
15
15
|
ensureCueclawHome,
|
|
16
16
|
loadConfig
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-5TV4LNC3.js";
|
|
18
18
|
import "./chunk-BVQG3WYO.js";
|
|
19
19
|
import {
|
|
20
20
|
loadSecrets
|
|
@@ -115,7 +115,7 @@ program.command("new").description("Create a new workflow from a natural languag
|
|
|
115
115
|
try {
|
|
116
116
|
const config = loadConfig();
|
|
117
117
|
const { generatePlan, confirmPlan } = await import("./planner-MJ3XBCWH.js");
|
|
118
|
-
const { executeWorkflow } = await import("./executor-
|
|
118
|
+
const { executeWorkflow } = await import("./executor-44MSZ76T.js");
|
|
119
119
|
logger.info({ description: description.slice(0, 100) }, "Starting plan generation");
|
|
120
120
|
console.log("Planning workflow...");
|
|
121
121
|
const workflow = await generatePlan(description, config);
|
|
@@ -295,7 +295,7 @@ program.command("resume").argument("<workflow-id>", "Workflow ID").description("
|
|
|
295
295
|
updateWorkflowPhase(db, workflowId, "executing");
|
|
296
296
|
logger.info({ workflowId }, "Resuming workflow execution");
|
|
297
297
|
console.log(`Executing workflow "${wf.name}"...`);
|
|
298
|
-
const { executeWorkflow } = await import("./executor-
|
|
298
|
+
const { executeWorkflow } = await import("./executor-44MSZ76T.js");
|
|
299
299
|
const result = await executeWorkflow({
|
|
300
300
|
workflow: { ...wf, phase: "executing" },
|
|
301
301
|
triggerData: null,
|
|
@@ -359,7 +359,7 @@ var daemonCmd = program.command("daemon").description("Manage background daemon"
|
|
|
359
359
|
daemonCmd.command("start").option("--foreground", "Run in foreground (for system services)").description("Start the daemon (runs in background by default)").action(async (opts) => {
|
|
360
360
|
if (opts.foreground) {
|
|
361
361
|
try {
|
|
362
|
-
const { startDaemon } = await import("./daemon-
|
|
362
|
+
const { startDaemon } = await import("./daemon-Y5HIGH44.js");
|
|
363
363
|
await startDaemon();
|
|
364
364
|
} catch (err) {
|
|
365
365
|
logger.error({ err }, "Daemon failed");
|
|
@@ -367,7 +367,7 @@ daemonCmd.command("start").option("--foreground", "Run in foreground (for system
|
|
|
367
367
|
}
|
|
368
368
|
return;
|
|
369
369
|
}
|
|
370
|
-
const { isDaemonRunning, spawnDaemonProcess } = await import("./daemon-
|
|
370
|
+
const { isDaemonRunning, spawnDaemonProcess } = await import("./daemon-Y5HIGH44.js");
|
|
371
371
|
if (isDaemonRunning()) {
|
|
372
372
|
console.log("Daemon is already running.");
|
|
373
373
|
return;
|
|
@@ -382,7 +382,7 @@ daemonCmd.command("start").option("--foreground", "Run in foreground (for system
|
|
|
382
382
|
}
|
|
383
383
|
});
|
|
384
384
|
daemonCmd.command("stop").description("Stop the daemon").action(async () => {
|
|
385
|
-
const { readPidFile, isProcessAlive, removePidFile } = await import("./daemon-
|
|
385
|
+
const { readPidFile, isProcessAlive, removePidFile } = await import("./daemon-Y5HIGH44.js");
|
|
386
386
|
const pid = readPidFile();
|
|
387
387
|
if (pid && isProcessAlive(pid)) {
|
|
388
388
|
process.kill(pid, "SIGTERM");
|
|
@@ -391,7 +391,7 @@ daemonCmd.command("stop").description("Stop the daemon").action(async () => {
|
|
|
391
391
|
console.log(`Daemon stopped (PID ${pid}).`);
|
|
392
392
|
return;
|
|
393
393
|
}
|
|
394
|
-
const { getServiceStatus, stopService } = await import("./service-
|
|
394
|
+
const { getServiceStatus, stopService } = await import("./service-Q7USNFFB.js");
|
|
395
395
|
const status = getServiceStatus();
|
|
396
396
|
if (status === "running") {
|
|
397
397
|
const result = stopService();
|
|
@@ -409,14 +409,14 @@ daemonCmd.command("stop").description("Stop the daemon").action(async () => {
|
|
|
409
409
|
console.log("Daemon is not running.");
|
|
410
410
|
});
|
|
411
411
|
daemonCmd.command("restart").description("Restart the daemon").action(async () => {
|
|
412
|
-
const { readPidFile, isProcessAlive, removePidFile } = await import("./daemon-
|
|
412
|
+
const { readPidFile, isProcessAlive, removePidFile } = await import("./daemon-Y5HIGH44.js");
|
|
413
413
|
const pid = readPidFile();
|
|
414
414
|
if (pid && isProcessAlive(pid)) {
|
|
415
415
|
process.kill(pid, "SIGTERM");
|
|
416
416
|
removePidFile();
|
|
417
417
|
console.log(`Stopped daemon (PID ${pid}).`);
|
|
418
418
|
} else {
|
|
419
|
-
const { getServiceStatus, stopService } = await import("./service-
|
|
419
|
+
const { getServiceStatus, stopService } = await import("./service-Q7USNFFB.js");
|
|
420
420
|
if (getServiceStatus() === "running") {
|
|
421
421
|
const result = stopService();
|
|
422
422
|
if (!result.success) {
|
|
@@ -426,7 +426,7 @@ daemonCmd.command("restart").description("Restart the daemon").action(async () =
|
|
|
426
426
|
console.log("Stopped system service daemon.");
|
|
427
427
|
}
|
|
428
428
|
}
|
|
429
|
-
const { spawnDaemonProcess } = await import("./daemon-
|
|
429
|
+
const { spawnDaemonProcess } = await import("./daemon-Y5HIGH44.js");
|
|
430
430
|
const newPid = spawnDaemonProcess();
|
|
431
431
|
if (newPid) {
|
|
432
432
|
console.log(`Daemon restarted in background (PID ${newPid})`);
|
|
@@ -436,7 +436,7 @@ daemonCmd.command("restart").description("Restart the daemon").action(async () =
|
|
|
436
436
|
}
|
|
437
437
|
});
|
|
438
438
|
daemonCmd.command("install").description("Install system service").action(async () => {
|
|
439
|
-
const { installService } = await import("./service-
|
|
439
|
+
const { installService } = await import("./service-Q7USNFFB.js");
|
|
440
440
|
const result = installService();
|
|
441
441
|
if (result.success) {
|
|
442
442
|
logger.info("System service installed");
|
|
@@ -448,7 +448,7 @@ daemonCmd.command("install").description("Install system service").action(async
|
|
|
448
448
|
}
|
|
449
449
|
});
|
|
450
450
|
daemonCmd.command("uninstall").description("Remove system service").action(async () => {
|
|
451
|
-
const { uninstallService } = await import("./service-
|
|
451
|
+
const { uninstallService } = await import("./service-Q7USNFFB.js");
|
|
452
452
|
const result = uninstallService();
|
|
453
453
|
if (result.success) {
|
|
454
454
|
logger.info("System service uninstalled");
|
|
@@ -460,13 +460,13 @@ daemonCmd.command("uninstall").description("Remove system service").action(async
|
|
|
460
460
|
}
|
|
461
461
|
});
|
|
462
462
|
daemonCmd.command("status").description("View daemon status").action(async () => {
|
|
463
|
-
const { readPidFile, isProcessAlive } = await import("./daemon-
|
|
463
|
+
const { readPidFile, isProcessAlive } = await import("./daemon-Y5HIGH44.js");
|
|
464
464
|
const pid = readPidFile();
|
|
465
465
|
if (pid && isProcessAlive(pid)) {
|
|
466
466
|
console.log(`Daemon status: running (PID ${pid})`);
|
|
467
467
|
return;
|
|
468
468
|
}
|
|
469
|
-
const { getServiceStatus } = await import("./service-
|
|
469
|
+
const { getServiceStatus } = await import("./service-Q7USNFFB.js");
|
|
470
470
|
const status = getServiceStatus();
|
|
471
471
|
if (status === "running") {
|
|
472
472
|
console.log(`Daemon status: running (system service)`);
|
|
@@ -476,7 +476,7 @@ daemonCmd.command("status").description("View daemon status").action(async () =>
|
|
|
476
476
|
});
|
|
477
477
|
daemonCmd.command("logs").description("View daemon logs").action(async () => {
|
|
478
478
|
const { join } = await import("path");
|
|
479
|
-
const { cueclawHome: cueclawHome2 } = await import("./config-
|
|
479
|
+
const { cueclawHome: cueclawHome2 } = await import("./config-FYL6T5JP.js");
|
|
480
480
|
const logPath = join(cueclawHome2(), "logs", "daemon.log");
|
|
481
481
|
const { existsSync } = await import("fs");
|
|
482
482
|
if (!existsSync(logPath)) {
|
|
@@ -495,7 +495,7 @@ botCmd.command("status").description("View channel connection status").action(()
|
|
|
495
495
|
program.command("setup").description("First-run setup: validate Docker, build container, smoke test").action(async () => {
|
|
496
496
|
try {
|
|
497
497
|
const config = loadConfig();
|
|
498
|
-
const { runSetup } = await import("./setup-
|
|
498
|
+
const { runSetup } = await import("./setup-JK664Y2M.js");
|
|
499
499
|
await runSetup(config, process.cwd());
|
|
500
500
|
} catch (err) {
|
|
501
501
|
logger.error({ err }, "Setup failed");
|
|
@@ -508,7 +508,7 @@ program.command("tui").description("Start interactive TUI").option("--skip-onboa
|
|
|
508
508
|
enableTuiLogging();
|
|
509
509
|
const React = await import("react");
|
|
510
510
|
const { render } = await import("ink");
|
|
511
|
-
const { App } = await import("./app-
|
|
511
|
+
const { App } = await import("./app-6SXWEUZZ.js");
|
|
512
512
|
render(React.createElement(App, { cwd: process.cwd(), skipOnboarding: opts.skipOnboarding }), { exitOnCtrlC: false });
|
|
513
513
|
} catch (err) {
|
|
514
514
|
logger.error({ err }, "Failed to start TUI");
|
|
@@ -522,7 +522,7 @@ program.option("--skip-onboarding", "Skip first-run onboarding wizard").action(a
|
|
|
522
522
|
enableTuiLogging();
|
|
523
523
|
const React = await import("react");
|
|
524
524
|
const { render } = await import("ink");
|
|
525
|
-
const { App } = await import("./app-
|
|
525
|
+
const { App } = await import("./app-6SXWEUZZ.js");
|
|
526
526
|
render(React.createElement(App, { cwd: process.cwd(), skipOnboarding }), { exitOnCtrlC: false });
|
|
527
527
|
} catch (err) {
|
|
528
528
|
logger.error({ err }, "Failed to start TUI");
|
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
spawnDaemonProcess,
|
|
8
8
|
startDaemon,
|
|
9
9
|
writePidFile
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-54BGF7G5.js";
|
|
11
11
|
import "./chunk-ZOFGQYXX.js";
|
|
12
12
|
import "./chunk-DVQFSFIZ.js";
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-3HV3MHME.js";
|
|
14
|
+
import "./chunk-HKZ6IN7X.js";
|
|
15
|
+
import "./chunk-5TV4LNC3.js";
|
|
16
16
|
import "./chunk-BVQG3WYO.js";
|
|
17
17
|
import "./chunk-ZCK3IFLC.js";
|
|
18
18
|
import "./chunk-KBLMQZ3P.js";
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
executeWorkflow,
|
|
3
3
|
resolveInputs,
|
|
4
4
|
resolveValue
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-3HV3MHME.js";
|
|
6
|
+
import "./chunk-HKZ6IN7X.js";
|
|
7
|
+
import "./chunk-5TV4LNC3.js";
|
|
8
8
|
import "./chunk-BVQG3WYO.js";
|
|
9
9
|
import "./chunk-ZCK3IFLC.js";
|
|
10
10
|
import "./chunk-KBLMQZ3P.js";
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
installService,
|
|
4
4
|
stopService,
|
|
5
5
|
uninstallService
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-MEAAX2SW.js";
|
|
7
|
+
import "./chunk-5TV4LNC3.js";
|
|
8
8
|
import "./chunk-BVQG3WYO.js";
|
|
9
9
|
import "./chunk-ZCK3IFLC.js";
|
|
10
10
|
import "./chunk-KBLMQZ3P.js";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
checkEnvironment,
|
|
3
3
|
validateAuth
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-FKKDQVRE.js";
|
|
5
5
|
import "./chunk-DVQFSFIZ.js";
|
|
6
6
|
import {
|
|
7
7
|
getDefaultImage
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-5TV4LNC3.js";
|
|
9
9
|
import "./chunk-BVQG3WYO.js";
|
|
10
10
|
import "./chunk-ZCK3IFLC.js";
|
|
11
11
|
import {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cueclaw",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Orchestrate agent workflows with natural language. Natural language in, executable DAG out.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"commit-msg": "pnpm commitlint --edit $1"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@anthropic-ai/claude-agent-sdk": "^0.2.
|
|
47
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.63",
|
|
48
48
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
49
49
|
"@inkjs/ui": "^2.0.0",
|
|
50
50
|
"@whiskeysockets/baileys": "7.0.0-rc.9",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"commander": "^14.0.3",
|
|
53
53
|
"cron-parser": "^5.5.0",
|
|
54
54
|
"dotenv": "^17.3.1",
|
|
55
|
-
"grammy": "^1.40.
|
|
55
|
+
"grammy": "^1.40.1",
|
|
56
56
|
"ink": "5",
|
|
57
57
|
"ink-spinner": "^5.0.0",
|
|
58
58
|
"ink-text-input": "^6.0.0",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"@commitlint/config-conventional": "^20.4.2",
|
|
71
71
|
"@eslint/js": "^10.0.1",
|
|
72
72
|
"@types/better-sqlite3": "^7.6.13",
|
|
73
|
-
"@types/node": "^25.3.
|
|
73
|
+
"@types/node": "^25.3.2",
|
|
74
74
|
"@types/react": "^19.2.14",
|
|
75
75
|
"@vitest/coverage-v8": "^4.0.18",
|
|
76
76
|
"eslint": "^10.0.2",
|