@dmsdc-ai/aigentry-deliberation 0.0.28 → 0.0.30

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 (2) hide show
  1. package/index.js +47 -12
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -719,7 +719,10 @@ function dedupeBrowserTabs(tabs = []) {
719
719
  const title = String(tab?.title || "").trim();
720
720
  const url = String(tab?.url || "").trim();
721
721
  if (!url || (!isLlmUrl(url) && !isExtensionLlmTab(url, title))) continue;
722
- const key = `${browser}\t${title}\t${url}`;
722
+ // Dedup by title+url (ignore browser name) so that the same tab detected
723
+ // via both AppleScript and CDP is not duplicated. The first occurrence wins,
724
+ // so callers should add preferred sources first (e.g., CDP before AppleScript).
725
+ const key = `${title}\t${url}`;
723
726
  if (seen.has(key)) continue;
724
727
  seen.add(key);
725
728
  out.push({
@@ -946,16 +949,28 @@ async function ensureCdpAvailable() {
946
949
 
947
950
  // Chrome 145+ requires --user-data-dir for CDP to work.
948
951
  // The default data dir is rejected, so we copy the profile to ~/.chrome-cdp.
952
+ // Profile can be set via env DELIBERATION_CHROME_PROFILE or config.chrome_profile (e.g., "Profile 1").
949
953
  const cdpDataDir = path.join(os.homedir(), ".chrome-cdp");
950
- const profileDir = "Default";
954
+ const cdpConfig = loadDeliberationConfig();
955
+ const profileDir = process.env.DELIBERATION_CHROME_PROFILE || cdpConfig.chrome_profile || "Default";
951
956
 
952
957
  try {
953
958
  if (chromeUserDataDir) {
954
959
  const srcProfile = path.join(chromeUserDataDir, profileDir);
955
960
  const dstProfile = path.join(cdpDataDir, profileDir);
956
- if (!fs.existsSync(dstProfile) && fs.existsSync(srcProfile)) {
961
+ // Track which profile was copied; re-copy if profile changed
962
+ const profileMarker = path.join(cdpDataDir, ".cdp-profile");
963
+ const lastProfile = fs.existsSync(profileMarker) ? fs.readFileSync(profileMarker, "utf8").trim() : null;
964
+ const needsCopy = !fs.existsSync(dstProfile) || (lastProfile && lastProfile !== profileDir);
965
+ if (needsCopy && fs.existsSync(srcProfile)) {
966
+ // Clean old profile if switching
967
+ if (lastProfile && lastProfile !== profileDir) {
968
+ const oldDst = path.join(cdpDataDir, lastProfile);
969
+ if (fs.existsSync(oldDst)) fs.rmSync(oldDst, { recursive: true, force: true });
970
+ }
957
971
  fs.mkdirSync(cdpDataDir, { recursive: true });
958
972
  execFileSync("cp", ["-R", srcProfile, dstProfile], { timeout: 30000, stdio: "ignore" });
973
+ fs.writeFileSync(profileMarker, profileDir);
959
974
  // Create minimal Local State with single profile to avoid profile picker
960
975
  const localStateSrc = path.join(chromeUserDataDir, "Local State");
961
976
  if (fs.existsSync(localStateSrc)) {
@@ -1133,6 +1148,16 @@ async function collectBrowserLlmTabs() {
1133
1148
  };
1134
1149
  }
1135
1150
 
1151
+ // CDP first: CDP-detected tabs are preferred over AppleScript-detected ones
1152
+ // because they carry CDP metadata (tab ID, WebSocket URL) for browser_auto transport.
1153
+ // Since dedupeBrowserTabs keeps the first occurrence, CDP entries win the dedup.
1154
+ const shouldUseCdp = mode === "auto" || mode === "cdp";
1155
+ if (shouldUseCdp) {
1156
+ const cdp = await collectBrowserLlmTabsViaCdp();
1157
+ tabs.push(...cdp.tabs);
1158
+ if (cdp.note) notes.push(cdp.note);
1159
+ }
1160
+
1136
1161
  const shouldUseAppleScript = mode === "auto" || mode === "applescript";
1137
1162
  if (shouldUseAppleScript && process.platform === "darwin") {
1138
1163
  const mac = collectBrowserLlmTabsViaAppleScript();
@@ -1142,13 +1167,6 @@ async function collectBrowserLlmTabs() {
1142
1167
  notes.push("AppleScript scanning is macOS only. Switch to CDP scanning.");
1143
1168
  }
1144
1169
 
1145
- const shouldUseCdp = mode === "auto" || mode === "cdp";
1146
- if (shouldUseCdp) {
1147
- const cdp = await collectBrowserLlmTabsViaCdp();
1148
- tabs.push(...cdp.tabs);
1149
- if (cdp.note) notes.push(cdp.note);
1150
- }
1151
-
1152
1170
  const uniqTabs = dedupeBrowserTabs(tabs);
1153
1171
  return {
1154
1172
  tabs: uniqTabs,
@@ -1333,6 +1351,17 @@ async function collectSpeakerCandidates({ include_cli = true, include_browser =
1333
1351
  }
1334
1352
  }
1335
1353
  }
1354
+
1355
+ // Third pass: upgrade browser-detected candidates that missed the first hostname match.
1356
+ // When CDP is reachable, AppleScript-detected speakers should also get browser_auto
1357
+ // transport. The OrchestratedBrowserPort will create/navigate tabs on demand if needed.
1358
+ if (cdpReachable) {
1359
+ for (const candidate of candidates) {
1360
+ if (candidate.type !== "browser" || candidate.auto_registered) continue;
1361
+ if (candidate.cdp_available) continue; // already matched
1362
+ candidate.cdp_available = true;
1363
+ }
1364
+ }
1336
1365
  }
1337
1366
 
1338
1367
  return { candidates, browserNote };
@@ -3427,8 +3456,10 @@ server.tool(
3427
3456
  .describe("Default number of rounds (1-10, default 3)"),
3428
3457
  default_ordering: z.enum(["auto", "cyclic", "random", "weighted-random"]).optional()
3429
3458
  .describe("Default ordering strategy: auto (automatic based on speaker count), cyclic, random, weighted-random"),
3459
+ chrome_profile: z.string().optional()
3460
+ .describe("Chrome profile directory name for CDP (e.g., \"Default\", \"Profile 1\"). Stored for auto-launch."),
3430
3461
  },
3431
- safeToolHandler("deliberation_cli_config", async ({ enabled_clis, require_speaker_selection, default_rounds, default_ordering }) => {
3462
+ safeToolHandler("deliberation_cli_config", async ({ enabled_clis, require_speaker_selection, default_rounds, default_ordering, chrome_profile }) => {
3432
3463
  const config = loadDeliberationConfig();
3433
3464
 
3434
3465
  // Handle setup config updates
@@ -3445,6 +3476,10 @@ server.tool(
3445
3476
  config.default_ordering = default_ordering;
3446
3477
  configChanged = true;
3447
3478
  }
3479
+ if (chrome_profile !== undefined && chrome_profile !== null) {
3480
+ config.chrome_profile = chrome_profile;
3481
+ configChanged = true;
3482
+ }
3448
3483
  if (configChanged) {
3449
3484
  config.setup_complete = true;
3450
3485
  saveDeliberationConfig(config);
@@ -3459,7 +3494,7 @@ server.tool(
3459
3494
  return {
3460
3495
  content: [{
3461
3496
  type: "text",
3462
- text: `## Deliberation CLI Settings\n\n**Mode:** ${mode}\n**Speaker selection:** ${config.require_speaker_selection === false ? "auto (all detected speakers join)" : "manual (user selects)"}\n**Default rounds:** ${config.default_rounds || 3}\n**Ordering:** ${config.default_ordering || "auto"}\n**Configured CLIs:** ${configured.length > 0 ? configured.join(", ") : "(none — full auto-detection)"}\n**Currently detected CLIs:** ${detected.join(", ") || "(none)"}\n**All supported CLIs:** ${DEFAULT_CLI_CANDIDATES.join(", ")}\n\nTo change:\n\`deliberation_cli_config(require_speaker_selection: false, default_rounds: 3, default_ordering: "auto")\`\n\nTo revert to full auto-detection:\n\`deliberation_cli_config(enabled_clis: [])\``,
3497
+ text: `## Deliberation CLI Settings\n\n**Mode:** ${mode}\n**Speaker selection:** ${config.require_speaker_selection === false ? "auto (all detected speakers join)" : "manual (user selects)"}\n**Default rounds:** ${config.default_rounds || 3}\n**Ordering:** ${config.default_ordering || "auto"}\n**Chrome profile:** ${config.chrome_profile || "Default"} (env: DELIBERATION_CHROME_PROFILE)\n**Configured CLIs:** ${configured.length > 0 ? configured.join(", ") : "(none — full auto-detection)"}\n**Currently detected CLIs:** ${detected.join(", ") || "(none)"}\n**All supported CLIs:** ${DEFAULT_CLI_CANDIDATES.join(", ")}\n\nTo change:\n\`deliberation_cli_config(require_speaker_selection: false, default_rounds: 3, default_ordering: "auto")\`\n\nTo set Chrome profile for CDP:\n\`deliberation_cli_config(chrome_profile: "Profile 1")\`\n\nTo revert to full auto-detection:\n\`deliberation_cli_config(enabled_clis: [])\``,
3463
3498
  }],
3464
3499
  };
3465
3500
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dmsdc-ai/aigentry-deliberation",
3
- "version": "0.0.28",
3
+ "version": "0.0.30",
4
4
  "description": "MCP Deliberation Server — Multi-session AI deliberation with smart speaker ordering and persona roles",
5
5
  "type": "module",
6
6
  "license": "MIT",