pi-herdsman 0.19.0 → 0.19.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/index.js CHANGED
@@ -31,7 +31,7 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
31
31
  // package.json
32
32
  var package_default = {
33
33
  name: "pi-herdsman",
34
- version: "0.19.0",
34
+ version: "0.19.1",
35
35
  type: "module",
36
36
  description: "Asynchronous Pi subagents and agent fleet orchestration for parallel coding agents with nested delegation, background work, and supervision in herdr.",
37
37
  license: "Apache-2.0",
@@ -5140,10 +5140,9 @@ function projectSupervision(options) {
5140
5140
  const provenance = options.workspaceProvenance?.get(agent.workspaceId) ?? (agent.workspaceCwd ? { workspaceCwd: agent.workspaceCwd } : void 0);
5141
5141
  const workspaceLabel = provenance?.repoName && provenance.branch ? `${provenance.repoName}/${provenance.branch}` : provenance?.workspaceLabel || (provenance?.workspaceCwd ? basename3(provenance.workspaceCwd) : void 0) || agent.workspaceId;
5142
5142
  const tokensName = typeof agent.tokens?.pi_herdsman_name === "string" ? agent.tokens.pi_herdsman_name.trim() : "";
5143
- const sessionName = typeof agent.sessionName === "string" ? agent.sessionName.trim() : "";
5144
5143
  const herdrName = agent.herdrName?.trim();
5145
5144
  const tabLabel = agent.tabLabel?.trim();
5146
- const name = tokensName || sessionName || (herdrName && herdrName !== agent.sessionId && !/_[0-9a-f]{16}$/iu.test(herdrName) ? herdrName : void 0) || tabLabel || `lead-${agent.sessionId.slice(0, 8)}`;
5145
+ const name = tokensName || (herdrName && herdrName !== agent.sessionId && !/_[0-9a-f]{16}$/iu.test(herdrName) ? herdrName : void 0) || tabLabel || `lead-${agent.sessionId.slice(0, 8)}`;
5147
5146
  const herdRunStartedAt = metadataInteger(
5148
5147
  agent.tokens,
5149
5148
  "pi_herdsman_herd_run_started_at"
@@ -8815,30 +8814,6 @@ function supervisedSessionFile(agent, sessionId) {
8815
8814
  return void 0;
8816
8815
  }
8817
8816
  }
8818
- function persistedSessionName(agent) {
8819
- const session = sessionIdentity(agent?.agent_session);
8820
- if (session?.kind !== "path") return void 0;
8821
- try {
8822
- const manager = SessionManager.open(session.value);
8823
- const name = manager.getSessionName();
8824
- return typeof name === "string" && name.trim() ? name.trim() : void 0;
8825
- } catch {
8826
- return void 0;
8827
- }
8828
- }
8829
- function isLeadSessionBoundary(agent, pane, ownerSessionId) {
8830
- if (!isPiAgent(agent) || pane?.agent !== "pi") return false;
8831
- const session = sessionIdentity(agent?.agent_session);
8832
- if (session?.kind !== "path") return false;
8833
- try {
8834
- if (SessionManager.open(session.value).getSessionId() !== ownerSessionId)
8835
- return false;
8836
- const manager = SessionManager.open(session.value);
8837
- return !sessionAgentIdentity(manager.getEntries(), manager.getSessionId());
8838
- } catch {
8839
- return false;
8840
- }
8841
- }
8842
8817
  function herdrAliasMatchesIfReported(agent, expectedAlias) {
8843
8818
  const aliases = [agent?.name].filter(
8844
8819
  (value2) => typeof value2 === "string" && value2.length > 0
@@ -9499,7 +9474,7 @@ function assertUniqueDurableIdentities(states) {
9499
9474
  seen.add(key);
9500
9475
  }
9501
9476
  }
9502
- async function managedAgentSnapshots(pi, ctx, signal, proveLead = false, allWorkspaces = false, suppliedInventory) {
9477
+ async function managedAgentSnapshots(pi, ctx, signal, proveLead = false, allWorkspaces = false, suppliedInventory, allowTranscriptDefinitionFallback = true) {
9503
9478
  const inventory = suppliedInventory ?? await herdrSessionSnapshot(pi, ctx, signal);
9504
9479
  const currentWorkspaceId = process.env.HERDR_WORKSPACE_ID ?? ctx.cwd;
9505
9480
  const allMailboxes = listAgentStates();
@@ -9514,7 +9489,8 @@ async function managedAgentSnapshots(pi, ctx, signal, proveLead = false, allWork
9514
9489
  agentDefinition = agentDefinitionForRuntime(
9515
9490
  agent,
9516
9491
  state,
9517
- runtimes.get(state.agentLabel)
9492
+ runtimes.get(state.agentLabel),
9493
+ allowTranscriptDefinitionFallback
9518
9494
  );
9519
9495
  } catch {
9520
9496
  agentDefinition = "unknown";
@@ -9604,8 +9580,17 @@ async function managedAgentSnapshots(pi, ctx, signal, proveLead = false, allWork
9604
9580
  const ownerPanes = panes.filter(
9605
9581
  (pane) => pane?.workspace_id === currentWorkspaceId && pane?.pane_id === ownerAgent.pane_id
9606
9582
  );
9607
- if (ownerPanes.length === 1 && isLeadSessionBoundary(ownerAgent, ownerPanes[0], ownerSessionId))
9608
- leadSessionIds.push(ownerSessionId);
9583
+ if (ownerPanes.length !== 1 || !isPiAgent(ownerAgent) || ownerPanes[0]?.agent !== "pi")
9584
+ continue;
9585
+ try {
9586
+ const state = readLeadCoordinationState(
9587
+ supervisionRuntime(),
9588
+ ownerSessionId
9589
+ );
9590
+ if (state && (state.role ?? "lead") === "lead")
9591
+ leadSessionIds.push(ownerSessionId);
9592
+ } catch {
9593
+ }
9609
9594
  }
9610
9595
  }
9611
9596
  } catch {
@@ -9749,8 +9734,16 @@ function listedAgentRecord(view, snapshot, ownerSessionId, scope, unresolvedMail
9749
9734
  ...parentLabel ? { parent_label: parentLabel } : {}
9750
9735
  };
9751
9736
  }
9752
- async function agentSnapshotView(pi, ctx, scope, signal, proveLead = false) {
9753
- const snapshot = await managedAgentSnapshots(pi, ctx, signal, proveLead);
9737
+ async function agentSnapshotView(pi, ctx, scope, signal, proveLead = false, allowTranscriptDefinitionFallback = true) {
9738
+ const snapshot = await managedAgentSnapshots(
9739
+ pi,
9740
+ ctx,
9741
+ signal,
9742
+ proveLead,
9743
+ false,
9744
+ void 0,
9745
+ allowTranscriptDefinitionFallback
9746
+ );
9754
9747
  return {
9755
9748
  ...snapshot,
9756
9749
  visible: visibleAgentSnapshots(
@@ -10577,9 +10570,11 @@ function invalidateCachedRuntime(label) {
10577
10570
  function runtimeIdentityMatches(runtime, state, agent) {
10578
10571
  return runtime.runId === state.runId && runtime.ownerSessionId === state.ownerSessionId && runtime.workspaceId === agent.workspace_id && runtime.paneId === agent.pane_id && runtime.piSessionId === state.piSessionId && sameSessionPath(runtime.piSessionFile, state.piSessionFile) && sameCwd(runtime.cwd, agent.cwd);
10579
10572
  }
10580
- function agentDefinitionForRuntime(agent, state, cached) {
10573
+ function agentDefinitionForRuntime(agent, state, cached, allowTranscriptFallback = true) {
10581
10574
  if (state.agentDefinition !== void 0) return stateAgentDefinition(state);
10582
- return cached && runtimeIdentityMatches(cached, state, agent) ? cached.agentDefinition : stateAgentDefinition(state);
10575
+ if (cached && runtimeIdentityMatches(cached, state, agent))
10576
+ return cached.agentDefinition;
10577
+ return allowTranscriptFallback ? stateAgentDefinition(state) : "unknown";
10583
10578
  }
10584
10579
  function guardMailboxOccupancy(mailbox, label, operation, explicit) {
10585
10580
  const retainedRequest = (current) => {
@@ -10722,9 +10717,9 @@ async function resolveRuntime(pi, ctx, agentLabel, operation, signal) {
10722
10717
  await validateIntegration(pi, runtime, ctx, { signal });
10723
10718
  return { runtime, agent, controlState: agent.state };
10724
10719
  }
10725
- function runtimeForListedAgent(agent, state, cached) {
10720
+ function runtimeForListedAgent(agent, state, cached, allowTranscriptFallback = true) {
10726
10721
  const useCached = cached !== void 0 && runtimeIdentityMatches(cached, state, agent);
10727
- const agentDefinition = state.agentDefinition !== void 0 ? stateAgentDefinition(state) : useCached ? cached.agentDefinition : stateAgentDefinition(state);
10722
+ const agentDefinition = state.agentDefinition !== void 0 ? stateAgentDefinition(state) : useCached ? cached.agentDefinition : allowTranscriptFallback ? stateAgentDefinition(state) : "unknown";
10728
10723
  const runtime = (useCached ? cached : void 0) ?? {
10729
10724
  label: agent.label,
10730
10725
  herdrAgent: herdrAgentAlias(agent.workspace_id, agent.label, state.runId),
@@ -12919,6 +12914,7 @@ ${globalInstructions}
12919
12914
  const publishLeadRole = (ctx, mode, generation) => {
12920
12915
  const paneId = process.env.HERDR_PANE_ID;
12921
12916
  if (!paneId) return Promise.resolve();
12917
+ const leadName = mode === "inactive" && activeRole() === "lead" ? pi.getSessionName()?.trim() : void 0;
12922
12918
  const args = [
12923
12919
  "pane",
12924
12920
  "report-metadata",
@@ -12926,9 +12922,15 @@ ${globalInstructions}
12926
12922
  "--source",
12927
12923
  "pi-herdsman:lead",
12928
12924
  "--title",
12929
- mode === "active" ? "chief" : activeRole() === "manager" ? "Pi Herdsman manager" : "Pi Herdsman lead",
12925
+ mode === "active" ? "chief" : activeRole() === "manager" ? "Pi Herdsman manager" : leadName || "Pi Herdsman lead",
12930
12926
  ...mode === "active" ? ["--token", "pi_herdsman_role=chief"] : mode === "inactive" ? ["--token", `pi_herdsman_role=${activeRole()}`] : ["--clear-token", "pi_herdsman_role"]
12931
12927
  ];
12928
+ if (mode === "inactive" && activeRole() === "lead") {
12929
+ args.push(
12930
+ leadName ? "--token" : "--clear-token",
12931
+ leadName ? `pi_herdsman_name=${leadName}` : "pi_herdsman_name"
12932
+ );
12933
+ }
12932
12934
  if (mode !== "inactive" || activeRole() !== "lead")
12933
12935
  args.push(
12934
12936
  "--clear-token",
@@ -14629,11 +14631,17 @@ ${summary}` : "Herd run settled.",
14629
14631
  let healthTimer;
14630
14632
  let healthGeneration = 0;
14631
14633
  let supervisionTimer;
14634
+ let supervisionRefreshInFlight;
14635
+ let pendingSupervisionRefresh;
14632
14636
  let supervisionOverviewGeneration = 0;
14633
14637
  let activeSupervisionRender;
14634
14638
  const loadSupervisionSnapshot = async (ctx, suppliedInventory, suppliedAgents, includeAll = false) => {
14635
14639
  if (activeRole() === "chief" && !includeAll) {
14636
- const reports = await directReports(ctx);
14640
+ const reports = await directReports(
14641
+ ctx,
14642
+ suppliedInventory,
14643
+ suppliedAgents
14644
+ );
14637
14645
  const managers = reports.filter(
14638
14646
  (report) => report.role === "manager"
14639
14647
  );
@@ -14711,7 +14719,6 @@ ${summary}` : "Herd run settled.",
14711
14719
  const agents = live.flatMap((agent) => {
14712
14720
  const sessionId = herdrSessionId(agent);
14713
14721
  if (!isPiAgent(agent) || !sessionId) return [];
14714
- const sessionName = persistedSessionName(agent);
14715
14722
  const candidateSessionFile = supervisedSessionFile(agent, sessionId);
14716
14723
  const piSessionFile = candidateSessionFile && persistedTranscriptReady({
14717
14724
  piSessionId: sessionId,
@@ -14726,7 +14733,6 @@ ${summary}` : "Herd run settled.",
14726
14733
  tabId: agent.tab_id,
14727
14734
  workspaceCwd: agent.cwd,
14728
14735
  herdrName: agent.name,
14729
- ...sessionName ? { sessionName } : {},
14730
14736
  ...piSessionFile ? { piSessionFile } : {},
14731
14737
  tokens: agent.tokens,
14732
14738
  runtimeState: normalizeHerdrLifecycleState(agent)
@@ -14805,8 +14811,20 @@ ${summary}` : "Herd run settled.",
14805
14811
  if (!chiefAuthority)
14806
14812
  throw new Error("Staff is available only to an active supervisor");
14807
14813
  const managers = [];
14808
- const allLeads = (await loadSupervisionSnapshot(ctx, void 0, void 0, true)).leads;
14809
- const managedAgents = (await managedAgentSnapshots(pi, ctx, ctx.signal, false, true)).agents;
14814
+ const allLeads = (await loadSupervisionSnapshot(
14815
+ ctx,
14816
+ suppliedInventory,
14817
+ suppliedAgents,
14818
+ true
14819
+ )).leads;
14820
+ const managedAgents = (suppliedAgents ?? await managedAgentSnapshots(
14821
+ pi,
14822
+ ctx,
14823
+ ctx.signal,
14824
+ false,
14825
+ true,
14826
+ suppliedInventory
14827
+ )).agents;
14810
14828
  const managerLeadSessions = /* @__PURE__ */ new Set();
14811
14829
  const descriptors = listManagerDescriptors(supervisionRuntime());
14812
14830
  for (const descriptor of descriptors) {
@@ -15485,12 +15503,11 @@ ${summary}` : "Herd run settled.",
15485
15503
  throw error2;
15486
15504
  }
15487
15505
  };
15488
- const refreshSupervision = async (ctx, isCurrent) => {
15506
+ const refreshSupervisionOnce = async (ctx) => {
15489
15507
  if (chiefMode !== "active" && !(activeRole() === "manager" && !roleSuspended))
15490
- return false;
15508
+ return;
15491
15509
  const generation = currentSupervisionGeneration(ctx);
15492
- const refreshIsCurrent = () => currentSupervisionGeneration(ctx) === generation && (isCurrent?.() ?? true);
15493
- let refreshed = false;
15510
+ const refreshIsCurrent = () => currentSupervisionGeneration(ctx) === generation;
15494
15511
  try {
15495
15512
  const inventory = await herdrSessionSnapshot(pi, ctx, ctx.signal);
15496
15513
  const agents = await managedAgentSnapshots(
@@ -15499,15 +15516,15 @@ ${summary}` : "Herd run settled.",
15499
15516
  ctx.signal,
15500
15517
  false,
15501
15518
  true,
15502
- inventory
15519
+ inventory,
15520
+ false
15503
15521
  );
15504
15522
  const snapshot = await loadSupervisionSnapshot(ctx, inventory, agents);
15505
- if (!refreshIsCurrent()) return false;
15523
+ if (!refreshIsCurrent()) return;
15506
15524
  supervisionSnapshot = snapshot;
15507
15525
  supervisionSnapshotKnown = true;
15508
15526
  supervisionSnapshotGeneration = generation;
15509
15527
  supervisionStale = false;
15510
- refreshed = true;
15511
15528
  activeSupervisionRender?.();
15512
15529
  } catch {
15513
15530
  if (refreshIsCurrent())
@@ -15519,7 +15536,20 @@ ${summary}` : "Herd run settled.",
15519
15536
  } catch {
15520
15537
  }
15521
15538
  }
15522
- return refreshed;
15539
+ };
15540
+ const refreshSupervision = (ctx) => {
15541
+ pendingSupervisionRefresh = ctx;
15542
+ if (supervisionRefreshInFlight) return supervisionRefreshInFlight;
15543
+ supervisionRefreshInFlight = (async () => {
15544
+ while (pendingSupervisionRefresh) {
15545
+ const next = pendingSupervisionRefresh;
15546
+ pendingSupervisionRefresh = void 0;
15547
+ await refreshSupervisionOnce(next);
15548
+ }
15549
+ })().finally(() => {
15550
+ supervisionRefreshInFlight = void 0;
15551
+ });
15552
+ return supervisionRefreshInFlight;
15523
15553
  };
15524
15554
  const latestCustomMessageText = (ctx, customType) => {
15525
15555
  const entry = [
@@ -15541,7 +15571,7 @@ ${summary}` : "Herd run settled.",
15541
15571
  const generation = currentSupervisionGeneration(ctx);
15542
15572
  const isCurrent = () => (isCurrentChief(ctx) || activeRole() === "manager") && currentSupervisionGeneration(ctx) === generation;
15543
15573
  try {
15544
- await refreshSupervision(ctx, isCurrent);
15574
+ await refreshSupervision(ctx);
15545
15575
  if (!isCurrent()) return;
15546
15576
  const status = supervisionSnapshotStatus(ctx);
15547
15577
  const content = formatSupervisionContext(
@@ -15647,6 +15677,7 @@ This is the session-start definition snapshot. Use agent_list for live Agent sta
15647
15677
  void refreshSupervision(ctx);
15648
15678
  };
15649
15679
  clearSupervisionUI = (removeWidget = true) => {
15680
+ pendingSupervisionRefresh = void 0;
15650
15681
  activeSupervisionRender = void 0;
15651
15682
  requestSupervisionWidgetRender = void 0;
15652
15683
  if (supervisionTimer) clearInterval(supervisionTimer);
@@ -16002,13 +16033,14 @@ This is the session-start definition snapshot. Use agent_list for live Agent sta
16002
16033
  breadcrumb: initialStatusBreadcrumb,
16003
16034
  ...ownToolsSnapshot2()
16004
16035
  };
16005
- const loadStatusSnapshot = async (ctx, signal) => {
16036
+ const loadStatusSnapshot = async (ctx, signal, allowTranscriptDefinitionFallback = true) => {
16006
16037
  const view = await agentSnapshotView(
16007
16038
  pi,
16008
16039
  ctx,
16009
16040
  controllerScope,
16010
16041
  signal,
16011
- true
16042
+ true,
16043
+ allowTranscriptDefinitionFallback
16012
16044
  );
16013
16045
  const ownerSessionId = ctx.sessionManager.getSessionId();
16014
16046
  const unresolvedMailboxState = controllerScope?.kind === "lead" && listAgentStateIssues().length > 0;
@@ -16097,7 +16129,8 @@ This is the session-start definition snapshot. Use agent_list for live Agent sta
16097
16129
  try {
16098
16130
  lastValidStatus = await loadStatusSnapshot(
16099
16131
  ctx,
16100
- controllerAbortController?.signal
16132
+ controllerAbortController?.signal,
16133
+ false
16101
16134
  );
16102
16135
  if (generation !== statusGeneration || ctx !== statusContext) return;
16103
16136
  reconcilePendingStarts(lastValidStatus);
@@ -17586,7 +17619,7 @@ Active work or pending results may be discarded.`
17586
17619
  controllerScope,
17587
17620
  unresolvedMailboxState
17588
17621
  ).available_tools ?? []).map((tool) => tool.slice("agent_".length));
17589
- const publishAgentLoss = (ctx, state2, availableActions, nextReminderMs, signal) => {
17622
+ const publishAgentLoss = (ctx, state2, snapshotAgentDefinition, availableActions, nextReminderMs, signal) => {
17590
17623
  const mailbox = agentMailboxPath(state2.workspaceId, state2.agentLabel);
17591
17624
  const current = readAgentState(mailbox);
17592
17625
  if (!current || !sameManagedAgentIdentity(current, state2) || current.ownerSessionId !== ctx.sessionManager.getSessionId())
@@ -17648,7 +17681,7 @@ Active work or pending results may be discarded.`
17648
17681
  paneId: current.paneId,
17649
17682
  piSessionId: current.piSessionId,
17650
17683
  piSessionFile: current.piSessionFile,
17651
- agentDefinition: stateAgentDefinition(current),
17684
+ agentDefinition: current.agentDefinition ?? snapshotAgentDefinition ?? "unknown",
17652
17685
  requestId: latestRequestId,
17653
17686
  availableActions,
17654
17687
  nextReminderMs
@@ -17665,7 +17698,15 @@ Active work or pending results may be discarded.`
17665
17698
  if (signal.aborted || generation !== healthGeneration || !ctx.isIdle())
17666
17699
  return;
17667
17700
  const ownerSessionId = ctx.sessionManager.getSessionId();
17668
- const snapshot = await managedAgentSnapshots(pi, ctx, signal);
17701
+ const snapshot = await managedAgentSnapshots(
17702
+ pi,
17703
+ ctx,
17704
+ signal,
17705
+ false,
17706
+ false,
17707
+ void 0,
17708
+ false
17709
+ );
17669
17710
  if (signal.aborted || generation !== healthGeneration || !ctx.isIdle())
17670
17711
  return;
17671
17712
  const view = {
@@ -17746,7 +17787,14 @@ Active work or pending results may be discarded.`
17746
17787
  const episode2 = "lost";
17747
17788
  if (published || !attentionDue(state2.runId, episode2, now)) continue;
17748
17789
  const intervalMs2 = nextAttentionInterval(state2.runId, episode2);
17749
- if (publishAgentLoss(ctx, state2, availableActions, intervalMs2, signal)) {
17790
+ if (publishAgentLoss(
17791
+ ctx,
17792
+ state2,
17793
+ agent.agentDefinition,
17794
+ availableActions,
17795
+ intervalMs2,
17796
+ signal
17797
+ )) {
17750
17798
  recordAttention(state2.runId, episode2, intervalMs2);
17751
17799
  published = true;
17752
17800
  }
@@ -17994,7 +18042,8 @@ Active work or pending results may be discarded.`
17994
18042
  runtimeForListedAgent(
17995
18043
  agent.listed,
17996
18044
  current,
17997
- runtimes.get(current.agentLabel)
18045
+ runtimes.get(current.agentLabel),
18046
+ false
17998
18047
  ),
17999
18048
  diagnosticSignal
18000
18049
  );
@@ -18005,7 +18054,15 @@ Active work or pending results may be discarded.`
18005
18054
  if (attemptedDiagnostic && !diagnostic) {
18006
18055
  let refreshed;
18007
18056
  try {
18008
- refreshed = await managedAgentSnapshots(pi, ctx, signal);
18057
+ refreshed = await managedAgentSnapshots(
18058
+ pi,
18059
+ ctx,
18060
+ signal,
18061
+ false,
18062
+ false,
18063
+ void 0,
18064
+ false
18065
+ );
18009
18066
  } catch {
18010
18067
  continue;
18011
18068
  }
@@ -18896,7 +18953,10 @@ Active work or pending results may be discarded.`
18896
18953
  pi,
18897
18954
  ctx,
18898
18955
  metadataAbortController?.signal,
18899
- true
18956
+ true,
18957
+ false,
18958
+ void 0,
18959
+ false
18900
18960
  );
18901
18961
  if (generation !== leafStatusGeneration || ctx !== leafStatusContext)
18902
18962
  return;