@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.
- package/dist/AgentFactory.cjs +152 -0
- package/dist/AgentFactory.d.ts +121 -0
- package/dist/AgentFactory.d.ts.map +1 -0
- package/dist/AgentFactory.js +132 -0
- package/dist/AgentManager.cjs +226 -0
- package/dist/AgentManager.d.ts +191 -0
- package/dist/AgentManager.d.ts.map +1 -0
- package/dist/AgentManager.js +192 -0
- package/dist/config/config-enrichment.cjs +23 -3
- package/dist/config/config-enrichment.d.ts +20 -5
- package/dist/config/config-enrichment.d.ts.map +1 -1
- package/dist/config/config-enrichment.js +22 -3
- package/dist/config/config-manager.cjs +340 -3
- package/dist/config/config-manager.d.ts +158 -7
- package/dist/config/config-manager.d.ts.map +1 -1
- package/dist/config/config-manager.js +325 -3
- package/dist/config/discover-prompts.cjs +103 -0
- package/dist/config/discover-prompts.d.ts +28 -0
- package/dist/config/discover-prompts.d.ts.map +1 -0
- package/dist/config/discover-prompts.js +73 -0
- package/dist/config/errors.cjs +2 -2
- package/dist/config/errors.js +2 -2
- package/dist/config/index.cjs +14 -2
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +21 -3
- package/dist/index.cjs +109 -6
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +111 -6
- package/dist/installation.cjs +239 -0
- package/dist/installation.d.ts +72 -0
- package/dist/installation.d.ts.map +1 -0
- package/dist/installation.js +202 -0
- package/dist/models/custom-models.cjs +157 -0
- package/dist/models/custom-models.d.ts +94 -0
- package/dist/models/custom-models.d.ts.map +1 -0
- package/dist/models/custom-models.js +117 -0
- package/dist/models/index.cjs +89 -0
- package/dist/models/index.d.ts +11 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +68 -0
- package/dist/models/path-resolver.cjs +154 -0
- package/dist/models/path-resolver.d.ts +77 -0
- package/dist/models/path-resolver.d.ts.map +1 -0
- package/dist/models/path-resolver.js +108 -0
- package/dist/models/state-manager.cjs +220 -0
- package/dist/models/state-manager.d.ts +138 -0
- package/dist/models/state-manager.d.ts.map +1 -0
- package/dist/models/state-manager.js +184 -0
- package/dist/preferences/error-codes.cjs +2 -0
- package/dist/preferences/error-codes.d.ts +3 -1
- package/dist/preferences/error-codes.d.ts.map +1 -1
- package/dist/preferences/error-codes.js +2 -0
- package/dist/preferences/index.d.ts +1 -1
- package/dist/preferences/index.d.ts.map +1 -1
- package/dist/preferences/loader.cjs +32 -6
- package/dist/preferences/loader.d.ts +23 -4
- package/dist/preferences/loader.d.ts.map +1 -1
- package/dist/preferences/loader.js +32 -6
- package/dist/preferences/schemas.cjs +21 -3
- package/dist/preferences/schemas.d.ts +52 -24
- package/dist/preferences/schemas.d.ts.map +1 -1
- package/dist/preferences/schemas.js +28 -4
- package/dist/registry/registry.cjs +28 -45
- package/dist/registry/registry.d.ts +8 -6
- package/dist/registry/registry.d.ts.map +1 -1
- package/dist/registry/registry.js +26 -44
- package/dist/registry/types.d.ts +11 -13
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/resolver.cjs +82 -43
- package/dist/resolver.d.ts +7 -5
- package/dist/resolver.d.ts.map +1 -1
- package/dist/resolver.js +83 -44
- package/dist/utils/api-key-resolver.cjs +19 -1
- package/dist/utils/api-key-resolver.d.ts.map +1 -1
- package/dist/utils/api-key-resolver.js +19 -1
- package/dist/utils/api-key-store.cjs +46 -0
- package/dist/utils/api-key-store.d.ts +27 -0
- package/dist/utils/api-key-store.d.ts.map +1 -1
- package/dist/utils/api-key-store.js +44 -0
- package/dist/utils/env-file.cjs +20 -68
- package/dist/utils/env-file.d.ts +2 -1
- package/dist/utils/env-file.d.ts.map +1 -1
- package/dist/utils/env-file.js +20 -68
- package/dist/writer.cjs +20 -2
- package/dist/writer.d.ts +1 -0
- package/dist/writer.d.ts.map +1 -1
- package/dist/writer.js +20 -2
- package/package.json +2 -2
- package/dist/AgentOrchestrator.cjs +0 -263
- package/dist/AgentOrchestrator.d.ts +0 -191
- package/dist/AgentOrchestrator.d.ts.map +0 -1
- 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;
|
|
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,
|
|
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.
|
|
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.
|
|
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(
|
|
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
|
}
|