@dexto/agent-management 1.5.7 → 1.6.0
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/dist/AgentFactory.cjs +5 -9
- package/dist/AgentFactory.d.ts +6 -5
- package/dist/AgentFactory.d.ts.map +1 -1
- package/dist/AgentFactory.js +5 -9
- package/dist/AgentManager.cjs +2 -2
- package/dist/AgentManager.d.ts +1 -1
- package/dist/AgentManager.d.ts.map +1 -1
- package/dist/AgentManager.js +4 -4
- package/dist/agent-creation.cjs +95 -0
- package/dist/agent-creation.d.ts +15 -0
- package/dist/agent-creation.d.ts.map +1 -0
- package/dist/agent-creation.js +78 -0
- package/dist/config/config-enrichment.cjs +2 -12
- package/dist/config/config-enrichment.d.ts +1 -1
- package/dist/config/config-enrichment.d.ts.map +1 -1
- package/dist/config/config-enrichment.js +2 -12
- package/dist/config/config-manager.cjs +4 -4
- package/dist/config/config-manager.d.ts +1 -1
- package/dist/config/config-manager.d.ts.map +1 -1
- package/dist/config/config-manager.js +3 -1
- package/dist/config/loader.d.ts +3 -3
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/images/image-store.cjs +256 -0
- package/dist/images/image-store.d.ts +70 -0
- package/dist/images/image-store.d.ts.map +1 -0
- package/dist/images/image-store.js +210 -0
- package/dist/index.cjs +43 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -1
- package/dist/models/custom-models.cjs +1 -1
- package/dist/models/custom-models.d.ts +7 -7
- package/dist/models/custom-models.d.ts.map +1 -1
- package/dist/models/custom-models.js +1 -1
- package/dist/plugins/discover-plugins.cjs +15 -31
- package/dist/plugins/discover-plugins.d.ts.map +1 -1
- package/dist/plugins/discover-plugins.js +15 -31
- package/dist/plugins/discover-skills.cjs +4 -0
- package/dist/plugins/discover-skills.d.ts +6 -3
- package/dist/plugins/discover-skills.d.ts.map +1 -1
- package/dist/plugins/discover-skills.js +4 -0
- package/dist/plugins/index.cjs +0 -2
- package/dist/plugins/index.d.ts +5 -6
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +0 -2
- package/dist/plugins/list-plugins.cjs +3 -1
- package/dist/plugins/list-plugins.d.ts.map +1 -1
- package/dist/plugins/list-plugins.js +3 -1
- package/dist/plugins/load-plugin.cjs +0 -13
- package/dist/plugins/load-plugin.d.ts +3 -5
- package/dist/plugins/load-plugin.d.ts.map +1 -1
- package/dist/plugins/load-plugin.js +0 -13
- package/dist/plugins/schemas.cjs +1 -11
- package/dist/plugins/schemas.d.ts +14 -69
- package/dist/plugins/schemas.d.ts.map +1 -1
- package/dist/plugins/schemas.js +1 -10
- package/dist/plugins/types.d.ts +2 -20
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/plugins/validate-plugin.cjs +7 -37
- package/dist/plugins/validate-plugin.d.ts +6 -24
- package/dist/plugins/validate-plugin.d.ts.map +1 -1
- package/dist/plugins/validate-plugin.js +8 -38
- package/dist/preferences/errors.cjs +11 -0
- package/dist/preferences/errors.d.ts +1 -0
- package/dist/preferences/errors.d.ts.map +1 -1
- package/dist/preferences/errors.js +11 -0
- package/dist/preferences/loader.cjs +119 -6
- package/dist/preferences/loader.d.ts +21 -1
- package/dist/preferences/loader.d.ts.map +1 -1
- package/dist/preferences/loader.js +102 -1
- package/dist/preferences/schemas.cjs +12 -0
- package/dist/preferences/schemas.d.ts +38 -12
- package/dist/preferences/schemas.d.ts.map +1 -1
- package/dist/preferences/schemas.js +10 -0
- package/dist/registry/registry.d.ts +4 -44
- package/dist/registry/registry.d.ts.map +1 -1
- package/dist/runtime/AgentPool.d.ts +2 -2
- package/dist/runtime/AgentPool.d.ts.map +1 -1
- package/dist/runtime/AgentRuntime.cjs +20 -15
- package/dist/runtime/AgentRuntime.d.ts +2 -2
- package/dist/runtime/AgentRuntime.d.ts.map +1 -1
- package/dist/runtime/AgentRuntime.js +20 -15
- package/dist/runtime/approval-delegation.d.ts +2 -2
- package/dist/runtime/approval-delegation.d.ts.map +1 -1
- package/dist/runtime/schemas.d.ts +1 -1
- package/dist/runtime/types.d.ts +2 -1
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/{tool-provider → tool-factories/agent-spawner}/error-codes.d.ts +1 -1
- package/dist/tool-factories/agent-spawner/error-codes.d.ts.map +1 -0
- package/dist/{tool-provider → tool-factories/agent-spawner}/errors.d.ts +1 -1
- package/dist/tool-factories/agent-spawner/errors.d.ts.map +1 -0
- package/dist/tool-factories/agent-spawner/factory.cjs +290 -0
- package/dist/tool-factories/agent-spawner/factory.d.ts +4 -0
- package/dist/tool-factories/agent-spawner/factory.d.ts.map +1 -0
- package/dist/tool-factories/agent-spawner/factory.js +279 -0
- package/dist/{tool-provider → tool-factories/agent-spawner}/index.cjs +9 -9
- package/dist/{tool-provider → tool-factories/agent-spawner}/index.d.ts +3 -3
- package/dist/tool-factories/agent-spawner/index.d.ts.map +1 -0
- package/dist/{tool-provider → tool-factories/agent-spawner}/index.js +4 -4
- package/dist/{tool-provider → tool-factories/agent-spawner}/llm-resolution.cjs +1 -1
- package/dist/{tool-provider → tool-factories/agent-spawner}/llm-resolution.d.ts +4 -4
- package/dist/tool-factories/agent-spawner/llm-resolution.d.ts.map +1 -0
- package/dist/{tool-provider → tool-factories/agent-spawner}/llm-resolution.js +1 -1
- package/dist/{tool-provider/runtime-service.cjs → tool-factories/agent-spawner/runtime.cjs} +112 -73
- package/dist/{tool-provider/runtime-service.d.ts → tool-factories/agent-spawner/runtime.d.ts} +8 -6
- package/dist/tool-factories/agent-spawner/runtime.d.ts.map +1 -0
- package/dist/{tool-provider/runtime-service.js → tool-factories/agent-spawner/runtime.js} +98 -69
- package/dist/{tool-provider → tool-factories/agent-spawner}/schemas.cjs +2 -2
- package/dist/{tool-provider → tool-factories/agent-spawner}/schemas.d.ts +4 -4
- package/dist/tool-factories/agent-spawner/schemas.d.ts.map +1 -0
- package/dist/{tool-provider → tool-factories/agent-spawner}/schemas.js +2 -2
- package/dist/{tool-provider → tool-factories/agent-spawner}/spawn-agent-tool.cjs +8 -7
- package/dist/tool-factories/agent-spawner/spawn-agent-tool.d.ts +11 -0
- package/dist/tool-factories/agent-spawner/spawn-agent-tool.d.ts.map +1 -0
- package/dist/{tool-provider → tool-factories/agent-spawner}/spawn-agent-tool.js +8 -7
- package/dist/tool-factories/agent-spawner/types.d.ts.map +1 -0
- package/dist/utils/api-key-resolver.cjs +1 -1
- package/dist/utils/api-key-resolver.js +1 -1
- package/dist/utils/feature-flags.cjs +3 -1
- package/dist/utils/feature-flags.d.ts +2 -2
- package/dist/utils/feature-flags.d.ts.map +1 -1
- package/dist/utils/feature-flags.js +3 -1
- package/dist/writer.d.ts +2 -1
- package/dist/writer.d.ts.map +1 -1
- package/package.json +6 -3
- package/dist/tool-provider/error-codes.d.ts.map +0 -1
- package/dist/tool-provider/errors.d.ts.map +0 -1
- package/dist/tool-provider/index.d.ts.map +0 -1
- package/dist/tool-provider/llm-resolution.d.ts.map +0 -1
- package/dist/tool-provider/runtime-service.d.ts.map +0 -1
- package/dist/tool-provider/schemas.d.ts.map +0 -1
- package/dist/tool-provider/spawn-agent-tool.d.ts +0 -10
- package/dist/tool-provider/spawn-agent-tool.d.ts.map +0 -1
- package/dist/tool-provider/tool-provider.cjs +0 -46
- package/dist/tool-provider/tool-provider.d.ts +0 -24
- package/dist/tool-provider/tool-provider.d.ts.map +0 -1
- package/dist/tool-provider/tool-provider.js +0 -22
- package/dist/tool-provider/types.d.ts.map +0 -1
- /package/dist/{tool-provider → tool-factories/agent-spawner}/error-codes.cjs +0 -0
- /package/dist/{tool-provider → tool-factories/agent-spawner}/error-codes.js +0 -0
- /package/dist/{tool-provider → tool-factories/agent-spawner}/errors.cjs +0 -0
- /package/dist/{tool-provider → tool-factories/agent-spawner}/errors.js +0 -0
- /package/dist/{tool-provider → tool-factories/agent-spawner}/types.cjs +0 -0
- /package/dist/{tool-provider → tool-factories/agent-spawner}/types.d.ts +0 -0
- /package/dist/{tool-provider → tool-factories/agent-spawner}/types.js +0 -0
|
@@ -39,29 +39,14 @@ function validatePluginDirectory(pluginPath) {
|
|
|
39
39
|
const errors = [];
|
|
40
40
|
const warnings = [];
|
|
41
41
|
let manifest;
|
|
42
|
-
let format;
|
|
43
42
|
const absolutePath = path.isAbsolute(pluginPath) ? pluginPath : path.resolve(pluginPath);
|
|
44
43
|
if (!(0, import_fs.existsSync)(absolutePath)) {
|
|
45
44
|
errors.push(`Directory does not exist: ${absolutePath}`);
|
|
46
45
|
return { valid: false, errors, warnings };
|
|
47
46
|
}
|
|
48
|
-
const
|
|
49
|
-
const claudePluginDir = path.join(absolutePath, ".claude-plugin");
|
|
50
|
-
let manifestPath;
|
|
51
|
-
if ((0, import_fs.existsSync)(dextoPluginDir)) {
|
|
52
|
-
manifestPath = path.join(dextoPluginDir, "plugin.json");
|
|
53
|
-
format = "dexto";
|
|
54
|
-
} else if ((0, import_fs.existsSync)(claudePluginDir)) {
|
|
55
|
-
manifestPath = path.join(claudePluginDir, "plugin.json");
|
|
56
|
-
format = "claude-code";
|
|
57
|
-
} else {
|
|
58
|
-
errors.push("Missing .dexto-plugin or .claude-plugin directory");
|
|
59
|
-
return { valid: false, errors, warnings };
|
|
60
|
-
}
|
|
47
|
+
const manifestPath = path.join(absolutePath, ".claude-plugin", "plugin.json");
|
|
61
48
|
if (!(0, import_fs.existsSync)(manifestPath)) {
|
|
62
|
-
errors.push(
|
|
63
|
-
`Missing ${format === "dexto" ? ".dexto-plugin" : ".claude-plugin"}/plugin.json`
|
|
64
|
-
);
|
|
49
|
+
errors.push("Missing .claude-plugin/plugin.json");
|
|
65
50
|
return { valid: false, errors, warnings };
|
|
66
51
|
}
|
|
67
52
|
try {
|
|
@@ -75,8 +60,7 @@ function validatePluginDirectory(pluginPath) {
|
|
|
75
60
|
);
|
|
76
61
|
return { valid: false, errors, warnings };
|
|
77
62
|
}
|
|
78
|
-
const
|
|
79
|
-
const result = schema.safeParse(parsed);
|
|
63
|
+
const result = import_schemas.PluginManifestSchema.safeParse(parsed);
|
|
80
64
|
if (!result.success) {
|
|
81
65
|
const issues = result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`);
|
|
82
66
|
errors.push(`Schema validation failed: ${issues.join("; ")}`);
|
|
@@ -112,7 +96,6 @@ function validatePluginDirectory(pluginPath) {
|
|
|
112
96
|
return {
|
|
113
97
|
valid: errors.length === 0,
|
|
114
98
|
manifest,
|
|
115
|
-
format,
|
|
116
99
|
errors,
|
|
117
100
|
warnings
|
|
118
101
|
};
|
|
@@ -143,31 +126,18 @@ function checkDirectoryHasSkills(skillsDir) {
|
|
|
143
126
|
return false;
|
|
144
127
|
}
|
|
145
128
|
}
|
|
146
|
-
function tryLoadManifest(pluginPath
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
let manifestPath;
|
|
150
|
-
let format;
|
|
151
|
-
if ((0, import_fs.existsSync)(dextoManifestPath)) {
|
|
152
|
-
manifestPath = dextoManifestPath;
|
|
153
|
-
format = "dexto";
|
|
154
|
-
} else if ((0, import_fs.existsSync)(claudeManifestPath)) {
|
|
155
|
-
manifestPath = claudeManifestPath;
|
|
156
|
-
format = "claude-code";
|
|
157
|
-
} else {
|
|
129
|
+
function tryLoadManifest(pluginPath) {
|
|
130
|
+
const manifestPath = path.join(pluginPath, ".claude-plugin", "plugin.json");
|
|
131
|
+
if (!(0, import_fs.existsSync)(manifestPath)) {
|
|
158
132
|
return null;
|
|
159
133
|
}
|
|
160
134
|
try {
|
|
161
135
|
const content = (0, import_fs.readFileSync)(manifestPath, "utf-8");
|
|
162
136
|
const parsed = JSON.parse(content);
|
|
163
|
-
const
|
|
164
|
-
const result = schema.safeParse(parsed);
|
|
137
|
+
const result = import_schemas.PluginManifestSchema.safeParse(parsed);
|
|
165
138
|
if (!result.success) {
|
|
166
139
|
return null;
|
|
167
140
|
}
|
|
168
|
-
if (returnFormat) {
|
|
169
|
-
return { manifest: result.data, format };
|
|
170
|
-
}
|
|
171
141
|
return result.data;
|
|
172
142
|
} catch {
|
|
173
143
|
return null;
|
|
@@ -4,24 +4,16 @@
|
|
|
4
4
|
* Validates plugin directory structure and manifest.
|
|
5
5
|
* Checks for required files, valid JSON, and schema compliance.
|
|
6
6
|
*
|
|
7
|
-
* Supports
|
|
8
|
-
* - .claude-plugin/plugin.json
|
|
9
|
-
* - .dexto-plugin/plugin.json: Dexto-native format with extended features (preferred)
|
|
7
|
+
* Supports Claude Code compatible plugins:
|
|
8
|
+
* - .claude-plugin/plugin.json
|
|
10
9
|
*/
|
|
11
|
-
import type { PluginValidationResult, PluginManifest
|
|
12
|
-
/**
|
|
13
|
-
* Extended validation result with plugin format
|
|
14
|
-
*/
|
|
15
|
-
export interface ExtendedPluginValidationResult extends PluginValidationResult {
|
|
16
|
-
/** Plugin format detected */
|
|
17
|
-
format?: PluginFormat;
|
|
18
|
-
}
|
|
10
|
+
import type { PluginValidationResult, PluginManifest } from './types.js';
|
|
19
11
|
/**
|
|
20
12
|
* Validates a plugin directory structure and manifest.
|
|
21
13
|
*
|
|
22
14
|
* Checks:
|
|
23
15
|
* 1. Directory exists
|
|
24
|
-
* 2. .
|
|
16
|
+
* 2. .claude-plugin/plugin.json exists
|
|
25
17
|
* 3. plugin.json is valid JSON
|
|
26
18
|
* 4. plugin.json matches schema (name is required)
|
|
27
19
|
* 5. At least one command or skill exists (warning if none)
|
|
@@ -29,25 +21,15 @@ export interface ExtendedPluginValidationResult extends PluginValidationResult {
|
|
|
29
21
|
* @param pluginPath Absolute or relative path to plugin directory
|
|
30
22
|
* @returns Validation result with manifest (if valid), errors, and warnings
|
|
31
23
|
*/
|
|
32
|
-
export declare function validatePluginDirectory(pluginPath: string):
|
|
33
|
-
/**
|
|
34
|
-
* Result of manifest loading with format information
|
|
35
|
-
*/
|
|
36
|
-
export interface LoadedManifestResult {
|
|
37
|
-
manifest: PluginManifest | DextoPluginManifest;
|
|
38
|
-
format: PluginFormat;
|
|
39
|
-
}
|
|
24
|
+
export declare function validatePluginDirectory(pluginPath: string): PluginValidationResult;
|
|
40
25
|
/**
|
|
41
26
|
* Attempts to load and validate a plugin manifest from a directory.
|
|
42
27
|
* Returns null if the manifest doesn't exist, is invalid JSON, or fails schema validation.
|
|
43
28
|
*
|
|
44
|
-
* Checks for .dexto-plugin first (preferred), then falls back to .claude-plugin.
|
|
45
|
-
*
|
|
46
29
|
* This is a shared utility used by discover-plugins, list-plugins, and import-plugin.
|
|
47
30
|
*
|
|
48
31
|
* @param pluginPath Absolute path to the plugin directory
|
|
49
|
-
* @returns Validated manifest
|
|
32
|
+
* @returns Validated manifest or null if not a valid plugin
|
|
50
33
|
*/
|
|
51
34
|
export declare function tryLoadManifest(pluginPath: string): PluginManifest | null;
|
|
52
|
-
export declare function tryLoadManifest(pluginPath: string, returnFormat: true): LoadedManifestResult | null;
|
|
53
35
|
//# sourceMappingURL=validate-plugin.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-plugin.d.ts","sourceRoot":"","sources":["../../src/plugins/validate-plugin.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"validate-plugin.d.ts","sourceRoot":"","sources":["../../src/plugins/validate-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEzE;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,sBAAsB,CAsFlF;AAuCD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAmBzE"}
|
|
@@ -1,33 +1,18 @@
|
|
|
1
1
|
import * as path from "path";
|
|
2
2
|
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
3
|
-
import { PluginManifestSchema
|
|
3
|
+
import { PluginManifestSchema } from "./schemas.js";
|
|
4
4
|
function validatePluginDirectory(pluginPath) {
|
|
5
5
|
const errors = [];
|
|
6
6
|
const warnings = [];
|
|
7
7
|
let manifest;
|
|
8
|
-
let format;
|
|
9
8
|
const absolutePath = path.isAbsolute(pluginPath) ? pluginPath : path.resolve(pluginPath);
|
|
10
9
|
if (!existsSync(absolutePath)) {
|
|
11
10
|
errors.push(`Directory does not exist: ${absolutePath}`);
|
|
12
11
|
return { valid: false, errors, warnings };
|
|
13
12
|
}
|
|
14
|
-
const
|
|
15
|
-
const claudePluginDir = path.join(absolutePath, ".claude-plugin");
|
|
16
|
-
let manifestPath;
|
|
17
|
-
if (existsSync(dextoPluginDir)) {
|
|
18
|
-
manifestPath = path.join(dextoPluginDir, "plugin.json");
|
|
19
|
-
format = "dexto";
|
|
20
|
-
} else if (existsSync(claudePluginDir)) {
|
|
21
|
-
manifestPath = path.join(claudePluginDir, "plugin.json");
|
|
22
|
-
format = "claude-code";
|
|
23
|
-
} else {
|
|
24
|
-
errors.push("Missing .dexto-plugin or .claude-plugin directory");
|
|
25
|
-
return { valid: false, errors, warnings };
|
|
26
|
-
}
|
|
13
|
+
const manifestPath = path.join(absolutePath, ".claude-plugin", "plugin.json");
|
|
27
14
|
if (!existsSync(manifestPath)) {
|
|
28
|
-
errors.push(
|
|
29
|
-
`Missing ${format === "dexto" ? ".dexto-plugin" : ".claude-plugin"}/plugin.json`
|
|
30
|
-
);
|
|
15
|
+
errors.push("Missing .claude-plugin/plugin.json");
|
|
31
16
|
return { valid: false, errors, warnings };
|
|
32
17
|
}
|
|
33
18
|
try {
|
|
@@ -41,8 +26,7 @@ function validatePluginDirectory(pluginPath) {
|
|
|
41
26
|
);
|
|
42
27
|
return { valid: false, errors, warnings };
|
|
43
28
|
}
|
|
44
|
-
const
|
|
45
|
-
const result = schema.safeParse(parsed);
|
|
29
|
+
const result = PluginManifestSchema.safeParse(parsed);
|
|
46
30
|
if (!result.success) {
|
|
47
31
|
const issues = result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`);
|
|
48
32
|
errors.push(`Schema validation failed: ${issues.join("; ")}`);
|
|
@@ -78,7 +62,6 @@ function validatePluginDirectory(pluginPath) {
|
|
|
78
62
|
return {
|
|
79
63
|
valid: errors.length === 0,
|
|
80
64
|
manifest,
|
|
81
|
-
format,
|
|
82
65
|
errors,
|
|
83
66
|
warnings
|
|
84
67
|
};
|
|
@@ -109,31 +92,18 @@ function checkDirectoryHasSkills(skillsDir) {
|
|
|
109
92
|
return false;
|
|
110
93
|
}
|
|
111
94
|
}
|
|
112
|
-
function tryLoadManifest(pluginPath
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
let manifestPath;
|
|
116
|
-
let format;
|
|
117
|
-
if (existsSync(dextoManifestPath)) {
|
|
118
|
-
manifestPath = dextoManifestPath;
|
|
119
|
-
format = "dexto";
|
|
120
|
-
} else if (existsSync(claudeManifestPath)) {
|
|
121
|
-
manifestPath = claudeManifestPath;
|
|
122
|
-
format = "claude-code";
|
|
123
|
-
} else {
|
|
95
|
+
function tryLoadManifest(pluginPath) {
|
|
96
|
+
const manifestPath = path.join(pluginPath, ".claude-plugin", "plugin.json");
|
|
97
|
+
if (!existsSync(manifestPath)) {
|
|
124
98
|
return null;
|
|
125
99
|
}
|
|
126
100
|
try {
|
|
127
101
|
const content = readFileSync(manifestPath, "utf-8");
|
|
128
102
|
const parsed = JSON.parse(content);
|
|
129
|
-
const
|
|
130
|
-
const result = schema.safeParse(parsed);
|
|
103
|
+
const result = PluginManifestSchema.safeParse(parsed);
|
|
131
104
|
if (!result.success) {
|
|
132
105
|
return null;
|
|
133
106
|
}
|
|
134
|
-
if (returnFormat) {
|
|
135
|
-
return { manifest: result.data, format };
|
|
136
|
-
}
|
|
137
107
|
return result.data;
|
|
138
108
|
} catch {
|
|
139
109
|
return null;
|
|
@@ -66,6 +66,17 @@ class PreferenceError {
|
|
|
66
66
|
}));
|
|
67
67
|
return new import_core.DextoValidationError(issues);
|
|
68
68
|
}
|
|
69
|
+
static invalidAgentId(agentId) {
|
|
70
|
+
return new import_core.DextoValidationError([
|
|
71
|
+
{
|
|
72
|
+
code: import_error_codes.PreferenceErrorCode.INVALID_PREFERENCE_VALUE,
|
|
73
|
+
message: `agentId is invalid: ${agentId}`,
|
|
74
|
+
scope: "preference",
|
|
75
|
+
type: import_core.ErrorType.USER,
|
|
76
|
+
severity: "error"
|
|
77
|
+
}
|
|
78
|
+
]);
|
|
79
|
+
}
|
|
69
80
|
}
|
|
70
81
|
// Annotate the CommonJS export names for ESM import in node:
|
|
71
82
|
0 && (module.exports = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/preferences/errors.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAa,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,KAAK,CAAC;AAGpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,qBAAa,eAAe;IACxB,MAAM,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM;;;IAW3C,MAAM,CAAC,aAAa,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;IAW3D,MAAM,CAAC,cAAc,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;IAW5D,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/preferences/errors.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAa,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,KAAK,CAAC;AAGpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,qBAAa,eAAe;IACxB,MAAM,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM;;;IAW3C,MAAM,CAAC,aAAa,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;IAW3D,MAAM,CAAC,cAAc,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;IAW5D,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ;IAY1C,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM;CAWxC"}
|
|
@@ -42,6 +42,17 @@ class PreferenceError {
|
|
|
42
42
|
}));
|
|
43
43
|
return new DextoValidationError(issues);
|
|
44
44
|
}
|
|
45
|
+
static invalidAgentId(agentId) {
|
|
46
|
+
return new DextoValidationError([
|
|
47
|
+
{
|
|
48
|
+
code: PreferenceErrorCode.INVALID_PREFERENCE_VALUE,
|
|
49
|
+
message: `agentId is invalid: ${agentId}`,
|
|
50
|
+
scope: "preference",
|
|
51
|
+
type: ErrorType.USER,
|
|
52
|
+
severity: "error"
|
|
53
|
+
}
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
45
56
|
}
|
|
46
57
|
export {
|
|
47
58
|
PreferenceError,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,28 +17,42 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
var loader_exports = {};
|
|
20
30
|
__export(loader_exports, {
|
|
31
|
+
agentPreferencesExist: () => agentPreferencesExist,
|
|
21
32
|
createInitialPreferences: () => createInitialPreferences,
|
|
33
|
+
getAgentPreferencesPath: () => getAgentPreferencesPath,
|
|
22
34
|
getGlobalPreferencesPath: () => getGlobalPreferencesPath,
|
|
23
35
|
globalPreferencesExist: () => globalPreferencesExist,
|
|
36
|
+
loadAgentPreferences: () => loadAgentPreferences,
|
|
24
37
|
loadGlobalPreferences: () => loadGlobalPreferences,
|
|
38
|
+
saveAgentPreferences: () => saveAgentPreferences,
|
|
25
39
|
saveGlobalPreferences: () => saveGlobalPreferences,
|
|
40
|
+
updateAgentPreferences: () => updateAgentPreferences,
|
|
26
41
|
updateGlobalPreferences: () => updateGlobalPreferences
|
|
27
42
|
});
|
|
28
43
|
module.exports = __toCommonJS(loader_exports);
|
|
29
44
|
var import_fs = require("fs");
|
|
30
45
|
var import_fs2 = require("fs");
|
|
31
46
|
var import_yaml = require("yaml");
|
|
32
|
-
var import_path = require("
|
|
47
|
+
var import_path = __toESM(require("path"), 1);
|
|
48
|
+
var import_path2 = require("../utils/path.js");
|
|
33
49
|
var import_core = require("@dexto/core");
|
|
34
50
|
var import_core2 = require("@dexto/core");
|
|
35
51
|
var import_schemas = require("./schemas.js");
|
|
36
52
|
var import_constants = require("./constants.js");
|
|
37
53
|
var import_errors = require("./errors.js");
|
|
38
54
|
async function loadGlobalPreferences() {
|
|
39
|
-
const preferencesPath = (0,
|
|
55
|
+
const preferencesPath = (0, import_path2.getDextoGlobalPath)(import_constants.PREFERENCES_FILE);
|
|
40
56
|
if (!(0, import_fs.existsSync)(preferencesPath)) {
|
|
41
57
|
throw import_errors.PreferenceError.fileNotFound(preferencesPath);
|
|
42
58
|
}
|
|
@@ -70,15 +86,107 @@ const PREFERENCES_FILE_HEADER = `# Dexto Global Preferences
|
|
|
70
86
|
# Set sounds.enabled: false to disable all sounds.
|
|
71
87
|
|
|
72
88
|
`;
|
|
89
|
+
const AGENT_PREFERENCES_FILE_HEADER = `# Dexto Agent Preferences
|
|
90
|
+
# Stored per-agent to customize runtime behavior without changing base config.
|
|
91
|
+
# Tool control:
|
|
92
|
+
# tools.disabled: list of tool names to exclude from LLM context.
|
|
93
|
+
|
|
94
|
+
`;
|
|
95
|
+
function getAgentPreferencesPath(agentId) {
|
|
96
|
+
if (!agentId || typeof agentId !== "string") {
|
|
97
|
+
throw import_errors.PreferenceError.invalidAgentId(String(agentId));
|
|
98
|
+
}
|
|
99
|
+
const trimmedId = agentId.trim();
|
|
100
|
+
if (!trimmedId) {
|
|
101
|
+
throw import_errors.PreferenceError.invalidAgentId(agentId);
|
|
102
|
+
}
|
|
103
|
+
const hasSeparators = trimmedId.includes("/") || trimmedId.includes("\\");
|
|
104
|
+
if (hasSeparators || trimmedId !== import_path.default.basename(trimmedId)) {
|
|
105
|
+
throw import_errors.PreferenceError.invalidAgentId(agentId);
|
|
106
|
+
}
|
|
107
|
+
const allowedPattern = /^[a-zA-Z0-9_-]+$/;
|
|
108
|
+
if (!allowedPattern.test(trimmedId)) {
|
|
109
|
+
throw import_errors.PreferenceError.invalidAgentId(agentId);
|
|
110
|
+
}
|
|
111
|
+
const filename = `${trimmedId}.preferences.yml`;
|
|
112
|
+
return (0, import_path2.getDextoGlobalPath)(import_path.default.join("agents", filename));
|
|
113
|
+
}
|
|
114
|
+
async function loadAgentPreferences(agentId) {
|
|
115
|
+
const preferencesPath = getAgentPreferencesPath(agentId);
|
|
116
|
+
if (!(0, import_fs.existsSync)(preferencesPath)) {
|
|
117
|
+
throw import_errors.PreferenceError.fileNotFound(preferencesPath);
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const fileContent = await import_fs2.promises.readFile(preferencesPath, "utf-8");
|
|
121
|
+
const rawPreferences = (0, import_yaml.parse)(fileContent);
|
|
122
|
+
const validation = import_schemas.AgentPreferencesSchema.safeParse(rawPreferences);
|
|
123
|
+
if (!validation.success) {
|
|
124
|
+
throw import_errors.PreferenceError.validationFailed(validation.error);
|
|
125
|
+
}
|
|
126
|
+
import_core.logger.debug(`Loaded agent preferences from: ${preferencesPath}`);
|
|
127
|
+
return validation.data;
|
|
128
|
+
} catch (error) {
|
|
129
|
+
if (error instanceof import_core2.DextoValidationError || error instanceof import_core2.DextoRuntimeError) {
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
throw import_errors.PreferenceError.fileReadError(
|
|
133
|
+
preferencesPath,
|
|
134
|
+
error instanceof Error ? error.message : String(error)
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async function saveAgentPreferences(agentId, preferences) {
|
|
139
|
+
const preferencesPath = getAgentPreferencesPath(agentId);
|
|
140
|
+
const validation = import_schemas.AgentPreferencesSchema.safeParse(preferences);
|
|
141
|
+
if (!validation.success) {
|
|
142
|
+
throw import_errors.PreferenceError.validationFailed(validation.error);
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
import_core.logger.debug(`Saving agent preferences to: ${preferencesPath}`);
|
|
146
|
+
await import_fs2.promises.mkdir(import_path.default.dirname(preferencesPath), { recursive: true });
|
|
147
|
+
const yamlContent = (0, import_yaml.stringify)(preferences, {
|
|
148
|
+
indent: 2,
|
|
149
|
+
lineWidth: 100,
|
|
150
|
+
minContentWidth: 20
|
|
151
|
+
});
|
|
152
|
+
await import_fs2.promises.writeFile(preferencesPath, AGENT_PREFERENCES_FILE_HEADER + yamlContent, "utf-8");
|
|
153
|
+
import_core.logger.debug(
|
|
154
|
+
`\u2713 Saved agent preferences ${JSON.stringify(preferences)} to: ${preferencesPath}`
|
|
155
|
+
);
|
|
156
|
+
} catch (error) {
|
|
157
|
+
throw import_errors.PreferenceError.fileWriteError(
|
|
158
|
+
preferencesPath,
|
|
159
|
+
error instanceof Error ? error.message : String(error)
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function agentPreferencesExist(agentId) {
|
|
164
|
+
const preferencesPath = getAgentPreferencesPath(agentId);
|
|
165
|
+
return (0, import_fs.existsSync)(preferencesPath);
|
|
166
|
+
}
|
|
167
|
+
async function updateAgentPreferences(agentId, updates) {
|
|
168
|
+
const existing = await loadAgentPreferences(agentId);
|
|
169
|
+
const merged = {
|
|
170
|
+
...existing,
|
|
171
|
+
...updates,
|
|
172
|
+
tools: updates.tools ? { ...existing.tools, ...updates.tools } : existing.tools
|
|
173
|
+
};
|
|
174
|
+
const validation = import_schemas.AgentPreferencesSchema.safeParse(merged);
|
|
175
|
+
if (!validation.success) {
|
|
176
|
+
throw import_errors.PreferenceError.validationFailed(validation.error);
|
|
177
|
+
}
|
|
178
|
+
await saveAgentPreferences(agentId, validation.data);
|
|
179
|
+
return validation.data;
|
|
180
|
+
}
|
|
73
181
|
async function saveGlobalPreferences(preferences) {
|
|
74
|
-
const preferencesPath = (0,
|
|
182
|
+
const preferencesPath = (0, import_path2.getDextoGlobalPath)(import_constants.PREFERENCES_FILE);
|
|
75
183
|
const validation = import_schemas.GlobalPreferencesSchema.safeParse(preferences);
|
|
76
184
|
if (!validation.success) {
|
|
77
185
|
throw import_errors.PreferenceError.validationFailed(validation.error);
|
|
78
186
|
}
|
|
79
187
|
try {
|
|
80
188
|
import_core.logger.debug(`Saving global preferences to: ${preferencesPath}`);
|
|
81
|
-
const dextoDir = (0,
|
|
189
|
+
const dextoDir = (0, import_path2.getDextoGlobalPath)("");
|
|
82
190
|
await import_fs2.promises.mkdir(dextoDir, { recursive: true });
|
|
83
191
|
const yamlContent = (0, import_yaml.stringify)(preferences, {
|
|
84
192
|
indent: 2,
|
|
@@ -97,11 +205,11 @@ async function saveGlobalPreferences(preferences) {
|
|
|
97
205
|
}
|
|
98
206
|
}
|
|
99
207
|
function globalPreferencesExist() {
|
|
100
|
-
const preferencesPath = (0,
|
|
208
|
+
const preferencesPath = (0, import_path2.getDextoGlobalPath)(import_constants.PREFERENCES_FILE);
|
|
101
209
|
return (0, import_fs.existsSync)(preferencesPath);
|
|
102
210
|
}
|
|
103
211
|
function getGlobalPreferencesPath() {
|
|
104
|
-
return (0,
|
|
212
|
+
return (0, import_path2.getDextoGlobalPath)(import_constants.PREFERENCES_FILE);
|
|
105
213
|
}
|
|
106
214
|
function createInitialPreferences(options) {
|
|
107
215
|
const llmConfig = {
|
|
@@ -156,10 +264,15 @@ async function updateGlobalPreferences(updates) {
|
|
|
156
264
|
}
|
|
157
265
|
// Annotate the CommonJS export names for ESM import in node:
|
|
158
266
|
0 && (module.exports = {
|
|
267
|
+
agentPreferencesExist,
|
|
159
268
|
createInitialPreferences,
|
|
269
|
+
getAgentPreferencesPath,
|
|
160
270
|
getGlobalPreferencesPath,
|
|
161
271
|
globalPreferencesExist,
|
|
272
|
+
loadAgentPreferences,
|
|
162
273
|
loadGlobalPreferences,
|
|
274
|
+
saveAgentPreferences,
|
|
163
275
|
saveGlobalPreferences,
|
|
276
|
+
updateAgentPreferences,
|
|
164
277
|
updateGlobalPreferences
|
|
165
278
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LLMProvider } from '@dexto/core';
|
|
2
|
-
import { type GlobalPreferences } from './schemas.js';
|
|
2
|
+
import { type AgentPreferences, type GlobalPreferences } from './schemas.js';
|
|
3
3
|
/**
|
|
4
4
|
* Load global preferences from ~/.dexto/preferences.yml
|
|
5
5
|
* @returns Global preferences object
|
|
@@ -7,6 +7,26 @@ import { type GlobalPreferences } from './schemas.js';
|
|
|
7
7
|
* @throws DextoValidationError if preferences are invalid
|
|
8
8
|
*/
|
|
9
9
|
export declare function loadGlobalPreferences(): Promise<GlobalPreferences>;
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the agent preferences file path for an agent ID.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getAgentPreferencesPath(agentId: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Load agent preferences from ~/.dexto/agents/<agentId>.preferences.yml
|
|
16
|
+
*/
|
|
17
|
+
export declare function loadAgentPreferences(agentId: string): Promise<AgentPreferences>;
|
|
18
|
+
/**
|
|
19
|
+
* Save agent preferences to ~/.dexto/agents/<agentId>.preferences.yml
|
|
20
|
+
*/
|
|
21
|
+
export declare function saveAgentPreferences(agentId: string, preferences: AgentPreferences): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Check if agent preferences exist (for first-time detection)
|
|
24
|
+
*/
|
|
25
|
+
export declare function agentPreferencesExist(agentId: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Update agent preferences with partial updates
|
|
28
|
+
*/
|
|
29
|
+
export declare function updateAgentPreferences(agentId: string, updates: Partial<AgentPreferences>): Promise<AgentPreferences>;
|
|
10
30
|
/**
|
|
11
31
|
* Save global preferences to ~/.dexto/preferences.yml
|
|
12
32
|
* @param preferences Validated preferences object
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/preferences/loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/preferences/loader.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAGH,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACzB,MAAM,cAAc,CAAC;AAItB;;;;;GAKG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CA+BxE;AA2BD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAsB/D;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4BrF;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACtC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,gBAAgB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAG9D;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CACxC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GACnC,OAAO,CAAC,gBAAgB,CAAC,CAgB3B;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkCzF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAGhD;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACrC,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,CAAC;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAC3E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,yEAAyE;IACzE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qCAAqC;IACrC,MAAM,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,cAAc,CAAC,EAAE,OAAO,CAAC;KAC5B,CAAC;CACL;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAsC7F;AAED;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACnC,GAAG,CAAC,EAAE,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC;IAClD,KAAK,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5C,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;CACjD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CACzC,OAAO,EAAE,wBAAwB,GAClC,OAAO,CAAC,iBAAiB,CAAC,CA4B5B"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { existsSync } from "fs";
|
|
2
2
|
import { promises as fs } from "fs";
|
|
3
3
|
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
4
|
+
import path from "path";
|
|
4
5
|
import { getDextoGlobalPath } from "../utils/path.js";
|
|
5
6
|
import { logger } from "@dexto/core";
|
|
6
7
|
import { DextoValidationError, DextoRuntimeError } from "@dexto/core";
|
|
7
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
AgentPreferencesSchema,
|
|
10
|
+
GlobalPreferencesSchema
|
|
11
|
+
} from "./schemas.js";
|
|
8
12
|
import { PREFERENCES_FILE } from "./constants.js";
|
|
9
13
|
import { PreferenceError } from "./errors.js";
|
|
10
14
|
async function loadGlobalPreferences() {
|
|
@@ -42,6 +46,98 @@ const PREFERENCES_FILE_HEADER = `# Dexto Global Preferences
|
|
|
42
46
|
# Set sounds.enabled: false to disable all sounds.
|
|
43
47
|
|
|
44
48
|
`;
|
|
49
|
+
const AGENT_PREFERENCES_FILE_HEADER = `# Dexto Agent Preferences
|
|
50
|
+
# Stored per-agent to customize runtime behavior without changing base config.
|
|
51
|
+
# Tool control:
|
|
52
|
+
# tools.disabled: list of tool names to exclude from LLM context.
|
|
53
|
+
|
|
54
|
+
`;
|
|
55
|
+
function getAgentPreferencesPath(agentId) {
|
|
56
|
+
if (!agentId || typeof agentId !== "string") {
|
|
57
|
+
throw PreferenceError.invalidAgentId(String(agentId));
|
|
58
|
+
}
|
|
59
|
+
const trimmedId = agentId.trim();
|
|
60
|
+
if (!trimmedId) {
|
|
61
|
+
throw PreferenceError.invalidAgentId(agentId);
|
|
62
|
+
}
|
|
63
|
+
const hasSeparators = trimmedId.includes("/") || trimmedId.includes("\\");
|
|
64
|
+
if (hasSeparators || trimmedId !== path.basename(trimmedId)) {
|
|
65
|
+
throw PreferenceError.invalidAgentId(agentId);
|
|
66
|
+
}
|
|
67
|
+
const allowedPattern = /^[a-zA-Z0-9_-]+$/;
|
|
68
|
+
if (!allowedPattern.test(trimmedId)) {
|
|
69
|
+
throw PreferenceError.invalidAgentId(agentId);
|
|
70
|
+
}
|
|
71
|
+
const filename = `${trimmedId}.preferences.yml`;
|
|
72
|
+
return getDextoGlobalPath(path.join("agents", filename));
|
|
73
|
+
}
|
|
74
|
+
async function loadAgentPreferences(agentId) {
|
|
75
|
+
const preferencesPath = getAgentPreferencesPath(agentId);
|
|
76
|
+
if (!existsSync(preferencesPath)) {
|
|
77
|
+
throw PreferenceError.fileNotFound(preferencesPath);
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const fileContent = await fs.readFile(preferencesPath, "utf-8");
|
|
81
|
+
const rawPreferences = parseYaml(fileContent);
|
|
82
|
+
const validation = AgentPreferencesSchema.safeParse(rawPreferences);
|
|
83
|
+
if (!validation.success) {
|
|
84
|
+
throw PreferenceError.validationFailed(validation.error);
|
|
85
|
+
}
|
|
86
|
+
logger.debug(`Loaded agent preferences from: ${preferencesPath}`);
|
|
87
|
+
return validation.data;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (error instanceof DextoValidationError || error instanceof DextoRuntimeError) {
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
throw PreferenceError.fileReadError(
|
|
93
|
+
preferencesPath,
|
|
94
|
+
error instanceof Error ? error.message : String(error)
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function saveAgentPreferences(agentId, preferences) {
|
|
99
|
+
const preferencesPath = getAgentPreferencesPath(agentId);
|
|
100
|
+
const validation = AgentPreferencesSchema.safeParse(preferences);
|
|
101
|
+
if (!validation.success) {
|
|
102
|
+
throw PreferenceError.validationFailed(validation.error);
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
logger.debug(`Saving agent preferences to: ${preferencesPath}`);
|
|
106
|
+
await fs.mkdir(path.dirname(preferencesPath), { recursive: true });
|
|
107
|
+
const yamlContent = stringifyYaml(preferences, {
|
|
108
|
+
indent: 2,
|
|
109
|
+
lineWidth: 100,
|
|
110
|
+
minContentWidth: 20
|
|
111
|
+
});
|
|
112
|
+
await fs.writeFile(preferencesPath, AGENT_PREFERENCES_FILE_HEADER + yamlContent, "utf-8");
|
|
113
|
+
logger.debug(
|
|
114
|
+
`\u2713 Saved agent preferences ${JSON.stringify(preferences)} to: ${preferencesPath}`
|
|
115
|
+
);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
throw PreferenceError.fileWriteError(
|
|
118
|
+
preferencesPath,
|
|
119
|
+
error instanceof Error ? error.message : String(error)
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function agentPreferencesExist(agentId) {
|
|
124
|
+
const preferencesPath = getAgentPreferencesPath(agentId);
|
|
125
|
+
return existsSync(preferencesPath);
|
|
126
|
+
}
|
|
127
|
+
async function updateAgentPreferences(agentId, updates) {
|
|
128
|
+
const existing = await loadAgentPreferences(agentId);
|
|
129
|
+
const merged = {
|
|
130
|
+
...existing,
|
|
131
|
+
...updates,
|
|
132
|
+
tools: updates.tools ? { ...existing.tools, ...updates.tools } : existing.tools
|
|
133
|
+
};
|
|
134
|
+
const validation = AgentPreferencesSchema.safeParse(merged);
|
|
135
|
+
if (!validation.success) {
|
|
136
|
+
throw PreferenceError.validationFailed(validation.error);
|
|
137
|
+
}
|
|
138
|
+
await saveAgentPreferences(agentId, validation.data);
|
|
139
|
+
return validation.data;
|
|
140
|
+
}
|
|
45
141
|
async function saveGlobalPreferences(preferences) {
|
|
46
142
|
const preferencesPath = getDextoGlobalPath(PREFERENCES_FILE);
|
|
47
143
|
const validation = GlobalPreferencesSchema.safeParse(preferences);
|
|
@@ -127,10 +223,15 @@ async function updateGlobalPreferences(updates) {
|
|
|
127
223
|
return validation.data;
|
|
128
224
|
}
|
|
129
225
|
export {
|
|
226
|
+
agentPreferencesExist,
|
|
130
227
|
createInitialPreferences,
|
|
228
|
+
getAgentPreferencesPath,
|
|
131
229
|
getGlobalPreferencesPath,
|
|
132
230
|
globalPreferencesExist,
|
|
231
|
+
loadAgentPreferences,
|
|
133
232
|
loadGlobalPreferences,
|
|
233
|
+
saveAgentPreferences,
|
|
134
234
|
saveGlobalPreferences,
|
|
235
|
+
updateAgentPreferences,
|
|
135
236
|
updateGlobalPreferences
|
|
136
237
|
};
|