daedalus-cli 1.66.2 → 1.67.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/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # [1.67.0](https://github.com/bgill55/daedalus/compare/v1.66.2...v1.67.0) (2026-07-25)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **health:** centralize types in src/types.ts, fix maskKey empty string edge case, use ASCII hyphen in headers, and add unit test suite ([ad581ba](https://github.com/bgill55/daedalus/commit/ad581badf59c7e92fe99a5c676b3d73b1dd1645a))
7
+
8
+
9
+ ### Features
10
+
11
+ * **issue-6:** [Daedalus Spec] Add /health REPL command to display model router provider latency, health status, and API key status ([3be2e6f](https://github.com/bgill55/daedalus/commit/3be2e6f682138604e3325156280f3f201679ca03))
12
+
1
13
  ## [1.66.2](https://github.com/bgill55/daedalus/compare/v1.66.1...v1.66.2) (2026-07-25)
2
14
 
3
15
 
package/README.md CHANGED
@@ -158,6 +158,76 @@ AI assistance without:
158
158
  | `exit` / `/exit` / `/quit` / `quit` | Save session and exit |
159
159
  <!-- END_COMMANDS_TABLE -->
160
160
 
161
+ ### `/health` — Router Health Diagnostics
162
+
163
+ The `/health` command provides a real-time health summary of all configured LLM providers, including latency, availability status, and API key configuration. It is useful for diagnosing connectivity issues or verifying that your provider chain is functioning correctly.
164
+
165
+ **Syntax:**
166
+
167
+ ```
168
+ /health [--json | -j] [--samples <N>] [--timeout <ms>]
169
+ ```
170
+
171
+ **Options:**
172
+
173
+ | Option | Default | Description |
174
+ |--------|---------|-------------|
175
+ | `--json`, `-j` | `false` | Output raw JSON instead of the formatted table |
176
+ | `--samples <N>` | `5` | Number of latency samples to average per provider |
177
+ | `--timeout <ms>` | `2000` | Maximum time (in ms) to wait for a health probe per provider |
178
+
179
+ **Plain-text output example:**
180
+
181
+ ```text
182
+ ┌─────────────────┬───────┬───────────────┬─────────────────────┐
183
+ │ Provider │ Status│ Avg Latency │ API-Key │
184
+ ├─────────────────┼───────┼───────────────┼─────────────────────┤
185
+ │ OpenAI │ UP │ 112 ms │ SET (sk-…4a2f) │
186
+ │ Anthropic │ DOWN │ — │ MISSING │
187
+ │ Ollama │ UP │ 28 ms │ SET (sk-…9b3c) │
188
+ │ Groq │ UNKNOWN│ — │ SET (sk-…e7d1) │
189
+ ├─────────────────┼───────┼───────────────┼─────────────────────┤
190
+ │ Router Strategy │ round-robin │
191
+ └─────────────────┴───────┴───────────────┴─────────────────────┘
192
+ ```
193
+
194
+ **JSON output example (`/health --json`):**
195
+
196
+ ```json
197
+ {
198
+ "routerStrategy": "round-robin",
199
+ "providers": {
200
+ "openai": {
201
+ "status": "UP",
202
+ "avgLatencyMs": 112,
203
+ "apiKey": "SET (sk-…4a2f)"
204
+ },
205
+ "anthropic": {
206
+ "status": "DOWN",
207
+ "avgLatencyMs": null,
208
+ "apiKey": "MISSING"
209
+ },
210
+ "ollama": {
211
+ "status": "UP",
212
+ "avgLatencyMs": 28,
213
+ "apiKey": "SET (sk-…9b3c)"
214
+ },
215
+ "groq": {
216
+ "status": "UNKNOWN",
217
+ "avgLatencyMs": null,
218
+ "apiKey": "SET (sk-…e7d1)"
219
+ }
220
+ }
221
+ }
222
+ ```
223
+
224
+ **Notes:**
225
+
226
+ - API keys are **never** displayed in full. Only the first 3 and last 4 characters are shown.
227
+ - A provider marked `DOWN` failed its health probe; `UNKNOWN` indicates a network error or timeout.
228
+ - The command completes within `3 × timeout` even if some providers are unreachable.
229
+ - Use `/help health` inside the CLI for interactive help with examples.
230
+
161
231
  Tab completion works on all commands. You can get detailed manuals, parameter lists, and subcommand options for any command directly inside the CLI by running `/help <command>` (for example, `/help config` or `/help mcp`).
162
232
 
163
233
  ---
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=health.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/health.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { maskKey } from '../utils/apiKeyMask.js';
3
+ import { formatHealthTable } from '../utils/table.js';
4
+ describe('health utilities', () => {
5
+ describe('maskKey', () => {
6
+ it('returns MISSING for null, undefined, or empty string', () => {
7
+ expect(maskKey(null)).toBe('MISSING');
8
+ expect(maskKey(undefined)).toBe('MISSING');
9
+ expect(maskKey('')).toBe('MISSING');
10
+ expect(maskKey(' ')).toBe('MISSING');
11
+ });
12
+ it('masks short keys without stray spaces', () => {
13
+ expect(maskKey('12345')).toBe('SET (***)');
14
+ });
15
+ it('masks standard API keys correctly', () => {
16
+ expect(maskKey('sk-1234567890abcdef')).toBe('SET (sk-…cdef)');
17
+ });
18
+ });
19
+ describe('formatHealthTable', () => {
20
+ it('formats health payload into table string', () => {
21
+ const payload = {
22
+ routerStrategy: 'priority',
23
+ providers: {
24
+ openai: {
25
+ status: 'UP',
26
+ avgLatencyMs: 120,
27
+ apiKey: maskKey('sk-1234567890abcdef'),
28
+ },
29
+ ollama: {
30
+ status: 'UP',
31
+ avgLatencyMs: 15,
32
+ apiKey: maskKey(null),
33
+ },
34
+ },
35
+ };
36
+ const output = formatHealthTable(payload);
37
+ expect(output).toContain('Openai');
38
+ expect(output).toContain('120 ms');
39
+ expect(output).toContain('Ollama');
40
+ expect(output).toContain('MISSING');
41
+ expect(output).toContain('API-Key');
42
+ });
43
+ });
44
+ });
45
+ //# sourceMappingURL=health.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.test.js","sourceRoot":"","sources":["../../src/__tests__/health.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtD,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;QACvB,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACpC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,OAAO,GAAkB;gBAC7B,cAAc,EAAE,UAAU;gBAC1B,SAAS,EAAE;oBACT,MAAM,EAAE;wBACN,MAAM,EAAE,IAAI;wBACZ,YAAY,EAAE,GAAG;wBACjB,MAAM,EAAE,OAAO,CAAC,qBAAqB,CAAC;qBACvC;oBACD,MAAM,EAAE;wBACN,MAAM,EAAE,IAAI;wBACZ,YAAY,EAAE,EAAE;wBAChB,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC;qBACtB;iBACF;aACF,CAAC;YAEF,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YACpC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export interface CommandContext {
2
+ print: (message: string) => void;
3
+ }
4
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export type { ProviderStatus, ProviderHealth, HealthPayload } from '../types.js';
2
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/types/health.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/types/health.ts"],"names":[],"mappings":""}
package/dist/types.d.ts CHANGED
@@ -59,4 +59,14 @@ export interface PatchEntry {
59
59
  description: string;
60
60
  }
61
61
  export type ToolExecutor = (args: Record<string, unknown>, context: ToolContext) => Promise<ToolResult>;
62
+ export type ProviderStatus = 'UP' | 'DOWN' | 'UNKNOWN';
63
+ export interface ProviderHealth {
64
+ status: ProviderStatus;
65
+ avgLatencyMs: number | null;
66
+ apiKey: string;
67
+ }
68
+ export interface HealthPayload {
69
+ routerStrategy: string;
70
+ providers: Record<string, ProviderHealth>;
71
+ }
62
72
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ,CAAC;YACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;SAChC,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC/C,OAAO,EAAE,GAAG,CAAC;IACb,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC;IAC5B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IAC3C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,UAAU,EAAE,CAAC;IAC5B,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function maskKey(key?: string | null): string;
2
+ //# sourceMappingURL=apiKeyMask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiKeyMask.d.ts","sourceRoot":"","sources":["../../src/utils/apiKeyMask.ts"],"names":[],"mappings":"AAAA,wBAAgB,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAMnD"}
@@ -0,0 +1,10 @@
1
+ export function maskKey(key) {
2
+ if (!key || key.trim() === '')
3
+ return 'MISSING';
4
+ if (key.length <= 7)
5
+ return 'SET (***)';
6
+ const first = key.slice(0, 3);
7
+ const last = key.slice(-4);
8
+ return `SET (${first}…${last})`;
9
+ }
10
+ //# sourceMappingURL=apiKeyMask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiKeyMask.js","sourceRoot":"","sources":["../../src/utils/apiKeyMask.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,OAAO,CAAC,GAAmB;IACzC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAChD,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,WAAW,CAAC;IACxC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,OAAO,QAAQ,KAAK,IAAI,IAAI,GAAG,CAAC;AAClC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { HealthPayload } from '../types/health.js';
2
+ export declare function formatHealthTable(payload: HealthPayload): string;
3
+ //# sourceMappingURL=table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/utils/table.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAgBhE"}
@@ -0,0 +1,73 @@
1
+ export function formatHealthTable(payload) {
2
+ const rows = Object.entries(payload.providers).map(([name, p]) => [
3
+ capitalize(name),
4
+ p.status,
5
+ p.avgLatencyMs !== null ? `${p.avgLatencyMs} ms` : '—',
6
+ p.apiKey,
7
+ ]);
8
+ // Append router strategy as a spanning row
9
+ const table = buildTable({
10
+ headers: ['Provider', 'Status', 'Avg Latency', 'API-Key'],
11
+ rows,
12
+ footer: [['Router Strategy', payload.routerStrategy, '', '']],
13
+ });
14
+ return table;
15
+ }
16
+ function capitalize(str) {
17
+ return str.charAt(0).toUpperCase() + str.slice(1);
18
+ }
19
+ function buildTable(opts) {
20
+ const { headers, rows, footer } = opts;
21
+ // Calculate column widths
22
+ const colWidths = headers.map((h, i) => {
23
+ let maxLen = h.length;
24
+ for (const row of rows) {
25
+ if (row[i] && row[i].length > maxLen) {
26
+ maxLen = row[i].length;
27
+ }
28
+ }
29
+ if (footer) {
30
+ for (const fRow of footer) {
31
+ if (fRow[i] && fRow[i].length > maxLen) {
32
+ maxLen = fRow[i].length;
33
+ }
34
+ }
35
+ }
36
+ return maxLen;
37
+ });
38
+ // Helper to pad a cell
39
+ const padCell = (cell, width, align = 'left') => {
40
+ const padding = width - cell.length;
41
+ if (align === 'right') {
42
+ return ' '.repeat(padding) + cell;
43
+ }
44
+ return cell + ' '.repeat(padding);
45
+ };
46
+ // Helper to create a separator line
47
+ const createSeparator = () => {
48
+ const parts = colWidths.map(w => '─'.repeat(w + 2)); // +2 for padding
49
+ return '├' + parts.join('┼') + '┤';
50
+ };
51
+ // Helper to create a header/footer line
52
+ const createLine = (cells) => {
53
+ const parts = cells.map((cell, i) => ` ${padCell(cell, colWidths[i])} `);
54
+ return '│' + parts.join('│') + '│';
55
+ };
56
+ // Build the table
57
+ let table = '';
58
+ table += '┌' + colWidths.map(w => '─'.repeat(w + 2)).join('┬') + '┐\n';
59
+ table += createLine(headers) + '\n';
60
+ table += createSeparator() + '\n';
61
+ for (const row of rows) {
62
+ table += createLine(row) + '\n';
63
+ }
64
+ if (footer) {
65
+ table += createSeparator() + '\n';
66
+ for (const fRow of footer) {
67
+ table += createLine(fRow) + '\n';
68
+ }
69
+ }
70
+ table += '└' + colWidths.map(w => '─'.repeat(w + 2)).join('┴') + '┘';
71
+ return table;
72
+ }
73
+ //# sourceMappingURL=table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.js","sourceRoot":"","sources":["../../src/utils/table.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"daedalus-cli","version":"1.66.2","description":"Local-first AI coding CLI with embedded model router, multi-agent orchestration, and codebase indexing","type":"module","bin":{"daedalus":"dist/index.js"},"files":["dist/","Daedalus.bat","README.md","CHANGELOG.md","CONTRIBUTING.md","CODE_OF_CONDUCT.md","SECURITY.md","AGENTS.md","scripts/postinstall.js"],"scripts":{"start":"tsx src/index.ts","bot":"tsx src/bot.ts","dev":"tsx watch src/index.ts","build":"tsc","prepublishOnly":"npm run build","test":"vitest run","lint":"eslint src --ext .ts","sync-docs":"tsx scripts/sync-docs.ts","postinstall":"node scripts/postinstall.js"},"engines":{"node":">=20.0.0"},"repository":{"type":"git","url":"git+https://github.com/bgill55/daedalus.git"},"homepage":"https://github.com/bgill55/daedalus#readme","bugs":{"url":"https://github.com/bgill55/daedalus/issues"},"keywords":["cli","ai","coding","assistant","local","llm","lm-studio","ollama","mcp","developer-tools"],"license":"MIT","dependencies":{"better-sqlite3":"^12.10.0","cli-highlight":"^2.1.11","diff":"^7.0.0","discord.js":"^14.27.0","dotenv":"^17.4.2","neo-blessed":"^0.2.0","openai":"^4.85.4","pdf-parse":"^2.4.5","picocolors":"^1.1.1","puppeteer-core":"^25.1.0","zod":"^3.23.8"},"devDependencies":{"@eslint/js":"^10.0.1","@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/github":"^11.0.6","@semantic-release/npm":"^12.0.2","@types/better-sqlite3":"^7.6.13","@types/blessed":"^0.1.27","@types/diff":"^6.0.0","@types/node":"^22.15.3","conventional-changelog-conventionalcommits":"^8.0.0","esbuild":"^0.24.0","eslint":"^10.5.0","globals":"^16.5.0","semantic-release":"^25.0.5","tsx":"^4.19.4","typescript":"^5.8.3","typescript-eslint":"^8.61.1","vitest":"^2.1.8"}}
1
+ {"name":"daedalus-cli","version":"1.67.0","description":"Local-first AI coding CLI with embedded model router, multi-agent orchestration, and codebase indexing","type":"module","bin":{"daedalus":"dist/index.js"},"files":["dist/","Daedalus.bat","README.md","CHANGELOG.md","CONTRIBUTING.md","CODE_OF_CONDUCT.md","SECURITY.md","AGENTS.md","scripts/postinstall.js"],"scripts":{"start":"tsx src/index.ts","bot":"tsx src/bot.ts","dev":"tsx watch src/index.ts","build":"tsc","prepublishOnly":"npm run build","test":"vitest run","lint":"eslint src --ext .ts","sync-docs":"tsx scripts/sync-docs.ts","postinstall":"node scripts/postinstall.js"},"engines":{"node":">=20.0.0"},"repository":{"type":"git","url":"git+https://github.com/bgill55/daedalus.git"},"homepage":"https://github.com/bgill55/daedalus#readme","bugs":{"url":"https://github.com/bgill55/daedalus/issues"},"keywords":["cli","ai","coding","assistant","local","llm","lm-studio","ollama","mcp","developer-tools"],"license":"MIT","dependencies":{"better-sqlite3":"^12.10.0","cli-highlight":"^2.1.11","diff":"^7.0.0","discord.js":"^14.27.0","dotenv":"^17.4.2","neo-blessed":"^0.2.0","openai":"^4.85.4","pdf-parse":"^2.4.5","picocolors":"^1.1.1","puppeteer-core":"^25.1.0","zod":"^3.23.8"},"devDependencies":{"@eslint/js":"^10.0.1","@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/github":"^11.0.6","@semantic-release/npm":"^12.0.2","@types/better-sqlite3":"^7.6.13","@types/blessed":"^0.1.27","@types/diff":"^6.0.0","@types/node":"^22.15.3","conventional-changelog-conventionalcommits":"^8.0.0","esbuild":"^0.24.0","eslint":"^10.5.0","globals":"^16.5.0","semantic-release":"^25.0.5","tsx":"^4.19.4","typescript":"^5.8.3","typescript-eslint":"^8.61.1","vitest":"^2.1.8"}}