@lightupai/polaris 0.0.35 → 0.0.37

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightupai/polaris",
3
- "version": "0.0.35",
3
+ "version": "0.0.37",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "polaris": "bin/polaris",
@@ -267,14 +267,17 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
267
267
  try {
268
268
  const res = await daemonGet("/team");
269
269
  if (res.ok) {
270
- const body = await res.json() as { members: Array<{ name: string; participant_id: string; slack_id: string | null; slack_display: string | null }> };
270
+ const body = await res.json() as { members: Array<{ name: string; participant_id: string | null; slack_id: string | null; slack_handle: string | null; slack_display: string | null; polaris_user: boolean }> };
271
271
  if (body.members.length === 0) {
272
272
  return { content: [{ type: "text", text: "No team members found." }] };
273
273
  }
274
- const list = body.members.map((m, i) =>
275
- ` ${i + 1}. ${m.name} (${m.participant_id})${m.slack_display ? ` — @${m.slack_display}` : ""}${m.slack_id ? ` [${m.slack_id}]` : ""}`
276
- ).join("\n");
277
- return { content: [{ type: "text", text: `Team members:\n${list}` }] };
274
+ const taggable = body.members.filter((m) => m.slack_id && m.slack_handle);
275
+ const list = taggable
276
+ .map((m) => ` @${m.slack_handle} — ${m.name}${m.polaris_user ? "" : ""} [${m.slack_id}]`)
277
+ .join("\n");
278
+ const notTaggable = body.members.filter((m) => !m.slack_id);
279
+ const note = notTaggable.length > 0 ? `\n\nNot on Slack: ${notTaggable.map(m => m.name).join(", ")}` : "";
280
+ return { content: [{ type: "text", text: `Team members (use @handle to tag, ✓ = Polaris user):\n${list}${note}` }] };
278
281
  }
279
282
  return { content: [{ type: "text", text: "Failed to fetch team list." }] };
280
283
  } catch {
@@ -451,40 +451,57 @@ export async function startServer(opts: {
451
451
  const org = await getOrgFn(sql, orgId);
452
452
 
453
453
  // Resolve Slack user info if bot token available
454
- let slackMembers: Array<{ id: string; name: string; display_name: string }> = [];
454
+ let slackMembers: Array<{ id: string; name: string; display_name: string; email: string; username: string }> = [];
455
455
  if (org?.slack_bot_token) {
456
456
  try {
457
457
  const slackRes = await fetch("https://slack.com/api/users.list?limit=200", {
458
458
  headers: { Authorization: `Bearer ${org.slack_bot_token}` },
459
459
  });
460
460
  if (slackRes.ok) {
461
- const slackData = (await slackRes.json()) as { members?: Array<{ id: string; real_name?: string; profile?: { display_name?: string }; deleted?: boolean; is_bot?: boolean }> };
461
+ const slackData = (await slackRes.json()) as { members?: Array<{ id: string; name: string; real_name?: string; profile?: { display_name?: string; email?: string }; deleted?: boolean; is_bot?: boolean }> };
462
462
  slackMembers = (slackData.members ?? [])
463
463
  .filter((m) => !m.deleted && !m.is_bot)
464
464
  .map((m) => ({
465
465
  id: m.id,
466
466
  name: m.real_name ?? "",
467
467
  display_name: m.profile?.display_name ?? "",
468
+ email: m.profile?.email ?? "",
469
+ username: m.name ?? "",
468
470
  }));
469
471
  }
470
472
  } catch { /* Slack API unavailable */ }
471
473
  }
472
474
 
473
- // Join Polaris users with Slack members by email match or name match
474
- const team = users.map((u) => {
475
- const slack = slackMembers.find((m) =>
476
- m.name.toLowerCase() === u.name.toLowerCase() ||
477
- m.display_name.toLowerCase() === u.name.toLowerCase().replace(/\s+/g, ".")
478
- );
475
+ // Build team from ALL Slack workspace members, annotate with Polaris identity
476
+ const matchedEmails = new Set<string>();
477
+ const team = slackMembers.map((m) => {
478
+ const polarisUser = users.find((u) => u.email.toLowerCase() === m.email.toLowerCase())
479
+ ?? users.find((u) => u.name.toLowerCase() === m.name.toLowerCase());
480
+ if (polarisUser) matchedEmails.add(polarisUser.email.toLowerCase());
479
481
  return {
480
- name: u.name,
481
- participant_id: u.participant_id,
482
- email: u.email,
483
- slack_id: slack?.id ?? null,
484
- slack_display: slack?.display_name || slack?.name || null,
482
+ name: m.name || m.display_name || m.username,
483
+ slack_id: m.id,
484
+ slack_handle: m.username,
485
+ slack_display: m.display_name || m.name,
486
+ participant_id: polarisUser?.participant_id ?? null,
487
+ polaris_user: !!polarisUser,
485
488
  };
486
489
  });
487
490
 
491
+ // Add Polaris users not in Slack (e.g., synthetic test users)
492
+ for (const u of users) {
493
+ if (!matchedEmails.has(u.email.toLowerCase())) {
494
+ team.push({
495
+ name: u.name,
496
+ slack_id: null,
497
+ slack_handle: null,
498
+ slack_display: null,
499
+ participant_id: u.participant_id,
500
+ polaris_user: true,
501
+ });
502
+ }
503
+ }
504
+
488
505
  return json({ members: team });
489
506
  }
490
507