dual-brain 0.2.8 → 0.2.9
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/package.json +2 -1
- package/src/profile.mjs +82 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dual-brain",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"description": "AI orchestration across Claude + OpenAI subscriptions — smart routing, budget awareness, and dual-brain collaboration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -129,6 +129,7 @@
|
|
|
129
129
|
"hooks/task-classifier.mjs",
|
|
130
130
|
"hooks/model-registry.mjs",
|
|
131
131
|
"hooks/auto-update-wrapper.mjs",
|
|
132
|
+
"hooks/session-end.mjs",
|
|
132
133
|
"hooks/head-guard.mjs",
|
|
133
134
|
"hooks/auto-update.sh",
|
|
134
135
|
"mcp-server/*.mjs",
|
package/src/profile.mjs
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
import { createInterface } from 'readline';
|
|
29
|
-
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'fs';
|
|
29
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from 'fs';
|
|
30
30
|
import { homedir } from 'os';
|
|
31
31
|
import { join } from 'path';
|
|
32
32
|
import { execSync } from 'child_process';
|
|
@@ -188,6 +188,71 @@ async function detectCapabilities(cwd) {
|
|
|
188
188
|
const checkpointsBin = existsSync(join(replitToolsDir, 'checkpoints'))
|
|
189
189
|
|| existsSync('/usr/local/bin/replit-checkpoint');
|
|
190
190
|
|
|
191
|
+
// --- MCP servers: check Claude settings files ---
|
|
192
|
+
let mcpServers = [];
|
|
193
|
+
try {
|
|
194
|
+
const claudeSettings = join(homedir(), '.claude', 'settings.json');
|
|
195
|
+
if (existsSync(claudeSettings)) {
|
|
196
|
+
const settings = JSON.parse(readFileSync(claudeSettings, 'utf8'));
|
|
197
|
+
if (settings.mcpServers) {
|
|
198
|
+
mcpServers = Object.keys(settings.mcpServers);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Also check project-local
|
|
202
|
+
const localSettings = join(root, '.claude', 'settings.json');
|
|
203
|
+
if (existsSync(localSettings)) {
|
|
204
|
+
const local = JSON.parse(readFileSync(localSettings, 'utf8'));
|
|
205
|
+
if (local.mcpServers) {
|
|
206
|
+
mcpServers.push(...Object.keys(local.mcpServers));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
} catch {}
|
|
210
|
+
|
|
211
|
+
// --- Claude plugins: check installed plugin marketplaces ---
|
|
212
|
+
let claudePlugins = [];
|
|
213
|
+
try {
|
|
214
|
+
const pluginDir = join(root, '.replit-tools', '.claude-persistent', 'plugins', 'marketplaces');
|
|
215
|
+
if (existsSync(pluginDir)) {
|
|
216
|
+
const marketplaces = readdirSync(pluginDir);
|
|
217
|
+
for (const m of marketplaces) {
|
|
218
|
+
const mDir = join(pluginDir, m, 'plugins');
|
|
219
|
+
if (existsSync(mDir)) {
|
|
220
|
+
claudePlugins.push(...readdirSync(mDir));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
} catch {}
|
|
225
|
+
|
|
226
|
+
// --- Codex plugins: check available plugins ---
|
|
227
|
+
let codexPlugins = [];
|
|
228
|
+
try {
|
|
229
|
+
const pluginDir = join(root, '.replit-tools', '.codex-persistent', '.tmp', 'plugins', 'plugins');
|
|
230
|
+
if (existsSync(pluginDir)) {
|
|
231
|
+
codexPlugins = readdirSync(pluginDir).filter(f => !f.startsWith('.'));
|
|
232
|
+
}
|
|
233
|
+
} catch {}
|
|
234
|
+
|
|
235
|
+
// --- Shell snapshots: count .sh files ---
|
|
236
|
+
let shellSnapshots = 0;
|
|
237
|
+
try {
|
|
238
|
+
const snapDir = join(root, '.replit-tools', '.claude-persistent', 'shell-snapshots');
|
|
239
|
+
if (existsSync(snapDir)) {
|
|
240
|
+
shellSnapshots = readdirSync(snapDir).filter(f => f.endsWith('.sh')).length;
|
|
241
|
+
}
|
|
242
|
+
} catch {}
|
|
243
|
+
|
|
244
|
+
// --- Configured hooks: count by type from settings.local.json ---
|
|
245
|
+
let configuredHooks = { PreToolUse: 0, PostToolUse: 0, Stop: 0, Notification: 0 };
|
|
246
|
+
try {
|
|
247
|
+
const localSettings = join(root, '.claude', 'settings.local.json');
|
|
248
|
+
if (existsSync(localSettings)) {
|
|
249
|
+
const s = JSON.parse(readFileSync(localSettings, 'utf8'));
|
|
250
|
+
for (const hookType of Object.keys(configuredHooks)) {
|
|
251
|
+
configuredHooks[hookType] = s.hooks?.[hookType]?.length || 0;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
} catch {}
|
|
255
|
+
|
|
191
256
|
return {
|
|
192
257
|
claude: {
|
|
193
258
|
available: claudeAvailable,
|
|
@@ -205,6 +270,11 @@ async function detectCapabilities(cwd) {
|
|
|
205
270
|
available: replitToolsAvailable,
|
|
206
271
|
checkpoints: checkpointsBin,
|
|
207
272
|
},
|
|
273
|
+
mcpServers,
|
|
274
|
+
claudePlugins,
|
|
275
|
+
codexPlugins,
|
|
276
|
+
shellSnapshots,
|
|
277
|
+
configuredHooks,
|
|
208
278
|
};
|
|
209
279
|
}
|
|
210
280
|
|
|
@@ -998,6 +1068,9 @@ export async function getCapabilityManifest(cwd = process.cwd()) {
|
|
|
998
1068
|
return 'unknown';
|
|
999
1069
|
}
|
|
1000
1070
|
|
|
1071
|
+
// ── Environment capabilities (MCP, plugins, hooks, snapshots) ─────────
|
|
1072
|
+
const envCaps = await detectCapabilities(cwd);
|
|
1073
|
+
|
|
1001
1074
|
// ── Health states ──────────────────────────────────────────────────────
|
|
1002
1075
|
let healthStates = {};
|
|
1003
1076
|
try {
|
|
@@ -1158,6 +1231,14 @@ export async function getCapabilityManifest(cwd = process.cwd()) {
|
|
|
1158
1231
|
recommendedAction,
|
|
1159
1232
|
zeroProviderMode: !hasAnyProvider,
|
|
1160
1233
|
},
|
|
1234
|
+
environment: {
|
|
1235
|
+
mcpServers: envCaps.mcpServers,
|
|
1236
|
+
claudePlugins: envCaps.claudePlugins,
|
|
1237
|
+
codexPlugins: envCaps.codexPlugins,
|
|
1238
|
+
shellSnapshots: envCaps.shellSnapshots,
|
|
1239
|
+
configuredHooks: envCaps.configuredHooks,
|
|
1240
|
+
replitTools: envCaps.replitTools,
|
|
1241
|
+
},
|
|
1161
1242
|
timestamp: new Date().toISOString(),
|
|
1162
1243
|
};
|
|
1163
1244
|
|