pi-subagents-j0k3r 1.3.0 → 1.3.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.3.1 - 2026-07-13
4
+
5
+ ### Fixed
6
+ - Fixed `/subagents` live rendering so `toolcall_delta` argument JSON is no longer displayed as assistant text before native tool cards.
7
+ - Preserved streamed thinking output while routing only `text_delta` events into assistant text, matching Pi's main-thread rendering behavior.
8
+
9
+ ## 1.3.0 - 2026-07-12
10
+
11
+ ### Changed
12
+ - Modularized extension composition, tools, renderers, UI, runner, and model-profile code into cohesive modules.
13
+ - Split each registered subagent tool into a dedicated file and separated complex rendering responsibilities.
14
+ - Reorganized monolithic tests into 24 domain-focused files with 206 passing scenarios.
15
+ - Preserved root exports, historical deep imports, runtime behavior, tool contracts, package contents, and privacy boundaries.
16
+
3
17
  ## 1.2.1 - 2026-07-12
4
18
 
5
19
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-subagents-j0k3r",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Installable Pi package that adds markdown-defined subagents, delegated task tools, history, and model profiles.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/manager.ts CHANGED
@@ -175,8 +175,19 @@ export class SubagentManager {
175
175
  private onTerminalBackgroundTask?: (task: SubagentTask) => void,
176
176
  ) {}
177
177
 
178
- listAgents(cwd: string) {
179
- return loadSubagents(cwd).map((a) => ({ name: a.name, description: a.description, filePath: a.filePath, tools: a.tools, model: a.model, effort: a.effort }));
178
+ listAgents(cwd: string, ctx: any = {}) {
179
+ const config = readSubagentsConfig(cwd);
180
+ return loadSubagents(cwd).map((definition) => {
181
+ const profile = resolveEffectiveSubagentProfile({ agentName: definition.name, definition, config, ctx });
182
+ return {
183
+ name: definition.name,
184
+ description: definition.description,
185
+ filePath: definition.filePath,
186
+ tools: definition.tools,
187
+ model: profile.model.value,
188
+ effort: profile.effort.value,
189
+ };
190
+ });
180
191
  }
181
192
 
182
193
  listTasks(cwd?: string) {
@@ -0,0 +1,45 @@
1
+ import type { ModelRef, ThinkingEffort } from '../types.js';
2
+ import { textComponent } from './components.js';
3
+
4
+ export type ListedSubagent = {
5
+ name: string;
6
+ model?: ModelRef;
7
+ effort?: ThinkingEffort;
8
+ tools: string[];
9
+ };
10
+
11
+ function modelLabel(model?: ModelRef): string {
12
+ return model ? `${model.provider}/${model.id}` : 'default/current';
13
+ }
14
+
15
+ function summary(agent: ListedSubagent): string {
16
+ return `${agent.name} · model: ${modelLabel(agent.model)} · effort: ${agent.effort ?? 'default/current'}`;
17
+ }
18
+
19
+ export function formatSubagentList(agents: ListedSubagent[], includeTools: boolean): string {
20
+ if (!agents.length) return 'No subagents available.';
21
+ return agents.map((agent) => (
22
+ includeTools ? `${summary(agent)} · tools: ${agent.tools.join(', ') || 'none'}` : summary(agent)
23
+ )).join('\n');
24
+ }
25
+
26
+ export function renderSubagentListResult(result: any, expanded: boolean, theme: any) {
27
+ const agents: ListedSubagent[] = Array.isArray(result?.details?.agents) ? result.details.agents : [];
28
+ if (!agents.length) return textComponent('No subagents available.');
29
+ const dim = (text: string) => theme?.fg?.('dim', text) ?? text;
30
+
31
+ if (expanded) {
32
+ return textComponent(agents.flatMap((agent) => [
33
+ summary(agent),
34
+ dim(` tools: ${agent.tools.join(', ') || 'none'}`),
35
+ ]).join('\n'));
36
+ }
37
+
38
+ const visible = agents.slice(0, 5);
39
+ const hidden = agents.length - visible.length;
40
+ return textComponent([
41
+ ...visible.map(summary),
42
+ hidden > 0 ? dim(`… ${hidden} more agents hidden`) : undefined,
43
+ dim('ctrl+o to expand'),
44
+ ].filter((line): line is string => Boolean(line)).join('\n'));
45
+ }
@@ -1 +1 @@
1
- export type { SubagentTask } from '../types.js';
1
+ export type { ModelRef, SubagentTask, ThinkingEffort } from '../types.js';
@@ -64,11 +64,9 @@ function formatToolCall(name: string, args: any): string {
64
64
 
65
65
  function eventTranscript(event: any): string {
66
66
  const messageEvent = event?.assistantMessageEvent;
67
- const delta = messageEvent?.type !== 'thinking_delta' && typeof messageEvent?.delta === 'string'
67
+ const delta = messageEvent?.type === 'text_delta' && typeof messageEvent.delta === 'string'
68
68
  ? messageEvent.delta
69
- : messageEvent?.type === 'text_delta' && typeof messageEvent.delta === 'string'
70
- ? messageEvent.delta
71
- : undefined;
69
+ : undefined;
72
70
  if (event?.type === 'message_update' && typeof delta === 'string') return sanitizeInteractionTransportText(delta);
73
71
 
74
72
  if (event?.type === 'tool_execution_start') {
@@ -188,11 +186,9 @@ export async function promptWithInactivity(
188
186
  }
189
187
  }
190
188
  const messageEvent = event?.assistantMessageEvent;
191
- const delta = messageEvent?.type !== 'thinking_delta' && typeof messageEvent?.delta === 'string'
189
+ const delta = messageEvent?.type === 'text_delta' && typeof messageEvent.delta === 'string'
192
190
  ? messageEvent.delta
193
- : messageEvent?.type === 'text_delta' && typeof messageEvent.delta === 'string'
194
- ? messageEvent.delta
195
- : undefined;
191
+ : undefined;
196
192
  if (event?.type === 'message_end' && event.message?.role === 'assistant') usage = addUsage(usage, event.message.usage);
197
193
  if (event?.type === 'message_update' && typeof delta === 'string') {
198
194
  output += sanitizeInteractionTransportText(delta);
@@ -103,12 +103,8 @@ export class ThreadSnapshotBuilder {
103
103
  update(event: any): void {
104
104
  const now = new Date().toISOString();
105
105
  const messageEvent = event?.assistantMessageEvent;
106
- const textDelta = event?.type === 'message_update' && messageEvent?.type !== 'thinking_delta'
107
- ? typeof messageEvent?.delta === 'string'
108
- ? messageEvent.delta
109
- : messageEvent?.type === 'text_delta' && typeof messageEvent.delta === 'string'
110
- ? messageEvent.delta
111
- : undefined
106
+ const textDelta = event?.type === 'message_update' && messageEvent?.type === 'text_delta' && typeof messageEvent.delta === 'string'
107
+ ? messageEvent.delta
112
108
  : undefined;
113
109
  const thinkingDelta = event?.type === 'message_update' && messageEvent?.type === 'thinking_delta' && typeof messageEvent.delta === 'string'
114
110
  ? messageEvent.delta
@@ -1,5 +1,6 @@
1
1
  import { Type } from 'typebox';
2
2
  import type { SubagentManager } from '../manager.js';
3
+ import { formatSubagentList, renderSubagentListResult } from '../render/tools/subagent-list-agents.js';
3
4
  import { ok, fail } from './tool-response.js';
4
5
 
5
6
  export function createSubagentListAgentsTool(manager: SubagentManager) {
@@ -10,7 +11,15 @@ export function createSubagentListAgentsTool(manager: SubagentManager) {
10
11
  promptSnippet: 'List available subagents loaded from global/project agents and subagents markdown directories.',
11
12
  parameters: Type.Object({}),
12
13
  async execute(_id: string, _params: any, _signal: any, _onUpdate: any, ctx: any) {
13
- try { const agents = manager.listAgents(ctx?.cwd ?? process.cwd()); return ok(`Found ${agents.length} subagent(s).`, { agents }); } catch (e) { return fail(e); }
14
+ try {
15
+ const agents = manager.listAgents(ctx?.cwd ?? process.cwd(), ctx);
16
+ return ok(formatSubagentList(agents, true), { agents });
17
+ } catch (e) {
18
+ return fail(e);
19
+ }
20
+ },
21
+ renderResult(result: any, { expanded }: any, theme: any) {
22
+ return renderSubagentListResult(result, Boolean(expanded), theme);
14
23
  },
15
24
  };
16
25
  }