dexto 1.1.4 → 1.1.6
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/README.md +480 -0
- package/dist/analytics/constants.d.ts +19 -0
- package/dist/analytics/constants.d.ts.map +1 -0
- package/dist/analytics/constants.js +24 -0
- package/dist/analytics/events.d.ts +112 -0
- package/dist/analytics/events.d.ts.map +1 -0
- package/dist/analytics/events.js +6 -0
- package/dist/analytics/index.d.ts +37 -0
- package/dist/analytics/index.d.ts.map +1 -0
- package/dist/analytics/index.js +145 -0
- package/dist/analytics/state.d.ts +23 -0
- package/dist/analytics/state.d.ts.map +1 -0
- package/dist/analytics/state.js +74 -0
- package/dist/analytics/wrapper.d.ts +11 -0
- package/dist/analytics/wrapper.d.ts.map +1 -0
- package/dist/analytics/wrapper.js +125 -0
- package/dist/cli/cli.d.ts +5 -0
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +10 -4
- package/dist/cli/commands/{interactive-commands/session/helpers → helpers}/formatters.d.ts +1 -1
- package/dist/cli/commands/helpers/formatters.d.ts.map +1 -0
- package/dist/cli/commands/{interactive-commands/session/helpers → helpers}/formatters.js +1 -1
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +56 -2
- package/dist/cli/commands/interactive-commands/session/index.d.ts +1 -1
- package/dist/cli/commands/interactive-commands/session/index.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/session/index.js +1 -1
- package/dist/cli/commands/interactive-commands/session/session-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/session/session-commands.js +10 -76
- package/dist/cli/commands/list-agents.d.ts +2 -2
- package/dist/cli/commands/session-commands.d.ts +28 -0
- package/dist/cli/commands/session-commands.d.ts.map +1 -0
- package/dist/cli/commands/session-commands.js +184 -0
- package/dist/cli/commands/setup.d.ts +2 -2
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +9 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -1
- package/dist/cli/commands/uninstall.js +42 -1
- package/dist/cli/utils/api-key-setup.js +1 -1
- package/dist/index.js +271 -75
- package/dist/webui/.next/standalone/.next/static/chunks/854-2a6d5a5297a15d52.js +1 -0
- package/dist/webui/.next/standalone/.next/static/chunks/app/{layout-615a56c6184a488f.js → layout-dde711766eda096b.js} +1 -1
- package/dist/webui/.next/standalone/.next/static/chunks/app/{page-24123c97236d46cb.js → page-cf95b233c1df6dcd.js} +1 -1
- package/dist/webui/.next/standalone/.next/static/css/9cdfb06589a2f6ce.css +3 -0
- package/dist/webui/.next/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/dist/webui/.next/standalone/package.json +2 -1
- package/dist/webui/.next/standalone/packages/webui/.next/BUILD_ID +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/app-build-manifest.json +5 -7
- package/dist/webui/.next/standalone/packages/webui/.next/build-manifest.json +2 -2
- package/dist/webui/.next/standalone/packages/webui/.next/prerender-manifest.json +3 -3
- package/dist/webui/.next/standalone/packages/webui/.next/required-server-files.json +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/app/_not-found/page.js +2 -2
- package/dist/webui/.next/standalone/packages/webui/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/app/page.js +3 -3
- package/dist/webui/.next/standalone/packages/webui/.next/server/app/page.js.nft.json +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/app/playground/page.js +3 -3
- package/dist/webui/.next/standalone/packages/webui/.next/server/app/playground/page.js.nft.json +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/app/playground/page_client-reference-manifest.js +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/43.js +1 -4
- package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/619.js +30 -0
- package/dist/webui/.next/standalone/packages/webui/.next/server/next-font-manifest.js +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/next-font-manifest.json +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/pages/500.html +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/pages/_error.js +2 -2
- package/dist/webui/.next/standalone/packages/webui/.next/server/server-reference-manifest.json +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/854-2a6d5a5297a15d52.js +1 -0
- package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/app/{layout-615a56c6184a488f.js → layout-dde711766eda096b.js} +1 -1
- package/dist/webui/.next/{static/chunks/app/page-24123c97236d46cb.js → standalone/packages/webui/.next/static/chunks/app/page-cf95b233c1df6dcd.js} +1 -1
- package/dist/webui/.next/standalone/packages/webui/.next/static/css/9cdfb06589a2f6ce.css +3 -0
- package/dist/webui/.next/standalone/packages/webui/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/dist/webui/.next/standalone/packages/webui/package.json +1 -1
- package/dist/webui/.next/standalone/packages/webui/public/logos/dexto/dexto_logo.svg +31 -0
- package/dist/webui/.next/standalone/packages/webui/public/logos/dexto/dexto_logo_icon.svg +14 -0
- package/dist/webui/.next/standalone/packages/webui/public/logos/dexto/dexto_logo_icon_light.svg +17 -0
- package/dist/webui/.next/standalone/packages/webui/public/logos/dexto/dexto_logo_light.svg +31 -0
- package/dist/webui/.next/standalone/packages/webui/server.js +1 -1
- package/dist/webui/.next/standalone/public/logos/dexto/dexto_logo.svg +31 -0
- package/dist/webui/.next/standalone/public/logos/dexto/dexto_logo_icon.svg +14 -0
- package/dist/webui/.next/standalone/public/logos/dexto/dexto_logo_icon_light.svg +17 -0
- package/dist/webui/.next/standalone/public/logos/dexto/dexto_logo_light.svg +31 -0
- package/dist/webui/.next/static/chunks/854-2a6d5a5297a15d52.js +1 -0
- package/dist/webui/.next/static/chunks/app/{layout-615a56c6184a488f.js → layout-dde711766eda096b.js} +1 -1
- package/dist/webui/.next/{standalone/packages/webui/.next/static/chunks/app/page-24123c97236d46cb.js → static/chunks/app/page-cf95b233c1df6dcd.js} +1 -1
- package/dist/webui/.next/static/css/9cdfb06589a2f6ce.css +3 -0
- package/dist/webui/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/dist/webui/package.json +1 -1
- package/dist/webui/public/logos/dexto/dexto_logo.svg +31 -0
- package/dist/webui/public/logos/dexto/dexto_logo_icon.svg +14 -0
- package/dist/webui/public/logos/dexto/dexto_logo_icon_light.svg +17 -0
- package/dist/webui/public/logos/dexto/dexto_logo_light.svg +31 -0
- package/package.json +7 -4
- package/dist/cli/commands/interactive-commands/session/helpers/formatters.d.ts.map +0 -1
- package/dist/webui/.next/standalone/.next/static/chunks/221-608218ab04068cb2.js +0 -1
- package/dist/webui/.next/standalone/.next/static/chunks/854-47418382efcea1d4.js +0 -1
- package/dist/webui/.next/standalone/.next/static/css/75b11629ebbc461a.css +0 -3
- package/dist/webui/.next/standalone/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
- package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/387.js +0 -14
- package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/392.js +0 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/450.js +0 -139
- package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/514.js +0 -2
- package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/531.js +0 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/723.js +0 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/737.js +0 -1
- package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/767.js +0 -20
- package/dist/webui/.next/standalone/packages/webui/.next/server/chunks/89.js +0 -95
- package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/221-608218ab04068cb2.js +0 -1
- package/dist/webui/.next/standalone/packages/webui/.next/static/chunks/854-47418382efcea1d4.js +0 -1
- package/dist/webui/.next/standalone/packages/webui/.next/static/css/75b11629ebbc461a.css +0 -3
- package/dist/webui/.next/standalone/packages/webui/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
- package/dist/webui/.next/standalone/packages/webui/public/logos/dexto_logo.svg +0 -1
- package/dist/webui/.next/standalone/packages/webui/public/logos/dexto_logo_light.svg +0 -18
- package/dist/webui/.next/standalone/packages/webui/public/logos/dexto_logo_no_text.png +0 -0
- package/dist/webui/.next/standalone/public/logos/dexto_logo.svg +0 -1
- package/dist/webui/.next/standalone/public/logos/dexto_logo_light.svg +0 -18
- package/dist/webui/.next/standalone/public/logos/dexto_logo_no_text.png +0 -0
- package/dist/webui/.next/static/chunks/221-608218ab04068cb2.js +0 -1
- package/dist/webui/.next/static/chunks/854-47418382efcea1d4.js +0 -1
- package/dist/webui/.next/static/css/75b11629ebbc461a.css +0 -3
- package/dist/webui/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
- package/dist/webui/public/logos/dexto_logo.svg +0 -1
- package/dist/webui/public/logos/dexto_logo_light.svg +0 -18
- package/dist/webui/public/logos/dexto_logo_no_text.png +0 -0
- /package/dist/webui/.next/standalone/.next/static/{abgua6ybDH7yT2b5rvLlU → OsQGbLQi9bS4RzNw_6wgr}/_buildManifest.js +0 -0
- /package/dist/webui/.next/standalone/.next/static/{abgua6ybDH7yT2b5rvLlU → OsQGbLQi9bS4RzNw_6wgr}/_ssgManifest.js +0 -0
- /package/dist/webui/.next/standalone/packages/webui/.next/static/{abgua6ybDH7yT2b5rvLlU → OsQGbLQi9bS4RzNw_6wgr}/_buildManifest.js +0 -0
- /package/dist/webui/.next/standalone/packages/webui/.next/static/{abgua6ybDH7yT2b5rvLlU → OsQGbLQi9bS4RzNw_6wgr}/_ssgManifest.js +0 -0
- /package/dist/webui/.next/static/{abgua6ybDH7yT2b5rvLlU → OsQGbLQi9bS4RzNw_6wgr}/_buildManifest.js +0 -0
- /package/dist/webui/.next/static/{abgua6ybDH7yT2b5rvLlU → OsQGbLQi9bS4RzNw_6wgr}/_ssgManifest.js +0 -0
package/dist/index.js
CHANGED
|
@@ -8,12 +8,14 @@ import { createRequire } from 'module';
|
|
|
8
8
|
import { Command } from 'commander';
|
|
9
9
|
import * as p from '@clack/prompts';
|
|
10
10
|
import chalk from 'chalk';
|
|
11
|
+
import { initAnalytics, capture } from './analytics/index.js';
|
|
12
|
+
import { withAnalytics, safeExit, ExitSignal } from './analytics/wrapper.js';
|
|
11
13
|
// Use createRequire to import package.json without experimental warning
|
|
12
14
|
const require = createRequire(import.meta.url);
|
|
13
15
|
const pkg = require('../package.json');
|
|
14
16
|
import { logger, getProviderFromModel, getAllSupportedModels, DextoAgent, loadAgentConfig, } from '@dexto/core';
|
|
15
17
|
import { resolveAgentPath, getAgentRegistry, isPath, resolveApiKeyForProvider } from '@dexto/core';
|
|
16
|
-
import { startAiCli, startHeadlessCli } from './cli/cli.js';
|
|
18
|
+
import { startAiCli, startHeadlessCli, loadMostRecentSession } from './cli/cli.js';
|
|
17
19
|
import { startApiServer } from './api/server.js';
|
|
18
20
|
import { startDiscordBot } from './discord/bot.js';
|
|
19
21
|
import { startTelegramBot } from './telegram/bot.js';
|
|
@@ -23,6 +25,7 @@ import { applyCLIOverrides } from './config/cli-overrides.js';
|
|
|
23
25
|
import { getPort } from '@dexto/core';
|
|
24
26
|
import { createDextoProject, createTsconfigJson, addDextoScriptsToPackageJson, postCreateDexto, initDexto, postInitDexto, getUserInputToInitDextoApp, } from './cli/commands/index.js';
|
|
25
27
|
import { handleSetupCommand, handleInstallCommand, handleUninstallCommand, handleListAgentsCommand, handleWhichCommand, } from './cli/commands/index.js';
|
|
28
|
+
import { handleSessionListCommand, handleSessionHistoryCommand, handleSessionDeleteCommand, handleSessionSearchCommand, } from './cli/commands/session-commands.js';
|
|
26
29
|
import { requiresSetup } from './cli/utils/setup-utils.js';
|
|
27
30
|
import { checkForFileInCurrentDirectory, FileNotFoundError } from './cli/utils/package-mgmt.js';
|
|
28
31
|
import { startNextJsWebServer } from './web.js';
|
|
@@ -30,19 +33,22 @@ import { initializeMcpServer, createMcpTransport } from './api/mcp/mcp_handler.j
|
|
|
30
33
|
import { createAgentCard } from '@dexto/core';
|
|
31
34
|
import { initializeMcpToolAggregationServer } from './api/mcp/tool-aggregation-handler.js';
|
|
32
35
|
const program = new Command();
|
|
36
|
+
// Initialize analytics early (no-op if disabled)
|
|
37
|
+
await initAnalytics({ appVersion: pkg.version });
|
|
33
38
|
// 1) GLOBAL OPTIONS
|
|
34
39
|
program
|
|
35
40
|
.name('dexto')
|
|
36
41
|
.description('AI-powered CLI and WebUI for interacting with MCP servers')
|
|
37
42
|
.version(pkg.version, '-v, --version', 'output the current version')
|
|
38
43
|
.option('-a, --agent <name|path>', 'Agent name or path to agent config file')
|
|
39
|
-
.option('-p, --prompt <text>', '
|
|
44
|
+
.option('-p, --prompt <text>', 'Run prompt and exit. Alternatively provide a single quoted string as positional argument.')
|
|
40
45
|
.option('-s, --strict', 'Require all server connections to succeed')
|
|
41
46
|
.option('--no-verbose', 'Disable verbose output')
|
|
42
47
|
.option('--no-interactive', 'Disable interactive prompts and API key setup')
|
|
43
48
|
.option('-m, --model <model>', 'Specify the LLM model to use')
|
|
44
|
-
.option('
|
|
45
|
-
.option('
|
|
49
|
+
.option('--router <router>', 'Specify the LLM router to use (vercel or in-built)')
|
|
50
|
+
.option('-c, --continue', 'Continue most recent conversation')
|
|
51
|
+
.option('-r, --resume <sessionId>', 'Resume session by ID')
|
|
46
52
|
.option('--mode <mode>', 'The application in which dexto should talk to you - cli | web | server | discord | telegram | mcp', 'cli')
|
|
47
53
|
.option('--web-port <port>', 'optional port for the web UI', '3000')
|
|
48
54
|
.option('--no-auto-install', 'Disable automatic installation of missing agents from registry')
|
|
@@ -51,13 +57,22 @@ program
|
|
|
51
57
|
program
|
|
52
58
|
.command('create-app')
|
|
53
59
|
.description('Scaffold a new Dexto Typescript app')
|
|
54
|
-
.action(async () => {
|
|
60
|
+
.action(withAnalytics('create-app', async () => {
|
|
55
61
|
try {
|
|
56
62
|
p.intro(chalk.inverse('Dexto Create App'));
|
|
57
63
|
// first setup the initial files in the project and get the project path
|
|
58
64
|
const appPath = await createDextoProject();
|
|
59
65
|
// then get user inputs for directory, llm etc.
|
|
60
66
|
const userInput = await getUserInputToInitDextoApp();
|
|
67
|
+
try {
|
|
68
|
+
capture('dexto_create', {
|
|
69
|
+
provider: userInput.llmProvider,
|
|
70
|
+
providedKey: Boolean(userInput.llmApiKey),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Analytics failures should not block CLI execution.
|
|
75
|
+
}
|
|
61
76
|
// move to project directory, then add the dexto scripts to the package.json and create the tsconfig.json
|
|
62
77
|
process.chdir(appPath);
|
|
63
78
|
await addDextoScriptsToPackageJson(userInput.directory, appPath);
|
|
@@ -67,18 +82,20 @@ program
|
|
|
67
82
|
p.outro(chalk.greenBright('Dexto app created and initialized successfully!'));
|
|
68
83
|
// add notes for users to get started with their newly created Dexto project
|
|
69
84
|
await postCreateDexto(appPath, userInput.directory);
|
|
70
|
-
|
|
85
|
+
safeExit('create-app', 0);
|
|
71
86
|
}
|
|
72
87
|
catch (err) {
|
|
88
|
+
if (err instanceof ExitSignal)
|
|
89
|
+
throw err;
|
|
73
90
|
console.error(`❌ dexto create-app command failed: ${err}`);
|
|
74
|
-
|
|
91
|
+
safeExit('create-app', 1, 'error');
|
|
75
92
|
}
|
|
76
|
-
});
|
|
93
|
+
}));
|
|
77
94
|
// 3) `init-app` SUB-COMMAND
|
|
78
95
|
program
|
|
79
96
|
.command('init-app')
|
|
80
97
|
.description('Initialize an existing Typescript app with Dexto')
|
|
81
|
-
.action(async () => {
|
|
98
|
+
.action(withAnalytics('init-app', async () => {
|
|
82
99
|
try {
|
|
83
100
|
// pre-condition: check that package.json and tsconfig.json exist in current directory to know that project is valid
|
|
84
101
|
await checkForFileInCurrentDirectory('package.json');
|
|
@@ -86,22 +103,33 @@ program
|
|
|
86
103
|
// start intro
|
|
87
104
|
p.intro(chalk.inverse('Dexto Init App'));
|
|
88
105
|
const userInput = await getUserInputToInitDextoApp();
|
|
106
|
+
try {
|
|
107
|
+
capture('dexto_init', {
|
|
108
|
+
provider: userInput.llmProvider,
|
|
109
|
+
providedKey: Boolean(userInput.llmApiKey),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// Analytics failures should not block CLI execution.
|
|
114
|
+
}
|
|
89
115
|
await initDexto(userInput.directory, userInput.createExampleFile, userInput.llmProvider, userInput.llmApiKey);
|
|
90
116
|
p.outro(chalk.greenBright('Dexto app initialized successfully!'));
|
|
91
117
|
// add notes for users to get started with their new initialized Dexto project
|
|
92
118
|
await postInitDexto(userInput.directory);
|
|
93
|
-
|
|
119
|
+
safeExit('init-app', 0);
|
|
94
120
|
}
|
|
95
121
|
catch (err) {
|
|
122
|
+
if (err instanceof ExitSignal)
|
|
123
|
+
throw err;
|
|
96
124
|
// if the package.json or tsconfig.json is not found, we give instructions to create a new project
|
|
97
125
|
if (err instanceof FileNotFoundError) {
|
|
98
126
|
console.error(`❌ ${err.message} Run "dexto create-app" to create a new app`);
|
|
99
|
-
|
|
127
|
+
safeExit('init-app', 1, 'file-not-found');
|
|
100
128
|
}
|
|
101
129
|
console.error(`❌ Initialization failed: ${err}`);
|
|
102
|
-
|
|
130
|
+
safeExit('init-app', 1, 'error');
|
|
103
131
|
}
|
|
104
|
-
});
|
|
132
|
+
}));
|
|
105
133
|
// 4) `setup` SUB-COMMAND
|
|
106
134
|
program
|
|
107
135
|
.command('setup')
|
|
@@ -111,16 +139,18 @@ program
|
|
|
111
139
|
.option('--default-agent <agent>', 'Default agent name (default: default-agent)')
|
|
112
140
|
.option('--no-interactive', 'Skip interactive prompts and API key setup')
|
|
113
141
|
.option('--force', 'Overwrite existing setup without confirmation')
|
|
114
|
-
.action(async (options) => {
|
|
142
|
+
.action(withAnalytics('setup', async (options) => {
|
|
115
143
|
try {
|
|
116
144
|
await handleSetupCommand(options);
|
|
117
|
-
|
|
145
|
+
safeExit('setup', 0);
|
|
118
146
|
}
|
|
119
147
|
catch (err) {
|
|
148
|
+
if (err instanceof ExitSignal)
|
|
149
|
+
throw err;
|
|
120
150
|
console.error(`❌ dexto setup command failed: ${err}. Check logs in ~/.dexto/logs/dexto.log for more information`);
|
|
121
|
-
|
|
151
|
+
safeExit('setup', 1, 'error');
|
|
122
152
|
}
|
|
123
|
-
});
|
|
153
|
+
}));
|
|
124
154
|
// 5) `install` SUB-COMMAND
|
|
125
155
|
program
|
|
126
156
|
.command('install [agents...]')
|
|
@@ -128,32 +158,36 @@ program
|
|
|
128
158
|
.option('--all', 'Install all available agents from registry')
|
|
129
159
|
.option('--no-inject-preferences', 'Skip injecting global preferences into installed agents')
|
|
130
160
|
.option('--force', 'Force reinstall even if agent is already installed')
|
|
131
|
-
.action(async (agents = [], options) => {
|
|
161
|
+
.action(withAnalytics('install', async (agents = [], options) => {
|
|
132
162
|
try {
|
|
133
163
|
await handleInstallCommand(agents, options);
|
|
134
|
-
|
|
164
|
+
safeExit('install', 0);
|
|
135
165
|
}
|
|
136
166
|
catch (err) {
|
|
167
|
+
if (err instanceof ExitSignal)
|
|
168
|
+
throw err;
|
|
137
169
|
console.error(`❌ dexto install command failed: ${err}`);
|
|
138
|
-
|
|
170
|
+
safeExit('install', 1, 'error');
|
|
139
171
|
}
|
|
140
|
-
});
|
|
172
|
+
}));
|
|
141
173
|
// 6) `uninstall` SUB-COMMAND
|
|
142
174
|
program
|
|
143
175
|
.command('uninstall [agents...]')
|
|
144
176
|
.description('Uninstall agents from the local installation')
|
|
145
177
|
.option('--all', 'Uninstall all installed agents')
|
|
146
178
|
.option('--force', 'Force uninstall even if agent is protected (e.g., default-agent)')
|
|
147
|
-
.action(async (agents, options) => {
|
|
179
|
+
.action(withAnalytics('uninstall', async (agents, options) => {
|
|
148
180
|
try {
|
|
149
181
|
await handleUninstallCommand(agents, options);
|
|
150
|
-
|
|
182
|
+
safeExit('uninstall', 0);
|
|
151
183
|
}
|
|
152
184
|
catch (err) {
|
|
185
|
+
if (err instanceof ExitSignal)
|
|
186
|
+
throw err;
|
|
153
187
|
console.error(`❌ dexto uninstall command failed: ${err}`);
|
|
154
|
-
|
|
188
|
+
safeExit('uninstall', 1, 'error');
|
|
155
189
|
}
|
|
156
|
-
});
|
|
190
|
+
}));
|
|
157
191
|
// 7) `list-agents` SUB-COMMAND
|
|
158
192
|
program
|
|
159
193
|
.command('list-agents')
|
|
@@ -161,31 +195,153 @@ program
|
|
|
161
195
|
.option('--verbose', 'Show detailed agent information')
|
|
162
196
|
.option('--installed', 'Show only installed agents')
|
|
163
197
|
.option('--available', 'Show only available agents')
|
|
164
|
-
.action(async (options) => {
|
|
198
|
+
.action(withAnalytics('list-agents', async (options) => {
|
|
165
199
|
try {
|
|
166
200
|
await handleListAgentsCommand(options);
|
|
167
|
-
|
|
201
|
+
safeExit('list-agents', 0);
|
|
168
202
|
}
|
|
169
203
|
catch (err) {
|
|
204
|
+
if (err instanceof ExitSignal)
|
|
205
|
+
throw err;
|
|
170
206
|
console.error(`❌ dexto list-agents command failed: ${err}`);
|
|
171
|
-
|
|
207
|
+
safeExit('list-agents', 1, 'error');
|
|
172
208
|
}
|
|
173
|
-
});
|
|
209
|
+
}));
|
|
174
210
|
// 8) `which` SUB-COMMAND
|
|
175
211
|
program
|
|
176
212
|
.command('which <agent>')
|
|
177
213
|
.description('Show the path to an agent')
|
|
178
|
-
.action(async (agent) => {
|
|
214
|
+
.action(withAnalytics('which', async (agent) => {
|
|
179
215
|
try {
|
|
180
216
|
await handleWhichCommand(agent);
|
|
181
|
-
|
|
217
|
+
safeExit('which', 0);
|
|
182
218
|
}
|
|
183
219
|
catch (err) {
|
|
220
|
+
if (err instanceof ExitSignal)
|
|
221
|
+
throw err;
|
|
184
222
|
console.error(`❌ dexto which command failed: ${err}`);
|
|
185
|
-
|
|
223
|
+
safeExit('which', 1, 'error');
|
|
224
|
+
}
|
|
225
|
+
}));
|
|
226
|
+
// Helper to bootstrap a minimal agent for non-interactive session/search ops
|
|
227
|
+
async function bootstrapAgentFromGlobalOpts() {
|
|
228
|
+
const globalOpts = program.opts();
|
|
229
|
+
const resolvedPath = await resolveAgentPath(globalOpts.agent, globalOpts.autoInstall !== false, true);
|
|
230
|
+
const rawConfig = await loadAgentConfig(resolvedPath);
|
|
231
|
+
const mergedConfig = applyCLIOverrides(rawConfig, globalOpts);
|
|
232
|
+
const agent = new DextoAgent(mergedConfig, globalOpts.agent);
|
|
233
|
+
await agent.start();
|
|
234
|
+
// Register graceful shutdown
|
|
235
|
+
const shutdown = async () => {
|
|
236
|
+
try {
|
|
237
|
+
await agent.stop();
|
|
238
|
+
}
|
|
239
|
+
catch (_err) {
|
|
240
|
+
// Ignore shutdown errors
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
process.on('SIGINT', shutdown);
|
|
244
|
+
process.on('SIGTERM', shutdown);
|
|
245
|
+
return agent;
|
|
246
|
+
}
|
|
247
|
+
// 9) `session` SUB-COMMAND
|
|
248
|
+
const sessionCommand = program.command('session').description('Manage chat sessions');
|
|
249
|
+
sessionCommand
|
|
250
|
+
.command('list')
|
|
251
|
+
.description('List all sessions')
|
|
252
|
+
.action(withAnalytics('session list', async () => {
|
|
253
|
+
try {
|
|
254
|
+
const agent = await bootstrapAgentFromGlobalOpts();
|
|
255
|
+
await handleSessionListCommand(agent);
|
|
256
|
+
await agent.stop();
|
|
257
|
+
safeExit('session list', 0);
|
|
186
258
|
}
|
|
187
|
-
|
|
188
|
-
|
|
259
|
+
catch (err) {
|
|
260
|
+
if (err instanceof ExitSignal)
|
|
261
|
+
throw err;
|
|
262
|
+
console.error(`❌ dexto session list command failed: ${err}`);
|
|
263
|
+
safeExit('session list', 1, 'error');
|
|
264
|
+
}
|
|
265
|
+
}));
|
|
266
|
+
sessionCommand
|
|
267
|
+
.command('history')
|
|
268
|
+
.description('Show session history')
|
|
269
|
+
.argument('[sessionId]', 'Session ID (defaults to current session)')
|
|
270
|
+
.action(withAnalytics('session history', async (sessionId) => {
|
|
271
|
+
try {
|
|
272
|
+
const agent = await bootstrapAgentFromGlobalOpts();
|
|
273
|
+
await handleSessionHistoryCommand(agent, sessionId);
|
|
274
|
+
await agent.stop();
|
|
275
|
+
safeExit('session history', 0);
|
|
276
|
+
}
|
|
277
|
+
catch (err) {
|
|
278
|
+
if (err instanceof ExitSignal)
|
|
279
|
+
throw err;
|
|
280
|
+
console.error(`❌ dexto session history command failed: ${err}`);
|
|
281
|
+
safeExit('session history', 1, 'error');
|
|
282
|
+
}
|
|
283
|
+
}));
|
|
284
|
+
sessionCommand
|
|
285
|
+
.command('delete')
|
|
286
|
+
.description('Delete a session')
|
|
287
|
+
.argument('<sessionId>', 'Session ID to delete')
|
|
288
|
+
.action(withAnalytics('session delete', async (sessionId) => {
|
|
289
|
+
try {
|
|
290
|
+
const agent = await bootstrapAgentFromGlobalOpts();
|
|
291
|
+
await handleSessionDeleteCommand(agent, sessionId);
|
|
292
|
+
await agent.stop();
|
|
293
|
+
safeExit('session delete', 0);
|
|
294
|
+
}
|
|
295
|
+
catch (err) {
|
|
296
|
+
if (err instanceof ExitSignal)
|
|
297
|
+
throw err;
|
|
298
|
+
console.error(`❌ dexto session delete command failed: ${err}`);
|
|
299
|
+
safeExit('session delete', 1, 'error');
|
|
300
|
+
}
|
|
301
|
+
}));
|
|
302
|
+
// 10) `search` SUB-COMMAND
|
|
303
|
+
program
|
|
304
|
+
.command('search')
|
|
305
|
+
.description('Search session history')
|
|
306
|
+
.argument('<query>', 'Search query')
|
|
307
|
+
.option('--session <sessionId>', 'Search in specific session')
|
|
308
|
+
.option('--role <role>', 'Filter by role (user, assistant, system, tool)')
|
|
309
|
+
.option('--limit <number>', 'Limit number of results', '10')
|
|
310
|
+
.action(withAnalytics('search', async (query, options) => {
|
|
311
|
+
try {
|
|
312
|
+
const agent = await bootstrapAgentFromGlobalOpts();
|
|
313
|
+
const searchOptions = {};
|
|
314
|
+
if (options.session) {
|
|
315
|
+
searchOptions.sessionId = options.session;
|
|
316
|
+
}
|
|
317
|
+
if (options.role) {
|
|
318
|
+
const allowed = new Set(['user', 'assistant', 'system', 'tool']);
|
|
319
|
+
if (!allowed.has(options.role)) {
|
|
320
|
+
console.error(`❌ Invalid role: ${options.role}. Use one of: user, assistant, system, tool`);
|
|
321
|
+
safeExit('search', 1, 'invalid-role');
|
|
322
|
+
}
|
|
323
|
+
searchOptions.role = options.role;
|
|
324
|
+
}
|
|
325
|
+
if (options.limit) {
|
|
326
|
+
const parsed = parseInt(options.limit, 10);
|
|
327
|
+
if (Number.isNaN(parsed) || parsed <= 0) {
|
|
328
|
+
console.error(`❌ Invalid --limit: ${options.limit}. Use a positive integer (e.g., 10).`);
|
|
329
|
+
safeExit('search', 1, 'invalid-limit');
|
|
330
|
+
}
|
|
331
|
+
searchOptions.limit = parsed;
|
|
332
|
+
}
|
|
333
|
+
await handleSessionSearchCommand(agent, query, searchOptions);
|
|
334
|
+
await agent.stop();
|
|
335
|
+
safeExit('search', 0);
|
|
336
|
+
}
|
|
337
|
+
catch (err) {
|
|
338
|
+
if (err instanceof ExitSignal)
|
|
339
|
+
throw err;
|
|
340
|
+
console.error(`❌ dexto search command failed: ${err}`);
|
|
341
|
+
safeExit('search', 1, 'error');
|
|
342
|
+
}
|
|
343
|
+
}));
|
|
344
|
+
// 11) `mcp` SUB-COMMAND
|
|
189
345
|
// For now, this mode simply aggregates and re-expose tools from configured MCP servers (no agent)
|
|
190
346
|
// dexto --mode mcp will be moved to this sub-command in the future
|
|
191
347
|
program
|
|
@@ -196,13 +352,13 @@ program
|
|
|
196
352
|
.option('--group-servers', 'Aggregate and re-expose tools from configured MCP servers (required for now)')
|
|
197
353
|
.option('--name <n>', 'Name for the MCP server', 'dexto-tools')
|
|
198
354
|
.option('--version <version>', 'Version for the MCP server', '1.0.0')
|
|
199
|
-
.action(async (options) => {
|
|
355
|
+
.action(withAnalytics('mcp', async (options) => {
|
|
200
356
|
try {
|
|
201
357
|
// Validate that --group-servers flag is provided (mandatory for now)
|
|
202
358
|
if (!options.groupServers) {
|
|
203
359
|
console.error('❌ The --group-servers flag is required. This command currently only supports aggregating and re-exposing tools from configured MCP servers.');
|
|
204
360
|
console.error('Usage: dexto mcp --group-servers');
|
|
205
|
-
|
|
361
|
+
safeExit('mcp', 1, 'missing-group-servers');
|
|
206
362
|
}
|
|
207
363
|
// Load and resolve config
|
|
208
364
|
// Get the global agent option from the main program
|
|
@@ -215,7 +371,7 @@ program
|
|
|
215
371
|
// Validate that MCP servers are configured
|
|
216
372
|
if (!config.mcpServers || Object.keys(config.mcpServers).length === 0) {
|
|
217
373
|
console.error('❌ No MCP servers configured. Please configure mcpServers in your config file.');
|
|
218
|
-
|
|
374
|
+
safeExit('mcp', 1, 'no-mcp-servers');
|
|
219
375
|
}
|
|
220
376
|
const { ServerConfigsSchema } = await import('@dexto/core');
|
|
221
377
|
const validatedServers = ServerConfigsSchema.parse(config.mcpServers);
|
|
@@ -231,28 +387,37 @@ program
|
|
|
231
387
|
logger.info('MCP tool aggregation server started successfully');
|
|
232
388
|
}
|
|
233
389
|
catch (err) {
|
|
390
|
+
if (err instanceof ExitSignal)
|
|
391
|
+
throw err;
|
|
234
392
|
// Write to stderr to avoid interfering with MCP protocol
|
|
235
393
|
process.stderr.write(`MCP tool aggregation server startup failed: ${err}\n`);
|
|
236
|
-
|
|
394
|
+
safeExit('mcp', 1, 'mcp-agg-failed');
|
|
237
395
|
}
|
|
238
|
-
});
|
|
396
|
+
}, { timeoutMs: 0 }));
|
|
239
397
|
// 10) Main dexto CLI - Interactive/One shot (CLI/HEADLESS) or run in other modes (--mode web/discord/telegram)
|
|
240
398
|
program
|
|
241
399
|
.argument('[prompt...]', 'Natural-language prompt to run once. If not passed, dexto will start as an interactive CLI')
|
|
242
400
|
// Main customer facing description
|
|
243
|
-
.description('Dexto CLI
|
|
244
|
-
'
|
|
245
|
-
|
|
246
|
-
'
|
|
247
|
-
'
|
|
248
|
-
'
|
|
249
|
-
'
|
|
250
|
-
'
|
|
251
|
-
'
|
|
252
|
-
'
|
|
253
|
-
'
|
|
254
|
-
'
|
|
255
|
-
|
|
401
|
+
.description('Dexto CLI - AI-powered assistant with session management\n\n' +
|
|
402
|
+
'Basic Usage:\n' +
|
|
403
|
+
' dexto Start interactive REPL\n' +
|
|
404
|
+
' dexto "query" Start REPL with initial prompt\n' +
|
|
405
|
+
' dexto -p "query" Run query, then exit\n' +
|
|
406
|
+
' cat file | dexto -p "query" Process piped content\n\n' +
|
|
407
|
+
'Session Management:\n' +
|
|
408
|
+
' dexto -c Continue most recent conversation\n' +
|
|
409
|
+
' dexto -c -p "query" Continue conversation, then exit\n' +
|
|
410
|
+
' dexto -r "<session-id>" "query" Resume session by ID\n\n' +
|
|
411
|
+
'Advanced Modes:\n' +
|
|
412
|
+
' dexto --mode web Run web UI\n' +
|
|
413
|
+
' dexto --mode server Run as API server\n' +
|
|
414
|
+
' dexto --mode discord Run as Discord bot\n' +
|
|
415
|
+
' dexto --mode telegram Run as Telegram bot\n' +
|
|
416
|
+
' dexto --mode mcp Run as MCP server\n\n' +
|
|
417
|
+
'Session Commands: dexto session list|history|delete • search\n' +
|
|
418
|
+
'Search: dexto search <query> [--session <id>] [--role <role>]\n\n' +
|
|
419
|
+
'See https://github.com/truffle-ai/dexto for more examples and documentation')
|
|
420
|
+
.action(withAnalytics('main', async (prompt = []) => {
|
|
256
421
|
// ——— ENV CHECK (optional) ———
|
|
257
422
|
if (!existsSync('.env')) {
|
|
258
423
|
logger.debug('WARNING: .env file not found; copy .env.example and set your API keys.');
|
|
@@ -266,7 +431,7 @@ program
|
|
|
266
431
|
else if (opts.prompt !== undefined) {
|
|
267
432
|
// Explicit empty -p "" was provided
|
|
268
433
|
console.error('❌ For headless one-shot mode, prompt cannot be empty. Provide a non-empty prompt with -p/--prompt or use positional argument.');
|
|
269
|
-
|
|
434
|
+
safeExit('main', 1, 'empty-prompt');
|
|
270
435
|
}
|
|
271
436
|
else if (prompt.length > 0) {
|
|
272
437
|
// Enforce quoted single positional argument for headless mode
|
|
@@ -275,7 +440,7 @@ program
|
|
|
275
440
|
}
|
|
276
441
|
else {
|
|
277
442
|
console.error('❌ For headless one-shot mode, pass the prompt in double quotes as a single argument (e.g., "say hello") or use -p/--prompt.');
|
|
278
|
-
|
|
443
|
+
safeExit('main', 1, 'too-many-positional');
|
|
279
444
|
}
|
|
280
445
|
}
|
|
281
446
|
// Note: Agent selection must be passed via -a/--agent. We no longer interpret
|
|
@@ -289,12 +454,12 @@ program
|
|
|
289
454
|
catch (err) {
|
|
290
455
|
console.error(`❌ ${err.message}`);
|
|
291
456
|
console.error(`Supported models: ${getAllSupportedModels().join(', ')}`);
|
|
292
|
-
|
|
457
|
+
safeExit('main', 1, 'invalid-model');
|
|
293
458
|
}
|
|
294
459
|
const apiKey = resolveApiKeyForProvider(provider);
|
|
295
460
|
if (!apiKey) {
|
|
296
461
|
console.error(`❌ Missing API key for provider '${provider}' - please set the appropriate environment variable`);
|
|
297
|
-
|
|
462
|
+
safeExit('main', 1, 'missing-api-key');
|
|
298
463
|
}
|
|
299
464
|
opts.provider = provider;
|
|
300
465
|
opts.apiKey = apiKey;
|
|
@@ -328,7 +493,8 @@ program
|
|
|
328
493
|
else {
|
|
329
494
|
console.log('📋 No agents available in registry');
|
|
330
495
|
}
|
|
331
|
-
|
|
496
|
+
safeExit('main', 1, 'agent-not-in-registry');
|
|
497
|
+
return;
|
|
332
498
|
}
|
|
333
499
|
}
|
|
334
500
|
// Check setup state and auto-trigger if needed
|
|
@@ -336,7 +502,7 @@ program
|
|
|
336
502
|
if (opts.interactive === false) {
|
|
337
503
|
console.error('❌ Setup required but --no-interactive flag is set.');
|
|
338
504
|
console.error('💡 Run `dexto setup` to configure preferences first.');
|
|
339
|
-
|
|
505
|
+
safeExit('main', 1, 'setup-required-non-interactive');
|
|
340
506
|
}
|
|
341
507
|
await handleSetupCommand({ interactive: true });
|
|
342
508
|
}
|
|
@@ -350,9 +516,11 @@ program
|
|
|
350
516
|
validatedConfig = await validateAgentConfig(mergedConfig, opts.interactive !== false);
|
|
351
517
|
}
|
|
352
518
|
catch (err) {
|
|
519
|
+
if (err instanceof ExitSignal)
|
|
520
|
+
throw err;
|
|
353
521
|
// Config loading failed completely
|
|
354
522
|
console.error(`❌ Failed to load configuration: ${err}`);
|
|
355
|
-
|
|
523
|
+
safeExit('main', 1, 'config-load-failed');
|
|
356
524
|
}
|
|
357
525
|
// ——— CREATE AGENT ———
|
|
358
526
|
let agent;
|
|
@@ -371,27 +539,55 @@ program
|
|
|
371
539
|
agent = new DextoAgent(validatedConfig, opts.agent);
|
|
372
540
|
// Start the agent (initialize async services)
|
|
373
541
|
await agent.start();
|
|
374
|
-
// Handle
|
|
375
|
-
if (opts.
|
|
542
|
+
// Handle session options - simplified logic
|
|
543
|
+
if (opts.resume) {
|
|
544
|
+
try {
|
|
545
|
+
// Resume specific session by ID
|
|
546
|
+
await agent.loadSessionAsDefault(opts.resume);
|
|
547
|
+
logger.info(`Resumed session: ${opts.resume}`, null, 'cyan');
|
|
548
|
+
}
|
|
549
|
+
catch (err) {
|
|
550
|
+
console.error(`❌ Failed to resume session '${opts.resume}': ${err instanceof Error ? err.message : String(err)}`);
|
|
551
|
+
console.error('💡 Use `dexto session list` to see available sessions');
|
|
552
|
+
safeExit('main', 1, 'resume-failed');
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
else if (opts.continue) {
|
|
556
|
+
try {
|
|
557
|
+
// Continue from most recent session
|
|
558
|
+
await loadMostRecentSession(agent);
|
|
559
|
+
// If no sessions existed, create a new one to honor default-new invariant
|
|
560
|
+
const sessionsAfter = await agent.listSessions();
|
|
561
|
+
if (sessionsAfter.length === 0) {
|
|
562
|
+
const session = await agent.createSession();
|
|
563
|
+
await agent.loadSessionAsDefault(session.id);
|
|
564
|
+
logger.info(`Created new session: ${session.id}`, null, 'green');
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
catch (err) {
|
|
568
|
+
console.error(`❌ Failed to continue session: ${err instanceof Error ? err.message : String(err)}`);
|
|
569
|
+
safeExit('main', 1, 'continue-failed');
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
// Default behavior: create new session
|
|
376
574
|
try {
|
|
377
|
-
|
|
378
|
-
const sessionId = typeof opts.newSession === 'string' && opts.newSession
|
|
379
|
-
? opts.newSession
|
|
380
|
-
: undefined; // Let agent generate random ID
|
|
381
|
-
const session = await agent.createSession(sessionId);
|
|
575
|
+
const session = await agent.createSession();
|
|
382
576
|
await agent.loadSessionAsDefault(session.id);
|
|
383
|
-
logger.info(`Created
|
|
577
|
+
logger.info(`Created new session: ${session.id}`, null, 'green');
|
|
384
578
|
}
|
|
385
579
|
catch (err) {
|
|
386
580
|
console.error(`❌ Failed to create new session: ${err instanceof Error ? err.message : String(err)}`);
|
|
387
|
-
|
|
581
|
+
safeExit('main', 1, 'create-session-failed');
|
|
388
582
|
}
|
|
389
583
|
}
|
|
390
584
|
}
|
|
391
585
|
catch (err) {
|
|
586
|
+
if (err instanceof ExitSignal)
|
|
587
|
+
throw err;
|
|
392
588
|
// Ensure config errors are shown to user, not hidden in logs
|
|
393
589
|
console.error(`❌ Configuration Error: ${err.message}`);
|
|
394
|
-
|
|
590
|
+
safeExit('main', 1, 'config-error');
|
|
395
591
|
}
|
|
396
592
|
// ——— Dispatch based on --mode ———
|
|
397
593
|
switch (opts.mode) {
|
|
@@ -404,7 +600,7 @@ program
|
|
|
404
600
|
if (headlessInput) {
|
|
405
601
|
// One shot CLI
|
|
406
602
|
await startHeadlessCli(agent, headlessInput);
|
|
407
|
-
|
|
603
|
+
safeExit('main', 0);
|
|
408
604
|
}
|
|
409
605
|
else {
|
|
410
606
|
await startAiCli(agent); // Interactive CLI
|
|
@@ -459,7 +655,7 @@ program
|
|
|
459
655
|
}
|
|
460
656
|
catch (err) {
|
|
461
657
|
console.error('❌ Discord startup failed:', err);
|
|
462
|
-
|
|
658
|
+
safeExit('main', 1, 'discord-startup-failed');
|
|
463
659
|
}
|
|
464
660
|
break;
|
|
465
661
|
case 'telegram':
|
|
@@ -469,7 +665,7 @@ program
|
|
|
469
665
|
}
|
|
470
666
|
catch (err) {
|
|
471
667
|
console.error('❌ Telegram startup failed:', err);
|
|
472
|
-
|
|
668
|
+
safeExit('main', 1, 'telegram-startup-failed');
|
|
473
669
|
}
|
|
474
670
|
break;
|
|
475
671
|
// TODO: Remove if server mode is stable and supports mcp
|
|
@@ -497,14 +693,14 @@ program
|
|
|
497
693
|
catch (err) {
|
|
498
694
|
// Write to stderr instead of stdout to avoid interfering with MCP protocol
|
|
499
695
|
process.stderr.write(`MCP server startup failed: ${err}\n`);
|
|
500
|
-
|
|
696
|
+
safeExit('main', 1, 'mcp-startup-failed');
|
|
501
697
|
}
|
|
502
698
|
break;
|
|
503
699
|
}
|
|
504
700
|
default:
|
|
505
701
|
console.error(`❌ Unknown mode '${opts.mode}'. Use cli, web, server, discord, telegram, or mcp.`);
|
|
506
|
-
|
|
702
|
+
safeExit('main', 1, 'unknown-mode');
|
|
507
703
|
}
|
|
508
|
-
});
|
|
704
|
+
}, { timeoutMs: 0 }));
|
|
509
705
|
// 11) PARSE & EXECUTE
|
|
510
706
|
program.parseAsync(process.argv);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[854],{1236:(e,t,n)=>{n.d(t,{kz:()=>m,EQ:()=>p,j0:()=>g,PI:()=>f,P2:()=>d,KU:()=>u,Y_:()=>h});var r=n(5789);let o=["apikey","api_key","token","access_token","refresh_token","password","secret"],s=["base64","filedata","file_data","imagedata","image_data","audiodata","audio_data","data"],a=[/\bsk-[A-Za-z0-9]{20,}\b/g,/\bBearer\s+[A-Za-z0-9\-_.=]+\b/gi,/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,/\beyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*/g],i="[REDACTED]",l="[REDACTED_CIRCULAR]";function c(e){return e instanceof Error?e:e&&"object"==typeof e?"message"in e&&"string"==typeof e.message?Error(e.message,{cause:e}):"error"in e&&"string"==typeof e.error?Error(e.error,{cause:e}):"details"in e&&"string"==typeof e.details?Error(e.details,{cause:e}):"description"in e&&"string"==typeof e.description?Error(e.description,{cause:e}):Error(function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1e3;try{if("bigint"==typeof e)return e.toString();let n=function e(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:new WeakSet;if("string"==typeof t){let e=t;for(let t of a)e=e.replace(t,i);return e}if(Array.isArray(t))return n.has(t)?l:(n.add(t),t.map(t=>e(t,n)));if(t&&"object"==typeof t){if(n.has(t))return l;n.add(t);let r={};for(let[a,l]of Object.entries(t))if(o.includes(a.toLowerCase()))r[a]=i;else{let o=function(e,t,n){var r;if("string"!=typeof e)return e;let o=t.toLowerCase();return(s.includes(o)||"data"===o&&n&&("mimeType"in n||"filename"in n||"fileName"in n))&&(r=e).length>1e3&&/^[A-Za-z0-9+/=]{1000,}$/.test(r.substring(0,1e3))?"".concat("[FILE_DATA_TRUNCATED]"," (").concat(e.length," chars)"):e}(l,a,t);r[a]=e(o,n)}return r}return t}(e),r=JSON.stringify(n,(e,t)=>t instanceof Error?{name:t.name,message:t.message,stack:t.stack}:"bigint"==typeof t?t.toString():t),c="…(truncated)",u=Number.isFinite(t)&&t>0?Math.floor(t):1e3;if("string"==typeof r){if(r.length<=u)return r;let e=Math.max(0,u-c.length);return"".concat(r.slice(0,e)).concat(c)}return String(e)}catch(t){try{return String(e)}catch(e){return"[Unserializable value]"}}}(e)):"string"==typeof e?Error(e,{cause:e}):Error(String(e),{cause:e})}function u(e){return"object"==typeof e&&null!==e&&"error"in e}function d(e){return"object"==typeof e&&null!==e&&"content"in e&&Array.isArray(e.content)}function f(e){return"object"==typeof e&&null!==e&&"type"in e&&"text"===e.type}function g(e){return"object"==typeof e&&null!==e&&"type"in e&&"image"===e.type}function m(e){return"object"==typeof e&&null!==e&&"type"in e&&"audio"===e.type}function p(e){return"object"==typeof e&&null!==e&&"type"in e&&"file"===e.type}let y=()=>"msg-".concat(Date.now(),"-").concat(Math.random().toString(36).substring(2,9));function h(e,t){let n=(0,r.useRef)(null),[o,s]=(0,r.useState)([]),a=(0,r.useRef)(null),[i,l]=(0,r.useState)("connecting"),[u,d]=(0,r.useState)(!1),[f,g]=(0,r.useState)(null),m=(0,r.useRef)(!1),p=(0,r.useRef)(t);(0,r.useEffect)(()=>{p.current=t},[t]);let h=(0,r.useCallback)(e=>{if(!e)return!1;let t=p.current,n=t?t():null;return!!n&&e===n},[]);(0,r.useEffect)(()=>{let t=new globalThis.WebSocket(e);return n.current=t,t.onopen=()=>l("open"),t.onclose=()=>l("closed"),t.onerror=e=>{l("closed"),g({id:y(),message:"Connection error. Please try again.",timestamp:Date.now(),context:"websocket"})},t.onmessage=e=>{let t;try{t=JSON.parse(e.data)}catch(t){let e=c(t);console.error("[useChat] WebSocket message parse error: ".concat(e.message),{error:e});return}let n=t.data||{};switch(t.event){case"thinking":if(!h(n.sessionId))return;d(!0),s(e=>[...e,{id:y(),role:"system",content:"Dexto is thinking...",createdAt:Date.now()}]);break;case"chunk":{if(!h(n.sessionId))return;let e="string"==typeof n.content?n.content:"";if(!e)break;"reasoning"===n.type?s(t=>{let n=t.filter(e=>"system"!==e.role||"Dexto is thinking..."!==e.content),r=n[n.length-1];if(r&&"assistant"===r.role){let t={...r,reasoning:(r.reasoning||"")+e,createdAt:Date.now()};return[...n.slice(0,-1),t]}return[...n,{id:y(),role:"assistant",content:"",reasoning:e,createdAt:Date.now()}]}):s(t=>{let n=t.filter(e=>"system"!==e.role||"Dexto is thinking..."!==e.content),r=n[n.length-1];if(r&&"assistant"===r.role){let t="string"==typeof r.content?r.content:"",o={...r,content:t+e,createdAt:Date.now()};return[...n.slice(0,-1),o]}return[...n,{id:y(),role:"assistant",content:e,createdAt:Date.now()}]});break}case"response":{if(!h(n.sessionId))return;d(!1);let e="string"==typeof n.text?n.text:"",t="string"==typeof n.reasoning?n.reasoning:void 0,r=n&&"object"==typeof n.tokenUsage?n.tokenUsage:void 0,o="string"==typeof n.model?n.model:void 0,a="string"==typeof n.provider?n.provider:void 0,i="string"==typeof n.router?n.router:void 0,l="string"==typeof n.sessionId?n.sessionId:void 0;s(n=>{let s=n.filter(e=>"system"!==e.role||"Dexto is thinking..."!==e.content),c=s[s.length-1];if(c&&"assistant"===c.role){let n="string"==typeof e?e:"",u={...c,content:n,tokenUsage:r,reasoning:t,model:o,provider:a,router:i,createdAt:Date.now(),sessionId:null!=l?l:c.sessionId};return[...s.slice(0,-1),u]}return[...s,{id:y(),role:"assistant",content:e,createdAt:Date.now(),tokenUsage:r,reasoning:t,model:o,provider:a,router:i,sessionId:l}]}),window.dispatchEvent(new CustomEvent("dexto:response",{detail:{text:e,sessionId:l,reasoning:t,tokenUsage:r,model:o,timestamp:Date.now()}}));break}case"conversationReset":if(!h(n.sessionId))return;d(!1),s([]),a.current=null;break;case"toolCall":{if(!h(n.sessionId))return;let e=n.toolName,t=n.args;s(n=>[...n,{id:y(),role:"tool",content:null,toolName:e,toolArgs:t,createdAt:Date.now()}]);break}case"toolResult":{if(!h(n.sessionId))return;let e=n.toolName,t=n.result,r=t;if(t&&Array.isArray(t.content)){let e=t.content.map(e=>{if("object"==typeof e&&null!==e&&"image"===e.type){if(e.data&&e.mimeType)return{type:"image",base64:e.data,mimeType:e.mimeType};if(e.base64&&e.mimeType)return{type:"image",base64:e.base64,mimeType:e.mimeType};e.image||e.url}else if("object"==typeof e&&null!==e&&"audio"===e.type){if(e.data&&e.mimeType)return{type:"audio",base64:e.data,mimeType:e.mimeType,filename:e.filename};if(e.base64&&e.mimeType)return{type:"audio",base64:e.base64,mimeType:e.mimeType,filename:e.filename};e.audio||e.url}return e});r={...t,content:e}}s(t=>{let n=t.findIndex(t=>"tool"===t.role&&t.toolName===e&&void 0===t.toolResult);if(-1!==n){let e={...t[n],toolResult:r};return[...t.slice(0,n),e,...t.slice(n+1)]}return console.warn("No matching tool call found for result of ".concat(e)),t});break}case"toolConfirmationResponse":break;case"error":{if(!h(n.sessionId))return;if(d(!1),s(e=>e.filter(e=>"system"!==e.role||"Dexto is thinking..."!==e.content)),m.current){m.current=!1;break}if((null==n?void 0:n.context)==="user_cancelled")break;let e=c(n).message;g({id:y(),message:e,timestamp:Date.now(),context:n.context,recoverable:n.recoverable,sessionId:n.sessionId,anchorMessageId:a.current||void 0,detailedIssues:Array.isArray(n.issues)?n.issues:[]})}}},()=>{t.close()}},[e]);let b=(0,r.useCallback)(function(e,t,r,o){var i;let l=arguments.length>4&&void 0!==arguments[4]&&arguments[4];if((null==(i=n.current)?void 0:i.readyState)===globalThis.WebSocket.OPEN){n.current.send(JSON.stringify({type:"message",content:e,imageData:t,fileData:r,sessionId:o,stream:l})),d(!0);let i=y();a.current=i,s(n=>[...n,{id:i,role:"user",content:e,createdAt:Date.now(),sessionId:o,imageData:t,fileData:r}]),window.dispatchEvent(new CustomEvent("dexto:message",{detail:{content:e,sessionId:o,timestamp:Date.now()}}))}else g({id:y(),message:"Cannot send message: connection is not open",timestamp:Date.now(),context:"websocket",recoverable:!0})},[]),w=(0,r.useCallback)(e=>{var t;(null==(t=n.current)?void 0:t.readyState)===globalThis.WebSocket.OPEN&&n.current.send(JSON.stringify({type:"reset",sessionId:e})),s([]),g(null),a.current=null,d(!1)},[]),v=(0,r.useCallback)(e=>{var t;(null==(t=n.current)?void 0:t.readyState)===globalThis.WebSocket.OPEN&&n.current.send(JSON.stringify({type:"cancel",sessionId:e})),d(!1),m.current=!0},[]),k=(0,r.useCallback)(()=>{g(null)},[]);return{messages:o,status:i,sendMessage:b,reset:w,setMessages:s,websocket:n.current,processing:u,cancel:v,activeError:f,clearError:k}}},9854:(e,t,n)=>{n.d(t,{ChatProvider:()=>l,v:()=>c});var r=n(5801),o=n(5789),s=n(1236),a=n(9246);let i=(0,o.createContext)(void 0);function l(e){let{children:t}=e,n=a.env.NEXT_PUBLIC_WS_URL||"ws://localhost:3001";try{let e=new URL(n);"localhost"===e.hostname&&(e.hostname=window.location.hostname,n=e.toString())}catch(e){console.warn("Invalid WS URL:",n)}let[l,c]=(0,o.useState)(null),[u,d]=(0,o.useState)(!0),[f,g]=(0,o.useState)(!0),{messages:m,sendMessage:p,status:y,reset:h,setMessages:b,websocket:w,activeError:v,clearError:k,processing:C,cancel:E}=(0,s.Y_)(n,()=>l),[S,A]=(0,o.useState)(null),T=(0,o.useCallback)(async e=>{try{let t=void 0!==e?e:l,n=await fetch(t?"/api/llm/current?sessionId=".concat(t):"/api/llm/current");if(n.ok){let e=await n.json(),t=e.config||e;A({provider:t.provider,model:t.model,displayName:t.displayName,router:t.router,baseURL:t.baseURL})}}catch(e){}},[l]);(0,o.useEffect)(()=>{S||T()},[S,T]);let{greeting:D}=function(e){let[t,n]=(0,o.useState)(null),[r,s]=(0,o.useState)(!1),[a,i]=(0,o.useState)(null);return(0,o.useEffect)(()=>{let t=new AbortController,{signal:r}=t;return(async()=>{s(!0),i(null);try{var t;let o=e?"/api/greeting?sessionId=".concat(encodeURIComponent(e)):"/api/greeting",s=await fetch(o,{signal:r});if(!s.ok){let e="Failed to fetch greeting: HTTP ".concat(s.status," ").concat(s.statusText);n(null),i(e);return}let a=await s.json();n(null!=(t=a.greeting)?t:null)}catch(t){if((null==t?void 0:t.name)==="AbortError")return;let e=t instanceof Error?t.message:"Failed to fetch greeting";i(e),console.error("Error fetching greeting: ".concat(e))}finally{s(!1)}})(),()=>t.abort()},[e]),{greeting:t,isLoading:r,error:a}}(l),x=(0,o.useCallback)(async()=>{try{let e=await fetch("/api/sessions",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})});if(!e.ok)throw Error("Failed to create session");return(await e.json()).session.id}catch(e){return console.error("Error creating auto session:",e),"chat-".concat(Date.now())}},[]),I=(0,o.useCallback)(async(e,t,n)=>{let r=l;!r&&u&&(c(r=await x()),d(!1),await T(r)),r?p(e,t,n,r,f):console.error("No session available for sending message")},[p,l,u,x,f]),N=(0,o.useCallback)(()=>{l&&h(l)},[h,l]),R=(0,o.useCallback)(async e=>{try{let t=await fetch("/api/sessions/".concat(e,"/history"));if(!t.ok){if(404===t.status){if(!(await fetch("/api/sessions",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:e})})).ok)throw Error("Failed to create session");b([]);return}throw Error("Failed to load session history")}let n=(await t.json()).history||[],r=[];for(let t=0;t<n.length;t++){let o=n[t],s={id:"session-".concat(e,"-").concat(t),role:o.role,content:o.content,createdAt:Date.now()-(n.length-t)*1e3,sessionId:e,tokenUsage:o.tokenUsage,reasoning:o.reasoning,model:o.model,router:o.router,provider:o.provider};if("assistant"===o.role&&o.toolCalls&&o.toolCalls.length>0)o.content&&r.push(s),o.toolCalls.forEach((o,s)=>{var a;let i,l=o.function?JSON.parse(o.function.arguments||"{}"):{},c=(null==(a=o.function)?void 0:a.name)||"unknown";for(let e=t+1;e<n.length;e++){let t=n[e];if("tool"===t.role&&t.toolCallId===o.id){i=t.content;break}}r.push({id:"session-".concat(e,"-").concat(t,"-tool-").concat(s),role:"tool",content:null,createdAt:Date.now()-(n.length-t)*1e3+s,sessionId:e,toolName:c,toolArgs:l,toolResult:i})});else{if("tool"===o.role)continue;r.push(s)}}b(r)}catch(e){console.error("Error loading session history:",e),b([])}},[b,T]),_=(0,o.useCallback)(async e=>{if(e!==l)try{c(e),d(!1),await R(e),await T(e)}catch(e){throw console.error("Error switching session:",e),e}},[l,R]),j=(0,o.useCallback)(()=>{c(null),d(!0),b([]),A(null)},[b]);return(0,o.useEffect)(()=>{let e=e=>{var t;let n=(null==e?void 0:e.detail)||{};if(null==(t=n.config)?void 0:t.llm){let e=n.config.llm;A({provider:e.provider,model:e.model,router:e.router,baseURL:e.baseURL})}},t=e=>{console.log("Servers changed:",e.detail)},n=e=>{let{sessionId:t}=e.detail||{};t===l&&b([])};return window.addEventListener("dexto:configChanged",e),window.addEventListener("dexto:serversChanged",t),window.addEventListener("dexto:conversationReset",n),()=>{window.removeEventListener("dexto:configChanged",e),window.removeEventListener("dexto:serversChanged",t),window.removeEventListener("dexto:conversationReset",n)}},[l,b]),(0,r.jsx)(i.Provider,{value:{messages:m,sendMessage:I,status:y,reset:N,currentSessionId:l,switchSession:_,loadSessionHistory:R,isWelcomeState:u,returnToWelcome:j,isStreaming:f,setStreaming:g,websocket:w,currentLLM:S,refreshCurrentLLM:T,processing:C,cancel:E,activeError:v,clearError:k,greeting:D},children:t})}function c(){let e=(0,o.useContext)(i);if(!e)throw Error("useChatContext must be used within a ChatProvider");return e}}}]);
|