Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tough-countries-sing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@dexto/core': patch
---

Replace `ErrorScope`, `ErrorType`, and `StorageErrorCode` enums with const-list-derived unions and update internal consumers to use plain string literals.
2 changes: 1 addition & 1 deletion docs/static/openapi/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"openapi": "3.0.0",
"info": {
"title": "Dexto API",
"version": "1.6.17",
"version": "1.6.19",
"description": "OpenAPI spec for the Dexto REST API server"
},
"servers": [
Expand Down
42 changes: 21 additions & 21 deletions packages/agent-management/src/config/errors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DextoRuntimeError, ErrorScope, ErrorType } from '@dexto/core';
import { DextoRuntimeError } from '@dexto/core';
import { ConfigErrorCode } from './error-codes.js';

/**
Expand All @@ -10,8 +10,8 @@ export class ConfigError {
static fileNotFound(configPath: string) {
return new DextoRuntimeError(
ConfigErrorCode.FILE_NOT_FOUND,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Configuration file not found: ${configPath}`,
{ configPath },
'Ensure the configuration file exists at the specified path'
Expand All @@ -21,8 +21,8 @@ export class ConfigError {
static fileReadError(configPath: string, cause: string) {
return new DextoRuntimeError(
ConfigErrorCode.FILE_READ_ERROR,
ErrorScope.CONFIG,
ErrorType.SYSTEM,
'config',
'system',
`Failed to read configuration file: ${cause}`,
{ configPath, cause },
'Check file permissions and ensure the file is not corrupted'
Expand All @@ -32,8 +32,8 @@ export class ConfigError {
static fileWriteError(configPath: string, cause: string) {
return new DextoRuntimeError(
ConfigErrorCode.FILE_WRITE_ERROR,
ErrorScope.CONFIG,
ErrorType.SYSTEM,
'config',
'system',
`Failed to write configuration file '${configPath}': ${cause}`,
{ configPath, cause },
'Check file permissions and available disk space'
Expand All @@ -44,8 +44,8 @@ export class ConfigError {
static parseError(configPath: string, cause: string) {
return new DextoRuntimeError(
ConfigErrorCode.PARSE_ERROR,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Failed to parse configuration file: ${cause}`,
{ configPath, cause },
'Ensure the configuration file contains valid YAML syntax'
Expand All @@ -56,8 +56,8 @@ export class ConfigError {
static noProjectDefault(projectPath: string) {
return new DextoRuntimeError(
ConfigErrorCode.NO_PROJECT_DEFAULT,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`No project agent found and no global preferences configured.\nSet a primaryAgent in a workspace registry under agents/, create a single workspace agent under agents/, or run \`dexto setup\` to configure preferences.`,
{ projectPath },
'Run `dexto setup` or create a project-specific agent config'
Expand All @@ -67,8 +67,8 @@ export class ConfigError {
static invalidProjectPrimary(registryPath: string, primaryAgent: string, reason?: string) {
return new DextoRuntimeError(
ConfigErrorCode.INVALID_PROJECT_PRIMARY,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Invalid primaryAgent '${primaryAgent}' in ${registryPath}${reason ? `: ${reason}` : ''}`,
{ registryPath, primaryAgent, reason },
'Update the workspace registry so primaryAgent points to a valid workspace agent config'
Expand All @@ -78,8 +78,8 @@ export class ConfigError {
static noGlobalPreferences() {
return new DextoRuntimeError(
ConfigErrorCode.NO_GLOBAL_PREFERENCES,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`No global preferences found. Run \`dexto setup\` to get started.`,
{},
'Run `dexto setup` to configure your AI preferences'
Expand All @@ -89,8 +89,8 @@ export class ConfigError {
static setupIncomplete() {
return new DextoRuntimeError(
ConfigErrorCode.SETUP_INCOMPLETE,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Global preferences setup is incomplete. Run \`dexto setup\` to complete.`,
{},
'Run `dexto setup` to complete your configuration'
Expand All @@ -100,8 +100,8 @@ export class ConfigError {
static bundledNotFound(bundledPath: string) {
return new DextoRuntimeError(
ConfigErrorCode.BUNDLED_NOT_FOUND,
ErrorScope.CONFIG,
ErrorType.NOT_FOUND,
'config',
'not_found',
`Bundled default agent not found: ${bundledPath}. Run npm run build first.`,
{ path: bundledPath },
'Run `npm run build` to build the bundled agents'
Expand All @@ -111,8 +111,8 @@ export class ConfigError {
static unknownContext(context: string) {
return new DextoRuntimeError(
ConfigErrorCode.UNKNOWN_CONTEXT,
ErrorScope.CONFIG,
ErrorType.SYSTEM,
'config',
'system',
`Unknown execution context: ${context}`,
{ context },
'This is an internal error - please report it'
Expand Down
25 changes: 12 additions & 13 deletions packages/agent-management/src/config/loader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { promises as fs } from 'fs';
import * as path from 'path';
import { fileURLToPath } from 'node:url';
import { loadAgentConfig } from './loader.js';
import { ErrorScope, ErrorType } from '@dexto/core';
import { ConfigErrorCode } from './error-codes.js';

// Temp config file path relative to this test file (stable across monorepo runners)
Expand Down Expand Up @@ -59,8 +58,8 @@ mcpServers:
await expect(loadAgentConfig(missing)).rejects.toThrow(
expect.objectContaining({
code: ConfigErrorCode.FILE_NOT_FOUND,
scope: ErrorScope.CONFIG,
type: ErrorType.USER,
scope: 'config',
type: 'user',
})
);
});
Expand All @@ -70,8 +69,8 @@ mcpServers:
await expect(loadAgentConfig(tmpFile)).rejects.toThrow(
expect.objectContaining({
code: ConfigErrorCode.FILE_READ_ERROR,
scope: ErrorScope.CONFIG,
type: ErrorType.SYSTEM,
scope: 'config',
type: 'system',
})
);
await fs.unlink(tmpFile);
Expand All @@ -94,8 +93,8 @@ mcpServers:
await expect(loadAgentConfig(tmpFile)).rejects.toThrow(
expect.objectContaining({
code: ConfigErrorCode.PARSE_ERROR,
scope: ErrorScope.CONFIG,
type: ErrorType.USER,
scope: 'config',
type: 'user',
})
);
});
Expand All @@ -106,8 +105,8 @@ mcpServers:
await expect(loadAgentConfig(nonExistentPath)).rejects.toThrow(
expect.objectContaining({
code: ConfigErrorCode.FILE_NOT_FOUND,
scope: ErrorScope.CONFIG,
type: ErrorType.USER,
scope: 'config',
type: 'user',
})
);
});
Expand Down Expand Up @@ -202,8 +201,8 @@ mcpServers:
await expect(loadAgentConfig(tmpFile)).rejects.toThrow(
expect.objectContaining({
code: ConfigErrorCode.PARSE_ERROR,
scope: ErrorScope.CONFIG,
type: ErrorType.USER,
scope: 'config',
type: 'user',
})
);
});
Expand Down Expand Up @@ -244,8 +243,8 @@ tools:
await expect(loadAgentConfig(tmpFile)).rejects.toThrow(
expect.objectContaining({
code: ConfigErrorCode.PARSE_ERROR,
scope: ErrorScope.CONFIG,
type: ErrorType.USER,
scope: 'config',
type: 'user',
})
);
});
Expand Down
66 changes: 33 additions & 33 deletions packages/agent-management/src/plugins/errors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DextoRuntimeError, ErrorScope, ErrorType } from '@dexto/core';
import { DextoRuntimeError } from '@dexto/core';
import { PluginErrorCode } from './error-codes.js';

/**
Expand All @@ -10,8 +10,8 @@ export class PluginError {
static manifestNotFound(pluginPath: string) {
return new DextoRuntimeError(
PluginErrorCode.MANIFEST_NOT_FOUND,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Plugin manifest not found: ${pluginPath}/.claude-plugin/plugin.json`,
{ pluginPath },
'Ensure the plugin has a valid .claude-plugin/plugin.json file'
Expand All @@ -21,8 +21,8 @@ export class PluginError {
static manifestInvalid(pluginPath: string, issues: string) {
return new DextoRuntimeError(
PluginErrorCode.MANIFEST_INVALID,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Invalid plugin manifest at ${pluginPath}: ${issues}`,
{ pluginPath, issues },
'Check the plugin.json file matches the expected schema (name is required)'
Expand All @@ -32,8 +32,8 @@ export class PluginError {
static manifestParseError(pluginPath: string, cause: string) {
return new DextoRuntimeError(
PluginErrorCode.MANIFEST_PARSE_ERROR,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Failed to parse plugin manifest at ${pluginPath}: ${cause}`,
{ pluginPath, cause },
'Ensure plugin.json contains valid JSON'
Expand All @@ -44,8 +44,8 @@ export class PluginError {
static directoryReadError(pluginPath: string, cause: string) {
return new DextoRuntimeError(
PluginErrorCode.DIRECTORY_READ_ERROR,
ErrorScope.CONFIG,
ErrorType.SYSTEM,
'config',
'system',
`Failed to read plugin directory ${pluginPath}: ${cause}`,
{ pluginPath, cause },
'Check file permissions and that the directory exists'
Expand All @@ -55,8 +55,8 @@ export class PluginError {
static mcpConfigInvalid(pluginPath: string, cause: string) {
return new DextoRuntimeError(
PluginErrorCode.MCP_CONFIG_INVALID,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Invalid MCP config in plugin ${pluginPath}: ${cause}`,
{ pluginPath, cause },
'Check the .mcp.json file contains valid JSON'
Expand All @@ -67,8 +67,8 @@ export class PluginError {
static installSourceNotFound(sourcePath: string) {
return new DextoRuntimeError(
PluginErrorCode.INSTALL_SOURCE_NOT_FOUND,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Plugin source not found: ${sourcePath}`,
{ sourcePath },
'Ensure the path points to a valid plugin directory with .claude-plugin/plugin.json'
Expand All @@ -78,8 +78,8 @@ export class PluginError {
static installAlreadyExists(pluginName: string, existingPath: string) {
return new DextoRuntimeError(
PluginErrorCode.INSTALL_ALREADY_EXISTS,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Plugin '${pluginName}' is already installed at ${existingPath}`,
{ pluginName, existingPath },
'Use --force to overwrite the existing installation'
Expand All @@ -89,8 +89,8 @@ export class PluginError {
static installCopyFailed(sourcePath: string, destPath: string, cause: string) {
return new DextoRuntimeError(
PluginErrorCode.INSTALL_COPY_FAILED,
ErrorScope.CONFIG,
ErrorType.SYSTEM,
'config',
'system',
`Failed to copy plugin from ${sourcePath} to ${destPath}: ${cause}`,
{ sourcePath, destPath, cause },
'Check file permissions and disk space'
Expand All @@ -100,8 +100,8 @@ export class PluginError {
static installManifestWriteFailed(manifestPath: string, cause: string) {
return new DextoRuntimeError(
PluginErrorCode.INSTALL_MANIFEST_WRITE_FAILED,
ErrorScope.CONFIG,
ErrorType.SYSTEM,
'config',
'system',
`Failed to update installed plugins manifest at ${manifestPath}: ${cause}`,
{ manifestPath, cause },
'Check file permissions and ensure the directory exists'
Expand All @@ -111,8 +111,8 @@ export class PluginError {
static invalidScope(scope: unknown) {
return new DextoRuntimeError(
PluginErrorCode.INSTALL_INVALID_SCOPE,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Invalid installation scope: ${scope}. Must be 'user', 'project', or 'local'.`,
{ scope },
"Check the scope parameter is one of: 'user', 'project', 'local'"
Expand All @@ -123,8 +123,8 @@ export class PluginError {
static importNotFound(pluginName: string) {
return new DextoRuntimeError(
PluginErrorCode.IMPORT_NOT_FOUND,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Plugin '${pluginName}' not found`,
{ pluginName },
'Use `dexto plugin list` to see available plugins'
Expand All @@ -135,8 +135,8 @@ export class PluginError {
static uninstallNotFound(pluginName: string, hint?: string) {
return new DextoRuntimeError(
PluginErrorCode.UNINSTALL_NOT_FOUND,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Plugin '${pluginName}' is not installed`,
{ pluginName },
hint || 'Use `dexto plugin list` to see installed plugins'
Expand All @@ -146,8 +146,8 @@ export class PluginError {
static uninstallDeleteFailed(pluginPath: string, cause: string) {
return new DextoRuntimeError(
PluginErrorCode.UNINSTALL_DELETE_FAILED,
ErrorScope.CONFIG,
ErrorType.SYSTEM,
'config',
'system',
`Failed to delete plugin at ${pluginPath}: ${cause}`,
{ pluginPath, cause },
'Check file permissions and ensure the plugin is not in use'
Expand All @@ -157,8 +157,8 @@ export class PluginError {
static uninstallManifestUpdateFailed(manifestPath: string, cause: string) {
return new DextoRuntimeError(
PluginErrorCode.UNINSTALL_MANIFEST_UPDATE_FAILED,
ErrorScope.CONFIG,
ErrorType.SYSTEM,
'config',
'system',
`Failed to update installed plugins manifest at ${manifestPath}: ${cause}`,
{ manifestPath, cause },
'Check file permissions'
Expand All @@ -169,8 +169,8 @@ export class PluginError {
static validationInvalidStructure(pluginPath: string, details: string) {
return new DextoRuntimeError(
PluginErrorCode.VALIDATION_INVALID_STRUCTURE,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Invalid plugin structure at ${pluginPath}: ${details}`,
{ pluginPath, details },
'Ensure the plugin has a .claude-plugin/plugin.json file'
Expand All @@ -180,8 +180,8 @@ export class PluginError {
static validationMissingRequired(pluginPath: string, missing: string[]) {
return new DextoRuntimeError(
PluginErrorCode.VALIDATION_MISSING_REQUIRED,
ErrorScope.CONFIG,
ErrorType.USER,
'config',
'user',
`Plugin at ${pluginPath} is missing required fields: ${missing.join(', ')}`,
{ pluginPath, missing },
'Add the missing fields to .claude-plugin/plugin.json'
Expand Down
Loading
Loading