dexto 1.6.8 → 1.6.10
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.d.ts.map +1 -1
- package/dist/cli/commands/sync-agents.js +16 -7
- 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>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-agents.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/sync-agents.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACrC,wCAAwC;IACxC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,mCAAmC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"sync-agents.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/sync-agents.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACrC,wCAAwC;IACxC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,mCAAmC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AA0MD;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CAyB5D;AAoDD;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiO9F"}
|
|
@@ -65,10 +65,19 @@ async function getBundledAgentHash(agentEntry) {
|
|
|
65
65
|
/**
|
|
66
66
|
* Get hash of installed agent
|
|
67
67
|
*/
|
|
68
|
-
async function getInstalledAgentHash(agentId) {
|
|
68
|
+
async function getInstalledAgentHash(agentId, agentEntry) {
|
|
69
69
|
try {
|
|
70
70
|
const installedPath = path.join(getDextoGlobalPath('agents'), agentId);
|
|
71
71
|
const stat = await fs.stat(installedPath);
|
|
72
|
+
// Single-file bundled agents are installed inside an agent directory.
|
|
73
|
+
// Hash the installed YAML file so bundled vs installed comparisons stay symmetric.
|
|
74
|
+
if (agentEntry && !agentEntry.source.endsWith('/')) {
|
|
75
|
+
if (!stat.isDirectory()) {
|
|
76
|
+
return await hashFile(installedPath);
|
|
77
|
+
}
|
|
78
|
+
const installedFile = path.join(installedPath, path.basename(agentEntry.source));
|
|
79
|
+
return await hashFile(installedFile);
|
|
80
|
+
}
|
|
72
81
|
if (stat.isDirectory()) {
|
|
73
82
|
return await hashDirectory(installedPath);
|
|
74
83
|
}
|
|
@@ -123,7 +132,7 @@ async function getAgentStatus(agentId, agentEntry) {
|
|
|
123
132
|
}
|
|
124
133
|
try {
|
|
125
134
|
const bundledHash = await getBundledAgentHash(agentEntry);
|
|
126
|
-
const installedHash = await getInstalledAgentHash(agentId);
|
|
135
|
+
const installedHash = await getInstalledAgentHash(agentId, agentEntry);
|
|
127
136
|
if (!bundledHash || !installedHash) {
|
|
128
137
|
return {
|
|
129
138
|
id: agentId,
|
|
@@ -178,7 +187,7 @@ export async function shouldPromptForSync() {
|
|
|
178
187
|
if (!agentEntry)
|
|
179
188
|
continue;
|
|
180
189
|
const bundledHash = await getBundledAgentHash(agentEntry);
|
|
181
|
-
const installedHash = await getInstalledAgentHash(agentId);
|
|
190
|
+
const installedHash = await getInstalledAgentHash(agentId, agentEntry);
|
|
182
191
|
if (bundledHash && installedHash && bundledHash !== installedHash) {
|
|
183
192
|
return true;
|
|
184
193
|
}
|
|
@@ -243,9 +252,9 @@ function formatStatus(status) {
|
|
|
243
252
|
*
|
|
244
253
|
* @example
|
|
245
254
|
* ```bash
|
|
246
|
-
* dexto sync
|
|
247
|
-
* dexto
|
|
248
|
-
* dexto
|
|
255
|
+
* dexto agents sync # Interactive - prompt for each
|
|
256
|
+
* dexto agents sync --list # Show what would be updated
|
|
257
|
+
* dexto agents sync --force # Update all without prompting
|
|
249
258
|
* ```
|
|
250
259
|
*/
|
|
251
260
|
export async function handleSyncAgentsCommand(options) {
|
|
@@ -363,7 +372,7 @@ export async function handleSyncAgentsCommand(options) {
|
|
|
363
372
|
console.log('');
|
|
364
373
|
// If list mode, stop here
|
|
365
374
|
if (list) {
|
|
366
|
-
p.outro('Use `dexto sync
|
|
375
|
+
p.outro('Use `dexto agents sync` to update agents');
|
|
367
376
|
return;
|
|
368
377
|
}
|
|
369
378
|
// 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
|
+
}
|