opencode-flema-engram-sidebar 0.2.0 → 0.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.
@@ -0,0 +1,335 @@
1
+ export const GENTLE_SHELL_SIDEBAR_STATE = Symbol.for("gentle-pi.experimental-sidebar.state");
2
+ const SHARED_RAIL_STACK = Symbol.for("mcp-sidebar.gentle-shell-rail-stack");
3
+ const ANSI_PATTERN = /\u001B(?:\[[0-?]*[ -/]*[@-~]|\][^\u0007]*(?:\u0007|\u001B\\))/g;
4
+ const COMBINING_MARK_PATTERN = /\p{Mark}/u;
5
+ export function visibleTextWidth(value) {
6
+ let width = 0;
7
+ for (const character of value.replace(ANSI_PATTERN, "")) {
8
+ const codePoint = character.codePointAt(0) ?? 0;
9
+ if (codePoint === 0 || codePoint < 32 || (codePoint >= 0x7f && codePoint < 0xa0))
10
+ continue;
11
+ if (COMBINING_MARK_PATTERN.test(character) || codePoint === 0xfe0f || codePoint === 0x200d)
12
+ continue;
13
+ width += isWideCodePoint(codePoint) ? 2 : 1;
14
+ }
15
+ return width;
16
+ }
17
+ function isWideCodePoint(codePoint) {
18
+ return codePoint >= 0x1100 && (codePoint <= 0x115f ||
19
+ codePoint === 0x2329 ||
20
+ codePoint === 0x232a ||
21
+ (codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f) ||
22
+ (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||
23
+ (codePoint >= 0xf900 && codePoint <= 0xfaff) ||
24
+ (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||
25
+ (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||
26
+ (codePoint >= 0xff00 && codePoint <= 0xff60) ||
27
+ (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||
28
+ (codePoint >= 0x1f300 && codePoint <= 0x1faff) ||
29
+ (codePoint >= 0x20000 && codePoint <= 0x3fffd));
30
+ }
31
+ function truncateText(value, width) {
32
+ if (width <= 0)
33
+ return "";
34
+ if (visibleTextWidth(value) <= width)
35
+ return value;
36
+ if (width === 1)
37
+ return "…";
38
+ let result = "";
39
+ let used = 0;
40
+ for (const character of value) {
41
+ const characterWidth = visibleTextWidth(character);
42
+ if (used + characterWidth > width - 1)
43
+ break;
44
+ result += character;
45
+ used += characterWidth;
46
+ }
47
+ return `${result}…`;
48
+ }
49
+ function aggregateOddProgress(state) {
50
+ return (state.odd?.features ?? []).reduce((total, feature) => ({
51
+ total: total.total + feature.progress.total,
52
+ done: total.done + feature.progress.done,
53
+ inProgress: total.inProgress + feature.progress.in_progress,
54
+ blocked: total.blocked + feature.progress.blocked,
55
+ }), { total: 0, done: 0, inProgress: 0, blocked: 0 });
56
+ }
57
+ function healthToken(state) {
58
+ if (state.health === "ok")
59
+ return "success";
60
+ if (state.health === "loading" || state.health === "stale")
61
+ return "warning";
62
+ return "error";
63
+ }
64
+ function panelDigest(state, collapsed) {
65
+ const progress = aggregateOddProgress(state);
66
+ return JSON.stringify({
67
+ collapsed,
68
+ projectName: state.projectName,
69
+ health: state.health,
70
+ loading: state.loading,
71
+ progress,
72
+ blockers: state.blockers.map((item) => [item.id, item.title, item.updated_at]),
73
+ recent: state.recentActivity.map((item) => [item.id, item.title, item.updated_at]),
74
+ error: state.error,
75
+ terminal: state.terminal,
76
+ });
77
+ }
78
+ function isRailComponent(value) {
79
+ return typeof value === "object" && value !== null
80
+ && typeof value.render === "function"
81
+ && typeof value.invalidate === "function";
82
+ }
83
+ function readRailHost(terminal) {
84
+ const candidate = terminal[GENTLE_SHELL_SIDEBAR_STATE];
85
+ if (typeof candidate !== "object" || candidate === null)
86
+ return undefined;
87
+ const parts = candidate.parts;
88
+ return parts instanceof Map ? candidate : undefined;
89
+ }
90
+ function hostOwnsRail(host) {
91
+ if (typeof host.ownsHost !== "function")
92
+ return host.active !== false;
93
+ try {
94
+ return host.ownsHost() === true;
95
+ }
96
+ catch {
97
+ return false;
98
+ }
99
+ }
100
+ function isSharedRailStack(value, host) {
101
+ if (typeof value !== "object" || value === null)
102
+ return false;
103
+ const stack = value;
104
+ return stack.host === host
105
+ && isRailComponent(stack.original)
106
+ && isRailComponent(stack.wrapper)
107
+ && stack.participants instanceof Map
108
+ && Array.isArray(stack.segments)
109
+ && typeof stack.revision === "number";
110
+ }
111
+ function createSharedRailStack(host, original) {
112
+ let stack;
113
+ const wrapper = {
114
+ render(width) {
115
+ const lines = [];
116
+ const segments = [];
117
+ const append = (component) => {
118
+ const rendered = [...component.render(width)];
119
+ if (rendered.length === 0)
120
+ return;
121
+ segments.push({ component, startY: lines.length, height: rendered.length });
122
+ lines.push(...rendered);
123
+ };
124
+ append(original);
125
+ for (const participant of stack.participants.values()) {
126
+ if (participant.visible)
127
+ append(participant.component);
128
+ }
129
+ stack.segments = segments;
130
+ return lines;
131
+ },
132
+ invalidate() {
133
+ stack.revision++;
134
+ stack.segments = [];
135
+ original.invalidate();
136
+ for (const participant of stack.participants.values())
137
+ participant.component.invalidate();
138
+ },
139
+ digest() {
140
+ let originalDigest = "";
141
+ try {
142
+ originalDigest = original.digest?.() ?? "";
143
+ }
144
+ catch {
145
+ // Explicit invalidation remains the fallback when a digest cannot be read.
146
+ }
147
+ const participants = [...stack.participants.values()]
148
+ .filter((participant) => participant.visible)
149
+ .map((participant) => {
150
+ try {
151
+ return participant.component.digest?.() ?? "";
152
+ }
153
+ catch {
154
+ return "";
155
+ }
156
+ });
157
+ return JSON.stringify([originalDigest, stack.revision, participants]);
158
+ },
159
+ handleMouse(event) {
160
+ if (event.y < 0 || event.y >= event.height)
161
+ return undefined;
162
+ const segment = stack.segments.find((candidate) => event.y >= candidate.startY
163
+ && event.y < candidate.startY + candidate.height);
164
+ if (!segment)
165
+ return undefined;
166
+ const result = segment.component.handleMouse?.({
167
+ ...event,
168
+ y: event.y - segment.startY,
169
+ height: segment.height,
170
+ });
171
+ if (result?.render)
172
+ stack.revision++;
173
+ return result;
174
+ },
175
+ };
176
+ stack = {
177
+ host,
178
+ original,
179
+ wrapper,
180
+ participants: new Map(),
181
+ revision: 0,
182
+ segments: [],
183
+ };
184
+ return stack;
185
+ }
186
+ export function attachGentleShellRailPanel(tui, component) {
187
+ if (tui.mode !== "fullscreen" || !tui.terminal)
188
+ return undefined;
189
+ const terminal = tui.terminal;
190
+ const host = readRailHost(terminal);
191
+ if (!host)
192
+ return undefined;
193
+ const existing = terminal[SHARED_RAIL_STACK];
194
+ let stack;
195
+ if (isSharedRailStack(existing, host) && host.parts.get("footer") === existing.wrapper) {
196
+ stack = existing;
197
+ }
198
+ else {
199
+ const original = host.parts.get("footer");
200
+ if (!isRailComponent(original))
201
+ return undefined;
202
+ stack = createSharedRailStack(host, original);
203
+ terminal[SHARED_RAIL_STACK] = stack;
204
+ host.parts.set("footer", stack.wrapper);
205
+ }
206
+ const participantId = Symbol("flema-engram-rail-participant");
207
+ const participant = { component, visible: true };
208
+ stack.participants.set(participantId, participant);
209
+ stack.revision++;
210
+ tui.requestRender();
211
+ let disposed = false;
212
+ const isMounted = () => !disposed && host.parts.get("footer") === stack.wrapper;
213
+ const invalidate = () => {
214
+ if (disposed)
215
+ return;
216
+ stack.revision++;
217
+ stack.segments = [];
218
+ tui.requestRender();
219
+ };
220
+ return {
221
+ isMounted,
222
+ isActive: () => isMounted() && hostOwnsRail(host),
223
+ setVisible(visible) {
224
+ if (disposed || participant.visible === visible)
225
+ return;
226
+ participant.visible = visible;
227
+ invalidate();
228
+ },
229
+ invalidate,
230
+ dispose() {
231
+ if (disposed)
232
+ return;
233
+ disposed = true;
234
+ stack.participants.delete(participantId);
235
+ stack.revision++;
236
+ stack.segments = [];
237
+ if (stack.participants.size === 0) {
238
+ if (host.parts.get("footer") === stack.wrapper)
239
+ host.parts.set("footer", stack.original);
240
+ if (terminal[SHARED_RAIL_STACK] === stack)
241
+ delete terminal[SHARED_RAIL_STACK];
242
+ }
243
+ tui.requestRender();
244
+ },
245
+ };
246
+ }
247
+ export function createPiSidebarPanel(tui, theme, initialState, onCollapsedChange) {
248
+ let state = initialState;
249
+ let collapsed = false;
250
+ const paint = (token, text, bold = false) => {
251
+ const emphasized = bold && theme.bold ? theme.bold(text) : text;
252
+ return theme.fg(token, emphasized);
253
+ };
254
+ const render = (width) => {
255
+ const boundedWidth = Math.max(0, Math.floor(width));
256
+ if (boundedWidth === 0)
257
+ return [];
258
+ if (boundedWidth === 1)
259
+ return [paint("dim", "…")];
260
+ const border = (text) => paint("border", text);
261
+ const title = truncateText(`${collapsed ? "▶" : "▼"} 🧠 Engram`, boundedWidth - 6);
262
+ const top = title
263
+ ? border("╭─ ") + paint("accent", title, true)
264
+ + border(` ${"─".repeat(boundedWidth - visibleTextWidth(title) - 5)}╮`)
265
+ : border(`╭${"─".repeat(boundedWidth - 2)}╮`);
266
+ const bottom = border(`╰${"─".repeat(boundedWidth - 2)}╯`);
267
+ const padding = boundedWidth >= 4 ? " " : "";
268
+ const contentWidth = boundedWidth - 2 - padding.length * 2;
269
+ const row = (token, text, bold = false) => {
270
+ const bounded = truncateText(text, contentWidth);
271
+ const padded = bounded + " ".repeat(contentWidth - visibleTextWidth(bounded));
272
+ return border(`│${padding}`) + paint(token, padded, bold) + border(`${padding}│`);
273
+ };
274
+ const project = state.projectName ?? "unresolved project";
275
+ const health = state.health.toUpperCase();
276
+ const lines = [top, row(healthToken(state), `${project} · ${health}`)];
277
+ if (collapsed)
278
+ return [...lines, bottom];
279
+ const progress = aggregateOddProgress(state);
280
+ lines.push(row("text", progress.total > 0
281
+ ? `ODD ${progress.done}/${progress.total} done · ${progress.inProgress} active · ${progress.blocked} blocked`
282
+ : "ODD no tracked feature"));
283
+ if (state.error)
284
+ lines.push(row("error", state.error));
285
+ lines.push(row("warning", `Blockers · ${state.blockers.length}`, true));
286
+ if (state.blockers.length === 0) {
287
+ lines.push(row("muted", "No blockers"));
288
+ }
289
+ else {
290
+ for (const item of state.blockers.slice(0, 3)) {
291
+ lines.push(row("muted", `• ${item.title}`));
292
+ }
293
+ }
294
+ lines.push(row("accent", "Recent", true));
295
+ if (state.recentActivity.length === 0) {
296
+ lines.push(row("muted", "No recent activity"));
297
+ }
298
+ else {
299
+ for (const item of state.recentActivity.slice(0, 3)) {
300
+ lines.push(row("muted", `• ${item.title}`));
301
+ }
302
+ }
303
+ return [...lines, bottom];
304
+ };
305
+ const setCollapsed = (nextCollapsed) => {
306
+ if (collapsed === nextCollapsed)
307
+ return;
308
+ collapsed = nextCollapsed;
309
+ tui.requestRender();
310
+ };
311
+ return {
312
+ render,
313
+ handleMouse(event) {
314
+ if (event.button !== "left" || event.y !== 0 || event.height <= 0
315
+ || event.x < 0 || event.x >= event.width)
316
+ return undefined;
317
+ if (event.type === "press")
318
+ return { handled: true, render: false };
319
+ if (event.type !== "click")
320
+ return undefined;
321
+ setCollapsed(!collapsed);
322
+ onCollapsedChange?.(collapsed);
323
+ return { handled: true, render: true };
324
+ },
325
+ invalidate: () => tui.requestRender(),
326
+ digest: () => panelDigest(state, collapsed),
327
+ setState: (nextState) => {
328
+ state = nextState;
329
+ tui.requestRender();
330
+ },
331
+ setCollapsed,
332
+ isCollapsed: () => collapsed,
333
+ };
334
+ }
335
+ //# sourceMappingURL=sidebar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sidebar.js","sourceRoot":"","sources":["../../src/pi/sidebar.ts"],"names":[],"mappings":"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"}
package/dist/pi.d.ts ADDED
@@ -0,0 +1,56 @@
1
+ import type { EngramAdapter } from "./adapters/types.js";
2
+ import { type ProjectResolution } from "./utils/project-resolver.js";
3
+ import { type PiSidebarPanel, type PiSidebarTheme, type PiSidebarTui } from "./pi/sidebar.js";
4
+ export interface PiExtensionOverlayHandle {
5
+ setHidden: (hidden: boolean) => void;
6
+ isHidden?: () => boolean;
7
+ }
8
+ export interface PiExtensionUi {
9
+ setStatus: (key: string, value: string | undefined) => void;
10
+ setWidget: (key: string, value: string[] | undefined, options?: {
11
+ placement?: "aboveEditor" | "belowEditor";
12
+ }) => void;
13
+ notify: (message: string, level?: "info" | "warning" | "error") => void;
14
+ custom?: (factory: (tui: PiSidebarTui, theme: PiSidebarTheme, keybindings: unknown, done: (value: unknown) => void) => PiSidebarPanel | Promise<PiSidebarPanel>, options: {
15
+ overlay: true;
16
+ overlayOptions: {
17
+ anchor: "bottom-right";
18
+ width: number;
19
+ minWidth: number;
20
+ maxHeight: string;
21
+ margin: {
22
+ right: number;
23
+ bottom: number;
24
+ };
25
+ nonCapturing: true;
26
+ visible: (terminalWidth: number, terminalHeight: number) => boolean;
27
+ };
28
+ onHandle: (handle: PiExtensionOverlayHandle) => void;
29
+ }) => Promise<unknown>;
30
+ }
31
+ export interface PiExtensionContext {
32
+ cwd: string;
33
+ hasUI: boolean;
34
+ mode?: "tui" | "rpc" | "json" | "print";
35
+ ui: PiExtensionUi;
36
+ }
37
+ export interface PiToolResultEvent {
38
+ type: "tool_result";
39
+ toolName: string;
40
+ isError: boolean;
41
+ }
42
+ export interface PiExtensionApi {
43
+ on: (event: string, handler: (event: Record<string, unknown>, context: PiExtensionContext) => unknown) => () => void;
44
+ registerCommand: (name: string, command: {
45
+ description: string;
46
+ handler: (args: string, context: PiExtensionContext) => unknown;
47
+ }) => void;
48
+ }
49
+ export interface PiEngramExtensionDependencies {
50
+ createAdapter?: () => EngramAdapter;
51
+ resolveProject?: (adapter: EngramAdapter, cwd: string) => Promise<ProjectResolution>;
52
+ }
53
+ export declare function createPiEngramExtension(dependencies?: PiEngramExtensionDependencies): (pi: PiExtensionApi) => void;
54
+ declare const _default: (pi: PiExtensionApi) => void;
55
+ export default _default;
56
+ //# sourceMappingURL=pi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi.d.ts","sourceRoot":"","sources":["../src/pi.ts"],"names":[],"mappings":"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"}
package/dist/pi.js ADDED
@@ -0,0 +1,249 @@
1
+ import { createConfiguredAdapter } from "./adapters/factory.js";
2
+ import { createEngramReadController, } from "./viewer/core.js";
3
+ import { resolveProject as resolveValidatedProject, } from "./utils/project-resolver.js";
4
+ import { attachGentleShellRailPanel, createPiSidebarPanel, } from "./pi/sidebar.js";
5
+ const UI_KEY = "flema-engram";
6
+ const REFRESH_COMMAND = "engram-refresh";
7
+ const SIDEBAR_COMMAND = "engram-sidebar";
8
+ const SIDEBAR_COLLAPSE_COMMAND = "engram-sidebar-collapse";
9
+ const WIDGET_COMMAND = "engram-widget";
10
+ const MEMORY_SAVE_TOOLS = new Set(["mem_save", "save_memory"]);
11
+ export function createPiEngramExtension(dependencies = {}) {
12
+ const createAdapter = dependencies.createAdapter ?? (() => createConfiguredAdapter());
13
+ const resolveProject = dependencies.resolveProject
14
+ ?? ((adapter, cwd) => resolveValidatedProject(adapter, cwd));
15
+ return (pi) => {
16
+ let active;
17
+ let presentation;
18
+ let sessionToken;
19
+ const clearUi = (context) => {
20
+ if (!context.hasUI)
21
+ return;
22
+ context.ui.setStatus(UI_KEY, undefined);
23
+ context.ui.setWidget(UI_KEY, undefined);
24
+ };
25
+ const syncPresentation = (current) => {
26
+ current.rail?.setVisible(current.visible);
27
+ current.rail?.invalidate();
28
+ current.handle?.setHidden(!current.visible || current.rail?.isActive() === true);
29
+ };
30
+ const setPresentationCollapsed = (current, collapsed) => {
31
+ if (presentation !== current)
32
+ return;
33
+ current.collapsed = collapsed;
34
+ current.panel?.setCollapsed(collapsed);
35
+ current.rail?.invalidate();
36
+ };
37
+ const stopPresentation = () => {
38
+ const current = presentation;
39
+ presentation = undefined;
40
+ if (!current)
41
+ return;
42
+ current.rail?.dispose();
43
+ current.finish?.();
44
+ };
45
+ const stopActive = () => {
46
+ stopPresentation();
47
+ if (!active)
48
+ return;
49
+ active.controller.dispose();
50
+ clearUi(active.context);
51
+ active = undefined;
52
+ };
53
+ const mountSidebar = (context, token, getState) => {
54
+ if (context.mode !== "tui" || !context.ui.custom)
55
+ return;
56
+ const current = {
57
+ token,
58
+ visible: true,
59
+ collapsed: false,
60
+ };
61
+ presentation = current;
62
+ void context.ui.custom((tui, theme, _keybindings, done) => {
63
+ const panel = createPiSidebarPanel(tui, theme, getState(), (collapsed) => {
64
+ if (current.panel !== panel)
65
+ return;
66
+ setPresentationCollapsed(current, collapsed);
67
+ });
68
+ panel.setCollapsed(current.collapsed);
69
+ if (presentation?.token !== token) {
70
+ done(undefined);
71
+ return panel;
72
+ }
73
+ current.rail?.dispose();
74
+ current.finish = () => done(undefined);
75
+ current.panel = panel;
76
+ current.rail = attachGentleShellRailPanel(tui, panel);
77
+ syncPresentation(current);
78
+ return panel;
79
+ }, {
80
+ overlay: true,
81
+ overlayOptions: {
82
+ anchor: "bottom-right",
83
+ width: 48,
84
+ minWidth: 29,
85
+ maxHeight: "70%",
86
+ margin: { right: 2, bottom: 1 },
87
+ nonCapturing: true,
88
+ visible: (terminalWidth) => current.visible && current.rail?.isActive() !== true && terminalWidth >= 100,
89
+ },
90
+ onHandle: (handle) => {
91
+ current.handle = handle;
92
+ syncPresentation(current);
93
+ },
94
+ }).catch(() => {
95
+ if (presentation?.token === token) {
96
+ context.ui.notify("Engram sidebar unavailable", "warning");
97
+ }
98
+ }).finally(() => {
99
+ current.rail?.dispose();
100
+ if (presentation?.token === token)
101
+ presentation = undefined;
102
+ });
103
+ };
104
+ const renderUnavailable = (context) => {
105
+ context.ui.setStatus(UI_KEY, "Engram unavailable");
106
+ context.ui.setWidget(UI_KEY, undefined);
107
+ };
108
+ const refreshActive = async () => {
109
+ const current = active;
110
+ if (!current)
111
+ return undefined;
112
+ const outcome = await current.controller.refresh();
113
+ return active?.token === current.token ? outcome : undefined;
114
+ };
115
+ pi.on("session_start", async (_event, context) => {
116
+ stopActive();
117
+ const token = Symbol("pi-engram-session");
118
+ sessionToken = token;
119
+ if (!context.hasUI)
120
+ return;
121
+ try {
122
+ const adapter = createAdapter();
123
+ const controller = createEngramReadController(adapter, {
124
+ resolveProject: () => resolveProject(adapter, context.cwd),
125
+ onState: (state) => {
126
+ if (active?.token !== token)
127
+ return;
128
+ renderState(active.context, state, active.widgetVisible);
129
+ if (presentation?.token === token) {
130
+ presentation.panel?.setState(state);
131
+ presentation.rail?.invalidate();
132
+ }
133
+ },
134
+ });
135
+ active = { controller, context, token, widgetVisible: false };
136
+ mountSidebar(context, token, controller.getState);
137
+ await refreshActive();
138
+ }
139
+ catch {
140
+ if (sessionToken !== token)
141
+ return;
142
+ stopActive();
143
+ renderUnavailable(context);
144
+ }
145
+ });
146
+ pi.on("tool_result", async (event, _context) => {
147
+ if (!isPiToolResultEvent(event) || event.isError || !MEMORY_SAVE_TOOLS.has(event.toolName))
148
+ return;
149
+ await refreshActive();
150
+ });
151
+ pi.on("session_shutdown", (_event, _context) => {
152
+ sessionToken = undefined;
153
+ stopActive();
154
+ });
155
+ pi.registerCommand(REFRESH_COMMAND, {
156
+ description: "Refresh the Flema Engram status and widget",
157
+ handler: async (_args, context) => {
158
+ if (!active) {
159
+ context.ui.notify("Engram viewer is not active", "warning");
160
+ return;
161
+ }
162
+ const current = active;
163
+ current.context = context;
164
+ const outcome = await refreshActive();
165
+ if (active !== current || !outcome)
166
+ return;
167
+ renderState(context, current.controller.getState(), current.widgetVisible);
168
+ if (outcome.status === "success") {
169
+ context.ui.notify("Engram refreshed", "info");
170
+ }
171
+ else {
172
+ context.ui.notify("Engram refresh incomplete", "warning");
173
+ }
174
+ },
175
+ });
176
+ pi.registerCommand(SIDEBAR_COMMAND, {
177
+ description: "Show or hide the Flema Engram sidebar",
178
+ handler: async (_args, context) => {
179
+ if (!active || !presentation) {
180
+ context.ui.notify("Engram sidebar is not active", "warning");
181
+ return;
182
+ }
183
+ presentation.visible = !presentation.visible;
184
+ syncPresentation(presentation);
185
+ context.ui.notify(`Engram sidebar ${presentation.visible ? "shown" : "hidden"}`, "info");
186
+ },
187
+ });
188
+ pi.registerCommand(SIDEBAR_COLLAPSE_COMMAND, {
189
+ description: "Collapse or expand the Flema Engram sidebar",
190
+ handler: async (_args, context) => {
191
+ if (!active || !presentation) {
192
+ context.ui.notify("Engram sidebar is not active", "warning");
193
+ return;
194
+ }
195
+ setPresentationCollapsed(presentation, !presentation.collapsed);
196
+ context.ui.notify(`Engram sidebar ${presentation.collapsed ? "collapsed" : "expanded"}`, "info");
197
+ },
198
+ });
199
+ pi.registerCommand(WIDGET_COMMAND, {
200
+ description: "Show or hide the compact Flema Engram widget for this session",
201
+ handler: async (_args, context) => {
202
+ if (!active) {
203
+ context.ui.notify("Engram viewer is not active", "warning");
204
+ return;
205
+ }
206
+ active.widgetVisible = !active.widgetVisible;
207
+ renderState(active.context, active.controller.getState(), active.widgetVisible);
208
+ context.ui.notify(`Engram widget ${active.widgetVisible ? "shown" : "hidden"}`, "info");
209
+ },
210
+ });
211
+ };
212
+ }
213
+ function isPiToolResultEvent(event) {
214
+ return typeof event.toolName === "string" && typeof event.isError === "boolean";
215
+ }
216
+ function renderState(context, state, widgetVisible = false) {
217
+ const health = state.health.toUpperCase();
218
+ const project = state.projectName ?? "unresolved project";
219
+ const progress = aggregateOddProgress(state);
220
+ const blockerCount = state.blockers.length + progress.blocked;
221
+ const statusParts = [`Engram ${health}`, project];
222
+ if (progress.total > 0)
223
+ statusParts.push(`ODD ${progress.done}/${progress.total}`);
224
+ if (blockerCount > 0)
225
+ statusParts.push(`${blockerCount} blocked`);
226
+ context.ui.setStatus(UI_KEY, statusParts.join(" · "));
227
+ if (!widgetVisible) {
228
+ context.ui.setWidget(UI_KEY, undefined);
229
+ return;
230
+ }
231
+ const lines = [`Engram · ${project} [${health}]`];
232
+ lines.push(progress.total > 0
233
+ ? `ODD ${progress.done}/${progress.total} done · ${progress.inProgress} active · ${blockerCount} blocked`
234
+ : "ODD no tracked feature");
235
+ const latest = state.recentActivity[0];
236
+ if (latest)
237
+ lines.push(`Latest: ${latest.title}`);
238
+ context.ui.setWidget(UI_KEY, lines, { placement: "belowEditor" });
239
+ }
240
+ function aggregateOddProgress(state) {
241
+ return (state.odd?.features ?? []).reduce((total, feature) => ({
242
+ total: total.total + feature.progress.total,
243
+ done: total.done + feature.progress.done,
244
+ inProgress: total.inProgress + feature.progress.in_progress,
245
+ blocked: total.blocked + feature.progress.blocked,
246
+ }), { total: 0, done: 0, inProgress: 0, blocked: 0 });
247
+ }
248
+ export default createPiEngramExtension();
249
+ //# sourceMappingURL=pi.js.map