zjbar-opencode 1.1.5 → 1.1.7

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.
Files changed (2) hide show
  1. package/dist/index.js +58 -11
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -61,7 +61,7 @@ function shouldNotify(hookEvent, paneId, termProgram) {
61
61
  }
62
62
  return true;
63
63
  }
64
- function sendNotification(hookEvent, paneId, zellijSession, termProgram) {
64
+ function sendNotification(hookEvent, paneId, zellijSession, termProgram, summary) {
65
65
  const appName = "OpenCode";
66
66
  const iconFile = "opencode-logo.png";
67
67
  const pluginDir = join(homedir(), ".config", "zellij", "plugins");
@@ -71,15 +71,15 @@ function sendNotification(hookEvent, paneId, zellijSession, termProgram) {
71
71
  switch (hookEvent) {
72
72
  case "PermissionRequest":
73
73
  title = `⚠ ${appName}`;
74
- message = "Permission requested";
74
+ message = summary || "Permission requested";
75
75
  break;
76
76
  case "Stop":
77
77
  title = `✅ ${appName}`;
78
- message = "Task completed";
78
+ message = summary || "Task completed";
79
79
  break;
80
80
  case "Notification":
81
81
  title = appName;
82
- message = "Notification received";
82
+ message = summary || "Notification received";
83
83
  break;
84
84
  default:
85
85
  title = appName;
@@ -107,13 +107,47 @@ function sendNotification(hookEvent, paneId, zellijSession, termProgram) {
107
107
  execFileCb("notify-send", [title, message]);
108
108
  }
109
109
  }
110
- var ZjbarPlugin = async ({ directory }) => {
110
+ function cleanAndTruncate(text, maxLen = 120) {
111
+ let cleaned = text.replace(/\*\*/g, "").replace(/\*/g, "").replace(/`/g, "").replace(/^#+ /gm, "").replace(/\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\n/g, " ").replace(/ {2,}/g, " ").trim();
112
+ if (cleaned.length > maxLen) {
113
+ cleaned = cleaned.slice(0, maxLen - 3);
114
+ const lastSpace = cleaned.lastIndexOf(" ");
115
+ if (lastSpace > 0)
116
+ cleaned = cleaned.slice(0, lastSpace);
117
+ cleaned += "...";
118
+ }
119
+ return cleaned;
120
+ }
121
+ async function getSessionSummary(client, sessionId) {
122
+ const res = await client.session.messages({
123
+ path: { id: sessionId }
124
+ });
125
+ if (!res.data)
126
+ return null;
127
+ const messages = Array.isArray(res.data) ? res.data : [];
128
+ for (let i = messages.length - 1;i >= 0; i--) {
129
+ const msg = messages[i];
130
+ if (msg.info?.role !== "assistant")
131
+ continue;
132
+ if (!msg.parts)
133
+ continue;
134
+ for (let j = msg.parts.length - 1;j >= 0; j--) {
135
+ const part = msg.parts[j];
136
+ if (part.type === "text" && part.text) {
137
+ return cleanAndTruncate(part.text);
138
+ }
139
+ }
140
+ }
141
+ return null;
142
+ }
143
+ var ZjbarPlugin = async ({ directory, client }) => {
111
144
  const zellijSession = process.env.ZELLIJ_SESSION_NAME;
112
145
  const paneId = process.env.ZELLIJ_PANE_ID;
113
146
  if (!zellijSession || !paneId)
114
147
  return {};
115
148
  const sessionId = crypto.randomUUID();
116
149
  const termProgram = process.env.TERM_PROGRAM || null;
150
+ let activeSessionId = null;
117
151
  let zellijBin = "zellij";
118
152
  try {
119
153
  const { execFileSync } = __require("node:child_process");
@@ -126,7 +160,7 @@ var ZjbarPlugin = async ({ directory }) => {
126
160
  }
127
161
  }
128
162
  }
129
- function sendToZjbar(hookEvent, toolName) {
163
+ function sendToZjbar(hookEvent, toolName, summary) {
130
164
  const payload = JSON.stringify({
131
165
  source: "opencode",
132
166
  pane_id: parseInt(paneId, 10),
@@ -148,7 +182,7 @@ var ZjbarPlugin = async ({ directory }) => {
148
182
  ], { detached: true, stdio: "ignore" });
149
183
  child.unref();
150
184
  if (shouldNotify(hookEvent, paneId, termProgram)) {
151
- sendNotification(hookEvent, paneId, zellijSession, termProgram);
185
+ sendNotification(hookEvent, paneId, zellijSession, termProgram, summary);
152
186
  }
153
187
  }
154
188
  sendToZjbar("SessionStart");
@@ -157,18 +191,31 @@ var ZjbarPlugin = async ({ directory }) => {
157
191
  const ev = event;
158
192
  switch (ev.type) {
159
193
  case "session.created":
194
+ activeSessionId = ev.properties?.sessionID || null;
160
195
  sendToZjbar("SessionStart");
161
196
  break;
162
- case "session.idle":
163
- sendToZjbar("Stop");
197
+ case "session.idle": {
198
+ const sid = ev.properties?.sessionID || activeSessionId;
199
+ let summary = null;
200
+ if (sid && client) {
201
+ try {
202
+ summary = await getSessionSummary(client, sid);
203
+ } catch {}
204
+ }
205
+ sendToZjbar("Stop", null, summary);
164
206
  break;
207
+ }
165
208
  case "session.deleted":
166
209
  sendToZjbar("SessionEnd");
167
210
  break;
168
- case "permission.asked":
169
- sendToZjbar("PermissionRequest");
211
+ case "permission.asked": {
212
+ const perm = ev.properties;
213
+ const permTitle = perm?.title || null;
214
+ sendToZjbar("PermissionRequest", null, permTitle);
170
215
  break;
216
+ }
171
217
  case "message.created":
218
+ activeSessionId = ev.properties?.info?.sessionID || activeSessionId;
172
219
  sendToZjbar("UserPromptSubmit");
173
220
  break;
174
221
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zjbar-opencode",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "description": "zjbar plugin for OpenCode — live AI activity indicators in Zellij status bar",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",