claude-memory-admin 1.9.0 → 1.10.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/README.md +41 -6
- package/package.json +1 -1
- package/public/state.mjs +2 -2
- package/public/store.mjs +8 -4
- package/public/styles.css +1 -1
- package/public/ui.mjs +12 -0
- package/public/views/cost.mjs +231 -0
- package/public/views/environment.mjs +2 -0
- package/public/views/header.mjs +16 -0
- package/server.mjs +48 -10
- package/src/agents.mjs +268 -0
- package/src/cost.mjs +277 -0
- package/src/mutate.mjs +7 -3
- package/src/settings.mjs +30 -3
package/src/settings.mjs
CHANGED
|
@@ -59,7 +59,7 @@ export function managedSettingsFiles() {
|
|
|
59
59
|
return files;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
function readJsonDetailed(file) {
|
|
62
|
+
export function readJsonDetailed(file) {
|
|
63
63
|
let raw;
|
|
64
64
|
try {
|
|
65
65
|
raw = fs.readFileSync(file, 'utf8');
|
|
@@ -81,7 +81,7 @@ function readJsonDetailed(file) {
|
|
|
81
81
|
return { status: 'ok', data: parsed, error: null };
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
function settingsCandidates({ projectDir = null, settingsFile = null } = {}) {
|
|
84
|
+
export function settingsCandidates({ projectDir = null, settingsFile = null, userFile = USER_SETTINGS } = {}) {
|
|
85
85
|
const candidates = [];
|
|
86
86
|
for (const file of managedSettingsFiles()) candidates.push({ scope: 'managed', file });
|
|
87
87
|
if (settingsFile) candidates.push({ scope: 'settings-flag', file: settingsFile });
|
|
@@ -89,7 +89,7 @@ function settingsCandidates({ projectDir = null, settingsFile = null } = {}) {
|
|
|
89
89
|
candidates.push({ scope: 'local', file: path.join(projectDir, '.claude', 'settings.local.json') });
|
|
90
90
|
candidates.push({ scope: 'project', file: path.join(projectDir, '.claude', 'settings.json') });
|
|
91
91
|
}
|
|
92
|
-
candidates.push({ scope: 'user', file:
|
|
92
|
+
candidates.push({ scope: 'user', file: userFile });
|
|
93
93
|
return candidates;
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -122,6 +122,33 @@ export function lookup(layers, key) {
|
|
|
122
122
|
return null;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Read a nested key out of one settings object, without ever inventing a level
|
|
127
|
+
* that is not there. `env` in particular is routinely a string or absent in a
|
|
128
|
+
* hand-edited file, and descending into it blindly would throw where the
|
|
129
|
+
* documented behaviour is simply that the layer does not set the key.
|
|
130
|
+
*/
|
|
131
|
+
export function readPath(data, keyPath) {
|
|
132
|
+
let current = data;
|
|
133
|
+
for (const key of keyPath) {
|
|
134
|
+
if (!current || typeof current !== 'object' || Array.isArray(current)) return undefined;
|
|
135
|
+
if (!Object.prototype.hasOwnProperty.call(current, key)) return undefined;
|
|
136
|
+
current = current[key];
|
|
137
|
+
}
|
|
138
|
+
return current;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** `lookup` for a nested key, such as ['env', 'CLAUDE_CODE_SUBAGENT_MODEL']. */
|
|
142
|
+
export function lookupPath(layers, keyPath) {
|
|
143
|
+
for (const layer of layers) {
|
|
144
|
+
const value = readPath(layer.data, keyPath);
|
|
145
|
+
if (value !== undefined) {
|
|
146
|
+
return { value, scope: layer.scope, file: layer.file };
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
|
|
125
152
|
export function expandHome(value) {
|
|
126
153
|
if (value.startsWith('~/')) return path.join(os.homedir(), value.slice(2));
|
|
127
154
|
return value;
|