@dexto/agent-management 1.3.0 → 1.5.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.
Files changed (94) hide show
  1. package/dist/AgentFactory.cjs +152 -0
  2. package/dist/AgentFactory.d.ts +121 -0
  3. package/dist/AgentFactory.d.ts.map +1 -0
  4. package/dist/AgentFactory.js +132 -0
  5. package/dist/AgentManager.cjs +226 -0
  6. package/dist/AgentManager.d.ts +191 -0
  7. package/dist/AgentManager.d.ts.map +1 -0
  8. package/dist/AgentManager.js +192 -0
  9. package/dist/config/config-enrichment.cjs +23 -3
  10. package/dist/config/config-enrichment.d.ts +20 -5
  11. package/dist/config/config-enrichment.d.ts.map +1 -1
  12. package/dist/config/config-enrichment.js +22 -3
  13. package/dist/config/config-manager.cjs +340 -3
  14. package/dist/config/config-manager.d.ts +158 -7
  15. package/dist/config/config-manager.d.ts.map +1 -1
  16. package/dist/config/config-manager.js +325 -3
  17. package/dist/config/discover-prompts.cjs +103 -0
  18. package/dist/config/discover-prompts.d.ts +28 -0
  19. package/dist/config/discover-prompts.d.ts.map +1 -0
  20. package/dist/config/discover-prompts.js +73 -0
  21. package/dist/config/errors.cjs +2 -2
  22. package/dist/config/errors.js +2 -2
  23. package/dist/config/index.cjs +14 -2
  24. package/dist/config/index.d.ts +2 -2
  25. package/dist/config/index.d.ts.map +1 -1
  26. package/dist/config/index.js +21 -3
  27. package/dist/index.cjs +109 -6
  28. package/dist/index.d.ts +9 -6
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +111 -6
  31. package/dist/installation.cjs +239 -0
  32. package/dist/installation.d.ts +72 -0
  33. package/dist/installation.d.ts.map +1 -0
  34. package/dist/installation.js +202 -0
  35. package/dist/models/custom-models.cjs +157 -0
  36. package/dist/models/custom-models.d.ts +94 -0
  37. package/dist/models/custom-models.d.ts.map +1 -0
  38. package/dist/models/custom-models.js +117 -0
  39. package/dist/models/index.cjs +89 -0
  40. package/dist/models/index.d.ts +11 -0
  41. package/dist/models/index.d.ts.map +1 -0
  42. package/dist/models/index.js +68 -0
  43. package/dist/models/path-resolver.cjs +154 -0
  44. package/dist/models/path-resolver.d.ts +77 -0
  45. package/dist/models/path-resolver.d.ts.map +1 -0
  46. package/dist/models/path-resolver.js +108 -0
  47. package/dist/models/state-manager.cjs +220 -0
  48. package/dist/models/state-manager.d.ts +138 -0
  49. package/dist/models/state-manager.d.ts.map +1 -0
  50. package/dist/models/state-manager.js +184 -0
  51. package/dist/preferences/error-codes.cjs +2 -0
  52. package/dist/preferences/error-codes.d.ts +3 -1
  53. package/dist/preferences/error-codes.d.ts.map +1 -1
  54. package/dist/preferences/error-codes.js +2 -0
  55. package/dist/preferences/index.d.ts +1 -1
  56. package/dist/preferences/index.d.ts.map +1 -1
  57. package/dist/preferences/loader.cjs +32 -6
  58. package/dist/preferences/loader.d.ts +23 -4
  59. package/dist/preferences/loader.d.ts.map +1 -1
  60. package/dist/preferences/loader.js +32 -6
  61. package/dist/preferences/schemas.cjs +21 -3
  62. package/dist/preferences/schemas.d.ts +52 -24
  63. package/dist/preferences/schemas.d.ts.map +1 -1
  64. package/dist/preferences/schemas.js +28 -4
  65. package/dist/registry/registry.cjs +28 -45
  66. package/dist/registry/registry.d.ts +8 -6
  67. package/dist/registry/registry.d.ts.map +1 -1
  68. package/dist/registry/registry.js +26 -44
  69. package/dist/registry/types.d.ts +11 -13
  70. package/dist/registry/types.d.ts.map +1 -1
  71. package/dist/resolver.cjs +82 -43
  72. package/dist/resolver.d.ts +7 -5
  73. package/dist/resolver.d.ts.map +1 -1
  74. package/dist/resolver.js +83 -44
  75. package/dist/utils/api-key-resolver.cjs +19 -1
  76. package/dist/utils/api-key-resolver.d.ts.map +1 -1
  77. package/dist/utils/api-key-resolver.js +19 -1
  78. package/dist/utils/api-key-store.cjs +46 -0
  79. package/dist/utils/api-key-store.d.ts +27 -0
  80. package/dist/utils/api-key-store.d.ts.map +1 -1
  81. package/dist/utils/api-key-store.js +44 -0
  82. package/dist/utils/env-file.cjs +20 -68
  83. package/dist/utils/env-file.d.ts +2 -1
  84. package/dist/utils/env-file.d.ts.map +1 -1
  85. package/dist/utils/env-file.js +20 -68
  86. package/dist/writer.cjs +20 -2
  87. package/dist/writer.d.ts +1 -0
  88. package/dist/writer.d.ts.map +1 -1
  89. package/dist/writer.js +20 -2
  90. package/package.json +2 -2
  91. package/dist/AgentOrchestrator.cjs +0 -263
  92. package/dist/AgentOrchestrator.d.ts +0 -191
  93. package/dist/AgentOrchestrator.d.ts.map +0 -1
  94. package/dist/AgentOrchestrator.js +0 -239
@@ -1,6 +1,8 @@
1
1
  import { promises as fs } from "fs";
2
- import { parseDocument } from "yaml";
2
+ import * as path from "path";
3
+ import { parseDocument, stringify } from "yaml";
3
4
  import { loadAgentConfig } from "./loader.js";
5
+ import { enrichAgentConfig } from "./config-enrichment.js";
4
6
  import { AgentConfigSchema } from "@dexto/core";
5
7
  import { DextoValidationError } from "@dexto/core";
6
8
  import { fail, zodToIssues } from "@dexto/core";
@@ -9,7 +11,8 @@ async function updateAgentConfigFile(configPath, updates) {
9
11
  const doc = parseDocument(rawYaml);
10
12
  const rawConfig = doc.toJSON();
11
13
  const updatedRawConfig = { ...rawConfig, ...updates };
12
- const parsed = AgentConfigSchema.safeParse(updatedRawConfig);
14
+ const enrichedConfig = enrichAgentConfig(updatedRawConfig, configPath);
15
+ const parsed = AgentConfigSchema.safeParse(enrichedConfig);
13
16
  if (!parsed.success) {
14
17
  const result = fail(zodToIssues(parsed.error, "error"));
15
18
  throw new DextoValidationError(result.issues);
@@ -26,7 +29,326 @@ async function updateAgentConfigFile(configPath, updates) {
26
29
  async function reloadAgentConfigFromFile(configPath) {
27
30
  return await loadAgentConfig(configPath);
28
31
  }
32
+ async function writeFileAtomic(configPath, content) {
33
+ const tmpPath = `${configPath}.tmp`;
34
+ await fs.writeFile(tmpPath, content, "utf-8");
35
+ await fs.rename(tmpPath, configPath);
36
+ }
37
+ function findMcpServerRange(lines, serverName) {
38
+ let inMcpServersSection = false;
39
+ let mcpServersIndent = "";
40
+ let serverLevelIndent = -1;
41
+ let serverIndent = "";
42
+ let inTargetServer = false;
43
+ let serverStartLine = -1;
44
+ let serverEndLine = -1;
45
+ for (let i = 0; i < lines.length; i++) {
46
+ const line = lines[i] ?? "";
47
+ const trimmed = line.trimStart();
48
+ if (!trimmed || trimmed.startsWith("#")) {
49
+ if (inTargetServer && serverStartLine >= 0) {
50
+ }
51
+ continue;
52
+ }
53
+ const currentIndent = line.slice(0, line.length - trimmed.length);
54
+ const currentIndentLen = currentIndent.length;
55
+ if (!inMcpServersSection && trimmed.startsWith("mcpServers:")) {
56
+ inMcpServersSection = true;
57
+ mcpServersIndent = currentIndent;
58
+ continue;
59
+ }
60
+ if (inMcpServersSection) {
61
+ if (currentIndentLen <= mcpServersIndent.length && trimmed.includes(":")) {
62
+ if (inTargetServer && serverStartLine >= 0) {
63
+ return {
64
+ startLine: serverStartLine,
65
+ endLine: serverEndLine >= 0 ? serverEndLine : serverStartLine,
66
+ indent: serverIndent
67
+ };
68
+ }
69
+ return null;
70
+ }
71
+ if (serverLevelIndent < 0 && currentIndentLen > mcpServersIndent.length) {
72
+ serverLevelIndent = currentIndentLen;
73
+ }
74
+ if (serverLevelIndent >= 0 && currentIndentLen === serverLevelIndent) {
75
+ const serverMatch = trimmed.match(/^([a-zA-Z0-9_-]+):(\s|$)/);
76
+ if (serverMatch) {
77
+ const foundServerName = serverMatch[1];
78
+ if (inTargetServer && serverStartLine >= 0) {
79
+ return {
80
+ startLine: serverStartLine,
81
+ endLine: serverEndLine >= 0 ? serverEndLine : serverStartLine,
82
+ indent: serverIndent
83
+ };
84
+ }
85
+ if (foundServerName === serverName) {
86
+ inTargetServer = true;
87
+ serverStartLine = i;
88
+ serverEndLine = i;
89
+ serverIndent = currentIndent;
90
+ } else {
91
+ inTargetServer = false;
92
+ }
93
+ }
94
+ } else if (inTargetServer && currentIndentLen > serverLevelIndent) {
95
+ serverEndLine = i;
96
+ }
97
+ }
98
+ }
99
+ if (inTargetServer && serverStartLine >= 0) {
100
+ return {
101
+ startLine: serverStartLine,
102
+ endLine: serverEndLine >= 0 ? serverEndLine : serverStartLine,
103
+ indent: serverIndent
104
+ };
105
+ }
106
+ return null;
107
+ }
108
+ async function updateMcpServerField(configPath, serverName, field, value) {
109
+ const rawYaml = await fs.readFile(configPath, "utf-8");
110
+ const lines = rawYaml.split("\n");
111
+ const serverRange = findMcpServerRange(lines, serverName);
112
+ if (!serverRange) {
113
+ return false;
114
+ }
115
+ const formattedValue = typeof value === "string" ? value.includes(":") ? `"${value}"` : value : String(value);
116
+ const fieldIndent = serverRange.indent + " ";
117
+ const fieldPrefix = `${fieldIndent}${field}:`;
118
+ let fieldLineIndex = -1;
119
+ for (let i = serverRange.startLine + 1; i <= serverRange.endLine; i++) {
120
+ const line = lines[i] ?? "";
121
+ if (line.startsWith(fieldPrefix)) {
122
+ fieldLineIndex = i;
123
+ break;
124
+ }
125
+ }
126
+ if (fieldLineIndex >= 0) {
127
+ lines[fieldLineIndex] = `${fieldIndent}${field}: ${formattedValue}`;
128
+ } else {
129
+ const newFieldLine = `${fieldIndent}${field}: ${formattedValue}`;
130
+ lines.splice(serverRange.startLine + 1, 0, newFieldLine);
131
+ }
132
+ await writeFileAtomic(configPath, lines.join("\n"));
133
+ return true;
134
+ }
135
+ async function removeMcpServerFromConfig(configPath, serverName) {
136
+ const rawYaml = await fs.readFile(configPath, "utf-8");
137
+ const lines = rawYaml.split("\n");
138
+ const serverRange = findMcpServerRange(lines, serverName);
139
+ if (!serverRange) {
140
+ return false;
141
+ }
142
+ lines.splice(serverRange.startLine, serverRange.endLine - serverRange.startLine + 1);
143
+ await writeFileAtomic(configPath, lines.join("\n"));
144
+ return true;
145
+ }
146
+ function findPromptsArrayEndPosition(lines) {
147
+ let inPromptsSection = false;
148
+ let promptsIndent = "";
149
+ let lastPromptEntryEnd = -1;
150
+ let itemIndent = "";
151
+ for (let i = 0; i < lines.length; i++) {
152
+ const line = lines[i] ?? "";
153
+ const trimmed = line.trimStart();
154
+ if (trimmed.startsWith("prompts:")) {
155
+ inPromptsSection = true;
156
+ const idx = line.indexOf("prompts:");
157
+ promptsIndent = idx >= 0 ? line.slice(0, idx) : "";
158
+ continue;
159
+ }
160
+ if (inPromptsSection) {
161
+ if (trimmed && !trimmed.startsWith("#") && !trimmed.startsWith("-")) {
162
+ const currentIndent = line.slice(0, line.length - trimmed.length);
163
+ if (currentIndent.length <= promptsIndent.length && trimmed.includes(":")) {
164
+ return { insertIndex: lastPromptEntryEnd + 1, indent: itemIndent };
165
+ }
166
+ }
167
+ if (trimmed.startsWith("- ")) {
168
+ const dashIdx = line.indexOf("-");
169
+ itemIndent = dashIdx >= 0 ? line.slice(0, dashIdx) : "";
170
+ lastPromptEntryEnd = i;
171
+ } else if (lastPromptEntryEnd >= 0 && trimmed && !trimmed.startsWith("#")) {
172
+ lastPromptEntryEnd = i;
173
+ }
174
+ }
175
+ }
176
+ if (inPromptsSection && lastPromptEntryEnd >= 0) {
177
+ return { insertIndex: lastPromptEntryEnd + 1, indent: itemIndent };
178
+ }
179
+ return null;
180
+ }
181
+ async function addPromptToAgentConfig(configPath, prompt) {
182
+ const rawYaml = await fs.readFile(configPath, "utf-8");
183
+ const lines = rawYaml.split("\n");
184
+ const position = findPromptsArrayEndPosition(lines);
185
+ if (position) {
186
+ const promptYaml = stringify([prompt], { indent: 2, lineWidth: 0 }).trim();
187
+ const indentedPrompt = promptYaml.split("\n").map((line) => position.indent + line).join("\n");
188
+ lines.splice(position.insertIndex, 0, indentedPrompt);
189
+ } else {
190
+ const promptYaml = stringify({ prompts: [prompt] }, { indent: 2, lineWidth: 0 }).trim();
191
+ lines.push("", promptYaml);
192
+ }
193
+ await writeFileAtomic(configPath, lines.join("\n"));
194
+ }
195
+ function findPromptEntryRanges(lines) {
196
+ const entries = [];
197
+ let inPromptsSection = false;
198
+ let promptsIndent = "";
199
+ let currentEntryStart = -1;
200
+ let currentEntryEnd = -1;
201
+ let itemIndent = "";
202
+ for (let i = 0; i < lines.length; i++) {
203
+ const line = lines[i] ?? "";
204
+ const trimmed = line.trimStart();
205
+ if (!inPromptsSection && trimmed.startsWith("prompts:")) {
206
+ inPromptsSection = true;
207
+ const idx = line.indexOf("prompts:");
208
+ promptsIndent = idx >= 0 ? line.slice(0, idx) : "";
209
+ continue;
210
+ }
211
+ if (inPromptsSection) {
212
+ if (trimmed && !trimmed.startsWith("-")) {
213
+ const currentIndent = line.slice(0, line.length - trimmed.length);
214
+ if (currentIndent.length <= promptsIndent.length && trimmed.includes(":")) {
215
+ if (currentEntryStart >= 0) {
216
+ entries.push({
217
+ startLine: currentEntryStart,
218
+ endLine: currentEntryEnd >= 0 ? currentEntryEnd : currentEntryStart,
219
+ content: lines.slice(
220
+ currentEntryStart,
221
+ (currentEntryEnd >= 0 ? currentEntryEnd : currentEntryStart) + 1
222
+ ).join("\n")
223
+ });
224
+ }
225
+ inPromptsSection = false;
226
+ break;
227
+ }
228
+ if (trimmed.startsWith("#") && currentIndent.length <= promptsIndent.length) {
229
+ if (currentEntryStart >= 0) {
230
+ entries.push({
231
+ startLine: currentEntryStart,
232
+ endLine: currentEntryEnd >= 0 ? currentEntryEnd : currentEntryStart,
233
+ content: lines.slice(
234
+ currentEntryStart,
235
+ (currentEntryEnd >= 0 ? currentEntryEnd : currentEntryStart) + 1
236
+ ).join("\n")
237
+ });
238
+ }
239
+ inPromptsSection = false;
240
+ break;
241
+ }
242
+ }
243
+ if (trimmed.startsWith("- ")) {
244
+ if (currentEntryStart >= 0) {
245
+ entries.push({
246
+ startLine: currentEntryStart,
247
+ endLine: currentEntryEnd >= 0 ? currentEntryEnd : currentEntryStart,
248
+ content: lines.slice(
249
+ currentEntryStart,
250
+ (currentEntryEnd >= 0 ? currentEntryEnd : currentEntryStart) + 1
251
+ ).join("\n")
252
+ });
253
+ }
254
+ currentEntryStart = i;
255
+ currentEntryEnd = i;
256
+ const dashIdx = line.indexOf("-");
257
+ itemIndent = dashIdx >= 0 ? line.slice(0, dashIdx) : "";
258
+ } else if (currentEntryStart >= 0 && trimmed) {
259
+ const lineIndent = line.slice(0, line.length - trimmed.length);
260
+ if (lineIndent.length > itemIndent.length) {
261
+ currentEntryEnd = i;
262
+ }
263
+ }
264
+ }
265
+ }
266
+ if (inPromptsSection && currentEntryStart >= 0) {
267
+ entries.push({
268
+ startLine: currentEntryStart,
269
+ endLine: currentEntryEnd >= 0 ? currentEntryEnd : currentEntryStart,
270
+ content: lines.slice(
271
+ currentEntryStart,
272
+ (currentEntryEnd >= 0 ? currentEntryEnd : currentEntryStart) + 1
273
+ ).join("\n")
274
+ });
275
+ }
276
+ return entries;
277
+ }
278
+ async function removePromptFromAgentConfig(configPath, matcher) {
279
+ const rawYaml = await fs.readFile(configPath, "utf-8");
280
+ const lines = rawYaml.split("\n");
281
+ const entries = findPromptEntryRanges(lines);
282
+ if (entries.length === 0) {
283
+ return;
284
+ }
285
+ const entriesToRemove = [];
286
+ for (const entry of entries) {
287
+ if (matcher.type === "file") {
288
+ if (entry.content.includes("type: file") && entry.content.includes(matcher.filePattern)) {
289
+ entriesToRemove.push(entry);
290
+ }
291
+ } else if (matcher.type === "inline") {
292
+ if (entry.content.includes("type: inline") && entry.content.includes(`id: ${matcher.id}`)) {
293
+ entriesToRemove.push(entry);
294
+ }
295
+ }
296
+ }
297
+ if (entriesToRemove.length === 0) {
298
+ return;
299
+ }
300
+ const sortedEntries = [...entriesToRemove].sort((a, b) => b.startLine - a.startLine);
301
+ for (const entry of sortedEntries) {
302
+ lines.splice(entry.startLine, entry.endLine - entry.startLine + 1);
303
+ }
304
+ await writeFileAtomic(configPath, lines.join("\n"));
305
+ }
306
+ async function deletePromptByMetadata(configPath, prompt, options = { deleteFile: true }) {
307
+ const result = {
308
+ success: false,
309
+ deletedFile: false,
310
+ removedFromConfig: false
311
+ };
312
+ const filePath = prompt.metadata?.filePath;
313
+ try {
314
+ if (filePath) {
315
+ const fileName = path.basename(filePath);
316
+ const isSharedPrompt = filePath.includes("/commands/") || filePath.includes("/.dexto/commands/");
317
+ if (!isSharedPrompt) {
318
+ await removePromptFromAgentConfig(configPath, {
319
+ type: "file",
320
+ filePattern: `/prompts/${fileName}`
321
+ });
322
+ result.removedFromConfig = true;
323
+ }
324
+ if (options.deleteFile) {
325
+ try {
326
+ await fs.unlink(filePath);
327
+ result.deletedFile = true;
328
+ } catch {
329
+ }
330
+ }
331
+ result.success = true;
332
+ } else {
333
+ const promptId = prompt.metadata?.originalId || prompt.name;
334
+ await removePromptFromAgentConfig(configPath, {
335
+ type: "inline",
336
+ id: promptId
337
+ });
338
+ result.removedFromConfig = true;
339
+ result.success = true;
340
+ }
341
+ } catch (err) {
342
+ result.error = err instanceof Error ? err.message : String(err);
343
+ }
344
+ return result;
345
+ }
29
346
  export {
347
+ addPromptToAgentConfig,
348
+ deletePromptByMetadata,
30
349
  reloadAgentConfigFromFile,
31
- updateAgentConfigFile
350
+ removeMcpServerFromConfig,
351
+ removePromptFromAgentConfig,
352
+ updateAgentConfigFile,
353
+ updateMcpServerField
32
354
  };
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
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
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var discover_prompts_exports = {};
30
+ __export(discover_prompts_exports, {
31
+ discoverCommandPrompts: () => discoverCommandPrompts
32
+ });
33
+ module.exports = __toCommonJS(discover_prompts_exports);
34
+ var import_execution_context = require("../utils/execution-context.js");
35
+ var import_path = require("../utils/path.js");
36
+ var path = __toESM(require("path"), 1);
37
+ var import_fs = require("fs");
38
+ function discoverCommandPrompts() {
39
+ const prompts = [];
40
+ const seenFiles = /* @__PURE__ */ new Set();
41
+ const context = (0, import_execution_context.getExecutionContext)();
42
+ let localCommandsDir = null;
43
+ switch (context) {
44
+ case "dexto-source": {
45
+ const isDevMode = process.env.DEXTO_DEV_MODE === "true";
46
+ if (isDevMode) {
47
+ const sourceRoot = (0, import_execution_context.findDextoSourceRoot)();
48
+ if (sourceRoot) {
49
+ localCommandsDir = path.join(sourceRoot, "commands");
50
+ }
51
+ }
52
+ break;
53
+ }
54
+ case "dexto-project": {
55
+ const projectRoot = (0, import_execution_context.findDextoProjectRoot)();
56
+ if (projectRoot) {
57
+ localCommandsDir = path.join(projectRoot, "commands");
58
+ }
59
+ break;
60
+ }
61
+ case "global-cli":
62
+ break;
63
+ }
64
+ const globalCommandsDir = (0, import_path.getDextoGlobalPath)("commands");
65
+ if (localCommandsDir && (0, import_fs.existsSync)(localCommandsDir)) {
66
+ const files = scanCommandsDirectory(localCommandsDir);
67
+ for (const file of files) {
68
+ const basename = path.basename(file).toLowerCase();
69
+ if (!seenFiles.has(basename)) {
70
+ seenFiles.add(basename);
71
+ prompts.push({ type: "file", file });
72
+ }
73
+ }
74
+ }
75
+ if ((0, import_fs.existsSync)(globalCommandsDir)) {
76
+ const files = scanCommandsDirectory(globalCommandsDir);
77
+ for (const file of files) {
78
+ const basename = path.basename(file).toLowerCase();
79
+ if (!seenFiles.has(basename)) {
80
+ seenFiles.add(basename);
81
+ prompts.push({ type: "file", file });
82
+ }
83
+ }
84
+ }
85
+ return prompts;
86
+ }
87
+ function scanCommandsDirectory(dir) {
88
+ const files = [];
89
+ try {
90
+ const entries = (0, import_fs.readdirSync)(dir, { withFileTypes: true });
91
+ for (const entry of entries) {
92
+ if (entry.isFile() && entry.name.endsWith(".md") && entry.name !== "README.md") {
93
+ files.push(path.join(dir, entry.name));
94
+ }
95
+ }
96
+ } catch {
97
+ }
98
+ return files;
99
+ }
100
+ // Annotate the CommonJS export names for ESM import in node:
101
+ 0 && (module.exports = {
102
+ discoverCommandPrompts
103
+ });
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Command Prompt Discovery
3
+ *
4
+ * Discovers command prompts from commands/ directories based on execution context.
5
+ * Extracted to separate file to enable proper unit testing with mocks.
6
+ */
7
+ /**
8
+ * File prompt entry for discovered commands
9
+ */
10
+ export interface FilePromptEntry {
11
+ type: 'file';
12
+ file: string;
13
+ showInStarters?: boolean;
14
+ }
15
+ /**
16
+ * Discovers command prompts from commands/ directories.
17
+ *
18
+ * Discovery locations based on execution context:
19
+ * - dexto-source (dev mode): <sourceRoot>/commands/
20
+ * - dexto-project: <projectRoot>/commands/
21
+ * - global-cli: skip local (use global only)
22
+ *
23
+ * Global commands (~/.dexto/commands/) are always included.
24
+ *
25
+ * @returns Array of file prompt entries for discovered .md files
26
+ */
27
+ export declare function discoverCommandPrompts(): FilePromptEntry[];
28
+ //# sourceMappingURL=discover-prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover-prompts.d.ts","sourceRoot":"","sources":["../../src/config/discover-prompts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,IAAI,eAAe,EAAE,CA8D1D"}
@@ -0,0 +1,73 @@
1
+ import {
2
+ getExecutionContext,
3
+ findDextoSourceRoot,
4
+ findDextoProjectRoot
5
+ } from "../utils/execution-context.js";
6
+ import { getDextoGlobalPath } from "../utils/path.js";
7
+ import * as path from "path";
8
+ import { existsSync, readdirSync } from "fs";
9
+ function discoverCommandPrompts() {
10
+ const prompts = [];
11
+ const seenFiles = /* @__PURE__ */ new Set();
12
+ const context = getExecutionContext();
13
+ let localCommandsDir = null;
14
+ switch (context) {
15
+ case "dexto-source": {
16
+ const isDevMode = process.env.DEXTO_DEV_MODE === "true";
17
+ if (isDevMode) {
18
+ const sourceRoot = findDextoSourceRoot();
19
+ if (sourceRoot) {
20
+ localCommandsDir = path.join(sourceRoot, "commands");
21
+ }
22
+ }
23
+ break;
24
+ }
25
+ case "dexto-project": {
26
+ const projectRoot = findDextoProjectRoot();
27
+ if (projectRoot) {
28
+ localCommandsDir = path.join(projectRoot, "commands");
29
+ }
30
+ break;
31
+ }
32
+ case "global-cli":
33
+ break;
34
+ }
35
+ const globalCommandsDir = getDextoGlobalPath("commands");
36
+ if (localCommandsDir && existsSync(localCommandsDir)) {
37
+ const files = scanCommandsDirectory(localCommandsDir);
38
+ for (const file of files) {
39
+ const basename = path.basename(file).toLowerCase();
40
+ if (!seenFiles.has(basename)) {
41
+ seenFiles.add(basename);
42
+ prompts.push({ type: "file", file });
43
+ }
44
+ }
45
+ }
46
+ if (existsSync(globalCommandsDir)) {
47
+ const files = scanCommandsDirectory(globalCommandsDir);
48
+ for (const file of files) {
49
+ const basename = path.basename(file).toLowerCase();
50
+ if (!seenFiles.has(basename)) {
51
+ seenFiles.add(basename);
52
+ prompts.push({ type: "file", file });
53
+ }
54
+ }
55
+ }
56
+ return prompts;
57
+ }
58
+ function scanCommandsDirectory(dir) {
59
+ const files = [];
60
+ try {
61
+ const entries = readdirSync(dir, { withFileTypes: true });
62
+ for (const entry of entries) {
63
+ if (entry.isFile() && entry.name.endsWith(".md") && entry.name !== "README.md") {
64
+ files.push(path.join(dir, entry.name));
65
+ }
66
+ }
67
+ } catch {
68
+ }
69
+ return files;
70
+ }
71
+ export {
72
+ discoverCommandPrompts
73
+ };
@@ -72,8 +72,8 @@ class ConfigError {
72
72
  import_error_codes.ConfigErrorCode.NO_PROJECT_DEFAULT,
73
73
  import_core.ErrorScope.CONFIG,
74
74
  import_core.ErrorType.USER,
75
- `No project default-agent.yml found and no global preferences configured.
76
- Either create default-agent.yml in your project root (${projectPath}) or run \`dexto setup\` to configure preferences.`,
75
+ `No project coding-agent.yml found and no global preferences configured.
76
+ Either create coding-agent.yml in your project root (${projectPath}) or run \`dexto setup\` to configure preferences.`,
77
77
  { projectPath },
78
78
  "Run `dexto setup` or create a project-specific agent config"
79
79
  );
@@ -49,8 +49,8 @@ class ConfigError {
49
49
  ConfigErrorCode.NO_PROJECT_DEFAULT,
50
50
  ErrorScope.CONFIG,
51
51
  ErrorType.USER,
52
- `No project default-agent.yml found and no global preferences configured.
53
- Either create default-agent.yml in your project root (${projectPath}) or run \`dexto setup\` to configure preferences.`,
52
+ `No project coding-agent.yml found and no global preferences configured.
53
+ Either create coding-agent.yml in your project root (${projectPath}) or run \`dexto setup\` to configure preferences.`,
54
54
  { projectPath },
55
55
  "Run `dexto setup` or create a project-specific agent config"
56
56
  );
@@ -20,11 +20,17 @@ var config_exports = {};
20
20
  __export(config_exports, {
21
21
  ConfigError: () => import_errors.ConfigError,
22
22
  ConfigErrorCode: () => import_error_codes.ConfigErrorCode,
23
+ addPromptToAgentConfig: () => import_config_manager.addPromptToAgentConfig,
24
+ deletePromptByMetadata: () => import_config_manager.deletePromptByMetadata,
23
25
  deriveAgentId: () => import_config_enrichment.deriveAgentId,
26
+ discoverCommandPrompts: () => import_config_enrichment.discoverCommandPrompts,
24
27
  enrichAgentConfig: () => import_config_enrichment.enrichAgentConfig,
25
28
  loadAgentConfig: () => import_loader.loadAgentConfig,
26
29
  reloadAgentConfigFromFile: () => import_config_manager.reloadAgentConfigFromFile,
27
- updateAgentConfigFile: () => import_config_manager.updateAgentConfigFile
30
+ removeMcpServerFromConfig: () => import_config_manager.removeMcpServerFromConfig,
31
+ removePromptFromAgentConfig: () => import_config_manager.removePromptFromAgentConfig,
32
+ updateAgentConfigFile: () => import_config_manager.updateAgentConfigFile,
33
+ updateMcpServerField: () => import_config_manager.updateMcpServerField
28
34
  });
29
35
  module.exports = __toCommonJS(config_exports);
30
36
  var import_config_manager = require("./config-manager.js");
@@ -36,9 +42,15 @@ var import_error_codes = require("./error-codes.js");
36
42
  0 && (module.exports = {
37
43
  ConfigError,
38
44
  ConfigErrorCode,
45
+ addPromptToAgentConfig,
46
+ deletePromptByMetadata,
39
47
  deriveAgentId,
48
+ discoverCommandPrompts,
40
49
  enrichAgentConfig,
41
50
  loadAgentConfig,
42
51
  reloadAgentConfigFromFile,
43
- updateAgentConfigFile
52
+ removeMcpServerFromConfig,
53
+ removePromptFromAgentConfig,
54
+ updateAgentConfigFile,
55
+ updateMcpServerField
44
56
  });
@@ -1,6 +1,6 @@
1
- export { updateAgentConfigFile, reloadAgentConfigFromFile } from './config-manager.js';
1
+ export { updateAgentConfigFile, reloadAgentConfigFromFile, addPromptToAgentConfig, removePromptFromAgentConfig, deletePromptByMetadata, updateMcpServerField, removeMcpServerFromConfig, type FilePromptInput, type InlinePromptInput, type PromptInput, type PromptMetadataForDeletion, type PromptDeletionResult, } from './config-manager.js';
2
2
  export { loadAgentConfig } from './loader.js';
3
- export { enrichAgentConfig, deriveAgentId } from './config-enrichment.js';
3
+ export { enrichAgentConfig, deriveAgentId, discoverCommandPrompts, type EnrichAgentConfigOptions, } from './config-enrichment.js';
4
4
  export { ConfigError } from './errors.js';
5
5
  export { ConfigErrorCode } from './error-codes.js';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,qBAAqB,EACrB,yBAAyB,EACzB,sBAAsB,EACtB,2BAA2B,EAC3B,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,EACzB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,GAC5B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACH,iBAAiB,EACjB,aAAa,EACb,sBAAsB,EACtB,KAAK,wBAAwB,GAChC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1,14 +1,32 @@
1
- import { updateAgentConfigFile, reloadAgentConfigFromFile } from "./config-manager.js";
1
+ import {
2
+ updateAgentConfigFile,
3
+ reloadAgentConfigFromFile,
4
+ addPromptToAgentConfig,
5
+ removePromptFromAgentConfig,
6
+ deletePromptByMetadata,
7
+ updateMcpServerField,
8
+ removeMcpServerFromConfig
9
+ } from "./config-manager.js";
2
10
  import { loadAgentConfig } from "./loader.js";
3
- import { enrichAgentConfig, deriveAgentId } from "./config-enrichment.js";
11
+ import {
12
+ enrichAgentConfig,
13
+ deriveAgentId,
14
+ discoverCommandPrompts
15
+ } from "./config-enrichment.js";
4
16
  import { ConfigError } from "./errors.js";
5
17
  import { ConfigErrorCode } from "./error-codes.js";
6
18
  export {
7
19
  ConfigError,
8
20
  ConfigErrorCode,
21
+ addPromptToAgentConfig,
22
+ deletePromptByMetadata,
9
23
  deriveAgentId,
24
+ discoverCommandPrompts,
10
25
  enrichAgentConfig,
11
26
  loadAgentConfig,
12
27
  reloadAgentConfigFromFile,
13
- updateAgentConfigFile
28
+ removeMcpServerFromConfig,
29
+ removePromptFromAgentConfig,
30
+ updateAgentConfigFile,
31
+ updateMcpServerField
14
32
  };