pi-crew 0.7.7 → 0.8.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.
@@ -65,7 +65,7 @@ export interface AgentOverlayState {
65
65
  export function createAgentOverlayState(entries: AgentEntry[], maxVisible = 20): AgentOverlayState {
66
66
  return {
67
67
  entries: entries.sort((a, b) => {
68
- const order: Record<ResourceSource, number> = { project: 0, user: 1, git: 2, builtin: 3, dynamic: 4 };
68
+ const order: Record<ResourceSource, number> = { project: 0, "project-pi": 1, user: 2, git: 3, builtin: 4, dynamic: 5 };
69
69
  const diff = (order[a.source] ?? 4) - (order[b.source] ?? 4);
70
70
  return diff !== 0 ? diff : a.name.localeCompare(b.name);
71
71
  }),
@@ -49,4 +49,34 @@ export function safeToPiSessionId(runId: string): string | undefined {
49
49
  } catch {
50
50
  return undefined;
51
51
  }
52
+ }
53
+
54
+ /**
55
+ * Extract the current Pi session id from an ExtensionContext.
56
+ *
57
+ * `ExtensionContext` does not declare `sessionId` in its type, but the runtime
58
+ * attaches it as an own property. We read it via `getOwnPropertyDescriptor`
59
+ * to safely bypass any Proxy traps, then validate it as a non-empty string.
60
+ *
61
+ * This is the canonical accessor — every site that filters the SHARED
62
+ * per-project `.crew/state/` tree down to the current session MUST use this,
63
+ * otherwise cross-session state leaks (e.g. compaction-guard resuming another
64
+ * session's runs, ambient-status injecting another session's runs).
65
+ *
66
+ * Returns undefined when the session id is absent or unparseable — callers
67
+ * must decide whether to treat that as "no filter" (back-compat) or "no runs".
68
+ */
69
+ export function extractSessionId(ctx: unknown): string | undefined {
70
+ if (typeof ctx !== "object" || ctx === null) return undefined;
71
+ let raw: unknown;
72
+ try {
73
+ raw = Object.getOwnPropertyDescriptor(ctx, "sessionId")?.value;
74
+ } catch {
75
+ // Defensive: a hostile Proxy or exotic object may trap descriptor
76
+ // access. Real Pi ExtensionContext objects are plain, so this is
77
+ // only hit by adversarial/degenerate inputs — treat as no session id.
78
+ return undefined;
79
+ }
80
+ if (typeof raw !== "string" || raw.length === 0) return undefined;
81
+ return raw;
52
82
  }