@doingdev/opencode-claude-manager-plugin 0.1.5 → 0.1.6

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/README.md CHANGED
@@ -50,7 +50,7 @@ If you are testing locally, point OpenCode at the local package or plugin file u
50
50
 
51
51
  ## OpenCode tools
52
52
 
53
- - `claude_manager_run` - run a task through Claude with optional splitting and worktrees
53
+ - `claude_manager_run` - run a task through Claude with optional splitting and worktrees; returns a compact output summary and a `runId` for deeper inspection
54
54
  - `claude_manager_metadata` - inspect available Claude commands, skills, hooks, and settings
55
55
  - `claude_manager_sessions` - list Claude sessions or inspect a saved transcript
56
56
  - `claude_manager_runs` - inspect persisted manager run records
@@ -136,10 +136,14 @@ function normalizeSdkMessage(message) {
136
136
  };
137
137
  }
138
138
  if (message.type === 'stream_event') {
139
+ const partialText = extractPartialEventText(message.event);
140
+ if (!partialText) {
141
+ return null;
142
+ }
139
143
  return {
140
144
  type: 'partial',
141
145
  sessionId,
142
- text: extractPartialEventText(message.event),
146
+ text: partialText,
143
147
  rawType: message.type,
144
148
  };
145
149
  }
@@ -191,21 +195,21 @@ function normalizeSdkMessage(message) {
191
195
  }
192
196
  function extractPartialEventText(event) {
193
197
  if (!event || typeof event !== 'object') {
194
- return 'stream_event';
198
+ return null;
195
199
  }
196
200
  const eventRecord = event;
197
- const eventType = typeof eventRecord.type === 'string' ? eventRecord.type : 'stream_event';
198
201
  const delta = eventRecord.delta;
199
202
  if (delta && typeof delta === 'object') {
200
203
  const deltaRecord = delta;
201
- if (typeof deltaRecord.text === 'string') {
204
+ if (typeof deltaRecord.text === 'string' && deltaRecord.text.length > 0) {
202
205
  return deltaRecord.text;
203
206
  }
204
- if (typeof deltaRecord.partial_json === 'string') {
207
+ if (typeof deltaRecord.partial_json === 'string' &&
208
+ deltaRecord.partial_json.length > 0) {
205
209
  return deltaRecord.partial_json;
206
210
  }
207
211
  }
208
- return eventType;
212
+ return null;
209
213
  }
210
214
  function extractText(payload) {
211
215
  if (typeof payload === 'string') {
@@ -1,2 +1,4 @@
1
1
  import { type Plugin } from '@opencode-ai/plugin';
2
+ import type { ManagerRunRecord } from '../types/contracts.js';
2
3
  export declare const ClaudeManagerPlugin: Plugin;
4
+ export declare function formatManagerRunToolResult(run: ManagerRunRecord): string;
@@ -127,7 +127,7 @@ export const ClaudeManagerPlugin = async ({ worktree }) => {
127
127
  lastProgressSignature = signature;
128
128
  context.metadata(progressView);
129
129
  });
130
- return JSON.stringify(result.run, null, 2);
130
+ return formatManagerRunToolResult(result.run);
131
131
  },
132
132
  }),
133
133
  claude_manager_metadata: tool({
@@ -243,6 +243,32 @@ function rewriteCommandParts(parts, text) {
243
243
  });
244
244
  return rewrittenParts;
245
245
  }
246
+ export function formatManagerRunToolResult(run) {
247
+ const finalSummary = run.finalSummary ?? summarizeSessionOutputs(run.sessions);
248
+ const output = run.sessions.length === 1
249
+ ? resolveSessionOutput(run.sessions[0])
250
+ : finalSummary;
251
+ return JSON.stringify({
252
+ runId: run.id,
253
+ status: run.status,
254
+ output,
255
+ finalSummary,
256
+ sessions: run.sessions.map((session) => ({
257
+ title: session.title,
258
+ status: session.status,
259
+ output: resolveSessionOutput(session),
260
+ claudeSessionId: session.claudeSessionId,
261
+ worktreeMode: session.worktreeMode,
262
+ branchName: session.branchName,
263
+ turns: session.turns,
264
+ totalCostUsd: session.totalCostUsd,
265
+ })),
266
+ inspectRun: {
267
+ tool: 'claude_manager_runs',
268
+ runId: run.id,
269
+ },
270
+ }, null, 2);
271
+ }
246
272
  function buildRunProgressView(run) {
247
273
  const completed = run.sessions.filter((session) => session.status === 'completed').length;
248
274
  const failed = run.sessions.filter((session) => session.status === 'failed').length;
@@ -284,18 +310,26 @@ function formatSessionActivity(session) {
284
310
  parts.push(session.claudeSessionId);
285
311
  }
286
312
  const latestEvent = findLatestDisplayEvent(session.events);
287
- if (latestEvent) {
288
- parts.push(`${latestEvent.type}: ${truncateForDisplay(latestEvent.text, 120)}`);
289
- }
290
- else if (session.finalText) {
313
+ if (session.finalText) {
291
314
  parts.push(truncateForDisplay(session.finalText, 120));
292
315
  }
293
316
  else if (session.error) {
294
317
  parts.push(truncateForDisplay(session.error, 120));
295
318
  }
319
+ else if (latestEvent) {
320
+ parts.push(`${latestEvent.type}: ${truncateForDisplay(latestEvent.text, 120)}`);
321
+ }
296
322
  return parts.join(' | ');
297
323
  }
298
324
  function findLatestDisplayEvent(events) {
325
+ const reversedEvents = [...events].reverse();
326
+ const preferredEvent = reversedEvents.find((event) => (event.type === 'result' ||
327
+ event.type === 'error' ||
328
+ event.type === 'assistant') &&
329
+ Boolean(event.text.trim()));
330
+ if (preferredEvent) {
331
+ return preferredEvent;
332
+ }
299
333
  return [...events]
300
334
  .reverse()
301
335
  .find((event) => event.type !== 'partial' && Boolean(event.text.trim()));
@@ -307,3 +341,15 @@ function truncateForDisplay(text, maxLength) {
307
341
  }
308
342
  return `${normalized.slice(0, maxLength - 3)}...`;
309
343
  }
344
+ function summarizeSessionOutputs(sessions) {
345
+ return sessions
346
+ .map((session) => `${session.title}: ${resolveSessionOutput(session)}`)
347
+ .join('\n');
348
+ }
349
+ function resolveSessionOutput(session) {
350
+ const latestEvent = findLatestDisplayEvent(session.events);
351
+ return (session.finalText?.trim() ||
352
+ session.error?.trim() ||
353
+ latestEvent?.text.trim() ||
354
+ session.status);
355
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doingdev/opencode-claude-manager-plugin",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "OpenCode plugin that orchestrates Claude Code sessions.",
5
5
  "keywords": [
6
6
  "opencode",