@sjawhar/pi-legion-envoy 6.0.2 → 6.0.4

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/envoy.js CHANGED
@@ -35463,7 +35463,7 @@ function sourceSession(sessionID) {
35463
35463
  }
35464
35464
 
35465
35465
  // extensions/envoy.ts
35466
- import { logger } from "@oh-my-pi/pi-utils";
35466
+ import { logger as logger2 } from "@oh-my-pi/pi-utils";
35467
35467
  var import_nats2 = __toESM(require_mod4(), 1);
35468
35468
 
35469
35469
  // src/agent-stream.ts
@@ -35941,33 +35941,56 @@ function sideTurn(pi, context) {
35941
35941
  import fs from "fs";
35942
35942
  import path3 from "path";
35943
35943
  import * as host from "@oh-my-pi/pi-coding-agent";
35944
+ import { logger } from "@oh-my-pi/pi-utils";
35944
35945
  var LEGION_BOOTSTRAPPED_SESSION = Symbol.for("legion.pi-envoy.bootstrapped-session");
35945
35946
  var bootstrappedSessionStore = globalThis;
35946
35947
  function recordBootstrappedSession(sessionFile) {
35947
35948
  bootstrappedSessionStore[LEGION_BOOTSTRAPPED_SESSION] = sessionFile;
35948
35949
  }
35949
35950
  async function isSubagentSession(context) {
35950
- await context.sessionManager.ensureOnDisk();
35951
+ const registered = registeredSubagent(context);
35952
+ if (registered !== undefined)
35953
+ return { subagent: registered, settled: true };
35954
+ try {
35955
+ await context.sessionManager.ensureOnDisk();
35956
+ } catch (error48) {
35957
+ const subagent = transcriptSaysSubagent(context);
35958
+ logger.warn("subagent check: publishing the transcript failed; answered from the transcript on disk, and the next call asks again", { sessionFile: context.sessionManager.getSessionFile(), subagent, error: messageFor(error48) });
35959
+ return { subagent, settled: false };
35960
+ }
35961
+ return { subagent: transcriptSaysSubagent(context), settled: true };
35962
+ }
35963
+ function transcriptSaysSubagent(context) {
35951
35964
  const sessionFile = context.sessionManager.getSessionFile();
35952
- if (sessionFile !== undefined && fs.existsSync(sessionFile)) {
35953
- return fs.existsSync(`${path3.dirname(sessionFile)}.jsonl`);
35965
+ if (sessionFile !== undefined) {
35966
+ if (fs.existsSync(`${path3.dirname(sessionFile)}.jsonl`))
35967
+ return true;
35968
+ if (fs.existsSync(sessionFile))
35969
+ return false;
35954
35970
  }
35955
35971
  const bootstrapped = bootstrappedSessionStore[LEGION_BOOTSTRAPPED_SESSION];
35956
35972
  return bootstrapped !== undefined && bootstrapped !== sessionFile;
35957
35973
  }
35958
- function isRegisteredSubagent(context) {
35974
+ function registeredSubagent(context) {
35959
35975
  const registry2 = host.AgentRegistry?.global();
35960
35976
  if (registry2 === undefined)
35961
- return false;
35977
+ return;
35962
35978
  const sessionID = context.sessionManager.getSessionId();
35963
35979
  const sessionFile = context.sessionManager.getSessionFile();
35964
- return registry2.list().some((ref) => ref.kind !== "main" && (ref.session === null ? sessionFile !== undefined && ref.sessionFile === sessionFile : ref.session.sessionManager.getSessionId() === sessionID));
35980
+ const own = registry2.list().filter((ref) => ref.session === null ? sessionFile !== undefined && ref.sessionFile === sessionFile : ref.session.sessionManager.getSessionId() === sessionID);
35981
+ if (own.length === 0)
35982
+ return;
35983
+ return own.some((ref) => ref.kind !== "main");
35965
35984
  }
35966
35985
  function subagentSessionCheck() {
35967
- let subagentSession;
35968
- return (context) => {
35969
- subagentSession ??= isSubagentSession(context);
35970
- return subagentSession;
35986
+ let settled;
35987
+ return async (context) => {
35988
+ if (settled !== undefined)
35989
+ return settled;
35990
+ const answer = await isSubagentSession(context);
35991
+ if (answer.settled)
35992
+ settled = answer.subagent;
35993
+ return answer.subagent;
35971
35994
  };
35972
35995
  }
35973
35996
 
@@ -36127,7 +36150,7 @@ function resolveSkillsDirectory() {
36127
36150
  var SKILLS_DIRECTORY = resolveSkillsDirectory();
36128
36151
  var DISPATCH_FIRST_CONTEXT = readDispatchFirstContext(dispatchFirstSkillFile(SKILLS_DIRECTORY));
36129
36152
  function envoyExtension(pi) {
36130
- logger.debug("extension instance loaded", { extension: import.meta.url });
36153
+ logger2.debug("extension instance loaded", { extension: import.meta.url });
36131
36154
  const defaults = envoyDefaultsFromEnvironment(process.env);
36132
36155
  const dispatchConfig = resolveDispatchConfig(process.env, { cwd: process.cwd() });
36133
36156
  const currentDispatchConfig = () => {
@@ -36190,7 +36213,7 @@ function envoyExtension(pi) {
36190
36213
  if (selfCheckWarningSessionIDs.has(failedSessionID))
36191
36214
  return;
36192
36215
  selfCheckWarningSessionIDs.add(failedSessionID);
36193
- logger.warn("envoy: run-end waiting self-check failed; no reminder was sent", {
36216
+ logger2.warn("envoy: run-end waiting self-check failed; no reminder was sent", {
36194
36217
  sessionID: failedSessionID,
36195
36218
  error: messageFor(error48)
36196
36219
  });
@@ -36258,7 +36281,7 @@ function envoyExtension(pi) {
36258
36281
  const { delivery } = rendered;
36259
36282
  const key = handledAttemptKey(delivery.id, delivery.attempt);
36260
36283
  if (handledDispatchAttempts.has(key)) {
36261
- logger.warn("envoy: a frame names a Dispatch attempt this session already delivered; it arrives as a card", { attempt: delivery.attempt, messageID: delivery.id });
36284
+ logger2.warn("envoy: a frame names a Dispatch attempt this session already delivered; it arrives as a card", { attempt: delivery.attempt, messageID: delivery.id });
36262
36285
  return;
36263
36286
  }
36264
36287
  handledDispatchAttempts.add(key);
@@ -36272,11 +36295,11 @@ function envoyExtension(pi) {
36272
36295
  });
36273
36296
  const turn = turnFromAccept(accepted);
36274
36297
  if (turn === undefined) {
36275
- logger.warn("envoy: Dispatch accepted a direct message without the stored body and mode to inject; it arrives as a card", { attempt: delivery.attempt, messageID: delivery.id });
36298
+ logger2.warn("envoy: Dispatch accepted a direct message without the stored body and mode to inject; it arrives as a card", { attempt: delivery.attempt, messageID: delivery.id });
36276
36299
  }
36277
36300
  return turn;
36278
36301
  } catch (error48) {
36279
- logger.warn("envoy: Dispatch did not accept a direct message as this session's turn; it arrives as a card", { attempt: delivery.attempt, messageID: delivery.id, error: messageFor(error48) });
36302
+ logger2.warn("envoy: Dispatch did not accept a direct message as this session's turn; it arrives as a card", { attempt: delivery.attempt, messageID: delivery.id, error: messageFor(error48) });
36280
36303
  return;
36281
36304
  }
36282
36305
  };
@@ -36435,7 +36458,7 @@ function envoyExtension(pi) {
36435
36458
  continue;
36436
36459
  connection?.publish(reply, codec2.encode(answer));
36437
36460
  } catch (error48) {
36438
- logger.warn("envoy: agent stream control message failed", {
36461
+ logger2.warn("envoy: agent stream control message failed", {
36439
36462
  error: messageFor(error48),
36440
36463
  sessionID: session
36441
36464
  });
@@ -36548,7 +36571,7 @@ function envoyExtension(pi) {
36548
36571
  }
36549
36572
  if (!result.claimed) {
36550
36573
  endRole();
36551
- logger.warn("envoy: role re-assertion refused; held by another live session", {
36574
+ logger2.warn("envoy: role re-assertion refused; held by another live session", {
36552
36575
  role,
36553
36576
  sessionID: id,
36554
36577
  holder: result.holder
@@ -36556,7 +36579,7 @@ function envoyExtension(pi) {
36556
36579
  context.ui.notify(`envoy: role ${role} is now held by session ${result.holder}; this session no longer holds it`, "warning");
36557
36580
  return;
36558
36581
  }
36559
- logger.warn("envoy: role re-asserted after the listener lost the claim", {
36582
+ logger2.warn("envoy: role re-asserted after the listener lost the claim", {
36560
36583
  role,
36561
36584
  sessionID: id,
36562
36585
  previousHolder: holder ?? null
@@ -36567,7 +36590,7 @@ function envoyExtension(pi) {
36567
36590
  if (regained === undefined)
36568
36591
  return;
36569
36592
  Promise.resolve().then(() => regained(role, reason)).catch((error48) => {
36570
- logger.warn("envoy: role regain hook failed", { role, reason, error: messageFor(error48) });
36593
+ logger2.warn("envoy: role regain hook failed", { role, reason, error: messageFor(error48) });
36571
36594
  });
36572
36595
  };
36573
36596
  const ensureHeartbeat = (context) => {
@@ -36624,7 +36647,7 @@ function envoyExtension(pi) {
36624
36647
  previousSessionID: options.previousSessionID
36625
36648
  });
36626
36649
  if (!result.claimed) {
36627
- logger.warn("envoy: role held by another live session; not reclaimed", {
36650
+ logger2.warn("envoy: role held by another live session; not reclaimed", {
36628
36651
  role,
36629
36652
  sessionID,
36630
36653
  holder: result.holder
@@ -36679,7 +36702,7 @@ function envoyExtension(pi) {
36679
36702
  return;
36680
36703
  const continued = carryPreviousSessionRole && previousSessionID !== "" && previousSessionID !== sessionID ? previousSessionID : undefined;
36681
36704
  await setEnvoyRole(role, { soft: true, previousSessionID: continued }).catch((error48) => {
36682
- logger.warn("envoy: role reclaim failed", { role, sessionID, error: messageFor(error48) });
36705
+ logger2.warn("envoy: role reclaim failed", { role, sessionID, error: messageFor(error48) });
36683
36706
  });
36684
36707
  };
36685
36708
  let sessionEstablishment = Promise.resolve();
@@ -36755,12 +36778,11 @@ function envoyExtension(pi) {
36755
36778
  sessionID: () => activeSessionContext?.sessionManager.getSessionId() ?? sessionID
36756
36779
  };
36757
36780
  bridge.instances.push(claimInstance);
36758
- const isSubagentTranscript = subagentSessionCheck();
36759
- const isSubagent = async (context) => await isSubagentTranscript(context) || isRegisteredSubagent(context);
36760
- const replyAddress = async (context, liveSessionID = "") => {
36781
+ const isSubagent = subagentSessionCheck();
36782
+ const replyAddress = async (context, liveSessionID = "", subagent) => {
36761
36783
  if (sessionID !== "")
36762
36784
  return liveSessionID || sessionID;
36763
- if (!await isSubagent(context))
36785
+ if (!(subagent ?? await isSubagent(context)))
36764
36786
  return liveSessionID;
36765
36787
  return resolveEnvoySession(context.sessionManager.getSessionFile());
36766
36788
  };
@@ -37125,14 +37147,15 @@ Warnings: ${warnings.join("; ")}`, {
37125
37147
  }
37126
37148
  case EnvoyToolOperation.publish: {
37127
37149
  const topic = stringFor(parameters, "topic");
37128
- const source = await replyAddress(context);
37150
+ const inSubagent = await isSubagent(context);
37151
+ const source = await replyAddress(context, "", inSubagent);
37129
37152
  const result = await client.publish({
37130
37153
  sourceSessionID: source,
37131
37154
  topic,
37132
37155
  message: stringFor(parameters, "message"),
37133
37156
  ...toMessageMetadata(parameters)
37134
37157
  });
37135
- const undelivered = source !== "" && result.holder === source && await isSubagent(context);
37158
+ const undelivered = source !== "" && result.holder === source && inSubagent;
37136
37159
  const published = result.holder === undefined ? `published ${result.envelope.event_id}` : `published ${result.envelope.event_id}; holder ${result.holder}`;
37137
37160
  return toolSuccess(undelivered ? `${published}
37138
37161
  Not delivered: that holder is the session this subagent sends as, and the listener drops a message whose source session is its recipient, so the agent that spawned you did not receive it. Reach it over hub instead.` : published, {
@@ -37153,7 +37176,7 @@ Not delivered: that holder is the session this subagent sends as, and the listen
37153
37176
  }
37154
37177
  case EnvoyToolOperation.whoami: {
37155
37178
  const inSubagent = await isSubagent(context);
37156
- const address = await replyAddress(context);
37179
+ const address = await replyAddress(context, "", inSubagent);
37157
37180
  const subagent = inSubagent ? {
37158
37181
  session_id: context.sessionManager.getSessionId(),
37159
37182
  note: address === "" ? "This session is a task subagent and registers no Envoy session of its own, and this process records no top-level session its transcript traces back to, so it has no reply address at all: say who you are in the message body, and reach the agent that spawned you over hub." : "This session is a task subagent and registers no Envoy session of its own; a reply to session_id reaches the agent that spawned it, which relays over hub. Your own envoy_publish never reaches that agent \u2014 use hub for that hop."
package/dist/legion.js CHANGED
@@ -17744,7 +17744,7 @@ function asObject(value) {
17744
17744
  }
17745
17745
 
17746
17746
  // extensions/legion.ts
17747
- import { logger } from "@oh-my-pi/pi-utils";
17747
+ import { logger as logger2 } from "@oh-my-pi/pi-utils";
17748
17748
 
17749
17749
  // src/dispatch-user-turn.ts
17750
17750
  function isUserTurnCandidate(rendered) {
@@ -17843,7 +17843,7 @@ function endInjectedUserTurns(sessionID) {
17843
17843
  // package.json
17844
17844
  var package_default = {
17845
17845
  name: "@sjawhar/pi-legion-envoy",
17846
- version: "6.0.2",
17846
+ version: "6.0.4",
17847
17847
  type: "module",
17848
17848
  omp: {
17849
17849
  extensions: [
@@ -17891,33 +17891,56 @@ var package_default = {
17891
17891
  import fs from "fs";
17892
17892
  import path2 from "path";
17893
17893
  import * as host from "@oh-my-pi/pi-coding-agent";
17894
+ import { logger } from "@oh-my-pi/pi-utils";
17894
17895
  var LEGION_BOOTSTRAPPED_SESSION = Symbol.for("legion.pi-envoy.bootstrapped-session");
17895
17896
  var bootstrappedSessionStore = globalThis;
17896
17897
  function recordBootstrappedSession(sessionFile) {
17897
17898
  bootstrappedSessionStore[LEGION_BOOTSTRAPPED_SESSION] = sessionFile;
17898
17899
  }
17899
17900
  async function isSubagentSession(context) {
17900
- await context.sessionManager.ensureOnDisk();
17901
+ const registered = registeredSubagent(context);
17902
+ if (registered !== undefined)
17903
+ return { subagent: registered, settled: true };
17904
+ try {
17905
+ await context.sessionManager.ensureOnDisk();
17906
+ } catch (error48) {
17907
+ const subagent = transcriptSaysSubagent(context);
17908
+ logger.warn("subagent check: publishing the transcript failed; answered from the transcript on disk, and the next call asks again", { sessionFile: context.sessionManager.getSessionFile(), subagent, error: messageFor(error48) });
17909
+ return { subagent, settled: false };
17910
+ }
17911
+ return { subagent: transcriptSaysSubagent(context), settled: true };
17912
+ }
17913
+ function transcriptSaysSubagent(context) {
17901
17914
  const sessionFile = context.sessionManager.getSessionFile();
17902
- if (sessionFile !== undefined && fs.existsSync(sessionFile)) {
17903
- return fs.existsSync(`${path2.dirname(sessionFile)}.jsonl`);
17915
+ if (sessionFile !== undefined) {
17916
+ if (fs.existsSync(`${path2.dirname(sessionFile)}.jsonl`))
17917
+ return true;
17918
+ if (fs.existsSync(sessionFile))
17919
+ return false;
17904
17920
  }
17905
17921
  const bootstrapped = bootstrappedSessionStore[LEGION_BOOTSTRAPPED_SESSION];
17906
17922
  return bootstrapped !== undefined && bootstrapped !== sessionFile;
17907
17923
  }
17908
- function isRegisteredSubagent(context) {
17924
+ function registeredSubagent(context) {
17909
17925
  const registry2 = host.AgentRegistry?.global();
17910
17926
  if (registry2 === undefined)
17911
- return false;
17927
+ return;
17912
17928
  const sessionID = context.sessionManager.getSessionId();
17913
17929
  const sessionFile = context.sessionManager.getSessionFile();
17914
- return registry2.list().some((ref) => ref.kind !== "main" && (ref.session === null ? sessionFile !== undefined && ref.sessionFile === sessionFile : ref.session.sessionManager.getSessionId() === sessionID));
17930
+ const own = registry2.list().filter((ref) => ref.session === null ? sessionFile !== undefined && ref.sessionFile === sessionFile : ref.session.sessionManager.getSessionId() === sessionID);
17931
+ if (own.length === 0)
17932
+ return;
17933
+ return own.some((ref) => ref.kind !== "main");
17915
17934
  }
17916
17935
  function subagentSessionCheck() {
17917
- let subagentSession;
17918
- return (context) => {
17919
- subagentSession ??= isSubagentSession(context);
17920
- return subagentSession;
17936
+ let settled;
17937
+ return async (context) => {
17938
+ if (settled !== undefined)
17939
+ return settled;
17940
+ const answer = await isSubagentSession(context);
17941
+ if (answer.settled)
17942
+ settled = answer.subagent;
17943
+ return answer.subagent;
17921
17944
  };
17922
17945
  }
17923
17946
 
@@ -18504,7 +18527,7 @@ function createClaimSession(deps) {
18504
18527
 
18505
18528
  // src/legion/controller-session.ts
18506
18529
  function createControllerSession(deps) {
18507
- const { daemon, persistedTranscript, checkSubagentSession } = deps;
18530
+ const { daemon, persistedTranscript } = deps;
18508
18531
  let controllerSessionID;
18509
18532
  let controllerCapability;
18510
18533
  let mintControllerGrant;
@@ -18555,8 +18578,6 @@ function createControllerSession(deps) {
18555
18578
  }
18556
18579
  };
18557
18580
  const reclaimAfterSessionChange = async (context) => {
18558
- if (await checkSubagentSession(context))
18559
- return;
18560
18581
  if (classifySession(process.env).kind !== "controller")
18561
18582
  return;
18562
18583
  if (context.sessionManager.getSessionId() === controllerSessionID && context.sessionManager.getSessionFile() === controllerTranscript) {
@@ -19225,7 +19246,7 @@ function isToolDeviceInvocation(toolCall) {
19225
19246
  }
19226
19247
  function legionExtension(pi) {
19227
19248
  const instance = randomUUID2().slice(0, 8);
19228
- logger.debug("extension instance loaded", { extension: import.meta.url, instance });
19249
+ logger2.debug("extension instance loaded", { extension: import.meta.url, instance });
19229
19250
  globalThis[LEGION_LOADED_MARKER] = import.meta.url;
19230
19251
  const checkSubagentSession = subagentSessionCheck();
19231
19252
  let paneRules;
@@ -19254,8 +19275,7 @@ function legionExtension(pi) {
19254
19275
  });
19255
19276
  const controllerSession = createControllerSession({
19256
19277
  daemon: roleDaemon,
19257
- persistedTranscript,
19258
- checkSubagentSession
19278
+ persistedTranscript
19259
19279
  });
19260
19280
  const titleSession = async (context) => {
19261
19281
  const title = legionSessionTitle(classifySession(process.env), process.env.LEGION_PROJECT);
@@ -19279,16 +19299,17 @@ function legionExtension(pi) {
19279
19299
  await activateLegionTool();
19280
19300
  });
19281
19301
  const afterSessionChange = async (context) => {
19282
- if (classifySession(process.env).kind === "controller" && !await checkSubagentSession(context)) {
19302
+ if (await checkSubagentSession(context))
19303
+ return;
19304
+ if (classifySession(process.env).kind === "controller")
19283
19305
  await titleSession(context);
19284
- }
19285
19306
  await controllerSession.reclaimAfterSessionChange(context);
19286
19307
  };
19287
19308
  pi.on("session_switch", (_event, context) => afterSessionChange(context));
19288
19309
  pi.on("session_branch", (_event, context) => afterSessionChange(context));
19289
19310
  pi.on("session_tree", (_event, context) => afterSessionChange(context));
19290
19311
  pi.on("tool_call", async (toolCall, context) => {
19291
- logger.debug("legion tool_call hook", {
19312
+ logger2.debug("legion tool_call hook", {
19292
19313
  instance,
19293
19314
  toolCallId: toolCall.toolCallId,
19294
19315
  toolName: toolCall.toolName
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion-envoy",
3
- "version": "6.0.2",
3
+ "version": "6.0.4",
4
4
  "type": "module",
5
5
  "omp": {
6
6
  "extensions": [