@josharsh/demon-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.
- package/LICENSE +21 -0
- package/README.md +130 -0
- package/dist/actions/base.d.ts +4 -0
- package/dist/actions/base.d.ts.map +1 -0
- package/dist/actions/base.js +32 -0
- package/dist/actions/base.js.map +1 -0
- package/dist/actions/file.d.ts +7 -0
- package/dist/actions/file.d.ts.map +1 -0
- package/dist/actions/file.js +35 -0
- package/dist/actions/file.js.map +1 -0
- package/dist/actions/github.d.ts +7 -0
- package/dist/actions/github.d.ts.map +1 -0
- package/dist/actions/github.js +125 -0
- package/dist/actions/github.js.map +1 -0
- package/dist/actions/index.d.ts +5 -0
- package/dist/actions/index.d.ts.map +1 -0
- package/dist/actions/index.js +22 -0
- package/dist/actions/index.js.map +1 -0
- package/dist/actions/log.d.ts +7 -0
- package/dist/actions/log.d.ts.map +1 -0
- package/dist/actions/log.js +30 -0
- package/dist/actions/log.js.map +1 -0
- package/dist/actions/notify.d.ts +11 -0
- package/dist/actions/notify.d.ts.map +1 -0
- package/dist/actions/notify.js +34 -0
- package/dist/actions/notify.js.map +1 -0
- package/dist/actions/script.d.ts +7 -0
- package/dist/actions/script.d.ts.map +1 -0
- package/dist/actions/script.js +46 -0
- package/dist/actions/script.js.map +1 -0
- package/dist/actions/slack.d.ts +7 -0
- package/dist/actions/slack.d.ts.map +1 -0
- package/dist/actions/slack.js +47 -0
- package/dist/actions/slack.js.map +1 -0
- package/dist/actions/webhook.d.ts +7 -0
- package/dist/actions/webhook.d.ts.map +1 -0
- package/dist/actions/webhook.js +41 -0
- package/dist/actions/webhook.js.map +1 -0
- package/dist/adapters/clock.d.ts +3 -0
- package/dist/adapters/clock.d.ts.map +1 -0
- package/dist/adapters/clock.js +8 -0
- package/dist/adapters/clock.js.map +1 -0
- package/dist/adapters/fs-kv.d.ts +3 -0
- package/dist/adapters/fs-kv.d.ts.map +1 -0
- package/dist/adapters/fs-kv.js +34 -0
- package/dist/adapters/fs-kv.js.map +1 -0
- package/dist/adapters/keys.d.ts +3 -0
- package/dist/adapters/keys.d.ts.map +1 -0
- package/dist/adapters/keys.js +17 -0
- package/dist/adapters/keys.js.map +1 -0
- package/dist/commands/ensure-provider.d.ts +7 -0
- package/dist/commands/ensure-provider.d.ts.map +1 -0
- package/dist/commands/ensure-provider.js +121 -0
- package/dist/commands/ensure-provider.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +196 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/inspect.d.ts +7 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +97 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/install.d.ts +3 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +192 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/logs.d.ts +8 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +103 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/providers.d.ts +5 -0
- package/dist/commands/providers.d.ts.map +1 -0
- package/dist/commands/providers.js +251 -0
- package/dist/commands/providers.js.map +1 -0
- package/dist/commands/ps.d.ts +2 -0
- package/dist/commands/ps.d.ts.map +1 -0
- package/dist/commands/ps.js +87 -0
- package/dist/commands/ps.js.map +1 -0
- package/dist/commands/secrets.d.ts +9 -0
- package/dist/commands/secrets.d.ts.map +1 -0
- package/dist/commands/secrets.js +97 -0
- package/dist/commands/secrets.js.map +1 -0
- package/dist/commands/start.d.ts +10 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +238 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +69 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/stop.d.ts +6 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +43 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +253 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/config.d.ts +8 -0
- package/dist/providers/config.d.ts.map +1 -0
- package/dist/providers/config.js +31 -0
- package/dist/providers/config.js.map +1 -0
- package/dist/providers/credentials.d.ts +5 -0
- package/dist/providers/credentials.d.ts.map +1 -0
- package/dist/providers/credentials.js +69 -0
- package/dist/providers/credentials.js.map +1 -0
- package/dist/providers/registry.d.ts +12 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +58 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/secrets.d.ts +9 -0
- package/dist/providers/secrets.d.ts.map +1 -0
- package/dist/providers/secrets.js +44 -0
- package/dist/providers/secrets.js.map +1 -0
- package/dist/providers/system-auth.d.ts +8 -0
- package/dist/providers/system-auth.d.ts.map +1 -0
- package/dist/providers/system-auth.js +168 -0
- package/dist/providers/system-auth.js.map +1 -0
- package/dist/runtime/daemon.d.ts +10 -0
- package/dist/runtime/daemon.d.ts.map +1 -0
- package/dist/runtime/daemon.js +264 -0
- package/dist/runtime/daemon.js.map +1 -0
- package/dist/runtime/supervisor.d.ts +6 -0
- package/dist/runtime/supervisor.d.ts.map +1 -0
- package/dist/runtime/supervisor.js +45 -0
- package/dist/runtime/supervisor.js.map +1 -0
- package/dist/types.d.ts +27 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/logger.d.ts +4 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +44 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/manifest.d.ts +5 -0
- package/dist/utils/manifest.d.ts.map +1 -0
- package/dist/utils/manifest.js +276 -0
- package/dist/utils/manifest.js.map +1 -0
- package/dist/utils/paths.d.ts +13 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +52 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/time.d.ts +11 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/time.js +40 -0
- package/dist/utils/time.js.map +1 -0
- package/dist/watchers/base.d.ts +3 -0
- package/dist/watchers/base.d.ts.map +1 -0
- package/dist/watchers/base.js +20 -0
- package/dist/watchers/base.js.map +1 -0
- package/dist/watchers/filesystem.d.ts +12 -0
- package/dist/watchers/filesystem.d.ts.map +1 -0
- package/dist/watchers/filesystem.js +211 -0
- package/dist/watchers/filesystem.js.map +1 -0
- package/dist/watchers/github.d.ts +3 -0
- package/dist/watchers/github.d.ts.map +1 -0
- package/dist/watchers/github.js +322 -0
- package/dist/watchers/github.js.map +1 -0
- package/dist/watchers/http.d.ts +13 -0
- package/dist/watchers/http.d.ts.map +1 -0
- package/dist/watchers/http.js +149 -0
- package/dist/watchers/http.js.map +1 -0
- package/dist/watchers/index.d.ts +8 -0
- package/dist/watchers/index.d.ts.map +1 -0
- package/dist/watchers/index.js +25 -0
- package/dist/watchers/index.js.map +1 -0
- package/examples/README.md +9 -0
- package/examples/codebase-guardian.yaml +22 -0
- package/examples/competitor-watch.yaml +18 -0
- package/examples/founder-sentinel.md +126 -0
- package/examples/founder-sentinel.yaml +27 -0
- package/package.json +62 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import { dirname } from 'path';
|
|
7
|
+
import { spawn } from 'child_process';
|
|
8
|
+
import { parseManifestFile, parseManifestNL } from '../utils/manifest.js';
|
|
9
|
+
import { ensureAll, statePath, memoryDir, secretsDir, providerPath, manifestsDir } from '../utils/paths.js';
|
|
10
|
+
import { parseInterval } from '../utils/time.js';
|
|
11
|
+
import { createLLMProvider } from '@josharsh/demon';
|
|
12
|
+
import { resolveKeysFromEnv } from '../adapters/keys.js';
|
|
13
|
+
import { ensureProviderForModel } from './ensure-provider.js';
|
|
14
|
+
import { installCommand } from './install.js';
|
|
15
|
+
import inquirer from 'inquirer';
|
|
16
|
+
// Load ~/.demon/secrets/*.json and ~/.demon/providers/*.json into process.env
|
|
17
|
+
// so buildLLMProvider can find keys regardless of how they were stored.
|
|
18
|
+
async function injectStoredCredentials() {
|
|
19
|
+
// 1. Per-key secrets (demon secrets set KEY)
|
|
20
|
+
const sDir = secretsDir();
|
|
21
|
+
if (await fs.pathExists(sDir)) {
|
|
22
|
+
const files = await fs.readdir(sDir).catch(() => []);
|
|
23
|
+
for (const file of files) {
|
|
24
|
+
if (!file.endsWith('.json'))
|
|
25
|
+
continue;
|
|
26
|
+
try {
|
|
27
|
+
const rec = await fs.readJson(join(sDir, file));
|
|
28
|
+
if (rec.key && rec.value && !process.env[rec.key]) {
|
|
29
|
+
process.env[rec.key] = rec.value;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch { }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// 2. Provider credential files (demon providers add anthropic)
|
|
36
|
+
const ENV_MAP = {
|
|
37
|
+
anthropic: ['ANTHROPIC_API_KEY', 'api_key'],
|
|
38
|
+
openai: ['OPENAI_API_KEY', 'api_key'],
|
|
39
|
+
openrouter: ['OPENROUTER_API_KEY', 'api_key'],
|
|
40
|
+
groq: ['GROQ_API_KEY', 'api_key'],
|
|
41
|
+
gemini: ['GEMINI_API_KEY', 'api_key'],
|
|
42
|
+
mistral: ['MISTRAL_API_KEY', 'api_key'],
|
|
43
|
+
github: ['GITHUB_TOKEN', 'token'],
|
|
44
|
+
};
|
|
45
|
+
for (const [provider, [envVar, field]] of Object.entries(ENV_MAP)) {
|
|
46
|
+
if (process.env[envVar])
|
|
47
|
+
continue;
|
|
48
|
+
const pFile = providerPath(provider);
|
|
49
|
+
if (await fs.pathExists(pFile)) {
|
|
50
|
+
try {
|
|
51
|
+
const rec = await fs.readJson(pFile);
|
|
52
|
+
const val = rec.credentials?.[field];
|
|
53
|
+
if (val)
|
|
54
|
+
process.env[envVar] = val;
|
|
55
|
+
}
|
|
56
|
+
catch { }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export async function startCommand(fileOrIntent, options) {
|
|
61
|
+
await ensureAll();
|
|
62
|
+
await injectStoredCredentials();
|
|
63
|
+
let manifest;
|
|
64
|
+
const spinner = ora('Parsing manifest...').start();
|
|
65
|
+
const isFilePath = fileOrIntent.endsWith('.yaml') ||
|
|
66
|
+
fileOrIntent.endsWith('.yml') ||
|
|
67
|
+
fileOrIntent.endsWith('.json') ||
|
|
68
|
+
(await fs.pathExists(fileOrIntent).catch(() => false));
|
|
69
|
+
if (isFilePath) {
|
|
70
|
+
try {
|
|
71
|
+
manifest = await parseManifestFile(fileOrIntent);
|
|
72
|
+
spinner.succeed(`Loaded manifest: ${chalk.bold(manifest.name)}`);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
spinner.fail(`Failed to load manifest: ${err.message}`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
// Pre-flight: make sure this manifest's model has a usable provider/key
|
|
79
|
+
// before we spawn the background daemon (which would otherwise fail silently).
|
|
80
|
+
await ensureProviderForModel(manifest.model);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
// Natural language intent — generate manifest via LLM.
|
|
84
|
+
// Pre-flight the provider first so we don't fail mid-spinner.
|
|
85
|
+
spinner.stop();
|
|
86
|
+
await ensureProviderForModel(options.model ?? 'claude-sonnet-4-6');
|
|
87
|
+
spinner.start('Generating manifest from natural language...');
|
|
88
|
+
let llmProvider;
|
|
89
|
+
try {
|
|
90
|
+
llmProvider = createLLMProvider(options.model ?? 'claude-sonnet-4-6', resolveKeysFromEnv());
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
spinner.fail(`Failed to initialize LLM: ${err.message}`);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
manifest = await parseManifestNL(fileOrIntent, llmProvider);
|
|
98
|
+
spinner.succeed('Generated manifest from intent');
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
spinner.fail(`Failed to generate manifest: ${err.message}`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
// Show manifest and ask for confirmation
|
|
105
|
+
console.log('\n' + chalk.bold('Generated manifest:'));
|
|
106
|
+
console.log(chalk.gray(JSON.stringify(manifest, null, 2)));
|
|
107
|
+
const { confirmed } = await inquirer.prompt([
|
|
108
|
+
{
|
|
109
|
+
type: 'confirm',
|
|
110
|
+
name: 'confirmed',
|
|
111
|
+
message: 'Start this demon with the above manifest?',
|
|
112
|
+
default: true,
|
|
113
|
+
},
|
|
114
|
+
]);
|
|
115
|
+
if (!confirmed) {
|
|
116
|
+
console.log(chalk.yellow('Aborted. Edit the manifest and try again.'));
|
|
117
|
+
process.exit(0);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Apply CLI overrides
|
|
121
|
+
if (options.dryRun)
|
|
122
|
+
manifest.action_mode = 'dry_run';
|
|
123
|
+
if (options.auto)
|
|
124
|
+
manifest.action_mode = 'auto';
|
|
125
|
+
if (options.interval)
|
|
126
|
+
manifest.interval = options.interval;
|
|
127
|
+
if (options.model)
|
|
128
|
+
manifest.model = options.model;
|
|
129
|
+
// Check if already running
|
|
130
|
+
const stateFile = statePath(manifest.name);
|
|
131
|
+
if (await fs.pathExists(stateFile)) {
|
|
132
|
+
const existing = await fs.readJson(stateFile);
|
|
133
|
+
if (existing.status === 'running') {
|
|
134
|
+
const alive = isProcessAlive(existing.pid);
|
|
135
|
+
if (alive) {
|
|
136
|
+
console.log(chalk.yellow(`Demon "${manifest.name}" is already running (PID ${existing.pid}).`));
|
|
137
|
+
console.log(chalk.dim('Use `demon stop <name>` first, or `demon ps` to list all demons.'));
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Validate interval
|
|
143
|
+
try {
|
|
144
|
+
parseInterval(manifest.interval);
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
console.error(chalk.red(`Invalid interval "${manifest.interval}": ${err.message}`));
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
// Ensure memory dir for this demon
|
|
151
|
+
await fs.ensureDir(join(memoryDir(), manifest.name));
|
|
152
|
+
// Write manifest to ~/.demon/manifests/<name>.json so the daemon can read it
|
|
153
|
+
const manifestJsonPath = join(manifestsDir(), `${manifest.name}.json`);
|
|
154
|
+
await fs.writeJson(manifestJsonPath, manifest, { spaces: 2 });
|
|
155
|
+
// Write initial state — pid is 0 placeholder; daemon will overwrite with its real pid
|
|
156
|
+
const state = {
|
|
157
|
+
pid: 0,
|
|
158
|
+
name: manifest.name,
|
|
159
|
+
manifestPath: isFilePath ? fileOrIntent : '(generated from natural language)',
|
|
160
|
+
startedAt: new Date().toISOString(),
|
|
161
|
+
cycles: 0,
|
|
162
|
+
actionsCount: 0,
|
|
163
|
+
lastCheck: null,
|
|
164
|
+
status: 'starting',
|
|
165
|
+
model: manifest.model,
|
|
166
|
+
actionMode: manifest.action_mode,
|
|
167
|
+
};
|
|
168
|
+
await fs.writeJson(stateFile, state, { spaces: 2 });
|
|
169
|
+
// Resolve path to compiled daemon entry point
|
|
170
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
171
|
+
const __dirname = dirname(__filename);
|
|
172
|
+
const daemonScript = join(__dirname, '../runtime/daemon.js');
|
|
173
|
+
// Spawn daemon as a true background process — detached, stdio ignored
|
|
174
|
+
const child = spawn(process.execPath, [daemonScript, manifestJsonPath, stateFile], {
|
|
175
|
+
detached: true,
|
|
176
|
+
stdio: 'ignore',
|
|
177
|
+
env: { ...process.env }, // pass injected secrets to child
|
|
178
|
+
});
|
|
179
|
+
child.unref(); // allow parent CLI to exit immediately
|
|
180
|
+
// Wait up to 3 seconds for daemon to update state to 'running'
|
|
181
|
+
const daemonPid = child.pid ?? 0;
|
|
182
|
+
const pollStart = Date.now();
|
|
183
|
+
let started = false;
|
|
184
|
+
while (Date.now() - pollStart < 3000) {
|
|
185
|
+
await sleep(200);
|
|
186
|
+
try {
|
|
187
|
+
const current = await fs.readJson(stateFile);
|
|
188
|
+
if (current.status === 'running') {
|
|
189
|
+
started = true;
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
if (current.status === 'error') {
|
|
193
|
+
console.error(chalk.red(`\n Demon "${manifest.name}" failed to start. Check logs: demon logs ${manifest.name}`));
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
// state file may not be readable yet
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (!started) {
|
|
202
|
+
// Daemon may still be initializing (slow LLM warmup etc.) — not a hard failure
|
|
203
|
+
console.log(chalk.yellow(`\n Demon "${manifest.name}" is starting (PID ${daemonPid}) — not yet confirmed running.`));
|
|
204
|
+
console.log(chalk.dim(` Check status: demon ps | demon logs ${manifest.name}`));
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
// Read back the real pid written by daemon
|
|
208
|
+
let realPid = daemonPid;
|
|
209
|
+
try {
|
|
210
|
+
const current = await fs.readJson(stateFile);
|
|
211
|
+
if (current.pid)
|
|
212
|
+
realPid = current.pid;
|
|
213
|
+
}
|
|
214
|
+
catch { }
|
|
215
|
+
console.log(chalk.bold.green(`\n Demon ${manifest.name} started (PID ${realPid})`));
|
|
216
|
+
console.log(chalk.dim(` Purpose: ${manifest.purpose}`));
|
|
217
|
+
console.log(chalk.dim(` Interval: ${manifest.interval}`));
|
|
218
|
+
console.log(chalk.dim(` Model: ${manifest.model}`));
|
|
219
|
+
console.log(chalk.dim(` Action mode: ${manifest.action_mode}`));
|
|
220
|
+
console.log(chalk.dim(` Logs: demon logs ${manifest.name}\n`));
|
|
221
|
+
if (options.install) {
|
|
222
|
+
await installCommand(manifest.name);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function isProcessAlive(pid) {
|
|
227
|
+
try {
|
|
228
|
+
process.kill(pid, 0);
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function sleep(ms) {
|
|
236
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAMA,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6D/D"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { statePath } from '../utils/paths.js';
|
|
4
|
+
import prettyMs from 'pretty-ms';
|
|
5
|
+
export async function statusCommand(name) {
|
|
6
|
+
const stateFile = statePath(name);
|
|
7
|
+
if (!(await fs.pathExists(stateFile))) {
|
|
8
|
+
console.error(chalk.red(`\n No demon named "${name}" found.\n`));
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
let state;
|
|
12
|
+
try {
|
|
13
|
+
state = await fs.readJson(stateFile);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
console.error(chalk.red(`\n Could not read state for demon "${name}". File may be corrupt.\n`));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
// Check live status
|
|
20
|
+
let effectiveStatus = state.status;
|
|
21
|
+
if (state.status === 'running') {
|
|
22
|
+
if (!isProcessAlive(state.pid)) {
|
|
23
|
+
effectiveStatus = 'stopped';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const statusColor = {
|
|
27
|
+
running: chalk.green,
|
|
28
|
+
paused: chalk.yellow,
|
|
29
|
+
stopped: chalk.gray,
|
|
30
|
+
error: chalk.red,
|
|
31
|
+
starting: chalk.cyan,
|
|
32
|
+
}[effectiveStatus] ?? chalk.white;
|
|
33
|
+
const uptime = state.startedAt
|
|
34
|
+
? prettyMs(Date.now() - new Date(state.startedAt).getTime())
|
|
35
|
+
: 'unknown';
|
|
36
|
+
const lastCheck = state.lastCheck
|
|
37
|
+
? `${new Date(state.lastCheck).toLocaleString()} (${prettyMs(Date.now() - new Date(state.lastCheck).getTime())} ago)`
|
|
38
|
+
: 'Never';
|
|
39
|
+
console.log();
|
|
40
|
+
console.log(chalk.bold.magenta(` ${state.name}`));
|
|
41
|
+
console.log(chalk.dim(' ─'.repeat(30)));
|
|
42
|
+
row('Status', statusColor(effectiveStatus));
|
|
43
|
+
row('PID', String(state.pid));
|
|
44
|
+
row('Model', state.model);
|
|
45
|
+
row('Action Mode', state.actionMode);
|
|
46
|
+
row('Started', `${new Date(state.startedAt).toLocaleString()} (${uptime} ago)`);
|
|
47
|
+
row('Last Check', lastCheck);
|
|
48
|
+
row('Cycles', String(state.cycles));
|
|
49
|
+
row('Actions Fired', String(state.actionsCount));
|
|
50
|
+
row('Manifest', state.manifestPath);
|
|
51
|
+
console.log();
|
|
52
|
+
if (effectiveStatus === 'stopped' && state.status === 'running') {
|
|
53
|
+
console.log(chalk.yellow(' Warning: demon process is not running but state shows "running". It may have crashed.\n'));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function row(label, value) {
|
|
57
|
+
const pad = 18;
|
|
58
|
+
console.log(` ${chalk.dim(label.padEnd(pad))} ${value}`);
|
|
59
|
+
}
|
|
60
|
+
function isProcessAlive(pid) {
|
|
61
|
+
try {
|
|
62
|
+
process.kill(pid, 0);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAKA,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA8CnF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { statePath } from '../utils/paths.js';
|
|
4
|
+
export async function stopCommand(name, options) {
|
|
5
|
+
const stateFile = statePath(name);
|
|
6
|
+
if (!(await fs.pathExists(stateFile))) {
|
|
7
|
+
console.error(chalk.red(`No demon named "${name}" found.`));
|
|
8
|
+
console.log(chalk.dim('Run `demon ps` to list running demons.'));
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
let state;
|
|
12
|
+
try {
|
|
13
|
+
state = await fs.readJson(stateFile);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
console.error(chalk.red(`Could not read state for demon "${name}". File may be corrupt.`));
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
if (state.status === 'stopped') {
|
|
20
|
+
console.log(chalk.yellow(`Demon "${name}" is already stopped.`));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
// Send SIGTERM to the process
|
|
24
|
+
try {
|
|
25
|
+
process.kill(state.pid, options.force ? 'SIGKILL' : 'SIGTERM');
|
|
26
|
+
console.log(chalk.green(`Sent ${options.force ? 'SIGKILL' : 'SIGTERM'} to demon "${name}" (PID ${state.pid})`));
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
const code = err.code;
|
|
30
|
+
if (code === 'ESRCH') {
|
|
31
|
+
// Process doesn't exist — clean up stale state
|
|
32
|
+
console.log(chalk.yellow(`Demon "${name}" (PID ${state.pid}) is not running. Cleaning up stale state.`));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
console.error(chalk.red(`Failed to stop demon "${name}": ${err.message}`));
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Update state on disk
|
|
40
|
+
await fs.writeJson(stateFile, { ...state, status: 'stopped' }, { spaces: 2 });
|
|
41
|
+
console.log(chalk.dim(`State updated → stopped`));
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=stop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,MAAM,UAAU,CAAA;AACzB,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAO7C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,OAAoB;IAClE,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAEjC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,IAAI,UAAU,CAAC,CAAC,CAAA;QAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC,CAAA;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,KAAiB,CAAA;IACrB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mCAAmC,IAAI,yBAAyB,CAAC,CAAC,CAAA;QAC1F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,IAAI,uBAAuB,CAAC,CAAC,CAAA;QAChE,OAAM;IACR,CAAC;IAED,8BAA8B;IAC9B,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;QAC9D,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CACT,QAAQ,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,cAAc,IAAI,UAAU,KAAK,CAAC,GAAG,GAAG,CACtF,CACF,CAAA;IACH,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAA;QAChD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,+CAA+C;YAC/C,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CAAC,UAAU,IAAI,UAAU,KAAK,CAAC,GAAG,4CAA4C,CAAC,CAC5F,CAAA;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,IAAI,MAAO,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;YACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC;IAED,uBAAuB;IACvB,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;IAC7E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,CAAA;AACnD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname, join } from 'path';
|
|
5
|
+
import { readFileSync } from 'fs';
|
|
6
|
+
// Load package.json for version
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
let version = '0.1.0';
|
|
9
|
+
try {
|
|
10
|
+
const pkgPath = join(__dirname, '..', 'package.json');
|
|
11
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
12
|
+
version = pkg.version;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
// fall back to hardcoded version
|
|
16
|
+
}
|
|
17
|
+
// Lazy imports for each command (avoids loading everything on every invocation)
|
|
18
|
+
import { initCommand } from './commands/init.js';
|
|
19
|
+
import { startCommand } from './commands/start.js';
|
|
20
|
+
import { stopCommand } from './commands/stop.js';
|
|
21
|
+
import { psCommand } from './commands/ps.js';
|
|
22
|
+
import { statusCommand } from './commands/status.js';
|
|
23
|
+
import { logsCommand } from './commands/logs.js';
|
|
24
|
+
import { inspectCommand } from './commands/inspect.js';
|
|
25
|
+
import { providersAddCommand, providersListCommand, providersRemoveCommand, } from './commands/providers.js';
|
|
26
|
+
import { secretsSetCommand, secretsGetCommand, secretsListCommand, } from './commands/secrets.js';
|
|
27
|
+
import { installCommand, uninstallCommand } from './commands/install.js';
|
|
28
|
+
const program = new Command();
|
|
29
|
+
program
|
|
30
|
+
.name('demon')
|
|
31
|
+
.description('AI-native daemon runtime — persistent reasoning processes with purpose')
|
|
32
|
+
.version(version, '-v, --version', 'Print version number')
|
|
33
|
+
.option('--verbose', 'Enable verbose/debug output')
|
|
34
|
+
.hook('preAction', (thisCommand) => {
|
|
35
|
+
if (thisCommand.opts().verbose) {
|
|
36
|
+
process.env.DEMON_LOG_LEVEL = 'debug';
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
// ─── demon init ───────────────────────────────────────────────
|
|
40
|
+
program
|
|
41
|
+
.command('init')
|
|
42
|
+
.description('Interactive wizard to create a new demon manifest')
|
|
43
|
+
.action(async () => {
|
|
44
|
+
try {
|
|
45
|
+
await initCommand();
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
handleError(err);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
// ─── demon start ──────────────────────────────────────────────
|
|
52
|
+
program
|
|
53
|
+
.command('start <fileOrIntent>')
|
|
54
|
+
.description('Start a demon from a manifest file (.yaml/.yml/.json) or natural language intent')
|
|
55
|
+
.option('--dry-run', 'Override action_mode to dry_run (never executes actions)')
|
|
56
|
+
.option('--auto', 'Override action_mode to auto (full autonomy)')
|
|
57
|
+
.option('--interval <interval>', 'Override check interval (e.g. 5m, 1h)')
|
|
58
|
+
.option('--model <model>', 'Override LLM model (e.g. claude-sonnet-4-6, gpt-4o)')
|
|
59
|
+
.option('--install', 'Register demon with OS init system for reboot persistence')
|
|
60
|
+
.action(async (fileOrIntent, options) => {
|
|
61
|
+
try {
|
|
62
|
+
await startCommand(fileOrIntent, options);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
handleError(err);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
// ─── demon stop ───────────────────────────────────────────────
|
|
69
|
+
program
|
|
70
|
+
.command('stop <name>')
|
|
71
|
+
.description('Stop a running demon by name')
|
|
72
|
+
.option('-f, --force', 'Send SIGKILL instead of SIGTERM')
|
|
73
|
+
.action(async (name, options) => {
|
|
74
|
+
try {
|
|
75
|
+
await stopCommand(name, options);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
handleError(err);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
// ─── demon install ────────────────────────────────────────────
|
|
82
|
+
program
|
|
83
|
+
.command('install <name>')
|
|
84
|
+
.description('Register a demon with the OS init system so it auto-starts on reboot')
|
|
85
|
+
.action(async (name) => {
|
|
86
|
+
try {
|
|
87
|
+
await installCommand(name);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
handleError(err);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
// ─── demon uninstall ──────────────────────────────────────────
|
|
94
|
+
program
|
|
95
|
+
.command('uninstall <name>')
|
|
96
|
+
.description('Unregister a demon from the OS init system')
|
|
97
|
+
.action(async (name) => {
|
|
98
|
+
try {
|
|
99
|
+
await uninstallCommand(name);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
handleError(err);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
// ─── demon ps ─────────────────────────────────────────────────
|
|
106
|
+
program
|
|
107
|
+
.command('ps')
|
|
108
|
+
.description('List all demons and their status')
|
|
109
|
+
.action(async () => {
|
|
110
|
+
try {
|
|
111
|
+
await psCommand();
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
handleError(err);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
// ─── demon status ─────────────────────────────────────────────
|
|
118
|
+
program
|
|
119
|
+
.command('status <name>')
|
|
120
|
+
.description('Show detailed status of a specific demon')
|
|
121
|
+
.action(async (name) => {
|
|
122
|
+
try {
|
|
123
|
+
await statusCommand(name);
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
handleError(err);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
// ─── demon logs ───────────────────────────────────────────────
|
|
130
|
+
program
|
|
131
|
+
.command('logs <name>')
|
|
132
|
+
.description('View logs for a demon')
|
|
133
|
+
.option('-f, --follow', 'Stream new logs as they arrive')
|
|
134
|
+
.option('-n, --lines <count>', 'Number of lines to show (default: 50)', '50')
|
|
135
|
+
.option('--raw', 'Print raw JSON log lines without formatting')
|
|
136
|
+
.action(async (name, options) => {
|
|
137
|
+
try {
|
|
138
|
+
await logsCommand(name, options);
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
handleError(err);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
// ─── demon inspect ────────────────────────────────────────────
|
|
145
|
+
program
|
|
146
|
+
.command('inspect <name>')
|
|
147
|
+
.description('Detailed view with reasoning history and action log')
|
|
148
|
+
.option('-n, --last <count>', 'Number of recent cycles to show (default: 10)', '10')
|
|
149
|
+
.option('--json', 'Output raw JSON')
|
|
150
|
+
.action(async (name, options) => {
|
|
151
|
+
try {
|
|
152
|
+
await inspectCommand(name, options);
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
handleError(err);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
// ─── demon providers ──────────────────────────────────────────
|
|
159
|
+
const providers = program
|
|
160
|
+
.command('providers')
|
|
161
|
+
.description('Manage action provider credentials (GitHub, Slack, etc.)');
|
|
162
|
+
providers
|
|
163
|
+
.command('add [name]')
|
|
164
|
+
.description('Add or update credentials for a provider')
|
|
165
|
+
.action(async (name) => {
|
|
166
|
+
try {
|
|
167
|
+
await providersAddCommand(name);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
handleError(err);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
providers
|
|
174
|
+
.command('list')
|
|
175
|
+
.description('List configured providers')
|
|
176
|
+
.action(async () => {
|
|
177
|
+
try {
|
|
178
|
+
await providersListCommand();
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
handleError(err);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
providers
|
|
185
|
+
.command('remove <name>')
|
|
186
|
+
.description('Remove a provider and its credentials')
|
|
187
|
+
.action(async (name) => {
|
|
188
|
+
try {
|
|
189
|
+
await providersRemoveCommand(name);
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
handleError(err);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
// ─── demon secrets ────────────────────────────────────────────
|
|
196
|
+
const secrets = program
|
|
197
|
+
.command('secrets')
|
|
198
|
+
.description('Manage secrets used by demons (API keys, tokens)');
|
|
199
|
+
secrets
|
|
200
|
+
.command('set <key> [value]')
|
|
201
|
+
.description('Set a secret (prompts for value if not provided)')
|
|
202
|
+
.action(async (key, value) => {
|
|
203
|
+
try {
|
|
204
|
+
await secretsSetCommand(key, value);
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
handleError(err);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
secrets
|
|
211
|
+
.command('get <key>')
|
|
212
|
+
.description('Print a secret value to stdout')
|
|
213
|
+
.action(async (key) => {
|
|
214
|
+
try {
|
|
215
|
+
await secretsGetCommand(key);
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
handleError(err);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
secrets
|
|
222
|
+
.command('list')
|
|
223
|
+
.description('List stored secret keys (values are never shown)')
|
|
224
|
+
.action(async () => {
|
|
225
|
+
try {
|
|
226
|
+
await secretsListCommand();
|
|
227
|
+
}
|
|
228
|
+
catch (err) {
|
|
229
|
+
handleError(err);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
// ─── Global error handling ────────────────────────────────────
|
|
233
|
+
process.on('uncaughtException', (err) => {
|
|
234
|
+
console.error('\n Uncaught exception:', err.message);
|
|
235
|
+
if (process.env.DEMON_LOG_LEVEL === 'debug') {
|
|
236
|
+
console.error(err.stack);
|
|
237
|
+
}
|
|
238
|
+
process.exit(1);
|
|
239
|
+
});
|
|
240
|
+
process.on('unhandledRejection', (reason) => {
|
|
241
|
+
console.error('\n Unhandled rejection:', reason);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
});
|
|
244
|
+
function handleError(err) {
|
|
245
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
246
|
+
console.error(`\n Error: ${message}\n`);
|
|
247
|
+
if (process.env.DEMON_LOG_LEVEL === 'debug' && err instanceof Error) {
|
|
248
|
+
console.error(err.stack);
|
|
249
|
+
}
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
program.parse(process.argv);
|
|
253
|
+
//# sourceMappingURL=index.js.map
|