@a-company/paradigm 5.3.3 → 5.4.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/dist/mcp.js CHANGED
@@ -74,17 +74,13 @@ import {
74
74
  validateProtocol,
75
75
  validatePurposeFile,
76
76
  validateUniversityContent
77
- } from "./chunk-S6MZ2IEX.js";
77
+ } from "./chunk-7HRBT23N.js";
78
+ import "./chunk-L27I3CPZ.js";
78
79
  import {
79
80
  getWorkLogSummary,
80
81
  loadWorkLogEntries,
81
82
  recordWorkLog
82
83
  } from "./chunk-TAIJOFOE.js";
83
- import {
84
- getDecisionSummary,
85
- loadDecisions,
86
- recordDecision
87
- } from "./chunk-EZ3GOCYC.js";
88
84
  import {
89
85
  getPluginUpdateNotice,
90
86
  schedulePluginUpdateCheck
@@ -115,6 +111,7 @@ import {
115
111
  emitAndProcess,
116
112
  engageNomination,
117
113
  filterContent,
114
+ getNeverlandMetrics,
118
115
  getNominationStats,
119
116
  init_data_policy_loader,
120
117
  init_event_stream,
@@ -130,13 +127,14 @@ import {
130
127
  queryEvents,
131
128
  resolveDebate,
132
129
  searchNotebooks
133
- } from "./chunk-GGMI6C2L.js";
130
+ } from "./chunk-ICSLIPUS.js";
134
131
  import {
135
132
  buildProfileEnrichment,
136
133
  init_agent_loader,
137
134
  loadAgentProfile,
138
135
  loadAllAgentProfiles,
139
136
  queryExpertise,
137
+ saveAgentProfile,
140
138
  verifyIntegrity
141
139
  } from "./chunk-A2L4TSLZ.js";
142
140
  import {
@@ -154,7 +152,11 @@ import {
154
152
  TimelineBuilder,
155
153
  loadAllSeedPatterns
156
154
  } from "./chunk-ZDHLG5VP.js";
157
- import "./chunk-L27I3CPZ.js";
155
+ import {
156
+ getDecisionSummary,
157
+ loadDecisions,
158
+ recordDecision
159
+ } from "./chunk-EZ3GOCYC.js";
158
160
  import {
159
161
  __esm,
160
162
  __export,
@@ -5917,12 +5919,26 @@ async function handleOrchestrateInline(args, ctx) {
5917
5919
  let agentProfiles = /* @__PURE__ */ new Map();
5918
5920
  try {
5919
5921
  const { loadAgentProfile: loadAgentProfile2, buildProfileEnrichment: buildProfileEnrichment2 } = await import("./agent-loader-SJPJJS33.js");
5922
+ const { loadDecisions: loadDecisions3 } = await import("./decision-loader-WWCLIQPJ.js");
5923
+ const { loadJournalEntries: loadJournalEntries2 } = await import("./journal-loader-5EYSBFFY.js");
5924
+ const { loadNominations: loadNominations2 } = await import("./nomination-engine-HDWMN4IO.js");
5925
+ const recentDecisions = loadDecisions3(ctx.rootDir, { status: "active", limit: 5 }).map((d) => ({ title: d.title, decision: d.decision.slice(0, 150) }));
5926
+ const pendingNominations = loadNominations2(ctx.rootDir, { pending_only: true, limit: 10 }).map((n) => ({ urgency: n.urgency, brief: n.brief }));
5920
5927
  for (const stage of plan.stages) {
5921
5928
  for (const agentStep of stage.agents) {
5922
5929
  if (!agentProfiles.has(agentStep.name)) {
5923
5930
  const profile = loadAgentProfile2(ctx.rootDir, agentStep.name);
5924
5931
  if (profile) {
5925
- let enrichment = buildProfileEnrichment2(profile, symbols);
5932
+ if (profile.benched) continue;
5933
+ const journalInsights = loadJournalEntries2(agentStep.name, {
5934
+ transferable: true,
5935
+ limit: 5
5936
+ }).map((j) => ({ trigger: j.trigger, insight: j.insight.slice(0, 150) }));
5937
+ let enrichment = buildProfileEnrichment2(profile, symbols, void 0, {
5938
+ recentDecisions,
5939
+ journalInsights,
5940
+ pendingNominations
5941
+ });
5926
5942
  if (profile.permissions) {
5927
5943
  const constraints = ["\n## Permission Constraints"];
5928
5944
  if (profile.permissions.paths?.deny?.length) {
@@ -5940,7 +5956,10 @@ async function handleOrchestrateInline(args, ctx) {
5940
5956
  enrichment += "\n" + constraints.join("\n");
5941
5957
  }
5942
5958
  if (enrichment.trim()) {
5943
- agentProfiles.set(agentStep.name, { enrichment });
5959
+ agentProfiles.set(agentStep.name, {
5960
+ enrichment,
5961
+ nickname: profile.nickname
5962
+ });
5944
5963
  }
5945
5964
  }
5946
5965
  }
@@ -5960,7 +5979,8 @@ async function handleOrchestrateInline(args, ctx) {
5960
5979
  task: agentStep.task,
5961
5980
  symbols,
5962
5981
  dependsOn: agentStep.dependsOn,
5963
- profileEnrichment: profileData?.enrichment
5982
+ profileEnrichment: profileData?.enrichment,
5983
+ nickname: profileData?.nickname
5964
5984
  });
5965
5985
  agentPrompts.push(promptResult);
5966
5986
  }
@@ -5984,7 +6004,9 @@ async function handleOrchestrateInline(args, ctx) {
5984
6004
  "Execute stages in order (stage 0, then stage 1, etc.)",
5985
6005
  "Agents within a stage can be run in parallel if your environment supports it",
5986
6006
  "Pass handoff context between stages",
5987
- "After each phase, summarize what was done before starting the next"
6007
+ 'Present each agent response as an attributed message using the attribution prefix (e.g., "[architect] Rate limiter should go before ^authenticated")',
6008
+ "Do NOT synthesize agent responses \u2014 show them as distinct contributions from each agent",
6009
+ "After all agents in a stage complete, reconcile their outputs before proceeding to the next stage"
5988
6010
  ],
5989
6011
  // Claude Code: Use Task tool for parallel agent spawning
5990
6012
  claudeCode: {
@@ -6010,6 +6032,24 @@ async function handleOrchestrateInline(args, ctx) {
6010
6032
  method: "paradigm team orchestrate",
6011
6033
  command: `paradigm team orchestrate "${task}"`,
6012
6034
  note: "Spawns independent agent processes \u2014 works from any terminal"
6035
+ },
6036
+ // Symphony: Record agent contributions as team thread messages
6037
+ symphony: {
6038
+ enabled: true,
6039
+ orchestrationThread: `thr-${orchestrationId}`,
6040
+ instructions: [
6041
+ "After each agent completes, call paradigm_symphony_send to record the contribution",
6042
+ 'Use intent "context" for analysis, "proposal" for recommendations, "decision" for decisions made',
6043
+ `Set threadRoot to "thr-${orchestrationId}" so all contributions are in one thread`,
6044
+ "Include the symbols array from the agent relay output",
6045
+ "This creates a visible team thread that Conductor and other sessions can observe"
6046
+ ],
6047
+ exampleCall: {
6048
+ intent: "context",
6049
+ text: "[architect] Rate limiter should be placed before ^authenticated gate to prevent unauthenticated flood",
6050
+ threadRoot: `thr-${orchestrationId}`,
6051
+ symbols: ["#rate-limiter", "^authenticated"]
6052
+ }
6013
6053
  }
6014
6054
  };
6015
6055
  const text = JSON.stringify(result, null, 2);
@@ -6033,11 +6073,23 @@ async function handleAgentPrompt(args, ctx) {
6033
6073
  };
6034
6074
  const symbols = extractSymbols(task);
6035
6075
  let profileEnrichment;
6076
+ let nickname;
6036
6077
  try {
6037
6078
  const { loadAgentProfile: loadAgentProfile2, buildProfileEnrichment: buildProfileEnrichment2 } = await import("./agent-loader-SJPJJS33.js");
6079
+ const { loadDecisions: loadDecisions3 } = await import("./decision-loader-WWCLIQPJ.js");
6080
+ const { loadJournalEntries: loadJournalEntries2 } = await import("./journal-loader-5EYSBFFY.js");
6081
+ const { loadNominations: loadNominations2 } = await import("./nomination-engine-HDWMN4IO.js");
6038
6082
  const profile = loadAgentProfile2(ctx.rootDir, agentName);
6039
6083
  if (profile) {
6040
- let enrichment = buildProfileEnrichment2(profile, symbols);
6084
+ nickname = profile.nickname;
6085
+ const recentDecisions = loadDecisions3(ctx.rootDir, { status: "active", limit: 5 }).map((d) => ({ title: d.title, decision: d.decision.slice(0, 150) }));
6086
+ const journalInsights = loadJournalEntries2(agentName, { transferable: true, limit: 5 }).map((j) => ({ trigger: j.trigger, insight: j.insight.slice(0, 150) }));
6087
+ const pendingNominations = loadNominations2(ctx.rootDir, { pending_only: true, limit: 10 }).map((n) => ({ urgency: n.urgency, brief: n.brief }));
6088
+ let enrichment = buildProfileEnrichment2(profile, symbols, void 0, {
6089
+ recentDecisions,
6090
+ journalInsights,
6091
+ pendingNominations
6092
+ });
6041
6093
  if (profile.permissions) {
6042
6094
  const constraints = ["\n## Permission Constraints"];
6043
6095
  if (profile.permissions.paths?.deny?.length) {
@@ -6064,12 +6116,14 @@ async function handleAgentPrompt(args, ctx) {
6064
6116
  symbols,
6065
6117
  handoffContext,
6066
6118
  previousAgent,
6067
- profileEnrichment
6119
+ profileEnrichment,
6120
+ nickname
6068
6121
  });
6069
6122
  const result = {
6070
6123
  agent: agentName,
6071
6124
  model: promptResult.model,
6072
6125
  prompt: promptResult.prompt,
6126
+ attribution: promptResult.attribution,
6073
6127
  taskToolParams: {
6074
6128
  description: promptResult.taskDescription,
6075
6129
  prompt: promptResult.prompt,
@@ -6077,7 +6131,7 @@ async function handleAgentPrompt(args, ctx) {
6077
6131
  model: promptResult.model
6078
6132
  },
6079
6133
  focusAreas: promptResult.focusAreas,
6080
- usage: "Use the Task tool with the taskToolParams to spawn this agent"
6134
+ usage: "Use the Task tool with the taskToolParams to spawn this agent. Present the response with the attribution prefix."
6081
6135
  };
6082
6136
  const text = JSON.stringify(result, null, 2);
6083
6137
  trackToolCall(text.length, "paradigm_agent_prompt");
@@ -6280,12 +6334,14 @@ handoff_context: |
6280
6334
  This structured output helps track progress and pass context between agents.`);
6281
6335
  const prompt = parts.join("\n");
6282
6336
  const model = agent.defaultModel || DEFAULT_MODELS[agent.name] || "sonnet";
6337
+ const attribution = options.nickname ? `[${options.nickname} (${agent.name})]` : `[${agent.name}]`;
6283
6338
  return {
6284
6339
  agent: agent.name,
6285
6340
  model,
6286
6341
  prompt,
6287
6342
  taskDescription: `${agent.name}: ${task.slice(0, 50)}${task.length > 50 ? "..." : ""}`,
6288
6343
  subagentType: "general-purpose",
6344
+ attribution,
6289
6345
  focusAreas: agent.focus
6290
6346
  };
6291
6347
  }
@@ -17861,6 +17917,42 @@ function getAgentToolsList() {
17861
17917
  readOnlyHint: true,
17862
17918
  destructiveHint: false
17863
17919
  }
17920
+ },
17921
+ {
17922
+ name: "paradigm_agent_bench",
17923
+ description: "Bench an agent \u2014 Maestro will skip this agent during orchestration and nomination scoring. Use when an agent is noisy or unhelpful. ~50 tokens.",
17924
+ inputSchema: {
17925
+ type: "object",
17926
+ properties: {
17927
+ id: {
17928
+ type: "string",
17929
+ description: 'Agent ID to bench (e.g., "architect")'
17930
+ }
17931
+ },
17932
+ required: ["id"]
17933
+ },
17934
+ annotations: {
17935
+ readOnlyHint: false,
17936
+ destructiveHint: false
17937
+ }
17938
+ },
17939
+ {
17940
+ name: "paradigm_agent_activate",
17941
+ description: "Activate a benched agent \u2014 restore it to active Maestro orchestration. ~50 tokens.",
17942
+ inputSchema: {
17943
+ type: "object",
17944
+ properties: {
17945
+ id: {
17946
+ type: "string",
17947
+ description: 'Agent ID to activate (e.g., "architect")'
17948
+ }
17949
+ },
17950
+ required: ["id"]
17951
+ },
17952
+ annotations: {
17953
+ readOnlyHint: false,
17954
+ destructiveHint: false
17955
+ }
17864
17956
  }
17865
17957
  ];
17866
17958
  }
@@ -17885,6 +17977,8 @@ async function handleAgentTool(name, args, ctx) {
17885
17977
  agents: profiles.map((p) => ({
17886
17978
  id: p.id,
17887
17979
  role: p.role,
17980
+ nickname: p.nickname,
17981
+ benched: p.benched || false,
17888
17982
  personality: p.personality,
17889
17983
  topExpertise: (p.expertise || []).sort((a, b) => b.confidence - a.confidence).slice(0, 5).map((e) => ({
17890
17984
  symbol: e.symbol,
@@ -17892,7 +17986,8 @@ async function handleAgentTool(name, args, ctx) {
17892
17986
  sessions: e.sessions
17893
17987
  })),
17894
17988
  projectContexts: Object.keys(p.contexts || {}),
17895
- transferableCount: (p.transferable || []).length
17989
+ transferableCount: (p.transferable || []).length,
17990
+ ...p.attention?.threshold != null ? { threshold: p.attention.threshold } : {}
17896
17991
  }))
17897
17992
  }, null, 2)
17898
17993
  };
@@ -17972,6 +18067,48 @@ async function handleAgentTool(name, args, ctx) {
17972
18067
  }, null, 2)
17973
18068
  };
17974
18069
  }
18070
+ case "paradigm_agent_bench": {
18071
+ const benchId = args.id;
18072
+ const benchProfile = loadAgentProfile(ctx.rootDir, benchId);
18073
+ if (!benchProfile) {
18074
+ return {
18075
+ handled: true,
18076
+ text: JSON.stringify({ error: `Agent "${benchId}" not found` }, null, 2)
18077
+ };
18078
+ }
18079
+ benchProfile.benched = true;
18080
+ benchProfile.updated = (/* @__PURE__ */ new Date()).toISOString();
18081
+ saveAgentProfile(benchId, benchProfile, "global");
18082
+ return {
18083
+ handled: true,
18084
+ text: JSON.stringify({
18085
+ id: benchId,
18086
+ benched: true,
18087
+ note: `${benchId} is now benched. Maestro will skip this agent during orchestration.`
18088
+ }, null, 2)
18089
+ };
18090
+ }
18091
+ case "paradigm_agent_activate": {
18092
+ const activateId = args.id;
18093
+ const activateProfile = loadAgentProfile(ctx.rootDir, activateId);
18094
+ if (!activateProfile) {
18095
+ return {
18096
+ handled: true,
18097
+ text: JSON.stringify({ error: `Agent "${activateId}" not found` }, null, 2)
18098
+ };
18099
+ }
18100
+ activateProfile.benched = false;
18101
+ activateProfile.updated = (/* @__PURE__ */ new Date()).toISOString();
18102
+ saveAgentProfile(activateId, activateProfile, "global");
18103
+ return {
18104
+ handled: true,
18105
+ text: JSON.stringify({
18106
+ id: activateId,
18107
+ benched: false,
18108
+ note: `${activateId} is now active. Maestro will include this agent in orchestration.`
18109
+ }, null, 2)
18110
+ };
18111
+ }
17975
18112
  default:
17976
18113
  return { handled: false, text: "" };
17977
18114
  }
@@ -19490,6 +19627,18 @@ function getAmbientToolsList() {
19490
19627
  readOnlyHint: false,
19491
19628
  destructiveHint: false
19492
19629
  }
19630
+ },
19631
+ {
19632
+ name: "paradigm_ambient_neverland",
19633
+ description: "Neverland Validation \u2014 aggregate learning metrics across all agents. Shows acceptance rates, threshold drift, expertise growth, notebook counts, cross-project transfer, and overall health status (cold-start \u2192 accumulating \u2192 calibrating \u2192 mature). ~200 tokens.",
19634
+ inputSchema: {
19635
+ type: "object",
19636
+ properties: {}
19637
+ },
19638
+ annotations: {
19639
+ readOnlyHint: true,
19640
+ destructiveHint: false
19641
+ }
19493
19642
  }
19494
19643
  ];
19495
19644
  }
@@ -19731,6 +19880,13 @@ async function handleAmbientTool(name, args, ctx) {
19731
19880
  handled: true
19732
19881
  };
19733
19882
  }
19883
+ case "paradigm_ambient_neverland": {
19884
+ const metrics = getNeverlandMetrics(ctx.rootDir);
19885
+ return {
19886
+ text: json(metrics),
19887
+ handled: true
19888
+ };
19889
+ }
19734
19890
  default:
19735
19891
  return { text: `Unknown ambient tool: ${name}`, handled: false };
19736
19892
  }
@@ -20805,7 +20961,7 @@ Update command:
20805
20961
  trackToolCall(noWsText.length, name);
20806
20962
  return { content: [{ type: "text", text: noWsText }] };
20807
20963
  }
20808
- const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-HRA2AUS6.js");
20964
+ const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-65H4WULU.js");
20809
20965
  const memberResults = [];
20810
20966
  for (const member of ctx.workspace.config.members) {
20811
20967
  const memberAbsPath = path34.resolve(path34.dirname(ctx.workspace.workspacePath), member.path);
@@ -7,6 +7,7 @@ import {
7
7
  emitAndProcess,
8
8
  engageNomination,
9
9
  forwardNominationsToRelay,
10
+ getNeverlandMetrics,
10
11
  getNominationStats,
11
12
  init_nomination_engine,
12
13
  loadDebates,
@@ -16,7 +17,7 @@ import {
16
17
  processEvent,
17
18
  processPendingEvents,
18
19
  resolveDebate
19
- } from "./chunk-GGMI6C2L.js";
20
+ } from "./chunk-ICSLIPUS.js";
20
21
  import "./chunk-A2L4TSLZ.js";
21
22
  import "./chunk-MCMOGQMU.js";
22
23
  import "./chunk-7N7GSU6K.js";
@@ -29,6 +30,7 @@ export {
29
30
  emitAndProcess,
30
31
  engageNomination,
31
32
  forwardNominationsToRelay,
33
+ getNeverlandMetrics,
32
34
  getNominationStats,
33
35
  loadDebates,
34
36
  loadNominations,
@@ -13,8 +13,8 @@ import "./chunk-PDX44BCA.js";
13
13
  // src/platform-server/index.ts
14
14
  import express from "express";
15
15
  import * as http from "http";
16
- import * as path3 from "path";
17
- import * as fs3 from "fs";
16
+ import * as path4 from "path";
17
+ import * as fs4 from "fs";
18
18
  import { fileURLToPath } from "url";
19
19
  import chalk from "chalk";
20
20
 
@@ -950,9 +950,156 @@ function createAmbientRouter(projectDir, wsContext) {
950
950
  return router;
951
951
  }
952
952
 
953
+ // src/platform-server/routes/team.ts
954
+ import { Router as Router4 } from "express";
955
+ import * as fs3 from "fs";
956
+ import * as path3 from "path";
957
+ import * as os from "os";
958
+ import * as yaml3 from "js-yaml";
959
+ function readJsonl(filePath) {
960
+ if (!fs3.existsSync(filePath)) return [];
961
+ try {
962
+ return fs3.readFileSync(filePath, "utf-8").trim().split("\n").filter((line) => line.trim()).map((line) => {
963
+ try {
964
+ return JSON.parse(line);
965
+ } catch {
966
+ return null;
967
+ }
968
+ }).filter((v) => v !== null);
969
+ } catch {
970
+ return [];
971
+ }
972
+ }
973
+ function loadAgentProfiles() {
974
+ const globalDir = path3.join(os.homedir(), ".paradigm", "agents");
975
+ const profiles = [];
976
+ if (!fs3.existsSync(globalDir)) return profiles;
977
+ for (const file of fs3.readdirSync(globalDir).filter((f) => f.endsWith(".agent"))) {
978
+ try {
979
+ const content = fs3.readFileSync(path3.join(globalDir, file), "utf-8");
980
+ const p = yaml3.load(content);
981
+ if (!p?.id) continue;
982
+ const expertise = p.expertise || [];
983
+ expertise.sort((a, b) => b.confidence - a.confidence);
984
+ profiles.push({
985
+ id: p.id,
986
+ role: p.role || p.id,
987
+ nickname: p.nickname,
988
+ benched: p.benched || false,
989
+ expertiseCount: expertise.length,
990
+ topExpertise: expertise.slice(0, 3).map((e) => ({
991
+ symbol: e.symbol,
992
+ confidence: parseFloat(e.confidence.toFixed(2))
993
+ })),
994
+ threshold: p.attention?.threshold
995
+ });
996
+ } catch {
997
+ }
998
+ }
999
+ return profiles;
1000
+ }
1001
+ function loadTeamThreads() {
1002
+ const mailDir = path3.join(os.homedir(), ".paradigm", "mail", "agents");
1003
+ if (!fs3.existsSync(mailDir)) return [];
1004
+ const allMessages = [];
1005
+ try {
1006
+ for (const agentDir of fs3.readdirSync(mailDir, { withFileTypes: true })) {
1007
+ if (!agentDir.isDirectory()) continue;
1008
+ const agentPath = path3.join(mailDir, agentDir.name);
1009
+ for (const file of ["inbox.jsonl", "outbox.jsonl"]) {
1010
+ const filePath = path3.join(agentPath, file);
1011
+ const notes = readJsonl(filePath);
1012
+ for (const note of notes) {
1013
+ if (!note.threadRoot?.startsWith("thr-orch-")) continue;
1014
+ if (allMessages.some((m) => m.id === note.id)) continue;
1015
+ allMessages.push({
1016
+ id: note.id,
1017
+ threadRoot: note.threadRoot,
1018
+ timestamp: note.timestamp,
1019
+ sender: {
1020
+ name: note.sender?.name || "unknown",
1021
+ role: note.sender?.role,
1022
+ project: note.sender?.project
1023
+ },
1024
+ intent: note.intent || "context",
1025
+ text: note.content?.text || "",
1026
+ symbols: note.symbols || [],
1027
+ diff: note.content?.diff,
1028
+ decision: note.content?.decision
1029
+ });
1030
+ }
1031
+ }
1032
+ }
1033
+ } catch {
1034
+ }
1035
+ const threadMap = /* @__PURE__ */ new Map();
1036
+ for (const msg of allMessages) {
1037
+ const threadId = msg.threadRoot;
1038
+ if (!threadMap.has(threadId)) threadMap.set(threadId, []);
1039
+ threadMap.get(threadId).push(msg);
1040
+ }
1041
+ const threads = [];
1042
+ for (const [threadId, messages] of threadMap) {
1043
+ messages.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
1044
+ const stripped = threadId.replace("thr-orch-", "");
1045
+ const parts = stripped.split("-");
1046
+ const displayName = parts[0] ? `Team ${parts[0]}` : threadId;
1047
+ threads.push({
1048
+ id: threadId,
1049
+ displayName,
1050
+ messages,
1051
+ lastActivity: messages[messages.length - 1]?.timestamp || ""
1052
+ });
1053
+ }
1054
+ threads.sort((a, b) => b.lastActivity.localeCompare(a.lastActivity));
1055
+ return threads;
1056
+ }
1057
+ function createTeamRouter(projectDir) {
1058
+ const router = Router4();
1059
+ router.get("/roster", (_req, res) => {
1060
+ try {
1061
+ const agents = loadAgentProfiles();
1062
+ const active = agents.filter((a) => !a.benched);
1063
+ const benched = agents.filter((a) => a.benched);
1064
+ res.json({ active, benched, total: agents.length });
1065
+ } catch (err) {
1066
+ res.status(500).json({ error: "Failed to load roster", detail: String(err) });
1067
+ }
1068
+ });
1069
+ router.get("/threads", (_req, res) => {
1070
+ try {
1071
+ const threads = loadTeamThreads();
1072
+ res.json({ threads, count: threads.length });
1073
+ } catch (err) {
1074
+ res.status(500).json({ error: "Failed to load threads", detail: String(err) });
1075
+ }
1076
+ });
1077
+ router.patch("/agents/:id/bench", (req, res) => {
1078
+ try {
1079
+ const { id } = req.params;
1080
+ const { benched } = req.body;
1081
+ const globalDir = path3.join(os.homedir(), ".paradigm", "agents");
1082
+ const filePath = path3.join(globalDir, `${id}.agent`);
1083
+ if (!fs3.existsSync(filePath)) {
1084
+ res.status(404).json({ error: `Agent "${id}" not found` });
1085
+ return;
1086
+ }
1087
+ const content = fs3.readFileSync(filePath, "utf-8");
1088
+ const profile = yaml3.load(content);
1089
+ profile.benched = benched;
1090
+ profile.updated = (/* @__PURE__ */ new Date()).toISOString();
1091
+ fs3.writeFileSync(filePath, yaml3.dump(profile, { lineWidth: 120, noRefs: true, sortKeys: false }), "utf-8");
1092
+ res.json({ id, benched, updated: profile.updated });
1093
+ } catch (err) {
1094
+ res.status(500).json({ error: "Failed to update agent", detail: String(err) });
1095
+ }
1096
+ });
1097
+ return router;
1098
+ }
1099
+
953
1100
  // src/platform-server/index.ts
954
1101
  var __filename = fileURLToPath(import.meta.url);
955
- var __dirname = path3.dirname(__filename);
1102
+ var __dirname = path4.dirname(__filename);
956
1103
  var log = {
957
1104
  component(name) {
958
1105
  const symbol = chalk.magenta(`#${name}`);
@@ -977,7 +1124,7 @@ var log = {
977
1124
  }
978
1125
  };
979
1126
  function resolveSections(options) {
980
- const always = ["overview", "lore", "graph", "git", "ambient"];
1127
+ const always = ["overview", "lore", "graph", "git", "ambient", "team"];
981
1128
  const requested = options.sections ?? [...always, "sentinel", "university", "symphony", "docs"];
982
1129
  const enabled = /* @__PURE__ */ new Set();
983
1130
  for (const section of requested) {
@@ -986,15 +1133,15 @@ function resolveSections(options) {
986
1133
  continue;
987
1134
  }
988
1135
  if (section === "sentinel") {
989
- const sentinelRoutesPath = path3.join(options.projectDir, ".paradigm");
990
- if (fs3.existsSync(sentinelRoutesPath)) {
1136
+ const sentinelRoutesPath = path4.join(options.projectDir, ".paradigm");
1137
+ if (fs4.existsSync(sentinelRoutesPath)) {
991
1138
  enabled.add(section);
992
1139
  }
993
1140
  } else if (section === "university") {
994
1141
  enabled.add(section);
995
1142
  } else if (section === "symphony") {
996
- const mailDir = path3.join(process.env.HOME || "~", ".paradigm", "score");
997
- if (fs3.existsSync(mailDir)) {
1143
+ const mailDir = path4.join(process.env.HOME || "~", ".paradigm", "score");
1144
+ if (fs4.existsSync(mailDir)) {
998
1145
  enabled.add(section);
999
1146
  }
1000
1147
  } else {
@@ -1038,15 +1185,15 @@ function createPlatformApp(options) {
1038
1185
  res.json({ status: "ok", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1039
1186
  });
1040
1187
  app.set("agentRouterSlot", true);
1041
- let uiDistPath = path3.join(__dirname, "..", "platform-ui", "dist");
1042
- if (!fs3.existsSync(uiDistPath)) {
1043
- uiDistPath = path3.join(__dirname, "..", "..", "platform-ui", "dist");
1188
+ let uiDistPath = path4.join(__dirname, "..", "platform-ui", "dist");
1189
+ if (!fs4.existsSync(uiDistPath)) {
1190
+ uiDistPath = path4.join(__dirname, "..", "..", "platform-ui", "dist");
1044
1191
  }
1045
- if (fs3.existsSync(uiDistPath)) {
1192
+ if (fs4.existsSync(uiDistPath)) {
1046
1193
  app.use(express.static(uiDistPath));
1047
1194
  app.get("{*path}", (req, res, next) => {
1048
1195
  if (!req.path.startsWith("/api")) {
1049
- res.sendFile(path3.join(uiDistPath, "index.html"));
1196
+ res.sendFile(path4.join(uiDistPath, "index.html"));
1050
1197
  } else {
1051
1198
  next();
1052
1199
  }
@@ -1080,6 +1227,7 @@ async function startPlatformServer(options) {
1080
1227
  const wsContext = attachWebSocket(httpServer);
1081
1228
  app.use("/api/platform/agent-command", createAgentRouter(wsContext));
1082
1229
  app.use("/api/ambient", createAmbientRouter(options.projectDir, wsContext));
1230
+ app.use("/api/team", createTeamRouter(options.projectDir));
1083
1231
  if (sections.has("sentinel")) {
1084
1232
  try {
1085
1233
  const { createSentinelBridge } = await import("./sentinel-bridge-MDUXTQRL.js");
@@ -3,9 +3,9 @@ import {
3
3
  getReindexToolsList,
4
4
  handleReindexTool,
5
5
  rebuildStaticFiles
6
- } from "./chunk-S6MZ2IEX.js";
7
- import "./chunk-5VKJBNJL.js";
6
+ } from "./chunk-7HRBT23N.js";
8
7
  import "./chunk-L27I3CPZ.js";
8
+ import "./chunk-5VKJBNJL.js";
9
9
  import "./chunk-7N7GSU6K.js";
10
10
  export {
11
11
  getReindexToolsList,
@@ -10,7 +10,7 @@ async function serveCommand(options) {
10
10
  const sections = options.sections ? options.sections.split(",").map((s) => s.trim()) : void 0;
11
11
  console.log(chalk.cyan("\n Starting Paradigm Platform...\n"));
12
12
  try {
13
- const { startPlatformServer } = await import("./platform-server-PMD57BEG.js");
13
+ const { startPlatformServer } = await import("./platform-server-2D6S6YTK.js");
14
14
  await startPlatformServer({ port, projectDir, open: shouldOpen, sections });
15
15
  console.log(chalk.green(` Platform running at ${chalk.bold(`http://localhost:${port}`)}`));
16
16
  console.log(chalk.gray(" Press Ctrl+C to stop\n"));