cronies-cli 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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +33 -0
  3. package/dist/bin/cronies.d.ts +3 -0
  4. package/dist/bin/cronies.d.ts.map +1 -0
  5. package/dist/chunk-FVB2S2MS.js +4229 -0
  6. package/dist/cronies.js +331 -0
  7. package/dist/index.js +189 -0
  8. package/dist/src/adapters/index.d.ts +2 -0
  9. package/dist/src/adapters/index.d.ts.map +1 -0
  10. package/dist/src/adapters/manager.d.ts +6 -0
  11. package/dist/src/adapters/manager.d.ts.map +1 -0
  12. package/dist/src/cli/index.d.ts +3 -0
  13. package/dist/src/cli/index.d.ts.map +1 -0
  14. package/dist/src/config/index.d.ts +4 -0
  15. package/dist/src/config/index.d.ts.map +1 -0
  16. package/dist/src/config/loader.d.ts +13 -0
  17. package/dist/src/config/loader.d.ts.map +1 -0
  18. package/dist/src/config/schema.d.ts +160 -0
  19. package/dist/src/config/schema.d.ts.map +1 -0
  20. package/dist/src/config/writer.d.ts +17 -0
  21. package/dist/src/config/writer.d.ts.map +1 -0
  22. package/dist/src/daemon.d.ts +11 -0
  23. package/dist/src/daemon.d.ts.map +1 -0
  24. package/dist/src/index.d.ts +14 -0
  25. package/dist/src/index.d.ts.map +1 -0
  26. package/dist/src/logger.d.ts +13 -0
  27. package/dist/src/logger.d.ts.map +1 -0
  28. package/dist/src/orchestrator/health.d.ts +20 -0
  29. package/dist/src/orchestrator/health.d.ts.map +1 -0
  30. package/dist/src/orchestrator/index.d.ts +2 -0
  31. package/dist/src/orchestrator/index.d.ts.map +1 -0
  32. package/dist/src/orchestrator/runner.d.ts +102 -0
  33. package/dist/src/orchestrator/runner.d.ts.map +1 -0
  34. package/dist/src/orchestrator/summary.d.ts +19 -0
  35. package/dist/src/orchestrator/summary.d.ts.map +1 -0
  36. package/dist/src/pid.d.ts +20 -0
  37. package/dist/src/pid.d.ts.map +1 -0
  38. package/dist/src/policy/engine.d.ts +41 -0
  39. package/dist/src/policy/engine.d.ts.map +1 -0
  40. package/dist/src/policy/index.d.ts +2 -0
  41. package/dist/src/policy/index.d.ts.map +1 -0
  42. package/dist/src/server.d.ts +8 -0
  43. package/dist/src/server.d.ts.map +1 -0
  44. package/dist/src/sessionHealthMonitor.d.ts +29 -0
  45. package/dist/src/sessionHealthMonitor.d.ts.map +1 -0
  46. package/dist/src/storage/database.d.ts +3 -0
  47. package/dist/src/storage/database.d.ts.map +1 -0
  48. package/dist/src/storage/index.d.ts +4 -0
  49. package/dist/src/storage/index.d.ts.map +1 -0
  50. package/dist/src/storage/migrations.d.ts +3 -0
  51. package/dist/src/storage/migrations.d.ts.map +1 -0
  52. package/dist/src/storage/store.d.ts +80 -0
  53. package/dist/src/storage/store.d.ts.map +1 -0
  54. package/dist/src/sync/connection.d.ts +37 -0
  55. package/dist/src/sync/connection.d.ts.map +1 -0
  56. package/dist/src/sync/index.d.ts +7 -0
  57. package/dist/src/sync/index.d.ts.map +1 -0
  58. package/dist/src/sync/queue.d.ts +22 -0
  59. package/dist/src/sync/queue.d.ts.map +1 -0
  60. package/dist/src/sync/reconciler.d.ts +42 -0
  61. package/dist/src/sync/reconciler.d.ts.map +1 -0
  62. package/dist/src/sync/rest-client.d.ts +62 -0
  63. package/dist/src/sync/rest-client.d.ts.map +1 -0
  64. package/package.json +60 -0
@@ -0,0 +1,331 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ ClaudeCodeAdapter,
4
+ CodexCliAdapter,
5
+ CursorAgentAdapter,
6
+ GeminiCliAdapter,
7
+ createLogger,
8
+ getDefaultConfigPath,
9
+ isDaemonRunning,
10
+ loadConfig,
11
+ readPidFile,
12
+ removePidFile,
13
+ resolveDataDir,
14
+ startDaemon,
15
+ writeConfigToken
16
+ } from "./chunk-FVB2S2MS.js";
17
+
18
+ // src/cli/index.ts
19
+ import { Command } from "commander";
20
+ import { mkdirSync, writeFileSync } from "fs";
21
+ import { join } from "path";
22
+ import { stringify as toYaml } from "yaml";
23
+ var AGENT_LABELS = {
24
+ "claude-code": "Claude Code",
25
+ "codex-cli": "Codex",
26
+ "gemini-cli": "Gemini",
27
+ "cursor-agent": "Cursor Agent"
28
+ };
29
+ async function runAgentAuthPreFlight() {
30
+ const adapters = [
31
+ new ClaudeCodeAdapter(),
32
+ new CodexCliAdapter(),
33
+ new GeminiCliAdapter(),
34
+ new CursorAgentAdapter()
35
+ ];
36
+ console.log("");
37
+ console.log("Checking agents...");
38
+ const results = await Promise.allSettled(
39
+ adapters.map(async (adapter) => {
40
+ const available = await adapter.isAvailable();
41
+ if (!available) return { adapter, available: false };
42
+ const auth = await adapter.checkAuth({ skipAvailabilityCheck: true });
43
+ return { adapter, available: true, auth };
44
+ })
45
+ );
46
+ let readyCount = 0;
47
+ let installedCount = 0;
48
+ const needsAuth = [];
49
+ for (const result of results) {
50
+ if (result.status === "rejected") continue;
51
+ const { adapter, available } = result.value;
52
+ const label = AGENT_LABELS[adapter.name] ?? adapter.name;
53
+ if (!available) {
54
+ console.log(` ${label}: not installed`);
55
+ continue;
56
+ }
57
+ installedCount++;
58
+ const authResult = result.value.auth;
59
+ switch (authResult.status) {
60
+ case "authenticated":
61
+ console.log(` ${label}: \u2713 authenticated`);
62
+ readyCount++;
63
+ break;
64
+ case "needs_auth":
65
+ console.log(` ${label}: \u2717 needs authentication`);
66
+ if (authResult.authCommand) {
67
+ console.log(` \u2192 Run: ${authResult.authCommand}`);
68
+ }
69
+ needsAuth.push({ name: adapter.name, label, authCommand: authResult.authCommand });
70
+ break;
71
+ case "error":
72
+ console.log(` ${label}: ? error (${authResult.error ?? "unknown"})`);
73
+ readyCount++;
74
+ break;
75
+ default:
76
+ break;
77
+ }
78
+ }
79
+ if (needsAuth.length > 0) {
80
+ console.log("");
81
+ for (const agent of needsAuth) {
82
+ if (!agent.authCommand) continue;
83
+ console.log(` Running auth for ${agent.label}...`);
84
+ try {
85
+ const { execSync } = await import("child_process");
86
+ execSync(agent.authCommand, { stdio: "inherit", timeout: 12e4 });
87
+ const adapter = adapters.find((a) => a.name === agent.name);
88
+ if (adapter) {
89
+ const recheck = await adapter.checkAuth();
90
+ if (recheck.status === "authenticated") {
91
+ console.log(` ${agent.label}: \u2713 authenticated`);
92
+ readyCount++;
93
+ } else {
94
+ console.log(` ${agent.label}: still needs authentication`);
95
+ }
96
+ }
97
+ } catch {
98
+ console.log(` ${agent.label}: auth command failed or timed out`);
99
+ }
100
+ }
101
+ }
102
+ console.log("");
103
+ if (readyCount === 0 && installedCount === 0) {
104
+ console.log(" No agents installed. Install at least one:");
105
+ console.log(" Claude Code: npm install -g @anthropic-ai/claude-code");
106
+ console.log(" Codex: npm install -g @openai/codex");
107
+ console.log(" Gemini: npm install -g @google/gemini-cli");
108
+ console.log("");
109
+ } else if (readyCount === 0) {
110
+ console.log(` ${installedCount} agent(s) installed but none authenticated.`);
111
+ console.log(" The daemon will start but sessions may fail until agents are authenticated.");
112
+ console.log("");
113
+ } else {
114
+ console.log(` ${readyCount} agent(s) ready.`);
115
+ console.log("");
116
+ }
117
+ }
118
+ var program = new Command().name("cronies").description("The outcome and coordination layer for autonomous engineering work").version("0.1.0");
119
+ program.command("start").description("Start the Cronies daemon").option("-f, --foreground", "Run in foreground (don't daemonize)").option("-p, --port <port>", "API port", "7890").option("-c, --config <path>", "Config file path").option("--skip-auth-check", "Skip agent authentication pre-flight check").action(async (options) => {
120
+ const config = loadConfig(options.config);
121
+ const port = Number.parseInt(options.port, 10);
122
+ if (!Number.isNaN(port)) {
123
+ config.daemon.port = port;
124
+ }
125
+ const dataDir = resolveDataDir(config);
126
+ if (isDaemonRunning(dataDir)) {
127
+ const pid = readPidFile(dataDir);
128
+ console.error(`Cronies daemon is already running (PID ${pid}).`);
129
+ process.exit(1);
130
+ }
131
+ if (!options.skipAuthCheck) {
132
+ await runAgentAuthPreFlight();
133
+ }
134
+ const logger = createLogger(config.daemon.logLevel);
135
+ if (!options.foreground) {
136
+ logger.warn("Background mode not yet implemented, running in foreground.");
137
+ }
138
+ await startDaemon(config, logger);
139
+ });
140
+ program.command("stop").description("Stop the running daemon").option("-c, --config <path>", "Config file path").action(async (options) => {
141
+ const config = loadConfig(options.config);
142
+ const dataDir = resolveDataDir(config);
143
+ const pid = readPidFile(dataDir);
144
+ if (pid === null) {
145
+ console.error("No daemon PID file found. Is the daemon running?");
146
+ process.exit(1);
147
+ }
148
+ if (!isDaemonRunning(dataDir)) {
149
+ console.log("Daemon is not running. Cleaning up stale PID file.");
150
+ removePidFile(dataDir);
151
+ return;
152
+ }
153
+ console.log(`Sending SIGTERM to daemon (PID ${pid})...`);
154
+ try {
155
+ process.kill(pid, "SIGTERM");
156
+ } catch {
157
+ console.error(`Failed to send SIGTERM to PID ${pid}.`);
158
+ process.exit(1);
159
+ }
160
+ const deadline = Date.now() + 5e3;
161
+ const poll = () => new Promise((resolve) => {
162
+ const check = () => {
163
+ if (!isDaemonRunning(dataDir)) {
164
+ resolve();
165
+ return;
166
+ }
167
+ if (Date.now() >= deadline) {
168
+ console.log("Daemon did not stop in time. Sending SIGKILL...");
169
+ try {
170
+ process.kill(pid, "SIGKILL");
171
+ } catch {
172
+ }
173
+ resolve();
174
+ return;
175
+ }
176
+ setTimeout(check, 250);
177
+ };
178
+ check();
179
+ });
180
+ await poll();
181
+ removePidFile(dataDir);
182
+ console.log("Daemon stopped.");
183
+ });
184
+ program.command("status").description("Show daemon status").option("-c, --config <path>", "Config file path").action(async (options) => {
185
+ const config = loadConfig(options.config);
186
+ const dataDir = resolveDataDir(config);
187
+ const pid = readPidFile(dataDir);
188
+ if (pid === null || !isDaemonRunning(dataDir)) {
189
+ console.log("Status: stopped");
190
+ if (pid !== null) {
191
+ console.log(`(Stale PID file for PID ${pid} exists. Run "cronies stop" to clean up.)`);
192
+ }
193
+ return;
194
+ }
195
+ console.log(`Status: running`);
196
+ console.log(`PID: ${pid}`);
197
+ console.log(`Port: ${config.daemon.port}`);
198
+ console.log(`Data: ${dataDir}`);
199
+ console.log(`Cloud: ${config.cloud.token ? "connected" : "not connected (no token)"}`);
200
+ });
201
+ program.command("login").description("Authenticate with Cronies cloud").option("-c, --config <path>", "Config file path").option("--cloud-url <url>", "Cloud dashboard URL").action(async (options) => {
202
+ const config = loadConfig(options.config);
203
+ const cloudUrl = (options.cloudUrl ?? config.cloud.url).replace(/\/$/, "");
204
+ console.log(`Connecting to ${cloudUrl}...`);
205
+ let deviceCode;
206
+ try {
207
+ const res = await fetch(`${cloudUrl}/api/auth/device`, { method: "POST" });
208
+ if (!res.ok) {
209
+ console.error(`Failed to initiate login (HTTP ${res.status}). Is the cloud URL correct?`);
210
+ process.exit(1);
211
+ }
212
+ const data = await res.json();
213
+ deviceCode = data.deviceCode;
214
+ } catch (err) {
215
+ console.error(`Could not reach ${cloudUrl}. Check your internet connection and cloud URL.`);
216
+ process.exit(1);
217
+ }
218
+ console.log("");
219
+ console.log(` Code: ${deviceCode}`);
220
+ console.log("");
221
+ console.log(" Opening browser for authorization...");
222
+ console.log(` If it doesn't open, visit: ${cloudUrl}/device?code=${deviceCode}`);
223
+ console.log("");
224
+ const verifyUrl = `${cloudUrl}/device?code=${deviceCode}`;
225
+ try {
226
+ const { exec } = await import("child_process");
227
+ const platform = process.platform;
228
+ if (platform === "win32") {
229
+ exec(`start "" "${verifyUrl}"`);
230
+ } else if (platform === "darwin") {
231
+ exec(`open "${verifyUrl}"`);
232
+ } else {
233
+ exec(`xdg-open "${verifyUrl}"`);
234
+ }
235
+ } catch {
236
+ }
237
+ console.log(" Waiting for authorization...");
238
+ const pollInterval = 2e3;
239
+ const maxWait = 15 * 60 * 1e3;
240
+ const startTime = Date.now();
241
+ while (Date.now() - startTime < maxWait) {
242
+ await new Promise((r) => setTimeout(r, pollInterval));
243
+ try {
244
+ const res = await fetch(`${cloudUrl}/api/auth/device/token`, {
245
+ method: "POST",
246
+ headers: { "Content-Type": "application/json" },
247
+ body: JSON.stringify({ deviceCode })
248
+ });
249
+ if (!res.ok) continue;
250
+ const data = await res.json();
251
+ if (data.status === "authorized" && data.token) {
252
+ const configPath = options.config ?? getDefaultConfigPath();
253
+ writeConfigToken(data.token, configPath);
254
+ console.log("");
255
+ console.log(` \u2713 Authenticated successfully!`);
256
+ console.log(` Token saved to ${configPath}`);
257
+ console.log("");
258
+ console.log(" Run `cronies start` to begin.");
259
+ return;
260
+ }
261
+ if (data.status === "expired") {
262
+ console.error("\n Device code expired. Please run `cronies login` again.");
263
+ process.exit(1);
264
+ }
265
+ process.stdout.write(".");
266
+ } catch {
267
+ process.stdout.write("x");
268
+ }
269
+ }
270
+ console.error("\n Timed out waiting for authorization. Please run `cronies login` again.");
271
+ process.exit(1);
272
+ });
273
+ program.command("config").description("Show current configuration").option("-c, --config <path>", "Config file path").option("-e, --edit", "Open config in $EDITOR").action(async (options) => {
274
+ if (options.edit) {
275
+ const editor = process.env["EDITOR"] || process.env["VISUAL"];
276
+ if (!editor) {
277
+ console.error("No $EDITOR set. Set the EDITOR environment variable and try again.");
278
+ process.exit(1);
279
+ }
280
+ const { execSync } = await import("child_process");
281
+ const configPath = options.config ?? join(resolveDataDir(loadConfig(options.config)), "config.yaml");
282
+ try {
283
+ execSync(`${editor} "${configPath}"`, { stdio: "inherit" });
284
+ } catch {
285
+ console.error(`Failed to open editor: ${editor}`);
286
+ process.exit(1);
287
+ }
288
+ return;
289
+ }
290
+ const config = loadConfig(options.config);
291
+ console.log(toYaml(config));
292
+ });
293
+ program.command("jobs").description("List active jobs").action(async () => {
294
+ console.log("Connect daemon first with: cronies start");
295
+ });
296
+ program.command("runs").description("Show recent runs").argument("[runId]", "Specific run ID for details").action(async (runId) => {
297
+ if (runId) {
298
+ console.log(`Run details for ${runId} not yet implemented.`);
299
+ } else {
300
+ console.log("Recent runs not yet implemented. Start the daemon first: cronies start");
301
+ }
302
+ });
303
+ var EXAMPLE_JOB_YAML = `# Example Cronies job definition
304
+ name: Example Maintenance Job
305
+ prompt: |
306
+ Check for any TODO comments in the codebase and create a summary.
307
+ List files with TODOs and the TODO text.
308
+ schedule:
309
+ type: manual
310
+ preferredAgent: claude-code
311
+ workingDirectory: .
312
+ maxAttempts: 3
313
+ timeout: 300000
314
+ `;
315
+ program.command("init").description("Initialize Cronies in current directory").action(async () => {
316
+ const croniesDir = join(process.cwd(), ".cronies");
317
+ const jobsDir = join(croniesDir, "jobs");
318
+ mkdirSync(jobsDir, { recursive: true });
319
+ const examplePath = join(jobsDir, "example.yaml");
320
+ writeFileSync(examplePath, EXAMPLE_JOB_YAML, "utf-8");
321
+ console.log("Initialized Cronies in current directory:");
322
+ console.log(` .cronies/`);
323
+ console.log(` .cronies/jobs/`);
324
+ console.log(` .cronies/jobs/example.yaml`);
325
+ console.log("");
326
+ console.log("Edit .cronies/jobs/example.yaml to define your first job.");
327
+ console.log("Then start the daemon with: cronies start");
328
+ });
329
+
330
+ // bin/cronies.ts
331
+ program.parse();
package/dist/index.js ADDED
@@ -0,0 +1,189 @@
1
+ import {
2
+ DaemonConfigSchema,
3
+ DaemonStore,
4
+ JobRunner,
5
+ LocalPolicyEngine,
6
+ PROTOCOL_VERSION,
7
+ SessionHealthMonitor,
8
+ SyncQueue,
9
+ SyncReconciler,
10
+ createAdapterManager,
11
+ createDatabase,
12
+ createEnvelope,
13
+ createLogger,
14
+ decodeMessage,
15
+ encodeMessage,
16
+ isDaemonRunning,
17
+ loadConfig,
18
+ readPidFile,
19
+ removePidFile,
20
+ resolveDataDir,
21
+ startDaemon,
22
+ writePidFile
23
+ } from "./chunk-FVB2S2MS.js";
24
+
25
+ // src/sync/connection.ts
26
+ import WebSocket from "ws";
27
+ var SyncClient = class {
28
+ ws = null;
29
+ options;
30
+ reconnectAttempts = 0;
31
+ maxReconnectDelay = 3e4;
32
+ heartbeatInterval = null;
33
+ reconnectTimer = null;
34
+ connected = false;
35
+ intentionallyClosed = false;
36
+ constructor(options) {
37
+ this.options = options;
38
+ }
39
+ // -----------------------------------------------------------------------
40
+ // Public API
41
+ // -----------------------------------------------------------------------
42
+ connect() {
43
+ this.intentionallyClosed = false;
44
+ const ws = new WebSocket(this.options.wsUrl, {
45
+ headers: {
46
+ authorization: `Bearer ${this.options.daemonToken}`
47
+ }
48
+ });
49
+ ws.on("open", () => {
50
+ this.ws = ws;
51
+ this.connected = true;
52
+ this.reconnectAttempts = 0;
53
+ this.send({
54
+ ...createEnvelope("daemon:hello", {}),
55
+ type: "daemon:hello",
56
+ daemonId: this.options.daemonId,
57
+ lastCloudSeq: 0,
58
+ // TODO: read from store
59
+ protocolVersion: PROTOCOL_VERSION,
60
+ daemonVersion: this.options.daemonVersion,
61
+ hostname: this.options.hostname
62
+ });
63
+ this.startHeartbeat();
64
+ this.options.onConnected();
65
+ });
66
+ ws.on("message", (data) => {
67
+ try {
68
+ const raw = typeof data === "string" ? data : data.toString();
69
+ const message = decodeMessage(raw);
70
+ if (message.type.startsWith("cloud:")) {
71
+ this.options.onMessage(message);
72
+ }
73
+ } catch (err) {
74
+ console.error("[sync:connection] Failed to decode message:", err);
75
+ }
76
+ });
77
+ ws.on("close", (_code, _reason) => {
78
+ this.handleDisconnect();
79
+ });
80
+ ws.on("error", (err) => {
81
+ console.error("[sync:connection] WebSocket error:", err.message);
82
+ });
83
+ }
84
+ disconnect() {
85
+ this.intentionallyClosed = true;
86
+ this.stopHeartbeat();
87
+ this.clearReconnectTimer();
88
+ if (this.ws) {
89
+ try {
90
+ this.ws.close(1e3, "Client disconnect");
91
+ } catch {
92
+ }
93
+ this.ws = null;
94
+ }
95
+ this.connected = false;
96
+ }
97
+ /**
98
+ * Send a message to the cloud.
99
+ * Returns true if the message was sent, false if not connected.
100
+ * When false, the caller should enqueue the message in the outbox.
101
+ */
102
+ send(message) {
103
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
104
+ return false;
105
+ }
106
+ try {
107
+ this.ws.send(encodeMessage(message));
108
+ return true;
109
+ } catch {
110
+ return false;
111
+ }
112
+ }
113
+ isConnected() {
114
+ return this.connected;
115
+ }
116
+ // -----------------------------------------------------------------------
117
+ // Private
118
+ // -----------------------------------------------------------------------
119
+ handleDisconnect() {
120
+ this.connected = false;
121
+ this.ws = null;
122
+ this.stopHeartbeat();
123
+ this.options.onDisconnected();
124
+ if (!this.intentionallyClosed) {
125
+ this.scheduleReconnect();
126
+ }
127
+ }
128
+ scheduleReconnect() {
129
+ this.clearReconnectTimer();
130
+ const delay = Math.min(
131
+ 1e3 * Math.pow(2, this.reconnectAttempts),
132
+ this.maxReconnectDelay
133
+ );
134
+ this.reconnectAttempts++;
135
+ console.log(
136
+ `[sync:connection] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`
137
+ );
138
+ this.reconnectTimer = setTimeout(() => {
139
+ this.reconnectTimer = null;
140
+ this.connect();
141
+ }, delay);
142
+ }
143
+ clearReconnectTimer() {
144
+ if (this.reconnectTimer !== null) {
145
+ clearTimeout(this.reconnectTimer);
146
+ this.reconnectTimer = null;
147
+ }
148
+ }
149
+ startHeartbeat() {
150
+ this.stopHeartbeat();
151
+ this.heartbeatInterval = setInterval(() => {
152
+ this.send({
153
+ ...createEnvelope("daemon:heartbeat", {}),
154
+ type: "daemon:heartbeat",
155
+ daemonId: this.options.daemonId,
156
+ activeJobs: 0,
157
+ // TODO: get from orchestrator
158
+ cpuUsage: 0,
159
+ memoryUsage: 0
160
+ });
161
+ }, 3e4);
162
+ }
163
+ stopHeartbeat() {
164
+ if (this.heartbeatInterval !== null) {
165
+ clearInterval(this.heartbeatInterval);
166
+ this.heartbeatInterval = null;
167
+ }
168
+ }
169
+ };
170
+ export {
171
+ DaemonConfigSchema,
172
+ DaemonStore,
173
+ JobRunner,
174
+ LocalPolicyEngine,
175
+ SessionHealthMonitor,
176
+ SyncClient,
177
+ SyncQueue,
178
+ SyncReconciler,
179
+ createAdapterManager,
180
+ createDatabase,
181
+ createLogger,
182
+ isDaemonRunning,
183
+ loadConfig,
184
+ readPidFile,
185
+ removePidFile,
186
+ resolveDataDir,
187
+ startDaemon,
188
+ writePidFile
189
+ };
@@ -0,0 +1,2 @@
1
+ export { createAdapterManager } from './manager.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { AdapterManager } from '@cronies/adapters';
2
+ /**
3
+ * Create a pre-configured AdapterManager with all supported agent adapters.
4
+ */
5
+ export declare function createAdapterManager(): AdapterManager;
6
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../src/adapters/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EAKf,MAAM,mBAAmB,CAAC;AAE3B;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,cAAc,CAOrD"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const program: Command;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkIpC,eAAO,MAAM,OAAO,SAGD,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { DaemonConfigSchema, type DaemonConfig } from './schema.js';
2
+ export { loadConfig, resolveDataDir } from './loader.js';
3
+ export { writeConfigToken, getDefaultConfigPath } from './writer.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type DaemonConfig } from './schema.js';
2
+ /**
3
+ * Load and validate daemon configuration.
4
+ *
5
+ * @param configPath - Path to YAML config file. Defaults to `~/.cronies/config.yaml`.
6
+ * @returns Validated daemon configuration with defaults applied.
7
+ */
8
+ export declare function loadConfig(configPath?: string): DaemonConfig;
9
+ /**
10
+ * Resolve the data directory from a daemon config, expanding `~` to the home directory.
11
+ */
12
+ export declare function resolveDataDir(config: DaemonConfig): string;
13
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/config/loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAapE;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,CAoB5D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAE3D"}