pi-subagents-lite 0.2.0 → 0.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/src/context.ts CHANGED
@@ -1,9 +1,13 @@
1
1
  /**
2
2
  * context.ts — Extract parent conversation context for subagent inheritance.
3
3
  *
4
- * Keep extractText only. buildParentContext removed (inherit_context is cut).
4
+ * Contains extractText (for message content) and buildSnapshotMarkdown
5
+ * (for agent session snapshot viewer). buildParentContext was removed
6
+ * when inherit_context was cut.
5
7
  */
6
8
 
9
+ import { summarizeToolArgs } from "./output-file.js";
10
+
7
11
  /** Extract text from a message content block array. */
8
12
  export function extractText(content: unknown[]): string {
9
13
  return content
@@ -11,3 +15,78 @@ export function extractText(content: unknown[]): string {
11
15
  .map((c: any) => c.text ?? "")
12
16
  .join("\n");
13
17
  }
18
+
19
+ /**
20
+ * Build a markdown snapshot of the full agent conversation from session messages.
21
+ *
22
+ * Formatting rules:
23
+ * - User messages: `> user: text` blockquote
24
+ * - Assistant messages: regular markdown text
25
+ * - Tool results: `> ToolName: summarized args` blockquote (using summarizeToolArgs)
26
+ * - Unrecognized message roles are skipped
27
+ *
28
+ * Tool arguments live on ToolCall blocks inside AssistantMessage.content (linked by id),
29
+ * not on ToolResultMessage. We pre-build a lookup map.
30
+ *
31
+ * @param messages - Agent session messages (from AgentSession.messages)
32
+ * @returns Formatted markdown string
33
+ */
34
+ export function buildSnapshotMarkdown(messages: readonly any[]): string {
35
+ // Build toolCallId -> arguments map from assistant messages
36
+ const argsMap = new Map<string, Record<string, unknown>>();
37
+ for (const msg of messages) {
38
+ if (msg.role === "assistant" && Array.isArray(msg.content)) {
39
+ for (const block of msg.content) {
40
+ if (block.type === "toolCall" && block.id && block.arguments) {
41
+ argsMap.set(block.id, block.arguments);
42
+ }
43
+ }
44
+ }
45
+ }
46
+
47
+ const lines: string[] = [];
48
+
49
+ for (const msg of messages) {
50
+ switch (msg.role) {
51
+ case "user": {
52
+ const content = msg.content;
53
+ const text =
54
+ typeof content === "string"
55
+ ? content
56
+ : extractText(content ?? []);
57
+ lines.push(`> user: ${text}`, "");
58
+ break;
59
+ }
60
+ case "assistant": {
61
+ const text = extractText(msg.content ?? []);
62
+ if (text) {
63
+ lines.push(text, "");
64
+ }
65
+ break;
66
+ }
67
+ case "toolResult": {
68
+ const name = msg.toolName ?? "tool";
69
+ const displayName = name.charAt(0).toUpperCase() + name.slice(1);
70
+
71
+ // Args live on the ToolCall (assistant message), looked up by toolCallId
72
+ const toolArgs = argsMap.get(msg.toolCallId);
73
+ let summary = summarizeToolArgs(name, toolArgs);
74
+ if (summary) {
75
+ // Strip outer parens from summarizeToolArgs output for cleaner display
76
+ if (summary.startsWith("(") && summary.endsWith(")")) {
77
+ summary = summary.slice(1, -1);
78
+ }
79
+ // Strip leading space from default multi-key output
80
+ if (summary.startsWith(" ")) {
81
+ summary = summary.trimStart();
82
+ }
83
+ }
84
+ lines.push(summary ? `> ${displayName}: ${summary}` : `> ${displayName}`, "");
85
+ break;
86
+ }
87
+ // Skip custom/unrecognized message types
88
+ }
89
+ }
90
+
91
+ return lines.join("\n");
92
+ }