daedalus-cli 1.26.0 → 1.26.2
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 +14 -0
- package/README.md +2 -1
- package/dist/agents/orchestrator.d.ts.map +1 -1
- package/dist/agents/orchestrator.js +21 -8
- package/dist/agents/orchestrator.js.map +1 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +214 -20
- package/dist/commands.js.map +1 -1
- package/dist/index.js +102 -37
- package/dist/index.js.map +1 -1
- package/dist/tools/builtin/project-config.d.ts +3 -2
- package/dist/tools/builtin/project-config.d.ts.map +1 -1
- package/dist/tools/builtin/project-config.js +40 -19
- package/dist/tools/builtin/project-config.js.map +1 -1
- package/dist/tools/mcp/registry.d.ts +2 -1
- package/dist/tools/mcp/registry.d.ts.map +1 -1
- package/dist/tools/mcp/registry.js +21 -7
- package/dist/tools/mcp/registry.js.map +1 -1
- package/dist/tools/mcp/stdio.d.ts.map +1 -1
- package/dist/tools/mcp/stdio.js +3 -1
- package/dist/tools/mcp/stdio.js.map +1 -1
- package/package.json +5 -3
- package/scripts/postinstall.js +10 -0
package/dist/commands.js
CHANGED
|
@@ -3,7 +3,7 @@ import fs from 'fs';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import pc from 'picocolors';
|
|
5
5
|
import { executeToolCalls } from './tools/executor.js';
|
|
6
|
-
import { discoverLocalServers } from './config/index.js';
|
|
6
|
+
import { discoverLocalServers, saveConfig } from './config/index.js';
|
|
7
7
|
import { getSessionTodos } from './tools/builtin/todo.js';
|
|
8
8
|
import { saveProfile } from './profile.js';
|
|
9
9
|
import { extractAndSave } from './extraction.js';
|
|
@@ -811,16 +811,29 @@ Once you have finished making changes, I will automatically re-run the command t
|
|
|
811
811
|
},
|
|
812
812
|
{
|
|
813
813
|
name: '/project',
|
|
814
|
-
description: 'View or set project config settings',
|
|
814
|
+
description: 'View or set project config settings (.daedalusrc)',
|
|
815
815
|
execute: async (args, _ctx) => {
|
|
816
816
|
const rest = args.trim();
|
|
817
|
-
const { loadProjectConfig, saveProjectConfig } = await import('./tools/builtin/project-config.js');
|
|
817
|
+
const { loadProjectConfig, saveProjectConfig, hasLocalConfig } = await import('./tools/builtin/project-config.js');
|
|
818
818
|
if (!rest) {
|
|
819
819
|
const cfg = loadProjectConfig(process.cwd());
|
|
820
|
-
|
|
820
|
+
const isLocal = hasLocalConfig(process.cwd());
|
|
821
|
+
console.log(pc.bold(`\n--- Project Config (${isLocal ? '.daedalusrc' : 'global'}) ---`));
|
|
821
822
|
console.log(JSON.stringify(cfg, null, 2));
|
|
822
823
|
console.log(pc.bold('----------------------------------'));
|
|
823
824
|
console.log(pc.gray('Use /project set <key> = <value> to update'));
|
|
825
|
+
console.log(pc.gray('Use /project init to create a .daedalusrc in this project'));
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
if (rest === 'init') {
|
|
829
|
+
const localPath = path.join(process.cwd(), '.daedalusrc');
|
|
830
|
+
if (fs.existsSync(localPath)) {
|
|
831
|
+
console.log(pc.yellow('.daedalusrc already exists in this project'));
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
const cfg = loadProjectConfig(process.cwd());
|
|
835
|
+
saveProjectConfig(cfg, true);
|
|
836
|
+
console.log(pc.green('Created .daedalusrc — project config is now local to this repo'));
|
|
824
837
|
return;
|
|
825
838
|
}
|
|
826
839
|
if (rest.startsWith('set ')) {
|
|
@@ -837,7 +850,7 @@ Once you have finished making changes, I will automatically re-run the command t
|
|
|
837
850
|
value = parts.slice(1).join(' ');
|
|
838
851
|
}
|
|
839
852
|
if (!key || !value) {
|
|
840
|
-
console.log(pc.red('
|
|
853
|
+
console.log(pc.red('Usage: /project set <key> = <value>'));
|
|
841
854
|
}
|
|
842
855
|
else {
|
|
843
856
|
const cfg = loadProjectConfig(process.cwd());
|
|
@@ -849,12 +862,13 @@ Once you have finished making changes, I will automatically re-run the command t
|
|
|
849
862
|
else if (!isNaN(Number(value)))
|
|
850
863
|
parsedVal = Number(value);
|
|
851
864
|
cfg[key] = parsedVal;
|
|
852
|
-
|
|
853
|
-
|
|
865
|
+
const isLocal = hasLocalConfig(process.cwd());
|
|
866
|
+
saveProjectConfig(cfg, isLocal);
|
|
867
|
+
console.log(pc.green(`Set ${key} = ${value} (${isLocal ? '.daedalusrc' : 'global'})`));
|
|
854
868
|
}
|
|
855
869
|
}
|
|
856
870
|
else {
|
|
857
|
-
console.log(pc.red(
|
|
871
|
+
console.log(pc.red(`Unknown subcommand: ${rest}. Try: /project, /project set <key> = <value>, /project init`));
|
|
858
872
|
}
|
|
859
873
|
}
|
|
860
874
|
},
|
|
@@ -881,28 +895,54 @@ Once you have finished making changes, I will automatically re-run the command t
|
|
|
881
895
|
});
|
|
882
896
|
}
|
|
883
897
|
console.log(pc.bold('---------------------\n'));
|
|
884
|
-
console.log(pc.gray('Use `/session load <id>` to
|
|
898
|
+
console.log(pc.gray('Use `/session load <id>` to resume a past session.'));
|
|
899
|
+
console.log(pc.gray('Use `/session search <query>` to search sessions.'));
|
|
885
900
|
console.log(pc.gray('Use `/session new [title]` to start a new session.'));
|
|
886
901
|
console.log(pc.gray('Use `/session rename <title>` to rename the current session.'));
|
|
887
902
|
console.log(pc.gray('Use `/session delete <id>` to delete a session.'));
|
|
888
903
|
return;
|
|
889
904
|
}
|
|
905
|
+
if (subcommand === 'search') {
|
|
906
|
+
if (!subcommandArg) {
|
|
907
|
+
console.log(pc.red('Usage: /session search <query>'));
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
const query = subcommandArg.toLowerCase();
|
|
911
|
+
const sessions = ctx.sessionManager.getSessionsForProject();
|
|
912
|
+
const matches = sessions.filter(s => s.title.toLowerCase().includes(query) ||
|
|
913
|
+
s.id.toLowerCase().includes(query));
|
|
914
|
+
if (matches.length === 0) {
|
|
915
|
+
console.log(pc.yellow(`No sessions matching "${subcommandArg}"`));
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
918
|
+
console.log(pc.bold(`\n--- Matching Sessions (${matches.length}) ---`));
|
|
919
|
+
matches.forEach(s => {
|
|
920
|
+
const currentTag = s.id === ctx.sessionManager.sessionId ? pc.green(' (current)') : '';
|
|
921
|
+
const dateStr = new Date(s.updated_at).toLocaleString();
|
|
922
|
+
console.log(` • ${pc.cyan(s.id)}${currentTag}`);
|
|
923
|
+
console.log(` Title: ${pc.white(s.title)}`);
|
|
924
|
+
console.log(` Updated: ${pc.dim(dateStr)}`);
|
|
925
|
+
});
|
|
926
|
+
console.log(pc.bold('----------------------------------\n'));
|
|
927
|
+
}
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
890
930
|
if (subcommand === 'load') {
|
|
891
931
|
if (!subcommandArg) {
|
|
892
|
-
console.log(pc.red('
|
|
932
|
+
console.log(pc.red('Usage: /session load <session-id>'));
|
|
893
933
|
return;
|
|
894
934
|
}
|
|
895
935
|
const sessions = ctx.sessionManager.getSessionsForProject();
|
|
896
936
|
const found = sessions.find(s => s.id === subcommandArg || s.id.startsWith(subcommandArg));
|
|
897
937
|
if (!found) {
|
|
898
|
-
console.log(pc.red(`
|
|
938
|
+
console.log(pc.red(`Session "${subcommandArg}" not found.`));
|
|
899
939
|
return;
|
|
900
940
|
}
|
|
901
941
|
const currentTodos = getSessionTodos(ctx.toolContext.sessionId);
|
|
902
942
|
ctx.sessionManager.saveSessionState(ctx.messages, ctx.activeFiles, currentTodos);
|
|
903
943
|
const loaded = ctx.sessionManager.startSession(found.id, found.title);
|
|
904
944
|
ctx.initializeSessionState(loaded);
|
|
905
|
-
console.log(pc.green(`
|
|
945
|
+
console.log(pc.green(`Loaded session: ${pc.bold(found.id)} ("${found.title}")`));
|
|
906
946
|
return;
|
|
907
947
|
}
|
|
908
948
|
if (subcommand === 'new') {
|
|
@@ -911,38 +951,38 @@ Once you have finished making changes, I will automatically re-run the command t
|
|
|
911
951
|
const title = subcommandArg || `Session on ${new Date().toLocaleDateString()}`;
|
|
912
952
|
const loaded = ctx.sessionManager.startSession(undefined, title);
|
|
913
953
|
ctx.initializeSessionState(loaded);
|
|
914
|
-
console.log(pc.green(`
|
|
954
|
+
console.log(pc.green(`Started new session: ${pc.bold(loaded.sessionId)}`));
|
|
915
955
|
return;
|
|
916
956
|
}
|
|
917
957
|
if (subcommand === 'rename') {
|
|
918
958
|
if (!subcommandArg) {
|
|
919
|
-
console.log(pc.red('
|
|
959
|
+
console.log(pc.red('Usage: /session rename <new-title>'));
|
|
920
960
|
return;
|
|
921
961
|
}
|
|
922
962
|
ctx.sessionManager.updateSessionTitle(subcommandArg);
|
|
923
|
-
console.log(pc.green(`
|
|
963
|
+
console.log(pc.green(`Session renamed to: "${subcommandArg}"`));
|
|
924
964
|
return;
|
|
925
965
|
}
|
|
926
966
|
if (subcommand === 'delete') {
|
|
927
967
|
if (!subcommandArg) {
|
|
928
|
-
console.log(pc.red('
|
|
968
|
+
console.log(pc.red('Usage: /session delete <session-id>'));
|
|
929
969
|
return;
|
|
930
970
|
}
|
|
931
971
|
if (subcommandArg === ctx.sessionManager.sessionId) {
|
|
932
|
-
console.log(pc.red('
|
|
972
|
+
console.log(pc.red('Cannot delete the current active session.'));
|
|
933
973
|
return;
|
|
934
974
|
}
|
|
935
975
|
const sessions = ctx.sessionManager.getSessionsForProject();
|
|
936
976
|
const found = sessions.find(s => s.id === subcommandArg || s.id.startsWith(subcommandArg));
|
|
937
977
|
if (!found) {
|
|
938
|
-
console.log(pc.red(`
|
|
978
|
+
console.log(pc.red(`Session "${subcommandArg}" not found.`));
|
|
939
979
|
return;
|
|
940
980
|
}
|
|
941
981
|
ctx.sessionManager.deleteSession(found.id);
|
|
942
|
-
console.log(pc.green(`
|
|
982
|
+
console.log(pc.green(`Deleted session: ${pc.bold(found.id)}`));
|
|
943
983
|
return;
|
|
944
984
|
}
|
|
945
|
-
console.log(pc.red(`
|
|
985
|
+
console.log(pc.red(`Unknown subcommand: ${subcommand}. Try: list, search, load, new, rename, delete`));
|
|
946
986
|
}
|
|
947
987
|
},
|
|
948
988
|
{
|
|
@@ -1551,6 +1591,53 @@ Once you have finished making changes, I will automatically re-run the command t
|
|
|
1551
1591
|
}
|
|
1552
1592
|
return;
|
|
1553
1593
|
}
|
|
1594
|
+
case 'reconnect':
|
|
1595
|
+
case 'rc': {
|
|
1596
|
+
const { loadConfig } = await import('./config/index.js');
|
|
1597
|
+
const config = loadConfig();
|
|
1598
|
+
const mcpConfigs = Object.entries(config.tools.mcpServers)
|
|
1599
|
+
.filter(([_, s]) => s.enabled)
|
|
1600
|
+
.map(([name, s]) => ({
|
|
1601
|
+
name,
|
|
1602
|
+
transport: s.transport,
|
|
1603
|
+
command: s.command,
|
|
1604
|
+
args: s.args,
|
|
1605
|
+
url: s.url,
|
|
1606
|
+
headers: s.headers,
|
|
1607
|
+
enabled: s.enabled,
|
|
1608
|
+
}));
|
|
1609
|
+
const already = mcpRegistry.getConnectedServers();
|
|
1610
|
+
const newServers = mcpConfigs.filter(c => !already.includes(c.name));
|
|
1611
|
+
if (newServers.length === 0) {
|
|
1612
|
+
if (mcpConfigs.length === 0) {
|
|
1613
|
+
console.log(pc.yellow(' No enabled MCP servers configured. Install one with /mcp install'));
|
|
1614
|
+
}
|
|
1615
|
+
else {
|
|
1616
|
+
console.log(pc.dim(' All enabled MCP servers are already connected.'));
|
|
1617
|
+
}
|
|
1618
|
+
return;
|
|
1619
|
+
}
|
|
1620
|
+
mcpRegistry.setConfigs(mcpConfigs);
|
|
1621
|
+
const connected = [];
|
|
1622
|
+
const failed = [];
|
|
1623
|
+
for (const s of newServers) {
|
|
1624
|
+
try {
|
|
1625
|
+
await mcpRegistry.connectServer(s);
|
|
1626
|
+
connected.push(s.name);
|
|
1627
|
+
}
|
|
1628
|
+
catch (err) {
|
|
1629
|
+
failed.push(`${s.name} (${err.message})`);
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
if (connected.length > 0) {
|
|
1633
|
+
const totalTools = mcpRegistry.getToolDefinitions().length;
|
|
1634
|
+
console.log(pc.green(` Connected: ${connected.join(', ')} (${totalTools} MCP tools total)`));
|
|
1635
|
+
}
|
|
1636
|
+
if (failed.length > 0) {
|
|
1637
|
+
console.log(pc.yellow(` Failed: ${failed.join(', ')}`));
|
|
1638
|
+
}
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1554
1641
|
case 'enable':
|
|
1555
1642
|
case 'e': {
|
|
1556
1643
|
if (!rest) {
|
|
@@ -1579,6 +1666,7 @@ Once you have finished making changes, I will automatically re-run the command t
|
|
|
1579
1666
|
console.log(` ${pc.cyan('/mcp list')} ${pc.dim('List installed servers')}`);
|
|
1580
1667
|
console.log(` ${pc.cyan('/mcp remove <name>')} ${pc.dim('Remove an installed server')}`);
|
|
1581
1668
|
console.log(` ${pc.cyan('/mcp info <name>')} ${pc.dim('Show server details')}`);
|
|
1669
|
+
console.log(` ${pc.cyan('/mcp reconnect')} ${pc.dim('Reconnect all enabled servers')}`);
|
|
1582
1670
|
console.log(` ${pc.cyan('/mcp enable <name>')} ${pc.dim('Enable a disabled server')}`);
|
|
1583
1671
|
console.log(` ${pc.cyan('/mcp disable <name>')} ${pc.dim('Disable a server without removing it')}`);
|
|
1584
1672
|
console.log(`\n ${pc.bold('Zero-config starters (no API keys needed):')}`);
|
|
@@ -1593,6 +1681,112 @@ Once you have finished making changes, I will automatically re-run the command t
|
|
|
1593
1681
|
}
|
|
1594
1682
|
}
|
|
1595
1683
|
},
|
|
1684
|
+
{
|
|
1685
|
+
name: '/onboard',
|
|
1686
|
+
description: 'First-time setup — discover local models, configure, and test',
|
|
1687
|
+
execute: async (_args, ctx) => {
|
|
1688
|
+
const config = ctx.config;
|
|
1689
|
+
console.log(pc.bold(pc.cyan('\n╔══════════════════════════════════════╗')));
|
|
1690
|
+
console.log(pc.bold(pc.cyan('║ Daedalus Onboarding ║')));
|
|
1691
|
+
console.log(pc.bold(pc.cyan('╚══════════════════════════════════════╝')));
|
|
1692
|
+
console.log();
|
|
1693
|
+
console.log('Daedalus runs AI models locally on your machine.');
|
|
1694
|
+
console.log('First, I need to know which model server to use.');
|
|
1695
|
+
console.log();
|
|
1696
|
+
// Step 1: Discover local model servers
|
|
1697
|
+
console.log(pc.bold('🔍 Scanning for local model servers...'));
|
|
1698
|
+
const discovered = await discoverLocalServers();
|
|
1699
|
+
let chosenEndpoint = '';
|
|
1700
|
+
let chosenModel = '';
|
|
1701
|
+
if (discovered.length > 0) {
|
|
1702
|
+
console.log(pc.green(`\n Found ${discovered.length} running server(s):\n`));
|
|
1703
|
+
for (let i = 0; i < discovered.length; i++) {
|
|
1704
|
+
const s = discovered[i];
|
|
1705
|
+
console.log(` ${i + 1}. ${pc.cyan(s.name)} at ${s.endpoint}`);
|
|
1706
|
+
for (const m of s.models.slice(0, 3)) {
|
|
1707
|
+
console.log(` - ${m}`);
|
|
1708
|
+
}
|
|
1709
|
+
if (s.models.length > 3) {
|
|
1710
|
+
console.log(pc.gray(` ... and ${s.models.length - 3} more`));
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
console.log();
|
|
1714
|
+
const serverChoice = await ctx.askLine(`Select a server (1-${discovered.length}) or press Enter to add manually: `);
|
|
1715
|
+
const idx = parseInt(serverChoice) - 1;
|
|
1716
|
+
if (idx >= 0 && idx < discovered.length) {
|
|
1717
|
+
const server = discovered[idx];
|
|
1718
|
+
chosenEndpoint = server.endpoint;
|
|
1719
|
+
if (server.models.length === 1) {
|
|
1720
|
+
chosenModel = server.models[0];
|
|
1721
|
+
}
|
|
1722
|
+
else {
|
|
1723
|
+
console.log(`\nModels on ${pc.cyan(server.name)}:`);
|
|
1724
|
+
for (let i = 0; i < server.models.length; i++) {
|
|
1725
|
+
console.log(` ${i + 1}. ${server.models[i]}`);
|
|
1726
|
+
}
|
|
1727
|
+
const modelChoice = await ctx.askLine(`Select a model (1-${server.models.length}): `);
|
|
1728
|
+
const midx = parseInt(modelChoice) - 1;
|
|
1729
|
+
if (midx >= 0 && midx < server.models.length) {
|
|
1730
|
+
chosenModel = server.models[midx];
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
if (!chosenEndpoint) {
|
|
1736
|
+
console.log(`\nEnter your model server details manually.`);
|
|
1737
|
+
chosenEndpoint = await ctx.askLine('API endpoint (e.g. http://localhost:1234/v1): ');
|
|
1738
|
+
if (!chosenEndpoint)
|
|
1739
|
+
chosenEndpoint = 'http://localhost:1234/v1';
|
|
1740
|
+
chosenModel = await ctx.askLine('Model name (e.g. qwen2.5-coder-7b-instruct): ');
|
|
1741
|
+
if (!chosenModel)
|
|
1742
|
+
chosenModel = 'auto';
|
|
1743
|
+
}
|
|
1744
|
+
if (!chosenModel)
|
|
1745
|
+
chosenModel = 'auto';
|
|
1746
|
+
// Step 2: Add to config
|
|
1747
|
+
const entry = {
|
|
1748
|
+
name: chosenModel,
|
|
1749
|
+
endpoint: chosenEndpoint,
|
|
1750
|
+
model: chosenModel,
|
|
1751
|
+
priority: 1,
|
|
1752
|
+
enabled: true,
|
|
1753
|
+
};
|
|
1754
|
+
// Replace any existing chain or add to it
|
|
1755
|
+
config.router.chain = [entry, ...config.router.chain.filter((e) => e.endpoint !== chosenEndpoint)];
|
|
1756
|
+
saveConfig(config);
|
|
1757
|
+
console.log(pc.green(`\n✓ Added model "${pc.bold(chosenModel)}" at ${chosenEndpoint}`));
|
|
1758
|
+
// Step 3: Test the model
|
|
1759
|
+
const testPrompt = await ctx.askLine('\nRun a quick test? (Y/n): ');
|
|
1760
|
+
if (testPrompt.toLowerCase() !== 'n') {
|
|
1761
|
+
console.log(pc.dim('\nSending test request...'));
|
|
1762
|
+
try {
|
|
1763
|
+
const start = Date.now();
|
|
1764
|
+
const testMessages = [
|
|
1765
|
+
{ role: 'system', content: 'You are a helpful assistant. Respond in 1-2 sentences.' },
|
|
1766
|
+
{ role: 'user', content: 'Say hello and confirm you are working.' },
|
|
1767
|
+
];
|
|
1768
|
+
const testRouter = ctx.router;
|
|
1769
|
+
const completion = await testRouter.chat.completions.create({
|
|
1770
|
+
model: chosenModel,
|
|
1771
|
+
messages: testMessages,
|
|
1772
|
+
temperature: 0.1,
|
|
1773
|
+
});
|
|
1774
|
+
const elapsed = Date.now() - start;
|
|
1775
|
+
const text = completion.choices?.[0]?.message?.content || '(no response)';
|
|
1776
|
+
console.log(pc.green(`\n✓ Response received in ${elapsed}ms:`));
|
|
1777
|
+
console.log(` ${pc.white(text)}`);
|
|
1778
|
+
}
|
|
1779
|
+
catch (err) {
|
|
1780
|
+
console.log(pc.yellow(`\n⚠ Test failed: ${err.message}`));
|
|
1781
|
+
console.log(' The model is configured but may need troubleshooting.');
|
|
1782
|
+
console.log(` Check ${pc.cyan(ctx.configDir + '/config.json')} and verify the endpoint.`);
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
console.log(pc.green(`\n✓ Onboarding complete! Configuration saved to:`));
|
|
1786
|
+
console.log(` ${pc.cyan(ctx.configDir + '/config.json')}`);
|
|
1787
|
+
console.log(`\nType ${pc.cyan('?')} to see all available commands, or just start typing.`);
|
|
1788
|
+
}
|
|
1789
|
+
},
|
|
1596
1790
|
{
|
|
1597
1791
|
name: 'exit',
|
|
1598
1792
|
aliases: ['/exit', '/quit', 'quit'],
|