dexto 1.5.8 → 1.6.1
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 +3 -3
- package/dist/agents/agent-template.yml +2 -2
- package/dist/agents/coding-agent/README.md +10 -10
- package/dist/agents/coding-agent/coding-agent.yml +84 -83
- package/dist/agents/default-agent.yml +32 -47
- package/dist/agents/explore-agent/explore-agent.yml +3 -6
- package/dist/agents/image-editor-agent/image-editor-agent.yml +1 -1
- package/dist/agents/nano-banana-agent/nano-banana-agent.yml +1 -1
- package/dist/agents/podcast-agent/podcast-agent.yml +1 -1
- package/dist/agents/product-name-researcher/product-name-researcher.yml +1 -1
- package/dist/agents/sora-video-agent/sora-video-agent.yml +4 -6
- package/dist/agents/triage-demo/triage-agent.yml +1 -1
- package/dist/analytics/events.d.ts +1 -1
- package/dist/analytics/events.d.ts.map +1 -1
- package/dist/api/mcp/tool-aggregation-handler.d.ts +2 -2
- package/dist/api/server-hono.d.ts +2 -2
- package/dist/api/server-hono.d.ts.map +1 -1
- package/dist/api/server-hono.js +37 -60
- package/dist/cli/approval/cli-approval-handler.d.ts +10 -3
- package/dist/cli/approval/cli-approval-handler.d.ts.map +1 -1
- package/dist/cli/approval/cli-approval-handler.js +1 -1
- package/dist/cli/assets/sounds/SOURCES.md +35 -0
- package/dist/cli/assets/sounds/boot.wav +0 -0
- package/dist/cli/assets/sounds/chime.wav +0 -0
- package/dist/cli/assets/sounds/coin.wav +0 -0
- package/dist/cli/assets/sounds/confirm.wav +0 -0
- package/dist/cli/assets/sounds/levelup.wav +0 -0
- package/dist/cli/assets/sounds/ping.wav +0 -0
- package/dist/cli/assets/sounds/powerup.wav +0 -0
- package/dist/cli/assets/sounds/startup.wav +0 -0
- package/dist/cli/assets/sounds/success.wav +0 -0
- package/dist/cli/assets/sounds/treasure.wav +0 -0
- package/dist/cli/assets/sounds/win.wav +0 -0
- package/dist/cli/commands/create-app.d.ts +1 -11
- package/dist/cli/commands/create-app.d.ts.map +1 -1
- package/dist/cli/commands/create-app.js +21 -545
- package/dist/cli/commands/create-image.d.ts.map +1 -1
- package/dist/cli/commands/create-image.js +54 -53
- package/dist/cli/commands/image.d.ts +52 -0
- package/dist/cli/commands/image.d.ts.map +1 -0
- package/dist/cli/commands/image.js +118 -0
- package/dist/cli/commands/index.d.ts +2 -1
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +3 -1
- package/dist/cli/commands/init-app.d.ts +4 -8
- package/dist/cli/commands/init-app.d.ts.map +1 -1
- package/dist/cli/commands/init-app.js +37 -161
- package/dist/cli/commands/interactive-commands/command-parser.d.ts +2 -0
- package/dist/cli/commands/interactive-commands/command-parser.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/commands.d.ts +1 -1
- package/dist/cli/commands/interactive-commands/commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/commands.js +2 -2
- package/dist/cli/commands/interactive-commands/exit-handler.d.ts +12 -0
- package/dist/cli/commands/interactive-commands/exit-handler.d.ts.map +1 -0
- package/dist/cli/commands/interactive-commands/exit-handler.js +20 -0
- package/dist/cli/commands/interactive-commands/exit-stats.d.ts +24 -0
- package/dist/cli/commands/interactive-commands/exit-stats.d.ts.map +1 -0
- package/dist/cli/commands/interactive-commands/exit-stats.js +17 -0
- package/dist/cli/commands/interactive-commands/general-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/general-commands.js +55 -5
- package/dist/cli/commands/interactive-commands/prompt-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/prompt-commands.js +14 -74
- package/dist/cli/commands/interactive-commands/session/index.d.ts +2 -1
- package/dist/cli/commands/interactive-commands/session/index.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/session/index.js +2 -1
- package/dist/cli/commands/interactive-commands/session/session-commands.d.ts +2 -2
- package/dist/cli/commands/interactive-commands/session/session-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/session/session-commands.js +2 -4
- package/dist/cli/commands/interactive-commands/system/system-commands.d.ts +1 -13
- package/dist/cli/commands/interactive-commands/system/system-commands.d.ts.map +1 -1
- package/dist/cli/commands/interactive-commands/system/system-commands.js +52 -83
- package/dist/cli/commands/plugin.d.ts +4 -4
- package/dist/cli/commands/sync-agents.d.ts +2 -12
- package/dist/cli/commands/sync-agents.d.ts.map +1 -1
- package/dist/cli/commands/sync-agents.js +2 -50
- package/dist/cli/ink-cli/InkCLIRefactored.d.ts +7 -1
- package/dist/cli/ink-cli/InkCLIRefactored.d.ts.map +1 -1
- package/dist/cli/ink-cli/InkCLIRefactored.js +138 -27
- package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts +2 -2
- package/dist/cli/ink-cli/components/ApprovalPrompt.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ApprovalPrompt.js +85 -30
- package/dist/cli/ink-cli/components/BackgroundTasksPanel.js +1 -1
- package/dist/cli/ink-cli/components/ElicitationForm.d.ts +5 -3
- package/dist/cli/ink-cli/components/ElicitationForm.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ElicitationForm.js +414 -180
- package/dist/cli/ink-cli/components/Footer.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/Footer.js +1 -2
- package/dist/cli/ink-cli/components/ResourceAutocomplete.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ResourceAutocomplete.js +20 -11
- package/dist/cli/ink-cli/components/SlashCommandAutocomplete.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/SlashCommandAutocomplete.js +47 -67
- package/dist/cli/ink-cli/components/StatusBar.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/StatusBar.js +20 -10
- package/dist/cli/ink-cli/components/TodoPanel.js +1 -1
- package/dist/cli/ink-cli/components/base/BaseSelector.d.ts +2 -1
- package/dist/cli/ink-cli/components/base/BaseSelector.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/base/BaseSelector.js +37 -27
- package/dist/cli/ink-cli/components/chat/Header.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/Header.js +1 -1
- package/dist/cli/ink-cli/components/chat/MessageItem.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/MessageItem.js +3 -1
- package/dist/cli/ink-cli/components/chat/ToolIcon.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/ToolIcon.js +5 -15
- package/dist/cli/ink-cli/components/chat/styled-boxes/ConfigBox.js +1 -1
- package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/styled-boxes/LogConfigBox.js +1 -1
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts +3 -1
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.js +5 -3
- package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts +3 -1
- package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/modes/StaticCLI.js +10 -3
- package/dist/cli/ink-cli/components/overlays/CommandOutputOverlay.d.ts +13 -0
- package/dist/cli/ink-cli/components/overlays/CommandOutputOverlay.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/CommandOutputOverlay.js +60 -0
- package/dist/cli/ink-cli/components/overlays/LogLevelSelector.js +1 -1
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/ModelSelectorRefactored.js +213 -100
- package/dist/cli/ink-cli/components/overlays/PromptList.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/PromptList.js +12 -16
- package/dist/cli/ink-cli/components/overlays/SoundsSelector.d.ts +21 -0
- package/dist/cli/ink-cli/components/overlays/SoundsSelector.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/overlays/SoundsSelector.js +566 -0
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.d.ts +1 -1
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/ToolBrowser.js +100 -45
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/overlays/custom-model-wizard/LocalModelWizard.js +8 -13
- package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.d.ts +3 -3
- package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/renderers/FilePreviewRenderer.js +6 -5
- package/dist/cli/ink-cli/components/renderers/FileRenderer.d.ts +3 -1
- package/dist/cli/ink-cli/components/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/renderers/FileRenderer.js +18 -7
- package/dist/cli/ink-cli/components/renderers/ShellRenderer.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/renderers/ShellRenderer.js +7 -17
- package/dist/cli/ink-cli/components/renderers/index.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/renderers/index.js +1 -1
- package/dist/cli/ink-cli/components/shared/FocusOverlayFrame.d.ts +7 -0
- package/dist/cli/ink-cli/components/shared/FocusOverlayFrame.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/shared/FocusOverlayFrame.js +8 -0
- package/dist/cli/ink-cli/components/shared/HintBar.d.ts +6 -0
- package/dist/cli/ink-cli/components/shared/HintBar.d.ts.map +1 -0
- package/dist/cli/ink-cli/components/shared/HintBar.js +6 -0
- package/dist/cli/ink-cli/constants/spinnerFrames.d.ts +2 -0
- package/dist/cli/ink-cli/constants/spinnerFrames.d.ts.map +1 -0
- package/dist/cli/ink-cli/constants/spinnerFrames.js +1 -0
- package/dist/cli/ink-cli/constants/tips.d.ts.map +1 -1
- package/dist/cli/ink-cli/constants/tips.js +2 -1
- package/dist/cli/ink-cli/containers/InputContainer.d.ts +4 -0
- package/dist/cli/ink-cli/containers/InputContainer.d.ts.map +1 -1
- package/dist/cli/ink-cli/containers/InputContainer.js +47 -21
- package/dist/cli/ink-cli/containers/OverlayContainer.d.ts +2 -0
- package/dist/cli/ink-cli/containers/OverlayContainer.d.ts.map +1 -1
- package/dist/cli/ink-cli/containers/OverlayContainer.js +101 -40
- package/dist/cli/ink-cli/hooks/useAgentEvents.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useAgentEvents.js +15 -16
- package/dist/cli/ink-cli/hooks/useAnimationTick.d.ts +11 -0
- package/dist/cli/ink-cli/hooks/useAnimationTick.d.ts.map +1 -0
- package/dist/cli/ink-cli/hooks/useAnimationTick.js +54 -0
- package/dist/cli/ink-cli/hooks/useCLIState.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useCLIState.js +1 -0
- package/dist/cli/ink-cli/hooks/useTokenCounter.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useTokenCounter.js +7 -4
- package/dist/cli/ink-cli/services/CommandService.d.ts +1 -1
- package/dist/cli/ink-cli/services/CommandService.d.ts.map +1 -1
- package/dist/cli/ink-cli/services/CommandService.js +2 -2
- package/dist/cli/ink-cli/services/processStream.d.ts +2 -2
- package/dist/cli/ink-cli/services/processStream.d.ts.map +1 -1
- package/dist/cli/ink-cli/services/processStream.js +27 -19
- package/dist/cli/ink-cli/state/initialState.d.ts.map +1 -1
- package/dist/cli/ink-cli/state/initialState.js +1 -0
- package/dist/cli/ink-cli/state/types.d.ts +15 -3
- package/dist/cli/ink-cli/state/types.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/commandOverlays.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/commandOverlays.js +1 -0
- package/dist/cli/ink-cli/utils/elicitationSchema.d.ts +11 -0
- package/dist/cli/ink-cli/utils/elicitationSchema.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/elicitationSchema.js +80 -0
- package/dist/cli/ink-cli/utils/index.d.ts +1 -1
- package/dist/cli/ink-cli/utils/index.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/index.js +1 -1
- package/dist/cli/ink-cli/utils/messageFormatting.d.ts +10 -19
- package/dist/cli/ink-cli/utils/messageFormatting.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/messageFormatting.js +43 -262
- package/dist/cli/ink-cli/utils/overlayPresentation.d.ts +19 -0
- package/dist/cli/ink-cli/utils/overlayPresentation.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/overlayPresentation.js +33 -0
- package/dist/cli/ink-cli/utils/overlaySizing.d.ts +19 -0
- package/dist/cli/ink-cli/utils/overlaySizing.d.ts.map +1 -0
- package/dist/cli/ink-cli/utils/overlaySizing.js +11 -0
- package/dist/cli/ink-cli/utils/soundNotification.d.ts +19 -13
- package/dist/cli/ink-cli/utils/soundNotification.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/soundNotification.js +120 -97
- package/dist/cli/ink-cli/utils/toolUtils.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/toolUtils.js +2 -9
- package/dist/cli/utils/config-validation.d.ts +11 -11
- package/dist/cli/utils/config-validation.d.ts.map +1 -1
- package/dist/cli/utils/config-validation.js +56 -290
- package/dist/cli/utils/image-store.d.ts +16 -0
- package/dist/cli/utils/image-store.d.ts.map +1 -0
- package/dist/cli/utils/image-store.js +289 -0
- package/dist/cli/utils/scaffolding-utils.d.ts +5 -0
- package/dist/cli/utils/scaffolding-utils.d.ts.map +1 -1
- package/dist/cli/utils/scaffolding-utils.js +46 -4
- package/dist/cli/utils/template-engine.d.ts +28 -16
- package/dist/cli/utils/template-engine.d.ts.map +1 -1
- package/dist/cli/utils/template-engine.js +339 -479
- package/dist/config/cli-overrides.d.ts +4 -3
- package/dist/config/cli-overrides.d.ts.map +1 -1
- package/dist/config/cli-overrides.js +7 -9
- package/dist/index-main.d.ts +2 -0
- package/dist/index-main.d.ts.map +1 -0
- package/dist/index-main.js +1554 -0
- package/dist/index.js +2 -1589
- package/dist/utils/session-logger-factory.d.ts +3 -0
- package/dist/utils/session-logger-factory.d.ts.map +1 -0
- package/dist/utils/session-logger-factory.js +34 -0
- package/dist/webui/assets/{index-Cz2z7NQ8.js → index-CKhumsZA.js} +231 -231
- package/dist/webui/index.html +1 -1
- package/package.json +11 -8
- package/dist/cli/cli-subscriber.d.ts +0 -45
- package/dist/cli/cli-subscriber.d.ts.map +0 -1
- package/dist/cli/cli-subscriber.js +0 -204
|
@@ -5,12 +5,15 @@ import fsExtra from 'fs-extra';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { getPackageManager, getPackageManagerInstallCommand } from '../utils/package-mgmt.js';
|
|
7
7
|
import { executeWithTimeout } from '../utils/execute.js';
|
|
8
|
-
import {
|
|
9
|
-
import { logger } from '@dexto/core';
|
|
10
|
-
import { updateDextoConfigFile } from '../utils/project-utils.js';
|
|
8
|
+
import { getDefaultModelForProvider } from '@dexto/core';
|
|
11
9
|
import { saveProviderApiKey } from '@dexto/agent-management';
|
|
12
10
|
import { getProviderDisplayName, isValidApiKeyFormat, PROVIDER_OPTIONS, } from '../utils/provider-setup.js';
|
|
13
|
-
|
|
11
|
+
import { generateIndexForCodeFirstDI } from '../utils/template-engine.js';
|
|
12
|
+
function debug(message) {
|
|
13
|
+
if (process.env.DEXTO_DEBUG_INIT === 'true' || process.env.DEXTO_DEBUG_ALL === 'true') {
|
|
14
|
+
console.error(`[dexto:init] ${message}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
14
17
|
/**
|
|
15
18
|
* Get user preferences needed to initialize a Dexto app
|
|
16
19
|
* @returns The user preferences
|
|
@@ -90,11 +93,17 @@ export async function initDexto(directory, createExampleFile = true, llmProvider
|
|
|
90
93
|
const installCommand = getPackageManagerInstallCommand(packageManager);
|
|
91
94
|
spinner.start('Installing Dexto...');
|
|
92
95
|
const label = 'latest';
|
|
93
|
-
|
|
96
|
+
debug(`Installing Dexto using ${packageManager} with install command: ${installCommand} and label: ${label}`);
|
|
94
97
|
try {
|
|
95
|
-
await executeWithTimeout(packageManager, [
|
|
96
|
-
|
|
97
|
-
|
|
98
|
+
await executeWithTimeout(packageManager, [
|
|
99
|
+
installCommand,
|
|
100
|
+
`@dexto/core@${label}`,
|
|
101
|
+
`@dexto/storage@${label}`,
|
|
102
|
+
// Intentionally omit tool packs to keep the example minimal.
|
|
103
|
+
// TODO: Revisit adding a default tool pack once tool IDs no longer require manual qualification.
|
|
104
|
+
'dotenv',
|
|
105
|
+
'tsx',
|
|
106
|
+
], { cwd: process.cwd() });
|
|
98
107
|
}
|
|
99
108
|
catch (installError) {
|
|
100
109
|
// Handle pnpm workspace root add error specifically
|
|
@@ -110,7 +119,7 @@ export async function initDexto(directory, createExampleFile = true, llmProvider
|
|
|
110
119
|
}
|
|
111
120
|
spinner.stop('Dexto installed successfully!');
|
|
112
121
|
spinner.start('Creating Dexto files...');
|
|
113
|
-
// create dexto directories (dexto
|
|
122
|
+
// create dexto directories (dexto)
|
|
114
123
|
const result = await createDextoDirectories(directory);
|
|
115
124
|
if (!result.ok) {
|
|
116
125
|
spinner.stop(chalk.inverse(`Dexto already initialized in ${path.join(directory, 'dexto')}. Would you like to overwrite it?`));
|
|
@@ -124,34 +133,16 @@ export async function initDexto(directory, createExampleFile = true, llmProvider
|
|
|
124
133
|
}
|
|
125
134
|
}
|
|
126
135
|
// create dexto config file
|
|
127
|
-
logger.debug('Creating dexto config file...');
|
|
128
136
|
const dextoDir = path.join(directory, 'dexto');
|
|
129
|
-
const agentsDir = path.join(dextoDir, 'agents');
|
|
130
|
-
let configPath;
|
|
131
|
-
try {
|
|
132
|
-
configPath = await createDextoConfigFile(agentsDir);
|
|
133
|
-
logger.debug(`Dexto config file created at ${configPath}`);
|
|
134
|
-
}
|
|
135
|
-
catch (configError) {
|
|
136
|
-
spinner.stop(chalk.red('Failed to create agent config file'));
|
|
137
|
-
logger.error(`Config creation error: ${configError}`);
|
|
138
|
-
throw new Error(`Failed to create coding-agent.yml: ${configError instanceof Error ? configError.message : String(configError)}`);
|
|
139
|
-
}
|
|
140
|
-
// update dexto config file based on llmProvider
|
|
141
|
-
if (llmProvider) {
|
|
142
|
-
logger.debug(`Updating dexto config file based on llmProvider: ${llmProvider}`);
|
|
143
|
-
await updateDextoConfigFile(configPath, llmProvider);
|
|
144
|
-
logger.debug(`Dexto config file updated with llmProvider: ${llmProvider}`);
|
|
145
|
-
}
|
|
146
137
|
// create dexto example file if requested
|
|
147
138
|
if (createExampleFile) {
|
|
148
|
-
|
|
149
|
-
await createDextoExampleFile(dextoDir);
|
|
150
|
-
|
|
139
|
+
debug('Creating dexto example file...');
|
|
140
|
+
await createDextoExampleFile(dextoDir, { llmProvider });
|
|
141
|
+
debug('Dexto example file created successfully!');
|
|
151
142
|
}
|
|
152
143
|
// add/update .env file (only if user provided a key)
|
|
153
144
|
spinner.start('Saving API key to .env file...');
|
|
154
|
-
|
|
145
|
+
debug(`Saving API key: provider=${llmProvider ?? 'none'}, hasApiKey=${Boolean(llmApiKey)}`);
|
|
155
146
|
if (llmProvider && llmApiKey) {
|
|
156
147
|
await saveProviderApiKey(llmProvider, llmApiKey, process.cwd());
|
|
157
148
|
}
|
|
@@ -159,29 +150,27 @@ export async function initDexto(directory, createExampleFile = true, llmProvider
|
|
|
159
150
|
}
|
|
160
151
|
catch (err) {
|
|
161
152
|
spinner.stop(chalk.inverse(`An error occurred initializing Dexto project - ${err}`));
|
|
162
|
-
|
|
153
|
+
debug(`Error: ${String(err)}`);
|
|
163
154
|
process.exit(1);
|
|
164
155
|
}
|
|
165
156
|
}
|
|
166
157
|
/** Adds notes for users to get started with their new initialized Dexto project */
|
|
167
158
|
export async function postInitDexto(directory) {
|
|
168
159
|
const nextSteps = [
|
|
169
|
-
`1. Run the example: ${chalk.cyan(`
|
|
160
|
+
`1. Run the example: ${chalk.cyan(`npx tsx ${path.join(directory, 'dexto', 'dexto-example.ts')}`)}`,
|
|
170
161
|
`2. Add/update your API key(s) in ${chalk.cyan('.env')}`,
|
|
171
|
-
`3.
|
|
172
|
-
`4.
|
|
173
|
-
`5. Read more about Dexto: ${chalk.cyan('https://github.com/truffle-ai/dexto')}`,
|
|
162
|
+
`3. Customize the agent in ${chalk.cyan(path.join(directory, 'dexto', 'dexto-example.ts'))}`,
|
|
163
|
+
`4. Read more about Dexto: ${chalk.cyan('https://github.com/truffle-ai/dexto')}`,
|
|
174
164
|
].join('\n');
|
|
175
165
|
p.note(nextSteps, chalk.rgb(255, 165, 0)('Next steps:'));
|
|
176
166
|
}
|
|
177
167
|
/**
|
|
178
|
-
* Creates the dexto
|
|
168
|
+
* Creates the dexto directory in the given directory.
|
|
179
169
|
* @param directory - The directory to create the dexto directories in
|
|
180
170
|
* @returns The path to the created dexto directory
|
|
181
171
|
*/
|
|
182
172
|
export async function createDextoDirectories(directory) {
|
|
183
173
|
const dirPath = path.join(directory, 'dexto');
|
|
184
|
-
const agentsPath = path.join(directory, 'dexto', 'agents');
|
|
185
174
|
try {
|
|
186
175
|
await fs.access(dirPath);
|
|
187
176
|
return { ok: false };
|
|
@@ -189,138 +178,25 @@ export async function createDextoDirectories(directory) {
|
|
|
189
178
|
catch {
|
|
190
179
|
// fsExtra.ensureDir creates directories recursively if they don't exist
|
|
191
180
|
await fsExtra.ensureDir(dirPath);
|
|
192
|
-
await fsExtra.ensureDir(agentsPath);
|
|
193
181
|
return { ok: true, dirPath };
|
|
194
182
|
}
|
|
195
183
|
}
|
|
196
|
-
/**
|
|
197
|
-
* Creates a dexto config file in the given directory. Pulls the config file from the installed Dexto package.
|
|
198
|
-
* @param directory - The directory to create the config file in
|
|
199
|
-
* @returns The path to the created config file
|
|
200
|
-
*/
|
|
201
|
-
export async function createDextoConfigFile(directory) {
|
|
202
|
-
// Ensure the directory exists
|
|
203
|
-
await fsExtra.ensureDir(directory);
|
|
204
|
-
try {
|
|
205
|
-
// Locate the Dexto package installation directory
|
|
206
|
-
const pkgJsonPath = require.resolve('dexto/package.json');
|
|
207
|
-
const pkgDir = path.dirname(pkgJsonPath);
|
|
208
|
-
logger.debug(`Package directory: ${pkgDir}`);
|
|
209
|
-
// Build path to the configuration template for create-app (with auto-approve toolConfirmation)
|
|
210
|
-
const templateConfigSrc = path.join(pkgDir, 'dist', 'agents', 'agent-template.yml');
|
|
211
|
-
logger.debug(`Looking for template at: ${templateConfigSrc}`);
|
|
212
|
-
// Check if template exists - fail if not found
|
|
213
|
-
const templateExists = await fsExtra.pathExists(templateConfigSrc);
|
|
214
|
-
if (!templateExists) {
|
|
215
|
-
throw new Error(`Template file not found at: ${templateConfigSrc}. This indicates a build issue - the template should be included in the package.`);
|
|
216
|
-
}
|
|
217
|
-
// Path to the destination config file
|
|
218
|
-
const destConfigPath = path.join(directory, 'coding-agent.yml');
|
|
219
|
-
logger.debug(`Copying template to: ${destConfigPath}`);
|
|
220
|
-
// Copy the config file from the Dexto package
|
|
221
|
-
await fsExtra.copy(templateConfigSrc, destConfigPath);
|
|
222
|
-
logger.debug(`Successfully created config file at: ${destConfigPath}`);
|
|
223
|
-
return destConfigPath;
|
|
224
|
-
}
|
|
225
|
-
catch (error) {
|
|
226
|
-
logger.error(`Failed to create Dexto config file: ${error}`);
|
|
227
|
-
throw error;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
184
|
/**
|
|
231
185
|
* Creates an example file in the given directory showing how to use Dexto in code. This file has example code to get you started.
|
|
232
186
|
* @param directory - The directory to create the example index file in
|
|
233
187
|
* @returns The path to the created example index file
|
|
234
188
|
*/
|
|
235
|
-
export async function createDextoExampleFile(directory) {
|
|
236
|
-
|
|
237
|
-
const
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
'try {',
|
|
246
|
-
' // Load the agent configuration',
|
|
247
|
-
` const config = await loadAgentConfig('${configPath}');`,
|
|
248
|
-
'',
|
|
249
|
-
' // Create a new DextoAgent instance',
|
|
250
|
-
' const agent = new DextoAgent(config);',
|
|
251
|
-
'',
|
|
252
|
-
' // Start the agent (connects to MCP servers)',
|
|
253
|
-
" console.log('🔗 Connecting to MCP servers...');",
|
|
254
|
-
' await agent.start();',
|
|
255
|
-
" console.log('✅ Agent started successfully!\\n');",
|
|
256
|
-
'',
|
|
257
|
-
' // Create a session for this conversation',
|
|
258
|
-
' const session = await agent.createSession();',
|
|
259
|
-
" console.log('📝 Session created:', session.id, '\\n');",
|
|
260
|
-
'',
|
|
261
|
-
' // Example 1: Simple task',
|
|
262
|
-
" console.log('📋 Example 1: Simple information request');",
|
|
263
|
-
" const request1 = 'What tools do you have available?';",
|
|
264
|
-
" console.log('Request:', request1);",
|
|
265
|
-
' const response1 = await agent.run(request1, undefined, undefined, session.id);',
|
|
266
|
-
" console.log('Response:', response1);",
|
|
267
|
-
" console.log('\\n——————\\n');",
|
|
268
|
-
'',
|
|
269
|
-
' // Example 2: File operation',
|
|
270
|
-
" console.log('📄 Example 2: File creation');",
|
|
271
|
-
' const request2 = \'Create a file called test-output.txt with the content "Hello from Dexto!"\';',
|
|
272
|
-
" console.log('Request:', request2);",
|
|
273
|
-
' const response2 = await agent.run(request2, undefined, undefined, session.id);',
|
|
274
|
-
" console.log('Response:', response2);",
|
|
275
|
-
" console.log('\\n——————\\n');",
|
|
276
|
-
'',
|
|
277
|
-
' // Example 3: Multi-step conversation',
|
|
278
|
-
" console.log('🗣️ Example 3: Multi-step conversation');",
|
|
279
|
-
' const request3a = \'Create a simple HTML file called demo.html with a heading that says "Dexto Demo"\';',
|
|
280
|
-
" console.log('Request 3a:', request3a);",
|
|
281
|
-
' const response3a = await agent.run(request3a, undefined, undefined, session.id);',
|
|
282
|
-
" console.log('Response:', response3a);",
|
|
283
|
-
" console.log('\\n\\n');",
|
|
284
|
-
" const request3b = 'Now add a paragraph to that HTML file explaining what Dexto is';",
|
|
285
|
-
" console.log('Request 3b:', request3b);",
|
|
286
|
-
' const response3b = await agent.run(request3b, undefined, undefined, session.id);',
|
|
287
|
-
" console.log('Response:', response3b);",
|
|
288
|
-
" console.log('\\n——————\\n');",
|
|
289
|
-
'',
|
|
290
|
-
' // Reset conversation (clear context)',
|
|
291
|
-
" console.log('🔄 Resetting conversation context...');",
|
|
292
|
-
' await agent.resetConversation(session.id);',
|
|
293
|
-
" console.log('🔄 Conversation context reset');",
|
|
294
|
-
" console.log('\\n——————\\n');",
|
|
295
|
-
'',
|
|
296
|
-
' // Example 4: Complex task',
|
|
297
|
-
" console.log('🏗️ Example 4: Complex multi-tool task');",
|
|
298
|
-
' const request4 = ',
|
|
299
|
-
" 'Create a simple webpage about AI agents with HTML, CSS, and JavaScript. ' +",
|
|
300
|
-
" 'The page should have a title, some content about what AI agents are, ' +",
|
|
301
|
-
" 'and a button that shows an alert when clicked.';",
|
|
302
|
-
" console.log('Request:', request4);",
|
|
303
|
-
' const response4 = await agent.run(request4, undefined, undefined, session.id);',
|
|
304
|
-
" console.log('Response:', response4);",
|
|
305
|
-
" console.log('\\n——————\\n');",
|
|
306
|
-
'',
|
|
307
|
-
' // Stop the agent (disconnect from MCP servers)',
|
|
308
|
-
" console.log('\\n🛑 Stopping agent...');",
|
|
309
|
-
' await agent.stop();',
|
|
310
|
-
" console.log('✅ Agent stopped successfully!');",
|
|
311
|
-
'',
|
|
312
|
-
'} catch (error) {',
|
|
313
|
-
" console.error('❌ Error:', error);",
|
|
314
|
-
'}',
|
|
315
|
-
'',
|
|
316
|
-
"console.log('\\n📖 Read Dexto documentation to understand more about using Dexto: https://docs.dexto.ai');",
|
|
317
|
-
];
|
|
318
|
-
const indexTsContent = indexTsLines.join('\n');
|
|
189
|
+
export async function createDextoExampleFile(directory, options) {
|
|
190
|
+
const provider = options?.llmProvider ?? 'openai';
|
|
191
|
+
const model = getDefaultModelForProvider(provider) ?? 'gpt-4o';
|
|
192
|
+
const indexTsContent = generateIndexForCodeFirstDI({
|
|
193
|
+
projectName: 'dexto-example',
|
|
194
|
+
packageName: 'dexto-example',
|
|
195
|
+
description: 'Dexto example',
|
|
196
|
+
llmProvider: provider,
|
|
197
|
+
llmModel: model,
|
|
198
|
+
});
|
|
319
199
|
const outputPath = path.join(directory, 'dexto-example.ts');
|
|
320
|
-
// Log the generated file content and paths for debugging
|
|
321
|
-
logger.debug(`Creating example file with config path: ${configPath}`);
|
|
322
|
-
logger.debug(`Base directory: ${baseDir}, Output path: ${outputPath}`);
|
|
323
|
-
logger.debug(`Generated file content:\n${indexTsContent}`);
|
|
324
200
|
// Ensure the directory exists before writing the file
|
|
325
201
|
await fs.writeFile(outputPath, indexTsContent);
|
|
326
202
|
return outputPath;
|
|
@@ -20,6 +20,8 @@ export type CommandHandlerResult = boolean | string | StyledOutput | SendMessage
|
|
|
20
20
|
export interface CommandContext {
|
|
21
21
|
/** Current session ID, or null if no active session */
|
|
22
22
|
sessionId: string | null;
|
|
23
|
+
/** Source config file path for persistence and display (if available) */
|
|
24
|
+
configFilePath: string | null;
|
|
23
25
|
}
|
|
24
26
|
export interface CommandDefinition {
|
|
25
27
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-parser.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/command-parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAEhG,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,MAAM,GAAG,YAAY,GAAG,iBAAiB,CAAC;AAEvF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,uDAAuD;IACvD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"command-parser.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/command-parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAEhG,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,MAAM,GAAG,YAAY,GAAG,iBAAiB,CAAC;AAEvF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,uDAAuD;IACvD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,yEAAyE;IACzE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAClC,OAAO,EAAE,CACL,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,UAAU,EACjB,GAAG,EAAE,cAAc,KAClB,OAAO,CAAC,oBAAoB,CAAC,CAAC;CACtC;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,oBAAoB,CAAS,CAAC;AA4ClF;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAiCvD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,EAAE,GAAG,MAAM,EAAE,CAoB9F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,EAAE,QAAQ,GAAE,OAAe,GAAG,MAAM,CAmB3F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAwDtE"}
|
|
@@ -43,7 +43,7 @@ export declare const CLI_COMMANDS: CommandDefinition[];
|
|
|
43
43
|
* @param sessionId - Session ID to use for agent.run() calls
|
|
44
44
|
* @returns CommandHandlerResult - boolean, string, or StyledOutput
|
|
45
45
|
*/
|
|
46
|
-
export declare function executeCommand(command: string, args: string[], agent: DextoAgent, sessionId?: string): Promise<CommandHandlerResult>;
|
|
46
|
+
export declare function executeCommand(command: string, args: string[], agent: DextoAgent, sessionId?: string, configFilePath?: string | null): Promise<CommandHandlerResult>;
|
|
47
47
|
/**
|
|
48
48
|
* Get all available command definitions
|
|
49
49
|
* This is used by external systems that need to inspect available commands
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAgBnF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,EAAE,iBAAiB,EAAO,CAAC;AA6CpD;;;;;GAKG;AACH,wBAAsB,cAAc,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,UAAU,EACjB,SAAS,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAgBnF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,EAAE,iBAAiB,EAAO,CAAC;AA6CpD;;;;;GAKG;AACH,wBAAsB,cAAc,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,UAAU,EACjB,SAAS,CAAC,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAyD/B;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,iBAAiB,EAAE,CAEpD"}
|
|
@@ -85,9 +85,9 @@ CLI_COMMANDS.push(...baseCommands);
|
|
|
85
85
|
* @param sessionId - Session ID to use for agent.run() calls
|
|
86
86
|
* @returns CommandHandlerResult - boolean, string, or StyledOutput
|
|
87
87
|
*/
|
|
88
|
-
export async function executeCommand(command, args, agent, sessionId) {
|
|
88
|
+
export async function executeCommand(command, args, agent, sessionId, configFilePath) {
|
|
89
89
|
// Create command context with sessionId
|
|
90
|
-
const ctx = { sessionId: sessionId ?? null };
|
|
90
|
+
const ctx = { sessionId: sessionId ?? null, configFilePath: configFilePath ?? null };
|
|
91
91
|
// Find the command (including aliases)
|
|
92
92
|
const cmd = CLI_COMMANDS.find((c) => c.name === command || (c.aliases && c.aliases.includes(command)));
|
|
93
93
|
if (cmd) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exit Handler
|
|
3
|
+
*
|
|
4
|
+
* Provides a way for commands to trigger a graceful CLI exit.
|
|
5
|
+
* The exit function is registered by the Ink app and can be called
|
|
6
|
+
* by commands to unmount the app properly.
|
|
7
|
+
*/
|
|
8
|
+
type ExitFunction = () => void;
|
|
9
|
+
export declare function registerExitHandler(fn: ExitFunction): void;
|
|
10
|
+
export declare function triggerExit(): void;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=exit-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-handler.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/exit-handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,KAAK,YAAY,GAAG,MAAM,IAAI,CAAC;AAI/B,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAE1D;AAED,wBAAgB,WAAW,IAAI,IAAI,CAOlC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exit Handler
|
|
3
|
+
*
|
|
4
|
+
* Provides a way for commands to trigger a graceful CLI exit.
|
|
5
|
+
* The exit function is registered by the Ink app and can be called
|
|
6
|
+
* by commands to unmount the app properly.
|
|
7
|
+
*/
|
|
8
|
+
let exitFn = null;
|
|
9
|
+
export function registerExitHandler(fn) {
|
|
10
|
+
exitFn = fn;
|
|
11
|
+
}
|
|
12
|
+
export function triggerExit() {
|
|
13
|
+
if (exitFn) {
|
|
14
|
+
exitFn();
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
// Fallback to process.exit if exit handler not registered
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exit Stats Storage
|
|
3
|
+
*
|
|
4
|
+
* Stores session statistics to be displayed after the CLI exits.
|
|
5
|
+
* This allows the stats to be printed to stdout after Ink unmounts,
|
|
6
|
+
* ensuring they appear at the bottom of the terminal.
|
|
7
|
+
*/
|
|
8
|
+
import type { SessionMetadata } from '@dexto/core';
|
|
9
|
+
export interface ExitSessionStats {
|
|
10
|
+
sessionId?: string;
|
|
11
|
+
duration?: string;
|
|
12
|
+
messageCount: {
|
|
13
|
+
total: number;
|
|
14
|
+
user: number;
|
|
15
|
+
assistant: number;
|
|
16
|
+
};
|
|
17
|
+
tokenUsage?: NonNullable<SessionMetadata['tokenUsage']>;
|
|
18
|
+
estimatedCost?: SessionMetadata['estimatedCost'];
|
|
19
|
+
modelStats?: NonNullable<SessionMetadata['modelStats']>;
|
|
20
|
+
}
|
|
21
|
+
export declare function setExitStats(stats: ExitSessionStats): void;
|
|
22
|
+
export declare function getExitStats(): ExitSessionStats | null;
|
|
23
|
+
export declare function clearExitStats(): void;
|
|
24
|
+
//# sourceMappingURL=exit-stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-stats.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/exit-stats.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE;QACV,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,UAAU,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC;IACxD,aAAa,CAAC,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;IACjD,UAAU,CAAC,EAAE,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC;CAC3D;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAE1D;AAED,wBAAgB,YAAY,IAAI,gBAAgB,GAAG,IAAI,CAEtD;AAED,wBAAgB,cAAc,IAAI,IAAI,CAErC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exit Stats Storage
|
|
3
|
+
*
|
|
4
|
+
* Stores session statistics to be displayed after the CLI exits.
|
|
5
|
+
* This allows the stats to be printed to stdout after Ink unmounts,
|
|
6
|
+
* ensuring they appear at the bottom of the terminal.
|
|
7
|
+
*/
|
|
8
|
+
let exitStats = null;
|
|
9
|
+
export function setExitStats(stats) {
|
|
10
|
+
exitStats = stats;
|
|
11
|
+
}
|
|
12
|
+
export function getExitStats() {
|
|
13
|
+
return exitStats;
|
|
14
|
+
}
|
|
15
|
+
export function clearExitStats() {
|
|
16
|
+
exitStats = null;
|
|
17
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"general-commands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/general-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAwC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"general-commands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/general-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAwC,MAAM,qBAAqB,CAAC;AAkGnG;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,iBAAiB,EAAE,GAAG,iBAAiB,CAgC9F;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,iBAAiB,EAid9C,CAAC"}
|
|
@@ -14,6 +14,8 @@ import { spawn } from 'child_process';
|
|
|
14
14
|
import { formatForInkCli } from './utils/format-output.js';
|
|
15
15
|
import { CommandOutputHelper } from './utils/command-output.js';
|
|
16
16
|
import { writeToClipboard } from '../../ink-cli/utils/clipboardUtils.js';
|
|
17
|
+
import { setExitStats } from './exit-stats.js';
|
|
18
|
+
import { triggerExit } from './exit-handler.js';
|
|
17
19
|
/**
|
|
18
20
|
* Get the shell rc file path for the given shell
|
|
19
21
|
*/
|
|
@@ -159,9 +161,57 @@ export const generalCommands = [
|
|
|
159
161
|
usage: '/exit',
|
|
160
162
|
category: 'General',
|
|
161
163
|
aliases: ['quit', 'q'],
|
|
162
|
-
handler: async (_args,
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
handler: async (_args, agent, ctx) => {
|
|
165
|
+
// Store session stats to be displayed after Ink exits
|
|
166
|
+
try {
|
|
167
|
+
const { sessionId } = ctx;
|
|
168
|
+
if (sessionId) {
|
|
169
|
+
const [sessionMetadata, history] = await Promise.all([
|
|
170
|
+
agent.sessionManager.getSessionMetadata(sessionId),
|
|
171
|
+
agent.getSessionHistory(sessionId),
|
|
172
|
+
]);
|
|
173
|
+
if (sessionMetadata) {
|
|
174
|
+
// Calculate session duration
|
|
175
|
+
let durationStr;
|
|
176
|
+
if (sessionMetadata.createdAt) {
|
|
177
|
+
const duration = Date.now() - new Date(sessionMetadata.createdAt).getTime();
|
|
178
|
+
const minutes = Math.floor(duration / 60000);
|
|
179
|
+
const seconds = Math.floor((duration % 60000) / 1000);
|
|
180
|
+
durationStr = minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
|
|
181
|
+
}
|
|
182
|
+
// Message counts
|
|
183
|
+
const messageCount = {
|
|
184
|
+
total: history?.length || 0,
|
|
185
|
+
user: history?.filter((msg) => msg.role === 'user').length || 0,
|
|
186
|
+
assistant: history?.filter((msg) => msg.role === 'assistant').length || 0,
|
|
187
|
+
};
|
|
188
|
+
// Store stats for display after exit
|
|
189
|
+
setExitStats({
|
|
190
|
+
...(sessionId && { sessionId }),
|
|
191
|
+
...(durationStr && { duration: durationStr }),
|
|
192
|
+
messageCount,
|
|
193
|
+
...(sessionMetadata.tokenUsage && {
|
|
194
|
+
tokenUsage: sessionMetadata.tokenUsage,
|
|
195
|
+
}),
|
|
196
|
+
...(sessionMetadata.estimatedCost !== undefined && {
|
|
197
|
+
estimatedCost: sessionMetadata.estimatedCost,
|
|
198
|
+
}),
|
|
199
|
+
...(sessionMetadata.modelStats && {
|
|
200
|
+
modelStats: sessionMetadata.modelStats,
|
|
201
|
+
}),
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
// Silently ignore errors - don't block exit
|
|
208
|
+
agent.logger.debug(`Failed to collect session stats on exit: ${error instanceof Error ? error.message : String(error)}`);
|
|
209
|
+
}
|
|
210
|
+
// Trigger graceful exit - this will unmount the Ink app
|
|
211
|
+
// After unmount, session stats will be printed to stdout
|
|
212
|
+
triggerExit();
|
|
213
|
+
// Return true to indicate command was handled
|
|
214
|
+
return true;
|
|
165
215
|
},
|
|
166
216
|
},
|
|
167
217
|
{
|
|
@@ -175,7 +225,7 @@ export const generalCommands = [
|
|
|
175
225
|
const newSession = await agent.createSession();
|
|
176
226
|
const newSessionId = newSession.id;
|
|
177
227
|
// Emit session:created to switch the CLI to the new session
|
|
178
|
-
agent.
|
|
228
|
+
agent.emit('session:created', {
|
|
179
229
|
sessionId: newSessionId,
|
|
180
230
|
switchTo: true,
|
|
181
231
|
});
|
|
@@ -397,7 +447,7 @@ export const generalCommands = [
|
|
|
397
447
|
name: 'Global',
|
|
398
448
|
shortcuts: [
|
|
399
449
|
{ keys: 'Ctrl+C', description: 'Clear input, then exit (press twice)' },
|
|
400
|
-
{ keys: 'Ctrl+T', description: 'Toggle
|
|
450
|
+
{ keys: 'Ctrl+T', description: 'Toggle todo list (show/hide todos)' },
|
|
401
451
|
{ keys: 'Escape', description: 'Cancel processing / close overlay' },
|
|
402
452
|
],
|
|
403
453
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-commands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/prompt-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"prompt-commands.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/interactive-commands/prompt-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAwC,MAAM,qBAAqB,CAAC;AAKnG;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,iBAAiB,EAiI7C,CAAC;AA6IF;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAiB9F"}
|