pilotswarm 0.5.19 → 0.5.21

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.
@@ -2199,13 +2199,6 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
2199
2199
  return s && !s.isSystem && !s.isGroup;
2200
2200
  })
2201
2201
  : activeSession?.isGroup ? true : Boolean(activeSession);
2202
- const activeSessionActionLabel = activeSession?.isGroup
2203
- ? "Delete"
2204
- : isBulkSelection
2205
- ? `Terminate (${selectedCount})`
2206
- : activeSession?.isSystem
2207
- ? "Restart"
2208
- : "Terminate";
2209
2202
  const hasExplicitSelection = selectedCount > 0;
2210
2203
  const groupableIds = hasExplicitSelection
2211
2204
  ? viewState.selectedIds.filter((id) => {
@@ -2300,7 +2293,7 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
2300
2293
  }),
2301
2294
  React.createElement(IconButton, {
2302
2295
  className: "ps-mini-button",
2303
- icon: activeSession?.isSystem ? "↻" : "⊗",
2296
+ icon: activeSession?.isSystem ? "↻" : activeSession?.isGroup ? "⊗" : React.createElement(LifecycleGlyph),
2304
2297
  onClick: () => controller.handleCommand(activeSession?.isGroup ? UI_COMMANDS.DELETE_SESSION : UI_COMMANDS.OPEN_TERMINATE_PICKER).catch(() => {}),
2305
2298
  disabled: !canTerminate,
2306
2299
  label: isBulkSelection
@@ -2309,7 +2302,7 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
2309
2302
  ? (activeGroupCanDelete ? "Delete this empty group" : "This group cannot be deleted yet")
2310
2303
  : activeSession?.isSystem
2311
2304
  ? "Restart this system session (complete, terminate, or hard delete)"
2312
- : `${activeSessionActionLabel} — mark completed, cancel, or delete`,
2305
+ : "Lifecycleregenerate context, mark completed, cancel, or delete",
2313
2306
  }),
2314
2307
  actions);
2315
2308
 
@@ -2476,6 +2469,20 @@ function LinkGlyph() {
2476
2469
  React.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" }));
2477
2470
  }
2478
2471
 
2472
+ // The "lifecycle" glyph (two curved arrows forming a cycle). Fronts the session
2473
+ // Lifecycle menu — Regenerate (rebirth) plus the terminal dispositions.
2474
+ function LifecycleGlyph() {
2475
+ return React.createElement("svg", {
2476
+ className: "ps-share-glyph", viewBox: "0 0 24 24", fill: "none",
2477
+ stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round",
2478
+ "aria-hidden": "true",
2479
+ },
2480
+ React.createElement("path", { d: "M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
2481
+ React.createElement("path", { d: "M3 3v5h5" }),
2482
+ React.createElement("path", { d: "M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" }),
2483
+ React.createElement("path", { d: "M21 21v-5h-5" }));
2484
+ }
2485
+
2479
2486
  /**
2480
2487
  * Fetch the caller's effective access to the active session (security model).
2481
2488
  * Returns { access, loading, reload }. access is the getSessionAccess payload
@@ -2854,12 +2861,18 @@ function ChatPane({ controller, mobile = false, fullWidth = false, showComposer
2854
2861
  );
2855
2862
  const navigationError = useControllerSelector(controller, selectNavigationError, shallowEqualObject);
2856
2863
  const composerBase = showComposer && !viewState.activeSessionIsGroup && viewState.chatViewMode !== "summary";
2857
- const readOnly = Boolean(access) && access.canWrite === false;
2864
+ // Service sessions ( tree-scoped machinery, e.g. the regen distiller) are
2865
+ // read-only BY KIND: their transcript is the trace of runtime machinery,
2866
+ // never a conversation surface — no prompt for anyone, owner included.
2867
+ const activeIsService = Boolean(viewState.sessionsById?.[viewState.activeSessionId]?.serviceKind);
2868
+ const readOnly = activeIsService || (Boolean(access) && access.canWrite === false);
2858
2869
  const composer = composerBase
2859
2870
  ? React.createElement("div", { className: "ps-chat-composer" },
2860
2871
  readOnly
2861
2872
  ? React.createElement("div", { className: "ps-composer-readonly" },
2862
- `You have view access to this session. Ask ${access.owner?.displayName || access.owner?.email || "the owner"} for write access to participate.`)
2873
+ activeIsService
2874
+ ? "⚗ Service session — runtime machinery. Its transcript is a read-only trace; it does not accept messages."
2875
+ : `You have view access to this session. Ask ${access.owner?.displayName || access.owner?.email || "the owner"} for write access to participate.`)
2863
2876
  : React.createElement(PromptComposer, { controller, mobile, active: true }))
2864
2877
  : null;
2865
2878
 
@@ -4499,6 +4512,10 @@ function ModalLayer({ controller }) {
4499
4512
  if (modal.type === "confirm" && modalState.confirm) {
4500
4513
  const isAlert = Boolean(modal.alert);
4501
4514
  const isDestructive = !isAlert && modal.action === "deleteSession";
4515
+ // The regenerate confirm carries distillation inputs: a mode select and
4516
+ // an optional distilling-instructions textarea, bound to modal.extras.
4517
+ const isRegen = modal.action === "regenerateSession";
4518
+ const extras = modal.extras || {};
4502
4519
  return React.createElement("div", { className: "ps-modal-backdrop", onClick: close },
4503
4520
  React.createElement("div", { className: "ps-modal is-narrow", onClick: (event) => event.stopPropagation() },
4504
4521
  React.createElement("div", { className: "ps-modal-header" },
@@ -4508,6 +4525,32 @@ function ModalLayer({ controller }) {
4508
4525
  React.createElement("div", { className: "ps-modal-body", style: { padding: "16px 20px" } },
4509
4526
  React.createElement("p", { style: { color: "#94a3b8", margin: 0 } }, modalState.confirm.message),
4510
4527
  ),
4528
+ isRegen
4529
+ ? React.createElement("div", { className: "ps-modal-body", style: { padding: "0 20px 12px", display: "flex", flexDirection: "column", gap: 10 } },
4530
+ React.createElement("label", { style: { color: "#94a3b8", fontSize: "12px", display: "flex", alignItems: "center", gap: 8 } },
4531
+ "Distillation",
4532
+ React.createElement("select", {
4533
+ className: "ps-modal-input",
4534
+ style: { flex: "1", padding: "4px 8px" },
4535
+ value: extras.distillMode || "llm",
4536
+ onChange: (event) => controller.updateConfirmExtras({ distillMode: event.currentTarget.value }),
4537
+ },
4538
+ React.createElement("option", { value: "llm" }, "Intelligent (LLM reads the whole transcript)"),
4539
+ React.createElement("option", { value: "deterministic" }, "Fast (no LLM — tail + pointers)"),
4540
+ ),
4541
+ ),
4542
+ (extras.distillMode || "llm") === "llm"
4543
+ ? React.createElement("textarea", {
4544
+ className: "ps-modal-input",
4545
+ style: { width: "100%", minHeight: "64px", resize: "vertical", fontFamily: "inherit", fontSize: "13px" },
4546
+ placeholder: "Distilling instructions (optional) — e.g. \"preserve every SQL snippet verbatim\"",
4547
+ value: extras.instructions || "",
4548
+ maxLength: 4000,
4549
+ onChange: (event) => controller.updateConfirmExtras({ instructions: event.currentTarget.value }),
4550
+ })
4551
+ : null,
4552
+ )
4553
+ : null,
4511
4554
  React.createElement("div", { className: "ps-modal-footer" },
4512
4555
  isAlert ? null : React.createElement("button", { type: "button", className: "ps-modal-button", onClick: close }, "Cancel"),
4513
4556
  React.createElement("button", {
@@ -4657,7 +4700,7 @@ function ModalLayer({ controller }) {
4657
4700
  return React.createElement("div", { className: "ps-modal-backdrop", onClick: close },
4658
4701
  React.createElement("div", { className: "ps-modal is-narrow", onClick: (event) => event.stopPropagation() },
4659
4702
  React.createElement("div", { className: "ps-modal-header" },
4660
- React.createElement("div", { className: "ps-modal-title" }, modal.title || "Terminate session"),
4703
+ React.createElement("div", { className: "ps-modal-title" }, modal.title || "Session Lifecycle"),
4661
4704
  React.createElement("button", { type: "button", className: "ps-modal-close", onClick: close }, "Close"),
4662
4705
  ),
4663
4706
  React.createElement("div", { className: "ps-modal-body", style: { padding: "12px 16px 4px" } },
@@ -4666,6 +4709,15 @@ function ModalLayer({ controller }) {
4666
4709
  className: "ps-modal-body",
4667
4710
  style: { padding: "10px 16px 16px", display: "flex", flexDirection: "column", gap: 8 },
4668
4711
  },
4712
+ modal.canRegenerate
4713
+ ? React.createElement("button", {
4714
+ type: "button",
4715
+ className: "ps-modal-button",
4716
+ style: { width: "100%", justifyContent: "flex-start" },
4717
+ title: "Archive and distill the transcript, then rebuild context fresh at the next turn boundary. Facts, artifacts, sub-agents, sharing, schedule, and chat history are preserved.",
4718
+ onClick: pick("regenerate"),
4719
+ }, "Regenerate Context")
4720
+ : null,
4669
4721
  React.createElement("button", {
4670
4722
  type: "button",
4671
4723
  className: "ps-modal-button is-primary",
@@ -4771,7 +4823,7 @@ function useKeyboardShortcuts(controller, mobile) {
4771
4823
  const handler = (event) => {
4772
4824
  const target = event.target;
4773
4825
  const editable = target instanceof HTMLElement
4774
- && (target.tagName === "TEXTAREA" || target.tagName === "INPUT" || target.isContentEditable);
4826
+ && (target.tagName === "TEXTAREA" || target.tagName === "INPUT" || target.tagName === "SELECT" || target.isContentEditable);
4775
4827
  const modal = controller.getState().ui.modal;
4776
4828
  const visibleInspectorTabs = getVisibleInspectorTabs(controller);
4777
4829
  const currentInspectorTab = controller.getState().ui.inspectorTab;