cueclaw 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,31 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ loadSecrets
4
+ } from "./chunk-ZCK3IFLC.js";
5
+ import {
6
+ deleteWorkflow,
7
+ getStepRunsByRunId,
8
+ getWorkflow,
9
+ getWorkflowRunsByWorkflowId,
3
10
  initDb,
4
- listWorkflows
5
- } from "./chunk-K4PGB2DU.js";
11
+ insertWorkflow,
12
+ listWorkflows,
13
+ updateWorkflowPhase
14
+ } from "./chunk-G43R5ASK.js";
6
15
  import {
7
16
  createDefaultConfig,
17
+ cueclawHome,
8
18
  ensureCueclawHome,
9
19
  loadConfig
10
- } from "./chunk-JRHM3Z4C.js";
20
+ } from "./chunk-RSKXBXSJ.js";
21
+ import "./chunk-BVQG3WYO.js";
11
22
  import {
12
23
  logger
13
- } from "./chunk-E7BP6DMO.js";
24
+ } from "./chunk-QBOYMF4A.js";
14
25
 
15
26
  // src/cli.ts
16
27
  import { Command } from "commander";
17
-
18
- // src/env.ts
19
- import { readFileSync, existsSync } from "fs";
20
- import { parse } from "dotenv";
21
- var secrets = {};
22
- function loadSecrets(envPath = ".env") {
23
- if (!existsSync(envPath)) return;
24
- const content = readFileSync(envPath, "utf-8");
25
- secrets = parse(content);
26
- }
27
-
28
- // src/cli.ts
28
+ import { createInterface } from "readline";
29
29
  var program = new Command().name("cueclaw").description("Orchestrate agent workflows with natural language").version("0.0.1");
30
30
  program.command("info").description("Show loaded config, paths, versions").action(() => {
31
31
  try {
@@ -63,8 +63,100 @@ configCmd.command("get").argument("[key]", "Config key (dot notation)").descript
63
63
  process.exit(1);
64
64
  }
65
65
  });
66
- program.command("new").description("Create a new workflow interactively").action(() => {
67
- console.log("Workflow creation coming in Phase 1");
66
+ configCmd.command("set").argument("<key>", "Config key (dot notation, e.g. claude.executor.model)").argument("<value>", "Value to set").description("Set config value").action(async (key, value) => {
67
+ try {
68
+ const { readFileSync, writeFileSync, existsSync } = await import("fs");
69
+ const { join } = await import("path");
70
+ const { parse: parseYaml, stringify: stringifyYaml } = await import("yaml");
71
+ const { isDev, writeEnvVar } = await import("./env-2ZIW4OD7.js");
72
+ const configPath = join(cueclawHome(), "config.yaml");
73
+ if (!existsSync(configPath)) {
74
+ createDefaultConfig();
75
+ }
76
+ const content = readFileSync(configPath, "utf-8");
77
+ const doc = parseYaml(content) ?? {};
78
+ const envVarMap = {
79
+ "claude.api_key": "ANTHROPIC_API_KEY",
80
+ "claude.base_url": "ANTHROPIC_BASE_URL"
81
+ };
82
+ const envVar = envVarMap[key];
83
+ if (isDev && envVar) {
84
+ writeEnvVar(envVar, value);
85
+ console.log(`Set ${key} (stored in .env as ${envVar})`);
86
+ } else {
87
+ let parsed = value;
88
+ if (value === "true") parsed = true;
89
+ else if (value === "false") parsed = false;
90
+ else if (/^\d+$/.test(value)) parsed = Number(value);
91
+ const parts = key.split(".");
92
+ let target = doc;
93
+ for (let i = 0; i < parts.length - 1; i++) {
94
+ const part = parts[i];
95
+ if (target[part] === void 0 || target[part] === null || typeof target[part] !== "object") {
96
+ target[part] = {};
97
+ }
98
+ target = target[part];
99
+ }
100
+ target[parts[parts.length - 1]] = parsed;
101
+ writeFileSync(configPath, stringifyYaml(doc), "utf-8");
102
+ console.log(`Set ${key} = ${JSON.stringify(parsed)}`);
103
+ }
104
+ } catch (err) {
105
+ logger.error({ err }, "Failed to set config");
106
+ process.exit(1);
107
+ }
108
+ });
109
+ program.command("new").description("Create a new workflow from a natural language description").argument("<description>", "Workflow description in natural language").action(async (description) => {
110
+ try {
111
+ const config = loadConfig();
112
+ const { generatePlan, confirmPlan } = await import("./planner-UU4T5IEN.js");
113
+ const { executeWorkflow } = await import("./executor-LS3Y4DO5.js");
114
+ console.log("Planning workflow...");
115
+ const workflow = await generatePlan(description, config);
116
+ console.log(`
117
+ Workflow: ${workflow.name}`);
118
+ console.log(`Trigger: ${workflow.trigger.type}`);
119
+ console.log(`Steps:`);
120
+ for (const step of workflow.steps) {
121
+ const deps = step.depends_on.length > 0 ? ` (after: ${step.depends_on.join(", ")})` : "";
122
+ console.log(` - ${step.id}: ${step.description.slice(0, 80)}${step.description.length > 80 ? "..." : ""}${deps}`);
123
+ }
124
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
125
+ const answer = await new Promise((resolve) => {
126
+ rl.question("\nConfirm and execute? (y/N) ", resolve);
127
+ });
128
+ rl.close();
129
+ if (answer.toLowerCase() !== "y") {
130
+ console.log("Cancelled.");
131
+ return;
132
+ }
133
+ ensureCueclawHome();
134
+ const db = initDb();
135
+ insertWorkflow(db, workflow);
136
+ const confirmed = confirmPlan(workflow);
137
+ updateWorkflowPhase(db, confirmed.id, confirmed.phase);
138
+ if (confirmed.phase === "executing") {
139
+ console.log("\nExecuting workflow...");
140
+ const result = await executeWorkflow({
141
+ workflow: confirmed,
142
+ triggerData: null,
143
+ db,
144
+ cwd: process.cwd(),
145
+ onProgress: (stepId, msg) => {
146
+ if (msg?.status) console.log(` [${stepId}] ${msg.status}`);
147
+ }
148
+ });
149
+ console.log(`
150
+ Workflow ${result.status}. Run ID: ${result.runId}`);
151
+ } else {
152
+ console.log(`
153
+ Workflow saved as "${confirmed.phase}". ID: ${confirmed.id}`);
154
+ }
155
+ db.close();
156
+ } catch (err) {
157
+ logger.error({ err }, "Failed to create workflow");
158
+ process.exit(1);
159
+ }
68
160
  });
69
161
  program.command("list").description("List all workflows").action(() => {
70
162
  try {
@@ -84,33 +176,189 @@ program.command("list").description("List all workflows").action(() => {
84
176
  process.exit(1);
85
177
  }
86
178
  });
87
- program.command("status").argument("[workflow-id]", "Workflow ID").description("View workflow status").action(() => {
88
- console.log("Status view coming in Phase 1");
179
+ program.command("status").argument("[workflow-id]", "Workflow ID").description("View workflow status").action((workflowId) => {
180
+ try {
181
+ ensureCueclawHome();
182
+ const db = initDb();
183
+ if (!workflowId) {
184
+ const workflows = listWorkflows(db);
185
+ if (workflows.length === 0) {
186
+ console.log("No workflows found.");
187
+ db.close();
188
+ return;
189
+ }
190
+ console.log("Workflows:\n");
191
+ for (const wf2 of workflows) {
192
+ console.log(` ${wf2.id} ${wf2.phase.padEnd(22)} ${wf2.name}`);
193
+ console.log(` Trigger: ${wf2.trigger.type} | Steps: ${wf2.steps.length} | Updated: ${wf2.updated_at}`);
194
+ }
195
+ db.close();
196
+ return;
197
+ }
198
+ const wf = getWorkflow(db, workflowId);
199
+ if (!wf) {
200
+ console.error(`Workflow not found: ${workflowId}`);
201
+ db.close();
202
+ process.exit(1);
203
+ }
204
+ console.log(`Workflow: ${wf.name}`);
205
+ console.log(`ID: ${wf.id}`);
206
+ console.log(`Phase: ${wf.phase}`);
207
+ console.log(`Trigger: ${wf.trigger.type}`);
208
+ console.log(`Created: ${wf.created_at}`);
209
+ console.log(`Updated: ${wf.updated_at}`);
210
+ console.log(`
211
+ Steps:`);
212
+ for (const step of wf.steps) {
213
+ const deps = step.depends_on.length > 0 ? ` (after: ${step.depends_on.join(", ")})` : "";
214
+ console.log(` - ${step.id}: ${step.description.slice(0, 100)}${step.description.length > 100 ? "..." : ""}${deps}`);
215
+ }
216
+ const runs = getWorkflowRunsByWorkflowId(db, workflowId);
217
+ if (runs.length > 0) {
218
+ const latest = runs[0];
219
+ console.log(`
220
+ Latest Run: ${latest.id}`);
221
+ console.log(` Status: ${latest.status}`);
222
+ console.log(` Started: ${latest.started_at}`);
223
+ if (latest.completed_at) console.log(` Ended: ${latest.completed_at}`);
224
+ if (latest.error) console.log(` Error: ${latest.error}`);
225
+ const stepRuns = getStepRunsByRunId(db, latest.id);
226
+ if (stepRuns.length > 0) {
227
+ console.log(` Step Results:`);
228
+ for (const sr of stepRuns) {
229
+ const output = sr.output_json ? ` \u2014 ${sr.output_json.slice(0, 60)}${sr.output_json.length > 60 ? "..." : ""}` : "";
230
+ console.log(` ${sr.step_id}: ${sr.status}${output}`);
231
+ }
232
+ }
233
+ }
234
+ db.close();
235
+ } catch (err) {
236
+ logger.error({ err }, "Failed to get workflow status");
237
+ process.exit(1);
238
+ }
89
239
  });
90
- program.command("pause").argument("<workflow-id>", "Workflow ID").description("Pause a workflow").action(() => {
91
- console.log("Pause coming in Phase 1");
240
+ program.command("pause").argument("<workflow-id>", "Workflow ID").description("Pause a workflow").action((workflowId) => {
241
+ try {
242
+ ensureCueclawHome();
243
+ const db = initDb();
244
+ const wf = getWorkflow(db, workflowId);
245
+ if (!wf) {
246
+ console.error(`Workflow not found: ${workflowId}`);
247
+ db.close();
248
+ process.exit(1);
249
+ }
250
+ if (wf.phase !== "active") {
251
+ console.error(`Cannot pause workflow in phase "${wf.phase}" (must be "active")`);
252
+ db.close();
253
+ process.exit(1);
254
+ }
255
+ updateWorkflowPhase(db, workflowId, "paused");
256
+ console.log(`Paused workflow "${wf.name}" (${workflowId})`);
257
+ db.close();
258
+ } catch (err) {
259
+ logger.error({ err }, "Failed to pause workflow");
260
+ process.exit(1);
261
+ }
92
262
  });
93
- program.command("resume").argument("<workflow-id>", "Workflow ID").description("Resume a paused workflow").action(() => {
94
- console.log("Resume coming in Phase 1");
263
+ program.command("resume").argument("<workflow-id>", "Workflow ID").description("Resume a paused workflow").action(async (workflowId) => {
264
+ try {
265
+ ensureCueclawHome();
266
+ const db = initDb();
267
+ const wf = getWorkflow(db, workflowId);
268
+ if (!wf) {
269
+ console.error(`Workflow not found: ${workflowId}`);
270
+ db.close();
271
+ process.exit(1);
272
+ }
273
+ if (wf.phase !== "paused") {
274
+ console.error(`Cannot resume workflow in phase "${wf.phase}" (must be "paused")`);
275
+ db.close();
276
+ process.exit(1);
277
+ }
278
+ if (wf.trigger.type === "manual") {
279
+ updateWorkflowPhase(db, workflowId, "executing");
280
+ console.log(`Executing workflow "${wf.name}"...`);
281
+ const { executeWorkflow } = await import("./executor-LS3Y4DO5.js");
282
+ const result = await executeWorkflow({
283
+ workflow: { ...wf, phase: "executing" },
284
+ triggerData: null,
285
+ db,
286
+ cwd: process.cwd(),
287
+ onProgress: (stepId, msg) => {
288
+ if (msg?.status) console.log(` [${stepId}] ${msg.status}`);
289
+ }
290
+ });
291
+ console.log(`Workflow ${result.status}. Run ID: ${result.runId}`);
292
+ } else {
293
+ updateWorkflowPhase(db, workflowId, "active");
294
+ console.log(`Resumed workflow "${wf.name}" (${workflowId})`);
295
+ }
296
+ db.close();
297
+ } catch (err) {
298
+ logger.error({ err }, "Failed to resume workflow");
299
+ process.exit(1);
300
+ }
95
301
  });
96
- program.command("delete").argument("<workflow-id>", "Workflow ID").description("Delete a workflow").action(() => {
97
- console.log("Delete coming in Phase 1");
302
+ program.command("delete").argument("<workflow-id>", "Workflow ID").description("Delete a workflow").action(async (workflowId) => {
303
+ try {
304
+ ensureCueclawHome();
305
+ const db = initDb();
306
+ const wf = getWorkflow(db, workflowId);
307
+ if (!wf) {
308
+ console.error(`Workflow not found: ${workflowId}`);
309
+ db.close();
310
+ process.exit(1);
311
+ }
312
+ if (wf.phase === "executing") {
313
+ console.error(`Cannot delete workflow while it is executing`);
314
+ db.close();
315
+ process.exit(1);
316
+ }
317
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
318
+ const answer = await new Promise((resolve) => {
319
+ rl.question(`Delete workflow "${wf.name}" (${workflowId})? (y/N) `, resolve);
320
+ });
321
+ rl.close();
322
+ if (answer.toLowerCase() !== "y") {
323
+ console.log("Cancelled.");
324
+ db.close();
325
+ return;
326
+ }
327
+ deleteWorkflow(db, workflowId);
328
+ console.log(`Deleted workflow "${wf.name}" (${workflowId})`);
329
+ db.close();
330
+ } catch (err) {
331
+ logger.error({ err }, "Failed to delete workflow");
332
+ process.exit(1);
333
+ }
98
334
  });
99
335
  var daemonCmd = program.command("daemon").description("Manage background daemon");
100
336
  daemonCmd.command("start").option("--detach", "Run in background").description("Start the daemon").action(async () => {
101
337
  try {
102
- const { startDaemon } = await import("./daemon-TWVEMRCU.js");
338
+ const { startDaemon } = await import("./daemon-R3LU23PR.js");
103
339
  await startDaemon();
104
340
  } catch (err) {
105
341
  logger.error({ err }, "Daemon failed");
106
342
  process.exit(1);
107
343
  }
108
344
  });
109
- daemonCmd.command("stop").description("Stop the daemon").action(() => {
110
- console.log("Use launchctl unload (macOS) or systemctl --user stop cueclaw (Linux)");
345
+ daemonCmd.command("stop").description("Stop the daemon").action(async () => {
346
+ const { getServiceStatus, stopService } = await import("./service-VTUYSAAZ.js");
347
+ const status = getServiceStatus();
348
+ if (status !== "running") {
349
+ console.log("Daemon is not running.");
350
+ return;
351
+ }
352
+ const result = stopService();
353
+ if (result.success) {
354
+ console.log("Daemon stopped.");
355
+ } else {
356
+ console.log(`Failed to stop daemon: ${result.error}`);
357
+ process.exit(1);
358
+ }
111
359
  });
112
360
  daemonCmd.command("install").description("Install system service").action(async () => {
113
- const { installService } = await import("./service-BHFOM6E2.js");
361
+ const { installService } = await import("./service-VTUYSAAZ.js");
114
362
  const result = installService();
115
363
  if (result.success) {
116
364
  console.log("Service installed successfully.");
@@ -120,7 +368,7 @@ daemonCmd.command("install").description("Install system service").action(async
120
368
  }
121
369
  });
122
370
  daemonCmd.command("uninstall").description("Remove system service").action(async () => {
123
- const { uninstallService } = await import("./service-BHFOM6E2.js");
371
+ const { uninstallService } = await import("./service-VTUYSAAZ.js");
124
372
  const result = uninstallService();
125
373
  if (result.success) {
126
374
  console.log("Service uninstalled successfully.");
@@ -130,16 +378,16 @@ daemonCmd.command("uninstall").description("Remove system service").action(async
130
378
  }
131
379
  });
132
380
  daemonCmd.command("status").description("View daemon status").action(async () => {
133
- const { getServiceStatus } = await import("./service-BHFOM6E2.js");
381
+ const { getServiceStatus } = await import("./service-VTUYSAAZ.js");
134
382
  const status = getServiceStatus();
135
383
  console.log(`Daemon status: ${status}`);
136
384
  });
137
385
  daemonCmd.command("logs").description("View daemon logs").action(async () => {
138
386
  const { join } = await import("path");
139
- const { cueclawHome } = await import("./config-HMHM7UAZ.js");
140
- const logPath = join(cueclawHome(), "logs", "daemon.log");
141
- const { existsSync: existsSync2 } = await import("fs");
142
- if (!existsSync2(logPath)) {
387
+ const { cueclawHome: cueclawHome2 } = await import("./config-6NWFKNLW.js");
388
+ const logPath = join(cueclawHome2(), "logs", "daemon.log");
389
+ const { existsSync } = await import("fs");
390
+ if (!existsSync(logPath)) {
143
391
  console.log("No daemon log file found.");
144
392
  return;
145
393
  }
@@ -151,10 +399,10 @@ botCmd.command("start").description("Start all configured bot channels").action(
151
399
  try {
152
400
  const config = loadConfig();
153
401
  const db = initDb();
154
- const { MessageRouter } = await import("./router-36O66FDW.js");
402
+ const { MessageRouter } = await import("./router-KEZ3YQXC.js");
155
403
  const router = new MessageRouter(db, config, process.cwd());
156
404
  if (config.whatsapp?.enabled) {
157
- const { WhatsAppChannel } = await import("./whatsapp-36XWDSJ5.js");
405
+ const { WhatsAppChannel } = await import("./whatsapp-HFMOFSFI.js");
158
406
  const wa = new WhatsAppChannel(
159
407
  config.whatsapp.auth_dir ?? `${process.env["HOME"]}/.cueclaw/auth/whatsapp`,
160
408
  config.whatsapp.allowed_jids ?? [],
@@ -165,7 +413,7 @@ botCmd.command("start").description("Start all configured bot channels").action(
165
413
  logger.info("WhatsApp channel started");
166
414
  }
167
415
  if (config.telegram?.enabled) {
168
- const { TelegramChannel } = await import("./telegram-BTTWEETO.js");
416
+ const { TelegramChannel } = await import("./telegram-P6DBJ7WZ.js");
169
417
  const tg = new TelegramChannel(
170
418
  config.telegram.token,
171
419
  config.telegram.allowed_users ?? [],
@@ -173,6 +421,7 @@ botCmd.command("start").description("Start all configured bot channels").action(
173
421
  );
174
422
  router.registerChannel(tg);
175
423
  await tg.connect();
424
+ tg.onCallback((wfId, action, chatId) => router.handleCallbackAction("telegram", chatId, wfId, action));
176
425
  logger.info("Telegram channel started");
177
426
  }
178
427
  router.start();
@@ -190,30 +439,35 @@ botCmd.command("status").description("View channel connection status").action(()
190
439
  program.command("setup").description("First-run setup: validate Docker, build container, smoke test").action(async () => {
191
440
  try {
192
441
  const config = loadConfig();
193
- const { runSetup } = await import("./setup-QZUEJUIN.js");
442
+ const { runSetup } = await import("./setup-NWBKTQCO.js");
194
443
  await runSetup(config, process.cwd());
195
444
  } catch (err) {
196
445
  logger.error({ err }, "Setup failed");
197
446
  process.exit(1);
198
447
  }
199
448
  });
200
- program.command("tui").description("Start interactive TUI").option("--no-banner", "Skip the startup banner").action(async (opts) => {
449
+ program.command("tui").description("Start interactive TUI").option("--skip-onboarding", "Skip first-run onboarding wizard").action(async (opts) => {
201
450
  try {
451
+ const { enableTuiLogging } = await import("./logger-HD23RPWS.js");
452
+ enableTuiLogging();
202
453
  const React = await import("react");
203
454
  const { render } = await import("ink");
204
- const { App } = await import("./app-UJ4M3TPW.js");
205
- render(React.createElement(App, { noBanner: opts.banner === false, cwd: process.cwd() }));
455
+ const { App } = await import("./app-DIUXV4XR.js");
456
+ render(React.createElement(App, { cwd: process.cwd(), skipOnboarding: opts.skipOnboarding }));
206
457
  } catch (err) {
207
458
  logger.error({ err }, "Failed to start TUI");
208
459
  process.exit(1);
209
460
  }
210
461
  });
211
- program.action(async () => {
462
+ program.option("--skip-onboarding", "Skip first-run onboarding wizard").action(async (_opts, cmd) => {
463
+ const skipOnboarding = cmd.opts().skipOnboarding;
212
464
  try {
465
+ const { enableTuiLogging } = await import("./logger-HD23RPWS.js");
466
+ enableTuiLogging();
213
467
  const React = await import("react");
214
468
  const { render } = await import("ink");
215
- const { App } = await import("./app-UJ4M3TPW.js");
216
- render(React.createElement(App, { cwd: process.cwd() }));
469
+ const { App } = await import("./app-DIUXV4XR.js");
470
+ render(React.createElement(App, { cwd: process.cwd(), skipOnboarding }));
217
471
  } catch (err) {
218
472
  logger.error({ err }, "Failed to start TUI");
219
473
  process.exit(1);
@@ -0,0 +1,21 @@
1
+ import {
2
+ createDefaultConfig,
3
+ cueclawHome,
4
+ ensureCueclawHome,
5
+ loadConfig,
6
+ loadExistingConfig,
7
+ needsOnboarding,
8
+ validateConfig,
9
+ writeConfig
10
+ } from "./chunk-RSKXBXSJ.js";
11
+ import "./chunk-BVQG3WYO.js";
12
+ export {
13
+ createDefaultConfig,
14
+ cueclawHome,
15
+ ensureCueclawHome,
16
+ loadConfig,
17
+ loadExistingConfig,
18
+ needsOnboarding,
19
+ validateConfig,
20
+ writeConfig
21
+ };
@@ -0,0 +1,95 @@
1
+ import {
2
+ TriggerLoop
3
+ } from "./chunk-W274JWEK.js";
4
+ import {
5
+ MessageRouter
6
+ } from "./chunk-F3EQAFH4.js";
7
+ import "./chunk-WE5J7GMR.js";
8
+ import "./chunk-DVQFSFIZ.js";
9
+ import "./chunk-ZCK3IFLC.js";
10
+ import "./chunk-SEYPA5M2.js";
11
+ import {
12
+ initDb
13
+ } from "./chunk-G43R5ASK.js";
14
+ import {
15
+ loadConfig
16
+ } from "./chunk-RSKXBXSJ.js";
17
+ import "./chunk-BVQG3WYO.js";
18
+ import {
19
+ logger
20
+ } from "./chunk-QBOYMF4A.js";
21
+
22
+ // src/daemon.ts
23
+ async function startDaemon() {
24
+ const config = loadConfig();
25
+ const db = initDb();
26
+ const cwd = process.cwd();
27
+ const router = new MessageRouter(db, config, cwd);
28
+ if (config.whatsapp?.enabled) {
29
+ try {
30
+ const { WhatsAppChannel } = await import("./whatsapp-HFMOFSFI.js");
31
+ const wa = new WhatsAppChannel(
32
+ config.whatsapp.auth_dir ?? `${process.env["HOME"]}/.cueclaw/auth/whatsapp`,
33
+ config.whatsapp.allowed_jids ?? [],
34
+ (jid, msg) => router.handleInbound("whatsapp", jid, msg)
35
+ );
36
+ router.registerChannel(wa);
37
+ await wa.connect();
38
+ logger.info("WhatsApp channel started");
39
+ } catch (err) {
40
+ logger.error({ err }, "Failed to start WhatsApp channel");
41
+ }
42
+ }
43
+ if (config.telegram?.enabled) {
44
+ try {
45
+ const { TelegramChannel } = await import("./telegram-P6DBJ7WZ.js");
46
+ const tg = new TelegramChannel(
47
+ config.telegram.token,
48
+ config.telegram.allowed_users ?? [],
49
+ (jid, msg) => router.handleInbound("telegram", jid, msg)
50
+ );
51
+ router.registerChannel(tg);
52
+ await tg.connect();
53
+ tg.onCallback((wfId, action, chatId) => router.handleCallbackAction("telegram", chatId, wfId, action));
54
+ logger.info("Telegram channel started");
55
+ } catch (err) {
56
+ logger.error({ err }, "Failed to start Telegram channel");
57
+ }
58
+ }
59
+ await recoverRunningWorkflows(db, router);
60
+ const maxConcurrent = 5;
61
+ const triggerLoop = new TriggerLoop(db, router, cwd, maxConcurrent);
62
+ triggerLoop.start();
63
+ router.start();
64
+ logger.info("Daemon started");
65
+ const shutdown = () => {
66
+ logger.info("Shutting down daemon...");
67
+ triggerLoop.stop();
68
+ router.stop();
69
+ db.close();
70
+ process.exit(0);
71
+ };
72
+ process.on("SIGTERM", shutdown);
73
+ process.on("SIGINT", shutdown);
74
+ }
75
+ async function recoverRunningWorkflows(db, router) {
76
+ const interruptedRuns = db.prepare(
77
+ "SELECT id, workflow_id FROM workflow_runs WHERE status = 'running'"
78
+ ).all();
79
+ if (interruptedRuns.length === 0) return;
80
+ logger.warn({ count: interruptedRuns.length }, "Recovering interrupted workflow runs");
81
+ for (const run of interruptedRuns) {
82
+ db.prepare(
83
+ "UPDATE workflow_runs SET status = 'failed', error = ?, completed_at = ? WHERE id = ?"
84
+ ).run("Daemon restarted during execution", (/* @__PURE__ */ new Date()).toISOString(), run.id);
85
+ db.prepare(
86
+ "UPDATE step_runs SET status = 'failed', error = ? WHERE run_id = ? AND status = 'running'"
87
+ ).run("Daemon restarted during execution", run.id);
88
+ router.broadcastNotification(
89
+ `Workflow ${run.workflow_id} was interrupted by daemon restart (run ${run.id})`
90
+ );
91
+ }
92
+ }
93
+ export {
94
+ startDaemon
95
+ };
@@ -0,0 +1,16 @@
1
+ import {
2
+ getConfiguredSecretKeys,
3
+ getSecret,
4
+ hasSecret,
5
+ isDev,
6
+ loadSecrets,
7
+ writeEnvVar
8
+ } from "./chunk-ZCK3IFLC.js";
9
+ export {
10
+ getConfiguredSecretKeys,
11
+ getSecret,
12
+ hasSecret,
13
+ isDev,
14
+ loadSecrets,
15
+ writeEnvVar
16
+ };
@@ -0,0 +1,14 @@
1
+ import {
2
+ executeWorkflow,
3
+ resolveInputs,
4
+ resolveValue
5
+ } from "./chunk-SEYPA5M2.js";
6
+ import "./chunk-G43R5ASK.js";
7
+ import "./chunk-RSKXBXSJ.js";
8
+ import "./chunk-BVQG3WYO.js";
9
+ import "./chunk-QBOYMF4A.js";
10
+ export {
11
+ executeWorkflow,
12
+ resolveInputs,
13
+ resolveValue
14
+ };
@@ -0,0 +1,12 @@
1
+ import {
2
+ createChildLogger,
3
+ enableTuiLogging,
4
+ logger,
5
+ onLogLine
6
+ } from "./chunk-QBOYMF4A.js";
7
+ export {
8
+ createChildLogger,
9
+ enableTuiLogging,
10
+ logger,
11
+ onLogLine
12
+ };
@@ -0,0 +1,28 @@
1
+ import {
2
+ PlannerOutputSchema,
3
+ askQuestionTool,
4
+ buildPlannerSystemPrompt,
5
+ confirmPlan,
6
+ generatePlan,
7
+ modifyPlan,
8
+ parsePlannerToolResponse,
9
+ plannerTool,
10
+ rejectPlan,
11
+ setSecretTool
12
+ } from "./chunk-WE5J7GMR.js";
13
+ import "./chunk-DVQFSFIZ.js";
14
+ import "./chunk-ZCK3IFLC.js";
15
+ import "./chunk-BVQG3WYO.js";
16
+ import "./chunk-QBOYMF4A.js";
17
+ export {
18
+ PlannerOutputSchema,
19
+ askQuestionTool,
20
+ buildPlannerSystemPrompt,
21
+ confirmPlan,
22
+ generatePlan,
23
+ modifyPlan,
24
+ parsePlannerToolResponse,
25
+ plannerTool as plannerCreateWorkflowTool,
26
+ rejectPlan,
27
+ setSecretTool
28
+ };
@@ -0,0 +1,14 @@
1
+ import {
2
+ MessageRouter
3
+ } from "./chunk-F3EQAFH4.js";
4
+ import "./chunk-WE5J7GMR.js";
5
+ import "./chunk-DVQFSFIZ.js";
6
+ import "./chunk-ZCK3IFLC.js";
7
+ import "./chunk-SEYPA5M2.js";
8
+ import "./chunk-G43R5ASK.js";
9
+ import "./chunk-RSKXBXSJ.js";
10
+ import "./chunk-BVQG3WYO.js";
11
+ import "./chunk-QBOYMF4A.js";
12
+ export {
13
+ MessageRouter
14
+ };
@@ -0,0 +1,15 @@
1
+ import {
2
+ getServiceStatus,
3
+ installService,
4
+ stopService,
5
+ uninstallService
6
+ } from "./chunk-PZZ6FBGB.js";
7
+ import "./chunk-RSKXBXSJ.js";
8
+ import "./chunk-BVQG3WYO.js";
9
+ import "./chunk-QBOYMF4A.js";
10
+ export {
11
+ getServiceStatus,
12
+ installService,
13
+ stopService,
14
+ uninstallService
15
+ };