@agent-finops/core 0.4.4 → 0.5.1
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/agentInventory.d.ts +2 -0
- package/dist/agentInventory.js +18 -14
- package/dist/deadContext.d.ts +2 -0
- package/dist/deadContext.js +2 -1
- package/package.json +1 -1
package/dist/agentInventory.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ export type InventoryItem = {
|
|
|
35
35
|
/** "estimated_understated" when an MCP tool schema is unavailable. */
|
|
36
36
|
weightConfidence: "estimated" | "estimated_understated";
|
|
37
37
|
path?: string;
|
|
38
|
+
/** For project-scoped MCP servers: the project dirs that load this server. */
|
|
39
|
+
ownerDirs?: string[];
|
|
38
40
|
};
|
|
39
41
|
export type AgentInventoryOptions = {
|
|
40
42
|
/** Default: ~/.claude */
|
package/dist/agentInventory.js
CHANGED
|
@@ -113,7 +113,7 @@ export async function loadAgentInventory(options = {}) {
|
|
|
113
113
|
// --- MCP servers (from ~/.claude.json: top-level + per-project map) ---
|
|
114
114
|
const config = await readJson(configPath);
|
|
115
115
|
const serverScopes = collectMcpServers(config, projectDir, options.includeAllProjectMcp ?? false);
|
|
116
|
-
for (const { id, scope } of serverScopes) {
|
|
116
|
+
for (const { id, scope, ownerDirs } of serverScopes) {
|
|
117
117
|
scanned.mcpServers += 1;
|
|
118
118
|
// We almost never have tool schemas from config, so we can't measure the
|
|
119
119
|
// real weight (full tool definitions). Use a conservative published-typical
|
|
@@ -128,7 +128,8 @@ export async function loadAgentInventory(options = {}) {
|
|
|
128
128
|
group: id,
|
|
129
129
|
alwaysLoadedTokens: MCP_SERVER_TOKEN_FLOOR,
|
|
130
130
|
weightConfidence: "estimated_understated",
|
|
131
|
-
path: configPath
|
|
131
|
+
path: configPath,
|
|
132
|
+
ownerDirs
|
|
132
133
|
});
|
|
133
134
|
}
|
|
134
135
|
return { items, scanned };
|
|
@@ -139,16 +140,19 @@ export async function loadAgentInventory(options = {}) {
|
|
|
139
140
|
function collectMcpServers(config, projectDir, includeAllProjectMcp) {
|
|
140
141
|
if (!isRecord(config))
|
|
141
142
|
return [];
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
const add = (id, scope) => {
|
|
143
|
+
const byKey = new Map();
|
|
144
|
+
const add = (id, scope, ownerDir) => {
|
|
145
145
|
// Dedupe by id across all scopes so a server configured in several projects
|
|
146
|
-
// is counted once in the global view
|
|
146
|
+
// is counted once in the global view — but keep EVERY owning project dir,
|
|
147
|
+
// because that's where `claude mcp remove` has to run.
|
|
147
148
|
const key = includeAllProjectMcp ? id : `${scope}:${id}`;
|
|
148
|
-
|
|
149
|
+
const existing = byKey.get(key);
|
|
150
|
+
if (existing) {
|
|
151
|
+
if (ownerDir && !existing.ownerDirs.includes(ownerDir))
|
|
152
|
+
existing.ownerDirs.push(ownerDir);
|
|
149
153
|
return;
|
|
150
|
-
|
|
151
|
-
|
|
154
|
+
}
|
|
155
|
+
byKey.set(key, { id, scope, ownerDirs: ownerDir ? [ownerDir] : [] });
|
|
152
156
|
};
|
|
153
157
|
// Top-level mcpServers are user-scope (global).
|
|
154
158
|
if (isRecord(config.mcpServers)) {
|
|
@@ -159,16 +163,16 @@ function collectMcpServers(config, projectDir, includeAllProjectMcp) {
|
|
|
159
163
|
// Global view: collect every project's servers; otherwise just this project's.
|
|
160
164
|
if (isRecord(config.projects)) {
|
|
161
165
|
const entries = includeAllProjectMcp
|
|
162
|
-
? Object.
|
|
163
|
-
: [config.projects[projectDir]];
|
|
164
|
-
for (const projectEntry of entries) {
|
|
166
|
+
? Object.entries(config.projects)
|
|
167
|
+
: [[projectDir, config.projects[projectDir]]];
|
|
168
|
+
for (const [dir, projectEntry] of entries) {
|
|
165
169
|
if (isRecord(projectEntry) && isRecord(projectEntry.mcpServers)) {
|
|
166
170
|
for (const id of Object.keys(projectEntry.mcpServers))
|
|
167
|
-
add(id, "project");
|
|
171
|
+
add(id, "project", dir);
|
|
168
172
|
}
|
|
169
173
|
}
|
|
170
174
|
}
|
|
171
|
-
return
|
|
175
|
+
return [...byKey.values()];
|
|
172
176
|
}
|
|
173
177
|
/**
|
|
174
178
|
* Extract `name` and `description` from a leading `---` fenced YAML block.
|
package/dist/deadContext.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export type DeadContextItem = {
|
|
|
8
8
|
weightConfidence: InventoryItem["weightConfidence"];
|
|
9
9
|
/** Config file the item is loaded from — the place to remove it. */
|
|
10
10
|
path?: string;
|
|
11
|
+
/** Project dirs that load this item (where `claude mcp remove` must run). */
|
|
12
|
+
ownerDirs?: string[];
|
|
11
13
|
};
|
|
12
14
|
export type DeadContextResult = {
|
|
13
15
|
/** True when we found inventory + transcripts AND at least one dead item. */
|
package/dist/deadContext.js
CHANGED
|
@@ -84,7 +84,8 @@ export function computeDeadContext(items, invocations, config) {
|
|
|
84
84
|
name: item.name,
|
|
85
85
|
alwaysLoadedTokens: item.alwaysLoadedTokens,
|
|
86
86
|
weightConfidence: item.weightConfidence,
|
|
87
|
-
path: item.path
|
|
87
|
+
path: item.path,
|
|
88
|
+
ownerDirs: item.ownerDirs
|
|
88
89
|
});
|
|
89
90
|
}
|
|
90
91
|
dead.sort((a, b) => b.alwaysLoadedTokens - a.alwaysLoadedTokens);
|