@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
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var state_manager_exports = {};
20
+ __export(state_manager_exports, {
21
+ addInstalledModel: () => addInstalledModel,
22
+ addToDownloadQueue: () => addToDownloadQueue,
23
+ getActiveModel: () => getActiveModel,
24
+ getActiveModelId: () => getActiveModelId,
25
+ getAllInstalledModels: () => getAllInstalledModels,
26
+ getDownloadQueue: () => getDownloadQueue,
27
+ getInstalledModel: () => getInstalledModel,
28
+ getInstalledModelCount: () => getInstalledModelCount,
29
+ getTotalInstalledSize: () => getTotalInstalledSize,
30
+ isModelInstalled: () => isModelInstalled,
31
+ loadModelState: () => loadModelState,
32
+ registerManualModel: () => registerManualModel,
33
+ removeFromDownloadQueue: () => removeFromDownloadQueue,
34
+ removeInstalledModel: () => removeInstalledModel,
35
+ saveModelState: () => saveModelState,
36
+ setActiveModel: () => setActiveModel,
37
+ syncStateWithFilesystem: () => syncStateWithFilesystem,
38
+ updateModelLastUsed: () => updateModelLastUsed
39
+ });
40
+ module.exports = __toCommonJS(state_manager_exports);
41
+ var import_fs = require("fs");
42
+ var import_path_resolver = require("./path-resolver.js");
43
+ const CURRENT_VERSION = "1.0";
44
+ function createDefaultState() {
45
+ return {
46
+ version: CURRENT_VERSION,
47
+ installed: {},
48
+ downloadQueue: []
49
+ };
50
+ }
51
+ async function loadModelState() {
52
+ const statePath = (0, import_path_resolver.getModelStatePath)();
53
+ try {
54
+ const content = await import_fs.promises.readFile(statePath, "utf-8");
55
+ const state = JSON.parse(content);
56
+ if (state.version !== CURRENT_VERSION) {
57
+ return migrateState(state);
58
+ }
59
+ return state;
60
+ } catch (error) {
61
+ if (error.code === "ENOENT") {
62
+ return createDefaultState();
63
+ }
64
+ console.warn("Invalid model state file, resetting to default");
65
+ return createDefaultState();
66
+ }
67
+ }
68
+ async function saveModelState(state) {
69
+ await (0, import_path_resolver.ensureModelsDirectory)();
70
+ const statePath = (0, import_path_resolver.getModelStatePath)();
71
+ await import_fs.promises.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
72
+ }
73
+ function migrateState(state) {
74
+ return {
75
+ ...state,
76
+ version: CURRENT_VERSION
77
+ };
78
+ }
79
+ async function addInstalledModel(model) {
80
+ const state = await loadModelState();
81
+ state.installed[model.id] = model;
82
+ await saveModelState(state);
83
+ }
84
+ async function removeInstalledModel(modelId) {
85
+ const state = await loadModelState();
86
+ if (!state.installed[modelId]) {
87
+ return false;
88
+ }
89
+ delete state.installed[modelId];
90
+ if (state.activeModelId === modelId) {
91
+ delete state.activeModelId;
92
+ }
93
+ state.downloadQueue = state.downloadQueue.filter((id) => id !== modelId);
94
+ await saveModelState(state);
95
+ return true;
96
+ }
97
+ async function getInstalledModel(modelId) {
98
+ const state = await loadModelState();
99
+ return state.installed[modelId] ?? null;
100
+ }
101
+ async function getAllInstalledModels() {
102
+ const state = await loadModelState();
103
+ return Object.values(state.installed);
104
+ }
105
+ async function isModelInstalled(modelId) {
106
+ const model = await getInstalledModel(modelId);
107
+ if (!model) {
108
+ return false;
109
+ }
110
+ return (0, import_path_resolver.modelFileExists)(modelId, model.filename);
111
+ }
112
+ async function updateModelLastUsed(modelId) {
113
+ const state = await loadModelState();
114
+ const model = state.installed[modelId];
115
+ if (model) {
116
+ model.lastUsedAt = (/* @__PURE__ */ new Date()).toISOString();
117
+ await saveModelState(state);
118
+ }
119
+ }
120
+ async function setActiveModel(modelId) {
121
+ const state = await loadModelState();
122
+ if (modelId === void 0) {
123
+ delete state.activeModelId;
124
+ } else {
125
+ state.activeModelId = modelId;
126
+ }
127
+ await saveModelState(state);
128
+ }
129
+ async function getActiveModelId() {
130
+ const state = await loadModelState();
131
+ return state.activeModelId;
132
+ }
133
+ async function getActiveModel() {
134
+ const activeId = await getActiveModelId();
135
+ if (!activeId) {
136
+ return null;
137
+ }
138
+ return getInstalledModel(activeId);
139
+ }
140
+ async function addToDownloadQueue(modelId) {
141
+ const state = await loadModelState();
142
+ if (!state.downloadQueue.includes(modelId)) {
143
+ state.downloadQueue.push(modelId);
144
+ await saveModelState(state);
145
+ }
146
+ }
147
+ async function removeFromDownloadQueue(modelId) {
148
+ const state = await loadModelState();
149
+ state.downloadQueue = state.downloadQueue.filter((id) => id !== modelId);
150
+ await saveModelState(state);
151
+ }
152
+ async function getDownloadQueue() {
153
+ const state = await loadModelState();
154
+ return [...state.downloadQueue];
155
+ }
156
+ async function syncStateWithFilesystem() {
157
+ const state = await loadModelState();
158
+ const removed = [];
159
+ const kept = [];
160
+ for (const [modelId, model] of Object.entries(state.installed)) {
161
+ const exists = await (0, import_path_resolver.modelFileExists)(modelId, model.filename);
162
+ if (exists) {
163
+ kept.push(modelId);
164
+ } else {
165
+ removed.push(modelId);
166
+ delete state.installed[modelId];
167
+ }
168
+ }
169
+ if (state.activeModelId && removed.includes(state.activeModelId)) {
170
+ delete state.activeModelId;
171
+ }
172
+ if (removed.length > 0) {
173
+ await saveModelState(state);
174
+ }
175
+ return { removed, kept };
176
+ }
177
+ async function getTotalInstalledSize() {
178
+ const state = await loadModelState();
179
+ return Object.values(state.installed).reduce((total, model) => total + model.sizeBytes, 0);
180
+ }
181
+ async function getInstalledModelCount() {
182
+ const state = await loadModelState();
183
+ return Object.keys(state.installed).length;
184
+ }
185
+ async function registerManualModel(modelId, filename, sizeBytes, sha256) {
186
+ const filePath = (0, import_path_resolver.getModelFilePath)(modelId, filename);
187
+ const model = {
188
+ id: modelId,
189
+ filePath,
190
+ sizeBytes,
191
+ downloadedAt: (/* @__PURE__ */ new Date()).toISOString(),
192
+ source: "manual",
193
+ filename
194
+ };
195
+ if (sha256 !== void 0) {
196
+ model.sha256 = sha256;
197
+ }
198
+ await addInstalledModel(model);
199
+ }
200
+ // Annotate the CommonJS export names for ESM import in node:
201
+ 0 && (module.exports = {
202
+ addInstalledModel,
203
+ addToDownloadQueue,
204
+ getActiveModel,
205
+ getActiveModelId,
206
+ getAllInstalledModels,
207
+ getDownloadQueue,
208
+ getInstalledModel,
209
+ getInstalledModelCount,
210
+ getTotalInstalledSize,
211
+ isModelInstalled,
212
+ loadModelState,
213
+ registerManualModel,
214
+ removeFromDownloadQueue,
215
+ removeInstalledModel,
216
+ saveModelState,
217
+ setActiveModel,
218
+ syncStateWithFilesystem,
219
+ updateModelLastUsed
220
+ });
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Model state manager for tracking downloaded local models.
3
+ *
4
+ * Persists model metadata to ~/.dexto/models/state.json including:
5
+ * - Which models are installed
6
+ * - File paths and sizes
7
+ * - Download timestamps
8
+ * - Usage tracking
9
+ *
10
+ * Note: ModelSource and InstalledModel types here intentionally differ from
11
+ * packages/core/src/llm/providers/local/types.ts. This package extends the core
12
+ * types with agent-management specific needs:
13
+ * - ModelSource adds 'manual' for user-placed model files
14
+ * - InstalledModel adds 'filename' for file system operations (isModelInstalled, syncStateWithFilesystem)
15
+ */
16
+ /**
17
+ * Source of the model download.
18
+ */
19
+ export type ModelSource = 'huggingface' | 'manual';
20
+ /**
21
+ * Installed model metadata.
22
+ */
23
+ export interface InstalledModel {
24
+ /** Model ID from registry */
25
+ id: string;
26
+ /** Absolute path to the .gguf file */
27
+ filePath: string;
28
+ /** File size in bytes */
29
+ sizeBytes: number;
30
+ /** When the model was downloaded (ISO timestamp) */
31
+ downloadedAt: string;
32
+ /** When the model was last used (ISO timestamp) */
33
+ lastUsedAt?: string;
34
+ /** SHA-256 hash of the file for integrity verification */
35
+ sha256?: string;
36
+ /** Source of the download */
37
+ source: ModelSource;
38
+ /** GGUF filename */
39
+ filename: string;
40
+ }
41
+ /**
42
+ * Persisted model state.
43
+ */
44
+ export interface ModelState {
45
+ /** Schema version for migrations */
46
+ version: string;
47
+ /** Map of model ID to installed model info */
48
+ installed: Record<string, InstalledModel>;
49
+ /** Currently active/selected model ID */
50
+ activeModelId?: string;
51
+ /** Queue of model IDs pending download */
52
+ downloadQueue: string[];
53
+ }
54
+ /**
55
+ * Load model state from disk.
56
+ * Returns default state if file doesn't exist.
57
+ */
58
+ export declare function loadModelState(): Promise<ModelState>;
59
+ /**
60
+ * Save model state to disk.
61
+ */
62
+ export declare function saveModelState(state: ModelState): Promise<void>;
63
+ /**
64
+ * Add an installed model to state.
65
+ *
66
+ * Note: These operations are not atomic. Ensure single-threaded access
67
+ * or implement file locking for concurrent usage scenarios.
68
+ */
69
+ export declare function addInstalledModel(model: InstalledModel): Promise<void>;
70
+ /**
71
+ * Remove an installed model from state.
72
+ *
73
+ * Note: These operations are not atomic. Ensure single-threaded access
74
+ * or implement file locking for concurrent usage scenarios.
75
+ */
76
+ export declare function removeInstalledModel(modelId: string): Promise<boolean>;
77
+ /**
78
+ * Get installed model info.
79
+ */
80
+ export declare function getInstalledModel(modelId: string): Promise<InstalledModel | null>;
81
+ /**
82
+ * Get all installed models.
83
+ */
84
+ export declare function getAllInstalledModels(): Promise<InstalledModel[]>;
85
+ /**
86
+ * Check if a model is installed.
87
+ */
88
+ export declare function isModelInstalled(modelId: string): Promise<boolean>;
89
+ /**
90
+ * Update last used timestamp for a model.
91
+ */
92
+ export declare function updateModelLastUsed(modelId: string): Promise<void>;
93
+ /**
94
+ * Set the active model.
95
+ */
96
+ export declare function setActiveModel(modelId: string | undefined): Promise<void>;
97
+ /**
98
+ * Get the active model ID.
99
+ */
100
+ export declare function getActiveModelId(): Promise<string | undefined>;
101
+ /**
102
+ * Get the active model info.
103
+ */
104
+ export declare function getActiveModel(): Promise<InstalledModel | null>;
105
+ /**
106
+ * Add a model to the download queue.
107
+ */
108
+ export declare function addToDownloadQueue(modelId: string): Promise<void>;
109
+ /**
110
+ * Remove a model from the download queue.
111
+ */
112
+ export declare function removeFromDownloadQueue(modelId: string): Promise<void>;
113
+ /**
114
+ * Get the download queue.
115
+ */
116
+ export declare function getDownloadQueue(): Promise<string[]>;
117
+ /**
118
+ * Sync state with actual filesystem.
119
+ * Removes entries for models that no longer exist on disk.
120
+ */
121
+ export declare function syncStateWithFilesystem(): Promise<{
122
+ removed: string[];
123
+ kept: string[];
124
+ }>;
125
+ /**
126
+ * Get total size of all installed models.
127
+ */
128
+ export declare function getTotalInstalledSize(): Promise<number>;
129
+ /**
130
+ * Get count of installed models.
131
+ */
132
+ export declare function getInstalledModelCount(): Promise<number>;
133
+ /**
134
+ * Register a manually added model file.
135
+ * Used when user places a GGUF file directly in the models directory.
136
+ */
137
+ export declare function registerManualModel(modelId: string, filename: string, sizeBytes: number, sha256?: string): Promise<void>;
138
+ //# sourceMappingURL=state-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-manager.d.ts","sourceRoot":"","sources":["../../src/models/state-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,184 @@
1
+ import { promises as fs } from "fs";
2
+ import {
3
+ getModelStatePath,
4
+ ensureModelsDirectory,
5
+ modelFileExists,
6
+ getModelFilePath
7
+ } from "./path-resolver.js";
8
+ const CURRENT_VERSION = "1.0";
9
+ function createDefaultState() {
10
+ return {
11
+ version: CURRENT_VERSION,
12
+ installed: {},
13
+ downloadQueue: []
14
+ };
15
+ }
16
+ async function loadModelState() {
17
+ const statePath = getModelStatePath();
18
+ try {
19
+ const content = await fs.readFile(statePath, "utf-8");
20
+ const state = JSON.parse(content);
21
+ if (state.version !== CURRENT_VERSION) {
22
+ return migrateState(state);
23
+ }
24
+ return state;
25
+ } catch (error) {
26
+ if (error.code === "ENOENT") {
27
+ return createDefaultState();
28
+ }
29
+ console.warn("Invalid model state file, resetting to default");
30
+ return createDefaultState();
31
+ }
32
+ }
33
+ async function saveModelState(state) {
34
+ await ensureModelsDirectory();
35
+ const statePath = getModelStatePath();
36
+ await fs.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
37
+ }
38
+ function migrateState(state) {
39
+ return {
40
+ ...state,
41
+ version: CURRENT_VERSION
42
+ };
43
+ }
44
+ async function addInstalledModel(model) {
45
+ const state = await loadModelState();
46
+ state.installed[model.id] = model;
47
+ await saveModelState(state);
48
+ }
49
+ async function removeInstalledModel(modelId) {
50
+ const state = await loadModelState();
51
+ if (!state.installed[modelId]) {
52
+ return false;
53
+ }
54
+ delete state.installed[modelId];
55
+ if (state.activeModelId === modelId) {
56
+ delete state.activeModelId;
57
+ }
58
+ state.downloadQueue = state.downloadQueue.filter((id) => id !== modelId);
59
+ await saveModelState(state);
60
+ return true;
61
+ }
62
+ async function getInstalledModel(modelId) {
63
+ const state = await loadModelState();
64
+ return state.installed[modelId] ?? null;
65
+ }
66
+ async function getAllInstalledModels() {
67
+ const state = await loadModelState();
68
+ return Object.values(state.installed);
69
+ }
70
+ async function isModelInstalled(modelId) {
71
+ const model = await getInstalledModel(modelId);
72
+ if (!model) {
73
+ return false;
74
+ }
75
+ return modelFileExists(modelId, model.filename);
76
+ }
77
+ async function updateModelLastUsed(modelId) {
78
+ const state = await loadModelState();
79
+ const model = state.installed[modelId];
80
+ if (model) {
81
+ model.lastUsedAt = (/* @__PURE__ */ new Date()).toISOString();
82
+ await saveModelState(state);
83
+ }
84
+ }
85
+ async function setActiveModel(modelId) {
86
+ const state = await loadModelState();
87
+ if (modelId === void 0) {
88
+ delete state.activeModelId;
89
+ } else {
90
+ state.activeModelId = modelId;
91
+ }
92
+ await saveModelState(state);
93
+ }
94
+ async function getActiveModelId() {
95
+ const state = await loadModelState();
96
+ return state.activeModelId;
97
+ }
98
+ async function getActiveModel() {
99
+ const activeId = await getActiveModelId();
100
+ if (!activeId) {
101
+ return null;
102
+ }
103
+ return getInstalledModel(activeId);
104
+ }
105
+ async function addToDownloadQueue(modelId) {
106
+ const state = await loadModelState();
107
+ if (!state.downloadQueue.includes(modelId)) {
108
+ state.downloadQueue.push(modelId);
109
+ await saveModelState(state);
110
+ }
111
+ }
112
+ async function removeFromDownloadQueue(modelId) {
113
+ const state = await loadModelState();
114
+ state.downloadQueue = state.downloadQueue.filter((id) => id !== modelId);
115
+ await saveModelState(state);
116
+ }
117
+ async function getDownloadQueue() {
118
+ const state = await loadModelState();
119
+ return [...state.downloadQueue];
120
+ }
121
+ async function syncStateWithFilesystem() {
122
+ const state = await loadModelState();
123
+ const removed = [];
124
+ const kept = [];
125
+ for (const [modelId, model] of Object.entries(state.installed)) {
126
+ const exists = await modelFileExists(modelId, model.filename);
127
+ if (exists) {
128
+ kept.push(modelId);
129
+ } else {
130
+ removed.push(modelId);
131
+ delete state.installed[modelId];
132
+ }
133
+ }
134
+ if (state.activeModelId && removed.includes(state.activeModelId)) {
135
+ delete state.activeModelId;
136
+ }
137
+ if (removed.length > 0) {
138
+ await saveModelState(state);
139
+ }
140
+ return { removed, kept };
141
+ }
142
+ async function getTotalInstalledSize() {
143
+ const state = await loadModelState();
144
+ return Object.values(state.installed).reduce((total, model) => total + model.sizeBytes, 0);
145
+ }
146
+ async function getInstalledModelCount() {
147
+ const state = await loadModelState();
148
+ return Object.keys(state.installed).length;
149
+ }
150
+ async function registerManualModel(modelId, filename, sizeBytes, sha256) {
151
+ const filePath = getModelFilePath(modelId, filename);
152
+ const model = {
153
+ id: modelId,
154
+ filePath,
155
+ sizeBytes,
156
+ downloadedAt: (/* @__PURE__ */ new Date()).toISOString(),
157
+ source: "manual",
158
+ filename
159
+ };
160
+ if (sha256 !== void 0) {
161
+ model.sha256 = sha256;
162
+ }
163
+ await addInstalledModel(model);
164
+ }
165
+ export {
166
+ addInstalledModel,
167
+ addToDownloadQueue,
168
+ getActiveModel,
169
+ getActiveModelId,
170
+ getAllInstalledModels,
171
+ getDownloadQueue,
172
+ getInstalledModel,
173
+ getInstalledModelCount,
174
+ getTotalInstalledSize,
175
+ isModelInstalled,
176
+ loadModelState,
177
+ registerManualModel,
178
+ removeFromDownloadQueue,
179
+ removeInstalledModel,
180
+ saveModelState,
181
+ setActiveModel,
182
+ syncStateWithFilesystem,
183
+ updateModelLastUsed
184
+ };
@@ -27,6 +27,8 @@ var PreferenceErrorCode = /* @__PURE__ */ ((PreferenceErrorCode2) => {
27
27
  PreferenceErrorCode2["FILE_WRITE_ERROR"] = "preference_file_write_error";
28
28
  PreferenceErrorCode2["VALIDATION_ERROR"] = "preference_validation_error";
29
29
  PreferenceErrorCode2["MODEL_INCOMPATIBLE"] = "preference_model_incompatible";
30
+ PreferenceErrorCode2["INVALID_PREFERENCE_VALUE"] = "preference_invalid_value";
31
+ PreferenceErrorCode2["MISSING_PREFERENCE"] = "preference_missing_required";
30
32
  return PreferenceErrorCode2;
31
33
  })(PreferenceErrorCode || {});
32
34
  // Annotate the CommonJS export names for ESM import in node:
@@ -3,6 +3,8 @@ export declare enum PreferenceErrorCode {
3
3
  FILE_READ_ERROR = "preference_file_read_error",
4
4
  FILE_WRITE_ERROR = "preference_file_write_error",
5
5
  VALIDATION_ERROR = "preference_validation_error",
6
- MODEL_INCOMPATIBLE = "preference_model_incompatible"
6
+ MODEL_INCOMPATIBLE = "preference_model_incompatible",
7
+ INVALID_PREFERENCE_VALUE = "preference_invalid_value",
8
+ MISSING_PREFERENCE = "preference_missing_required"
7
9
  }
8
10
  //# sourceMappingURL=error-codes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../../src/preferences/error-codes.ts"],"names":[],"mappings":"AAEA,oBAAY,mBAAmB;IAC3B,cAAc,8BAA8B;IAC5C,eAAe,+BAA+B;IAC9C,gBAAgB,gCAAgC;IAChD,gBAAgB,gCAAgC;IAChD,kBAAkB,kCAAkC;CACvD"}
1
+ {"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../../src/preferences/error-codes.ts"],"names":[],"mappings":"AAEA,oBAAY,mBAAmB;IAC3B,cAAc,8BAA8B;IAC5C,eAAe,+BAA+B;IAC9C,gBAAgB,gCAAgC;IAChD,gBAAgB,gCAAgC;IAChD,kBAAkB,kCAAkC;IACpD,wBAAwB,6BAA6B;IACrD,kBAAkB,gCAAgC;CACrD"}
@@ -4,6 +4,8 @@ var PreferenceErrorCode = /* @__PURE__ */ ((PreferenceErrorCode2) => {
4
4
  PreferenceErrorCode2["FILE_WRITE_ERROR"] = "preference_file_write_error";
5
5
  PreferenceErrorCode2["VALIDATION_ERROR"] = "preference_validation_error";
6
6
  PreferenceErrorCode2["MODEL_INCOMPATIBLE"] = "preference_model_incompatible";
7
+ PreferenceErrorCode2["INVALID_PREFERENCE_VALUE"] = "preference_invalid_value";
8
+ PreferenceErrorCode2["MISSING_PREFERENCE"] = "preference_missing_required";
7
9
  return PreferenceErrorCode2;
8
10
  })(PreferenceErrorCode || {});
9
11
  export {
@@ -1,6 +1,6 @@
1
1
  export type { GlobalPreferences, PreferenceLLM, PreferenceDefaults, PreferenceSetup, } from './schemas.js';
2
2
  export { GlobalPreferencesSchema, PreferenceLLMSchema, PreferenceDefaultsSchema, PreferenceSetupSchema, } from './schemas.js';
3
3
  export { PREFERENCES_FILE } from './constants.js';
4
- export { loadGlobalPreferences, saveGlobalPreferences, globalPreferencesExist, getGlobalPreferencesPath, createInitialPreferences, updateGlobalPreferences, } from './loader.js';
4
+ export { loadGlobalPreferences, saveGlobalPreferences, globalPreferencesExist, getGlobalPreferencesPath, createInitialPreferences, updateGlobalPreferences, type CreatePreferencesOptions, } from './loader.js';
5
5
  export { PreferenceError, PreferenceErrorCode } from './errors.js';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/preferences/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACR,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,eAAe,GAClB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACH,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,GACxB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,EACH,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,GAC1B,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/preferences/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACR,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,eAAe,GAClB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACH,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,qBAAqB,GACxB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,EACH,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,KAAK,wBAAwB,GAChC,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
@@ -66,7 +66,7 @@ async function saveGlobalPreferences(preferences) {
66
66
  throw import_errors.PreferenceError.validationFailed(validation.error);
67
67
  }
68
68
  try {
69
- import_core.logger.info(`Saving global preferences to: ${preferencesPath}`);
69
+ import_core.logger.debug(`Saving global preferences to: ${preferencesPath}`);
70
70
  const dextoDir = (0, import_path.getDextoGlobalPath)("");
71
71
  await import_fs2.promises.mkdir(dextoDir, { recursive: true });
72
72
  const yamlContent = (0, import_yaml.stringify)(preferences, {
@@ -75,7 +75,7 @@ async function saveGlobalPreferences(preferences) {
75
75
  minContentWidth: 20
76
76
  });
77
77
  await import_fs2.promises.writeFile(preferencesPath, yamlContent, "utf-8");
78
- import_core.logger.info(
78
+ import_core.logger.debug(
79
79
  `\u2713 Saved global preferences ${JSON.stringify(preferences)} to: ${preferencesPath}`
80
80
  );
81
81
  } catch (error) {
@@ -92,20 +92,46 @@ function globalPreferencesExist() {
92
92
  function getGlobalPreferencesPath() {
93
93
  return (0, import_path.getDextoGlobalPath)(import_constants.PREFERENCES_FILE);
94
94
  }
95
- function createInitialPreferences(provider, model, apiKeyVar, defaultAgent = "default-agent") {
95
+ function createInitialPreferences(providerOrOptions, model, apiKeyVar, defaultAgent = "coding-agent") {
96
+ if (typeof providerOrOptions === "object") {
97
+ const opts = providerOrOptions;
98
+ const llmConfig = {
99
+ provider: opts.provider,
100
+ model: opts.model
101
+ };
102
+ if (opts.apiKeyVar) {
103
+ llmConfig.apiKey = `$${opts.apiKeyVar}`;
104
+ }
105
+ if (opts.baseURL) {
106
+ llmConfig.baseURL = opts.baseURL;
107
+ }
108
+ return {
109
+ llm: llmConfig,
110
+ defaults: {
111
+ defaultAgent: opts.defaultAgent || "coding-agent",
112
+ defaultMode: opts.defaultMode || "web"
113
+ },
114
+ setup: {
115
+ completed: opts.setupCompleted ?? true,
116
+ apiKeyPending: opts.apiKeyPending ?? false,
117
+ baseURLPending: opts.baseURLPending ?? false
118
+ }
119
+ };
120
+ }
96
121
  return {
97
122
  llm: {
98
- provider,
123
+ provider: providerOrOptions,
99
124
  model,
100
125
  apiKey: `$${apiKeyVar}`
101
126
  },
102
127
  defaults: {
103
128
  defaultAgent,
104
129
  defaultMode: "web"
105
- // Default to web mode
106
130
  },
107
131
  setup: {
108
- completed: true
132
+ completed: true,
133
+ apiKeyPending: false,
134
+ baseURLPending: false
109
135
  }
110
136
  };
111
137
  }