dexto 1.6.8 → 1.6.9
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 +4 -4
- package/dist/analytics/wrapper.d.ts.map +1 -1
- package/dist/analytics/wrapper.js +43 -9
- package/dist/cli/auth/api-client.d.ts +50 -0
- package/dist/cli/auth/api-client.d.ts.map +1 -1
- package/dist/cli/auth/api-client.js +379 -15
- package/dist/cli/auth/browser-launch.d.ts +6 -0
- package/dist/cli/auth/browser-launch.d.ts.map +1 -0
- package/dist/cli/auth/browser-launch.js +24 -0
- package/dist/cli/auth/device.d.ts +14 -0
- package/dist/cli/auth/device.d.ts.map +1 -0
- package/dist/cli/auth/device.js +93 -0
- package/dist/cli/auth/index.d.ts +3 -1
- package/dist/cli/auth/index.d.ts.map +1 -1
- package/dist/cli/auth/index.js +2 -1
- package/dist/cli/auth/login-persistence.d.ts +13 -0
- package/dist/cli/auth/login-persistence.d.ts.map +1 -0
- package/dist/cli/auth/login-persistence.js +22 -0
- package/dist/cli/auth/oauth.d.ts +4 -1
- package/dist/cli/auth/oauth.d.ts.map +1 -1
- package/dist/cli/auth/oauth.js +6 -2
- package/dist/cli/auth/types.d.ts +12 -0
- package/dist/cli/auth/types.d.ts.map +1 -0
- package/dist/cli/auth/types.js +1 -0
- package/dist/cli/commands/agents/register.d.ts +6 -0
- package/dist/cli/commands/agents/register.d.ts.map +1 -0
- package/dist/cli/commands/agents/register.js +85 -0
- package/dist/cli/commands/auth/index.d.ts +1 -1
- package/dist/cli/commands/auth/index.d.ts.map +1 -1
- package/dist/cli/commands/auth/index.js +1 -1
- package/dist/cli/commands/auth/login.d.ts +6 -6
- package/dist/cli/commands/auth/login.d.ts.map +1 -1
- package/dist/cli/commands/auth/login.js +85 -115
- package/dist/cli/commands/auth/logout.d.ts.map +1 -1
- package/dist/cli/commands/auth/logout.js +32 -2
- package/dist/cli/commands/auth/register.d.ts +3 -0
- package/dist/cli/commands/auth/register.d.ts.map +1 -0
- package/dist/cli/commands/auth/register.js +94 -0
- package/dist/cli/commands/billing/register.d.ts +3 -0
- package/dist/cli/commands/billing/register.d.ts.map +1 -0
- package/dist/cli/commands/billing/register.js +20 -0
- package/dist/cli/commands/helpers/formatters.d.ts.map +1 -1
- package/dist/cli/commands/helpers/formatters.js +9 -0
- package/dist/cli/commands/image/register.d.ts +6 -0
- package/dist/cli/commands/image/register.d.ts.map +1 -0
- package/dist/cli/commands/image/register.js +144 -0
- package/dist/cli/commands/install.d.ts +2 -2
- package/dist/cli/commands/list-agents.d.ts.map +1 -1
- package/dist/cli/commands/list-agents.js +3 -3
- package/dist/cli/commands/mcp/register.d.ts +6 -0
- package/dist/cli/commands/mcp/register.d.ts.map +1 -0
- package/dist/cli/commands/mcp/register.js +64 -0
- package/dist/cli/commands/plugin/register.d.ts +6 -0
- package/dist/cli/commands/plugin/register.d.ts.map +1 -0
- package/dist/cli/commands/plugin/register.js +183 -0
- package/dist/cli/commands/plugin.d.ts +4 -4
- package/dist/cli/commands/register-context.d.ts +12 -0
- package/dist/cli/commands/register-context.d.ts.map +1 -0
- package/dist/cli/commands/register-context.js +1 -0
- package/dist/cli/commands/run/headless.d.ts +20 -0
- package/dist/cli/commands/run/headless.d.ts.map +1 -0
- package/dist/cli/commands/run/headless.js +275 -0
- package/dist/cli/commands/run/register.d.ts +3 -0
- package/dist/cli/commands/run/register.d.ts.map +1 -0
- package/dist/cli/commands/run/register.js +78 -0
- package/dist/cli/commands/search/register.d.ts +3 -0
- package/dist/cli/commands/search/register.d.ts.map +1 -0
- package/dist/cli/commands/search/register.js +55 -0
- package/dist/cli/commands/session/register.d.ts +3 -0
- package/dist/cli/commands/session/register.d.ts.map +1 -0
- package/dist/cli/commands/session/register.js +75 -0
- package/dist/cli/commands/setup.js +4 -4
- package/dist/cli/commands/sync-agents.d.ts +3 -3
- package/dist/cli/commands/sync-agents.js +4 -4
- package/dist/cli/commands/uninstall.d.ts +2 -2
- package/dist/cli/modes/cli.d.ts +3 -0
- package/dist/cli/modes/cli.d.ts.map +1 -0
- package/dist/cli/modes/cli.js +170 -0
- package/dist/cli/modes/context.d.ts +20 -0
- package/dist/cli/modes/context.d.ts.map +1 -0
- package/dist/cli/modes/context.js +1 -0
- package/dist/cli/modes/dispatch.d.ts +3 -0
- package/dist/cli/modes/dispatch.d.ts.map +1 -0
- package/dist/cli/modes/dispatch.js +52 -0
- package/dist/cli/modes/mcp.d.ts +3 -0
- package/dist/cli/modes/mcp.d.ts.map +1 -0
- package/dist/cli/modes/mcp.js +23 -0
- package/dist/cli/modes/server.d.ts +3 -0
- package/dist/cli/modes/server.d.ts.map +1 -0
- package/dist/cli/modes/server.js +36 -0
- package/dist/cli/modes/web.d.ts +3 -0
- package/dist/cli/modes/web.d.ts.map +1 -0
- package/dist/cli/modes/web.js +50 -0
- package/dist/cli/utils/setup-utils.js +1 -1
- package/dist/index-main.js +150 -991
- package/dist/utils/port-utils.d.ts +1 -1
- package/dist/utils/port-utils.d.ts.map +1 -1
- package/dist/utils/port-utils.js +7 -3
- package/dist/webui/assets/index-Bn9YuTdA.css +1 -0
- package/dist/webui/assets/index-CNiOYnOb.js +2059 -0
- package/dist/webui/index.html +2 -2
- package/package.json +12 -12
- package/dist/webui/assets/index-d6c-yJNn.js +0 -2059
- package/dist/webui/assets/index-yKdFLN1k.css +0 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { resolveAgentPath } from '@dexto/agent-management';
|
|
2
|
+
import { withAnalytics, safeExit, ExitSignal } from '../../../analytics/wrapper.js';
|
|
3
|
+
export function registerRunCommand({ program, cliVersion, bootstrapAgentFromGlobalOpts, }) {
|
|
4
|
+
program
|
|
5
|
+
.command('run [prompt]')
|
|
6
|
+
.description('Run a single prompt non-interactively (headless mode)')
|
|
7
|
+
.option('-m, --model <model>', 'Specify the LLM model to use for this run')
|
|
8
|
+
.addHelpText('after', `
|
|
9
|
+
Examples:
|
|
10
|
+
$ dexto run "summarize this repository"
|
|
11
|
+
$ echo "fix lint errors" | dexto run
|
|
12
|
+
$ dexto run - < prompt.txt
|
|
13
|
+
`)
|
|
14
|
+
.action(withAnalytics('run', async (promptArg, runOptions) => {
|
|
15
|
+
let agent;
|
|
16
|
+
let exitCode = 0;
|
|
17
|
+
let exitReason = 'ok';
|
|
18
|
+
try {
|
|
19
|
+
const { executeHeadlessRun, printHeadlessAssistantResponse, printHeadlessMcpStartup, printHeadlessRunSummary, resolveHeadlessPrompt, writeFinalMessageToStdout, writeHeadlessError, } = await import('./headless.js');
|
|
20
|
+
const prompt = await resolveHeadlessPrompt(promptArg);
|
|
21
|
+
if (prompt.trim().length === 0) {
|
|
22
|
+
writeHeadlessError('Prompt cannot be empty.');
|
|
23
|
+
exitCode = 1;
|
|
24
|
+
exitReason = 'empty-prompt';
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
const bootstrapOptions = runOptions?.model
|
|
28
|
+
? { mode: 'headless-run', modelOverride: runOptions.model }
|
|
29
|
+
: { mode: 'headless-run' };
|
|
30
|
+
agent = await bootstrapAgentFromGlobalOpts(bootstrapOptions);
|
|
31
|
+
const session = await agent.createSession();
|
|
32
|
+
const globalOpts = program.opts();
|
|
33
|
+
const resolvedAgentPath = await resolveAgentPath(globalOpts.agent, globalOpts.autoInstall !== false);
|
|
34
|
+
printHeadlessRunSummary({
|
|
35
|
+
agent,
|
|
36
|
+
sessionId: session.id,
|
|
37
|
+
prompt,
|
|
38
|
+
agentPath: resolvedAgentPath,
|
|
39
|
+
cliVersion,
|
|
40
|
+
});
|
|
41
|
+
printHeadlessMcpStartup(agent);
|
|
42
|
+
const runResult = await executeHeadlessRun(agent, session.id, prompt);
|
|
43
|
+
if (runResult.finalMessage !== undefined) {
|
|
44
|
+
printHeadlessAssistantResponse(runResult.finalMessage, runResult.totalTokens);
|
|
45
|
+
writeFinalMessageToStdout(runResult.finalMessage);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
writeHeadlessError('No final response was produced.');
|
|
49
|
+
exitCode = 1;
|
|
50
|
+
exitReason = 'no-final-response';
|
|
51
|
+
}
|
|
52
|
+
if (runResult.fatalError) {
|
|
53
|
+
exitCode = 1;
|
|
54
|
+
exitReason = 'fatal-error';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
if (err instanceof ExitSignal)
|
|
60
|
+
throw err;
|
|
61
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
62
|
+
process.stderr.write(`dexto run failed: ${errorMessage}\n`);
|
|
63
|
+
exitCode = 1;
|
|
64
|
+
exitReason = 'error';
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
if (agent) {
|
|
68
|
+
try {
|
|
69
|
+
await agent.stop();
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Ignore shutdown errors in headless mode cleanup
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
safeExit('run', exitCode, exitReason);
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/search/register.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAE5E,wBAAgB,qBAAqB,CAAC,EAClC,OAAO,EACP,4BAA4B,GAC/B,EAAE,6BAA6B,GAAG,IAAI,CA8EtC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { withAnalytics, safeExit, ExitSignal } from '../../../analytics/wrapper.js';
|
|
2
|
+
export function registerSearchCommand({ program, bootstrapAgentFromGlobalOpts, }) {
|
|
3
|
+
program
|
|
4
|
+
.command('search')
|
|
5
|
+
.description('Search session history')
|
|
6
|
+
.argument('<query>', 'Search query')
|
|
7
|
+
.option('--session <sessionId>', 'Search in specific session')
|
|
8
|
+
.option('--role <role>', 'Filter by role (user, assistant, system, tool)')
|
|
9
|
+
.option('--limit <number>', 'Limit number of results', '10')
|
|
10
|
+
.action(withAnalytics('search', async (query, options) => {
|
|
11
|
+
let agent = null;
|
|
12
|
+
try {
|
|
13
|
+
const searchOptions = {};
|
|
14
|
+
if (options.session) {
|
|
15
|
+
searchOptions.sessionId = options.session;
|
|
16
|
+
}
|
|
17
|
+
if (options.role) {
|
|
18
|
+
const allowed = new Set(['user', 'assistant', 'system', 'tool']);
|
|
19
|
+
if (!allowed.has(options.role)) {
|
|
20
|
+
console.error(`❌ Invalid role: ${options.role}. Use one of: user, assistant, system, tool`);
|
|
21
|
+
safeExit('search', 1, 'invalid-role');
|
|
22
|
+
}
|
|
23
|
+
searchOptions.role = options.role;
|
|
24
|
+
}
|
|
25
|
+
if (options.limit) {
|
|
26
|
+
const rawLimit = options.limit.trim();
|
|
27
|
+
const parsed = Number(rawLimit);
|
|
28
|
+
if (!/^\d+$/.test(rawLimit) ||
|
|
29
|
+
!Number.isInteger(parsed) ||
|
|
30
|
+
parsed <= 0) {
|
|
31
|
+
console.error(`❌ Invalid --limit: ${options.limit}. Use a positive integer (e.g., 10).`);
|
|
32
|
+
safeExit('search', 1, 'invalid-limit');
|
|
33
|
+
}
|
|
34
|
+
searchOptions.limit = parsed;
|
|
35
|
+
}
|
|
36
|
+
agent = await bootstrapAgentFromGlobalOpts({
|
|
37
|
+
mode: 'non-interactive',
|
|
38
|
+
});
|
|
39
|
+
const { handleSessionSearchCommand } = await import('../session-commands.js');
|
|
40
|
+
await handleSessionSearchCommand(agent, query, searchOptions);
|
|
41
|
+
safeExit('search', 0);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
if (err instanceof ExitSignal)
|
|
45
|
+
throw err;
|
|
46
|
+
console.error(`❌ dexto search command failed: ${err}`);
|
|
47
|
+
safeExit('search', 1, 'error');
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
if (agent) {
|
|
51
|
+
await agent.stop().catch(() => { });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/session/register.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AAE5E,wBAAgB,sBAAsB,CAAC,EACnC,OAAO,EACP,4BAA4B,GAC/B,EAAE,6BAA6B,GAAG,IAAI,CA4EtC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { withAnalytics, safeExit, ExitSignal } from '../../../analytics/wrapper.js';
|
|
2
|
+
export function registerSessionCommand({ program, bootstrapAgentFromGlobalOpts, }) {
|
|
3
|
+
const sessionCommand = program.command('session').description('Manage chat sessions');
|
|
4
|
+
sessionCommand
|
|
5
|
+
.command('list')
|
|
6
|
+
.description('List all sessions')
|
|
7
|
+
.action(withAnalytics('session list', async () => {
|
|
8
|
+
let agent = null;
|
|
9
|
+
try {
|
|
10
|
+
agent = await bootstrapAgentFromGlobalOpts({ mode: 'non-interactive' });
|
|
11
|
+
const { handleSessionListCommand } = await import('../session-commands.js');
|
|
12
|
+
await handleSessionListCommand(agent);
|
|
13
|
+
safeExit('session list', 0);
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
if (err instanceof ExitSignal)
|
|
17
|
+
throw err;
|
|
18
|
+
console.error(`❌ dexto session list command failed: ${err}`);
|
|
19
|
+
safeExit('session list', 1, 'error');
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
if (agent) {
|
|
23
|
+
await agent.stop().catch(() => { });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}));
|
|
27
|
+
sessionCommand
|
|
28
|
+
.command('history')
|
|
29
|
+
.description('Show session history')
|
|
30
|
+
.argument('[sessionId]', 'Session ID (defaults to current session)')
|
|
31
|
+
.action(withAnalytics('session history', async (sessionId) => {
|
|
32
|
+
let agent = null;
|
|
33
|
+
try {
|
|
34
|
+
agent = await bootstrapAgentFromGlobalOpts({ mode: 'non-interactive' });
|
|
35
|
+
const { handleSessionHistoryCommand } = await import('../session-commands.js');
|
|
36
|
+
await handleSessionHistoryCommand(agent, sessionId);
|
|
37
|
+
safeExit('session history', 0);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
if (err instanceof ExitSignal)
|
|
41
|
+
throw err;
|
|
42
|
+
console.error(`❌ dexto session history command failed: ${err}`);
|
|
43
|
+
safeExit('session history', 1, 'error');
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
if (agent) {
|
|
47
|
+
await agent.stop().catch(() => { });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}));
|
|
51
|
+
sessionCommand
|
|
52
|
+
.command('delete')
|
|
53
|
+
.description('Delete a session')
|
|
54
|
+
.argument('<sessionId>', 'Session ID to delete')
|
|
55
|
+
.action(withAnalytics('session delete', async (sessionId) => {
|
|
56
|
+
let agent = null;
|
|
57
|
+
try {
|
|
58
|
+
agent = await bootstrapAgentFromGlobalOpts({ mode: 'non-interactive' });
|
|
59
|
+
const { handleSessionDeleteCommand } = await import('../session-commands.js');
|
|
60
|
+
await handleSessionDeleteCommand(agent, sessionId);
|
|
61
|
+
safeExit('session delete', 0);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
if (err instanceof ExitSignal)
|
|
65
|
+
throw err;
|
|
66
|
+
console.error(`❌ dexto session delete command failed: ${err}`);
|
|
67
|
+
safeExit('session delete', 1, 'error');
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
if (agent) {
|
|
71
|
+
await agent.stop().catch(() => { });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
@@ -9,7 +9,7 @@ import { selectProvider, getProviderDisplayName, getProviderEnvVar, providerRequ
|
|
|
9
9
|
import { setupLocalModels, setupOllamaModels, hasSelectedModel, getModelFromResult, } from '../utils/local-model-setup.js';
|
|
10
10
|
import { requiresSetup } from '../utils/setup-utils.js';
|
|
11
11
|
import { canUseDextoProvider } from '../utils/dexto-setup.js';
|
|
12
|
-
import {
|
|
12
|
+
import { handleAutoLogin } from './auth/login.js';
|
|
13
13
|
import { loadAuth, getDextoApiClient } from '../auth/index.js';
|
|
14
14
|
import { DEXTO_CREDITS_URL } from '../auth/constants.js';
|
|
15
15
|
import * as p from '@clack/prompts';
|
|
@@ -431,16 +431,16 @@ async function handleDextoProviderSetup(options = {}) {
|
|
|
431
431
|
const hasKey = await canUseDextoProvider();
|
|
432
432
|
if (!hasKey) {
|
|
433
433
|
p.note(`Dexto gives you instant access to ${chalk.cyan('all AI models')} with a single account.\n\n` +
|
|
434
|
-
`We'll
|
|
434
|
+
`We'll guide you through device-code login.`, 'Login Required');
|
|
435
435
|
const shouldLogin = await p.confirm({
|
|
436
|
-
message: 'Continue with
|
|
436
|
+
message: 'Continue with Dexto login?',
|
|
437
437
|
initialValue: true,
|
|
438
438
|
});
|
|
439
439
|
if (p.isCancel(shouldLogin) || !shouldLogin) {
|
|
440
440
|
return abort('Setup cancelled');
|
|
441
441
|
}
|
|
442
442
|
try {
|
|
443
|
-
await
|
|
443
|
+
await handleAutoLogin();
|
|
444
444
|
// Verify key was actually provisioned (provisionKeys silently catches errors)
|
|
445
445
|
if (!(await canUseDextoProvider())) {
|
|
446
446
|
p.log.error('API key provisioning failed. Please try again or use `dexto setup` with a different provider.');
|
|
@@ -25,9 +25,9 @@ export declare function shouldPromptForSync(): Promise<boolean>;
|
|
|
25
25
|
*
|
|
26
26
|
* @example
|
|
27
27
|
* ```bash
|
|
28
|
-
* dexto sync
|
|
29
|
-
* dexto
|
|
30
|
-
* dexto
|
|
28
|
+
* dexto agents sync # Interactive - prompt for each
|
|
29
|
+
* dexto agents sync --list # Show what would be updated
|
|
30
|
+
* dexto agents sync --force # Update all without prompting
|
|
31
31
|
* ```
|
|
32
32
|
*/
|
|
33
33
|
export declare function handleSyncAgentsCommand(options: SyncAgentsCommandOptions): Promise<void>;
|
|
@@ -243,9 +243,9 @@ function formatStatus(status) {
|
|
|
243
243
|
*
|
|
244
244
|
* @example
|
|
245
245
|
* ```bash
|
|
246
|
-
* dexto sync
|
|
247
|
-
* dexto
|
|
248
|
-
* dexto
|
|
246
|
+
* dexto agents sync # Interactive - prompt for each
|
|
247
|
+
* dexto agents sync --list # Show what would be updated
|
|
248
|
+
* dexto agents sync --force # Update all without prompting
|
|
249
249
|
* ```
|
|
250
250
|
*/
|
|
251
251
|
export async function handleSyncAgentsCommand(options) {
|
|
@@ -363,7 +363,7 @@ export async function handleSyncAgentsCommand(options) {
|
|
|
363
363
|
console.log('');
|
|
364
364
|
// If list mode, stop here
|
|
365
365
|
if (list) {
|
|
366
|
-
p.outro('Use `dexto sync
|
|
366
|
+
p.outro('Use `dexto agents sync` to update agents');
|
|
367
367
|
return;
|
|
368
368
|
}
|
|
369
369
|
// No updates needed
|
|
@@ -4,13 +4,13 @@ declare const UninstallCommandSchema: z.ZodObject<{
|
|
|
4
4
|
all: z.ZodDefault<z.ZodBoolean>;
|
|
5
5
|
force: z.ZodDefault<z.ZodBoolean>;
|
|
6
6
|
}, "strict", z.ZodTypeAny, {
|
|
7
|
-
all: boolean;
|
|
8
7
|
agents: string[];
|
|
9
8
|
force: boolean;
|
|
9
|
+
all: boolean;
|
|
10
10
|
}, {
|
|
11
11
|
agents: string[];
|
|
12
|
-
all?: boolean | undefined;
|
|
13
12
|
force?: boolean | undefined;
|
|
13
|
+
all?: boolean | undefined;
|
|
14
14
|
}>;
|
|
15
15
|
export type UninstallCommandOptions = z.output<typeof UninstallCommandSchema>;
|
|
16
16
|
export declare function handleUninstallCommand(agents: string[], options: Partial<UninstallCommandOptions>): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/cli/modes/cli.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAsBpD,wBAAsB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuLxE"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { logger } from '@dexto/core';
|
|
4
|
+
import { safeExit, ExitSignal } from '../../analytics/wrapper.js';
|
|
5
|
+
async function getMostRecentSessionId(agent) {
|
|
6
|
+
const sessionIds = await agent.listSessions();
|
|
7
|
+
if (sessionIds.length === 0) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
let mostRecentId = null;
|
|
11
|
+
let mostRecentActivity = 0;
|
|
12
|
+
for (const sessionId of sessionIds) {
|
|
13
|
+
const metadata = await agent.getSessionMetadata(sessionId);
|
|
14
|
+
if (metadata && metadata.lastActivity > mostRecentActivity) {
|
|
15
|
+
mostRecentActivity = metadata.lastActivity;
|
|
16
|
+
mostRecentId = sessionId;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return mostRecentId;
|
|
20
|
+
}
|
|
21
|
+
export async function runCliMode(context) {
|
|
22
|
+
const { agent, opts, validatedConfig, resolvedPath, initialPrompt, getVersionCheckResult } = context;
|
|
23
|
+
const needsHandler = validatedConfig.permissions.mode === 'manual' || validatedConfig.elicitation.enabled;
|
|
24
|
+
if (needsHandler) {
|
|
25
|
+
const { createCLIApprovalHandler } = await import('../approval/index.js');
|
|
26
|
+
const handler = createCLIApprovalHandler(agent);
|
|
27
|
+
agent.setApprovalHandler(handler);
|
|
28
|
+
logger.debug('CLI approval handler configured for Ink CLI');
|
|
29
|
+
}
|
|
30
|
+
await agent.start();
|
|
31
|
+
try {
|
|
32
|
+
const llmConfig = agent.getCurrentLLMConfig();
|
|
33
|
+
const { requiresApiKey } = await import('@dexto/core');
|
|
34
|
+
if (requiresApiKey(llmConfig.provider) && !llmConfig.apiKey?.trim()) {
|
|
35
|
+
const { interactiveApiKeySetup } = await import('../utils/api-key-setup.js');
|
|
36
|
+
console.log(chalk.yellow(`\n⚠️ API key required for provider '${llmConfig.provider}'\n`));
|
|
37
|
+
const setupResult = await interactiveApiKeySetup(llmConfig.provider, {
|
|
38
|
+
exitOnCancel: false,
|
|
39
|
+
model: llmConfig.model,
|
|
40
|
+
});
|
|
41
|
+
if (setupResult.cancelled) {
|
|
42
|
+
safeExit('main', 0, 'api-key-setup-cancelled');
|
|
43
|
+
}
|
|
44
|
+
if (setupResult.skipped) {
|
|
45
|
+
safeExit('main', 0, 'api-key-pending');
|
|
46
|
+
}
|
|
47
|
+
if (setupResult.success && setupResult.apiKey) {
|
|
48
|
+
await agent.switchLLM({
|
|
49
|
+
provider: llmConfig.provider,
|
|
50
|
+
model: llmConfig.model,
|
|
51
|
+
apiKey: setupResult.apiKey,
|
|
52
|
+
});
|
|
53
|
+
logger.info('API key configured successfully, continuing...');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
let cliSessionId;
|
|
57
|
+
if (opts.resume) {
|
|
58
|
+
const existing = await agent.getSession(opts.resume);
|
|
59
|
+
if (!existing) {
|
|
60
|
+
console.error(`❌ Session '${opts.resume}' not found`);
|
|
61
|
+
console.error('💡 Use `dexto session list` to see available sessions');
|
|
62
|
+
safeExit('main', 1, 'resume-failed');
|
|
63
|
+
}
|
|
64
|
+
cliSessionId = opts.resume;
|
|
65
|
+
}
|
|
66
|
+
else if (opts.continue) {
|
|
67
|
+
const mostRecentSessionId = await getMostRecentSessionId(agent);
|
|
68
|
+
if (mostRecentSessionId) {
|
|
69
|
+
cliSessionId = mostRecentSessionId;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const session = await agent.createSession();
|
|
73
|
+
cliSessionId = session.id;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const session = await agent.createSession();
|
|
78
|
+
cliSessionId = session.id;
|
|
79
|
+
}
|
|
80
|
+
const cliUpdateInfo = await getVersionCheckResult();
|
|
81
|
+
const { shouldPromptForSync, handleSyncAgentsCommand } = await import('../commands/sync-agents.js');
|
|
82
|
+
const needsSync = await shouldPromptForSync();
|
|
83
|
+
if (needsSync) {
|
|
84
|
+
const shouldSync = await p.confirm({
|
|
85
|
+
message: 'Agent config updates available. Sync now?',
|
|
86
|
+
initialValue: true,
|
|
87
|
+
});
|
|
88
|
+
if (!p.isCancel(shouldSync) && shouldSync) {
|
|
89
|
+
await handleSyncAgentsCommand({ force: true, quiet: true });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const originalConsole = {
|
|
93
|
+
log: console.log,
|
|
94
|
+
error: console.error,
|
|
95
|
+
warn: console.warn,
|
|
96
|
+
info: console.info,
|
|
97
|
+
};
|
|
98
|
+
const noOp = () => { };
|
|
99
|
+
console.log = noOp;
|
|
100
|
+
console.error = noOp;
|
|
101
|
+
console.warn = noOp;
|
|
102
|
+
console.info = noOp;
|
|
103
|
+
let inkError = undefined;
|
|
104
|
+
try {
|
|
105
|
+
const [{ startInkCliRefactored, setTuiRuntimeServices }, { registerGracefulShutdown }, { applyLayeredEnvironmentLoading }, { getProviderDisplayName, isValidApiKeyFormat, getProviderInstructions }, { performDeviceCodeLogin, persistOAuthLoginResult, ensureDextoApiKeyForAuthToken, loadAuth, storeAuth, removeAuth, removeDextoApiKeyFromEnv, }, { isUsingDextoCredits }, { canUseDextoProvider }, { capture },] = await Promise.all([
|
|
106
|
+
import('@dexto/tui'),
|
|
107
|
+
import('../../utils/graceful-shutdown.js'),
|
|
108
|
+
import('../../utils/env.js'),
|
|
109
|
+
import('../utils/provider-setup.js'),
|
|
110
|
+
import('../auth/index.js'),
|
|
111
|
+
import('../../config/effective-llm.js'),
|
|
112
|
+
import('../utils/dexto-setup.js'),
|
|
113
|
+
import('../../analytics/index.js'),
|
|
114
|
+
]);
|
|
115
|
+
setTuiRuntimeServices({
|
|
116
|
+
registerGracefulShutdown,
|
|
117
|
+
capture: (event, properties) => {
|
|
118
|
+
capture(event, properties);
|
|
119
|
+
},
|
|
120
|
+
applyLayeredEnvironmentLoading,
|
|
121
|
+
getProviderDisplayName,
|
|
122
|
+
isValidApiKeyFormat,
|
|
123
|
+
getProviderInstructions,
|
|
124
|
+
performDeviceCodeLogin,
|
|
125
|
+
persistOAuthLoginResult,
|
|
126
|
+
ensureDextoApiKeyForAuthToken,
|
|
127
|
+
loadAuth,
|
|
128
|
+
storeAuth,
|
|
129
|
+
removeAuth,
|
|
130
|
+
removeDextoApiKeyFromEnv,
|
|
131
|
+
isUsingDextoCredits,
|
|
132
|
+
canUseDextoProvider,
|
|
133
|
+
});
|
|
134
|
+
await startInkCliRefactored(agent, cliSessionId, {
|
|
135
|
+
updateInfo: cliUpdateInfo ?? undefined,
|
|
136
|
+
configFilePath: resolvedPath,
|
|
137
|
+
...(initialPrompt && { initialPrompt }),
|
|
138
|
+
bypassPermissions: opts.bypassPermissions,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
inkError = error;
|
|
143
|
+
}
|
|
144
|
+
finally {
|
|
145
|
+
console.log = originalConsole.log;
|
|
146
|
+
console.error = originalConsole.error;
|
|
147
|
+
console.warn = originalConsole.warn;
|
|
148
|
+
console.info = originalConsole.info;
|
|
149
|
+
}
|
|
150
|
+
if (inkError) {
|
|
151
|
+
if (inkError instanceof ExitSignal)
|
|
152
|
+
throw inkError;
|
|
153
|
+
const errorMessage = inkError instanceof Error ? inkError.message : String(inkError);
|
|
154
|
+
console.error(`❌ Ink CLI failed: ${errorMessage}`);
|
|
155
|
+
if (inkError instanceof Error && inkError.stack) {
|
|
156
|
+
console.error(inkError.stack);
|
|
157
|
+
}
|
|
158
|
+
safeExit('main', 1, 'ink-cli-error');
|
|
159
|
+
}
|
|
160
|
+
safeExit('main', 0);
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
try {
|
|
164
|
+
await agent.stop();
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// Ignore shutdown errors
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ValidatedAgentConfig } from '@dexto/agent-config';
|
|
2
|
+
import type { DextoAgent } from '@dexto/core';
|
|
3
|
+
import type { UpdateInfo } from '../utils/version-check.js';
|
|
4
|
+
export interface MainModeOptions {
|
|
5
|
+
mode: string;
|
|
6
|
+
port?: string;
|
|
7
|
+
resume?: string;
|
|
8
|
+
continue?: boolean;
|
|
9
|
+
bypassPermissions?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface MainModeContext {
|
|
12
|
+
agent: DextoAgent;
|
|
13
|
+
opts: MainModeOptions;
|
|
14
|
+
validatedConfig: ValidatedAgentConfig;
|
|
15
|
+
resolvedPath: string;
|
|
16
|
+
derivedAgentId: string;
|
|
17
|
+
initialPrompt: string | undefined;
|
|
18
|
+
getVersionCheckResult: () => Promise<UpdateInfo | null>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/cli/modes/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,eAAe,CAAC;IACtB,eAAe,EAAE,oBAAoB,CAAC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,qBAAqB,EAAE,MAAM,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;CAC3D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/cli/modes/dispatch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAqD9E"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { safeExit, ExitSignal } from '../../analytics/wrapper.js';
|
|
2
|
+
export async function dispatchMainMode(context) {
|
|
3
|
+
const mode = context.opts.mode;
|
|
4
|
+
try {
|
|
5
|
+
switch (mode) {
|
|
6
|
+
case 'cli': {
|
|
7
|
+
const { runCliMode } = await import('./cli.js');
|
|
8
|
+
await runCliMode(context);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
case 'web': {
|
|
12
|
+
const { runWebMode } = await import('./web.js');
|
|
13
|
+
await runWebMode(context);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
case 'server': {
|
|
17
|
+
const { runServerMode } = await import('./server.js');
|
|
18
|
+
await runServerMode(context);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
case 'mcp': {
|
|
22
|
+
const { runMcpMode } = await import('./mcp.js');
|
|
23
|
+
await runMcpMode(context);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
default:
|
|
27
|
+
if (mode === 'discord' || mode === 'telegram') {
|
|
28
|
+
console.error(`❌ Error: '${mode}' mode has been moved to examples`);
|
|
29
|
+
console.error('');
|
|
30
|
+
console.error(`The ${mode} bot is now a standalone example that you can customize.`);
|
|
31
|
+
console.error('');
|
|
32
|
+
console.error(`📖 See: examples/${mode}-bot/README.md`);
|
|
33
|
+
console.error('');
|
|
34
|
+
console.error('To run it:');
|
|
35
|
+
console.error(` cd examples/${mode}-bot`);
|
|
36
|
+
console.error(' pnpm install');
|
|
37
|
+
console.error(' pnpm start');
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.error(`❌ Unknown mode '${mode}'. Use web, cli, server, or mcp.`);
|
|
41
|
+
}
|
|
42
|
+
safeExit('main', 1, 'unknown-mode');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
if (err instanceof ExitSignal)
|
|
47
|
+
throw err;
|
|
48
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
49
|
+
console.error(`❌ Failed to start '${mode}' mode: ${message}`);
|
|
50
|
+
safeExit('main', 1, 'mode-startup-failed');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../../src/cli/modes/mcp.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAsB,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBxE"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createAgentCard } from '@dexto/core';
|
|
2
|
+
import { safeExit } from '../../analytics/wrapper.js';
|
|
3
|
+
export async function runMcpMode(context) {
|
|
4
|
+
const { agent } = context;
|
|
5
|
+
const agentCardConfig = agent.config.agentCard || {
|
|
6
|
+
name: 'dexto',
|
|
7
|
+
version: '1.0.0',
|
|
8
|
+
};
|
|
9
|
+
try {
|
|
10
|
+
const agentCardData = createAgentCard({
|
|
11
|
+
defaultName: agentCardConfig.name ?? 'dexto',
|
|
12
|
+
defaultVersion: agentCardConfig.version ?? '1.0.0',
|
|
13
|
+
defaultBaseUrl: 'stdio://local-dexto',
|
|
14
|
+
}, agentCardConfig);
|
|
15
|
+
const { createMcpTransport, initializeMcpServer } = await import('@dexto/server');
|
|
16
|
+
const mcpTransport = await createMcpTransport('stdio');
|
|
17
|
+
await initializeMcpServer(agent, agentCardData, mcpTransport);
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
process.stderr.write(`MCP server startup failed: ${err}\n`);
|
|
21
|
+
safeExit('main', 1, 'mcp-startup-failed');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/cli/modes/server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAsB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C3E"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { getPort } from '../../utils/port-utils.js';
|
|
2
|
+
export async function runServerMode(context) {
|
|
3
|
+
const { agent, opts, derivedAgentId, resolvedPath, getVersionCheckResult } = context;
|
|
4
|
+
const { startHonoApiServer } = await import('../../api/server-hono.js');
|
|
5
|
+
const agentCard = agent.config.agentCard ?? {};
|
|
6
|
+
const defaultPort = (() => {
|
|
7
|
+
if (!opts.port) {
|
|
8
|
+
return 3001;
|
|
9
|
+
}
|
|
10
|
+
const rawPort = opts.port.trim();
|
|
11
|
+
const parsedPort = Number(rawPort);
|
|
12
|
+
if (!/^\d+$/.test(rawPort) ||
|
|
13
|
+
!Number.isInteger(parsedPort) ||
|
|
14
|
+
parsedPort <= 0 ||
|
|
15
|
+
parsedPort > 65535) {
|
|
16
|
+
throw new Error(`Invalid --port value "${opts.port}". Use a port between 1 and 65535.`);
|
|
17
|
+
}
|
|
18
|
+
return parsedPort;
|
|
19
|
+
})();
|
|
20
|
+
const apiPort = getPort(process.env.PORT, defaultPort, 'PORT');
|
|
21
|
+
const apiUrl = process.env.DEXTO_URL ?? `http://localhost:${apiPort}`;
|
|
22
|
+
console.log('🌐 Starting server (REST APIs + SSE)...');
|
|
23
|
+
await startHonoApiServer(agent, apiPort, agentCard, derivedAgentId, resolvedPath);
|
|
24
|
+
console.log(`✅ Server running at ${apiUrl}`);
|
|
25
|
+
console.log('Available endpoints:');
|
|
26
|
+
console.log(' POST /api/message - Send async message');
|
|
27
|
+
console.log(' POST /api/message-sync - Send sync message');
|
|
28
|
+
console.log(' POST /api/reset - Reset conversation');
|
|
29
|
+
console.log(' GET /api/mcp/servers - List MCP servers');
|
|
30
|
+
console.log(' SSE support available for real-time events');
|
|
31
|
+
const serverUpdateInfo = await getVersionCheckResult();
|
|
32
|
+
if (serverUpdateInfo) {
|
|
33
|
+
const { displayUpdateNotification } = await import('../utils/version-check.js');
|
|
34
|
+
displayUpdateNotification(serverUpdateInfo);
|
|
35
|
+
}
|
|
36
|
+
}
|