@oh-my-pi/pi-coding-agent 9.3.0 → 9.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
@@ -2,6 +2,22 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [9.3.1] - 2026-01-31
6
+ ### Added
7
+
8
+ - Added `getCompactContext()` API to retrieve parent conversation context for subagents, excluding system prompts and tool results
9
+ - Added automatic `submit_result` tool injection for subagents with explicit tool lists
10
+ - Added `contextFile` parameter to pass parent conversation context to subagent sessions
11
+
12
+ ### Changed
13
+
14
+ - Updated subagent system prompt to reference parent conversation context file when available
15
+ - Enhanced subagent system prompt formatting with clearer backtick notation for tool and parameter names
16
+
17
+ ### Removed
18
+
19
+ - Removed schema override notification from task summary prompt
20
+
5
21
  ## [9.2.5] - 2026-01-31
6
22
  ### Changed
7
23
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-coding-agent",
3
- "version": "9.3.0",
3
+ "version": "9.3.1",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "ompConfig": {
@@ -79,12 +79,12 @@
79
79
  "test": "bun test"
80
80
  },
81
81
  "dependencies": {
82
- "@oh-my-pi/omp-stats": "9.3.0",
83
- "@oh-my-pi/pi-agent-core": "9.3.0",
84
- "@oh-my-pi/pi-ai": "9.3.0",
85
- "@oh-my-pi/pi-natives": "9.3.0",
86
- "@oh-my-pi/pi-tui": "9.3.0",
87
- "@oh-my-pi/pi-utils": "9.3.0",
82
+ "@oh-my-pi/omp-stats": "9.3.1",
83
+ "@oh-my-pi/pi-agent-core": "9.3.1",
84
+ "@oh-my-pi/pi-ai": "9.3.1",
85
+ "@oh-my-pi/pi-natives": "9.3.1",
86
+ "@oh-my-pi/pi-tui": "9.3.1",
87
+ "@oh-my-pi/pi-utils": "9.3.1",
88
88
  "@openai/agents": "^0.4.4",
89
89
  "@sinclair/typebox": "^0.34.48",
90
90
  "ajv": "^8.17.1",
@@ -189,7 +189,12 @@ export function parseAgentFields(frontmatter: Record<string, unknown>): ParsedAg
189
189
  return null;
190
190
  }
191
191
 
192
- const tools = parseArrayOrCSV(frontmatter.tools);
192
+ let tools = parseArrayOrCSV(frontmatter.tools);
193
+
194
+ // Subagents with explicit tool lists always need submit_result
195
+ if (tools && !tools.includes("submit_result")) {
196
+ tools = [...tools, "submit_result"];
197
+ }
193
198
 
194
199
  // Parse spawns field (array, "*", or CSV)
195
200
  let spawns: string[] | "*" | undefined;
@@ -1,24 +1,31 @@
1
1
  {{base}}
2
- -----------------------------------
2
+
3
+ ====================================================
3
4
 
4
5
  {{agent}}
5
6
 
7
+ {{#if contextFile}}
8
+ <context>
9
+ If you need additional context about the parent conversation, check {{contextFile}} (e.g., `tail -100` or `grep` for relevant terms).
10
+ </context>
11
+ {{/if}}
12
+
6
13
  <critical>
7
14
  {{#if worktree}}
8
15
  - You MUST work under this working tree: {{worktree}}. Do not modify anything under the original repository.
9
16
  {{/if}}
10
- - You MUST call the submit_result tool exactly once when finished. Do not output JSON in text. Do not end with a plain-text summary. Call submit_result with your result as the data parameter.
17
+ - You MUST call the `submit_result` tool exactly once when finished. Do not output JSON in text. Do not end with a plain-text summary. Call `submit_result` with your result as the `data` parameter.
11
18
  {{#if outputSchema}}
12
- - If you cannot complete the task, call submit_result with status="aborted" and an error message. Do not provide a success result or pretend completion.
19
+ - If you cannot complete the task, call `submit_result` with `status="aborted"` and an error message. Do not provide a success result or pretend completion.
13
20
  {{else}}
14
- - If you cannot complete the task, call submit_result with status="aborted" and an error message. Do not claim success.
21
+ - If you cannot complete the task, call `submit_result` with `status="aborted"` and an error message. Do not claim success.
15
22
  {{/if}}
16
23
  {{#if outputSchema}}
17
- - The data parameter MUST be valid JSON matching this TypeScript interface:
18
- ```typescript
24
+ - The `data` parameter MUST be valid JSON matching this TypeScript interface:
25
+ ```ts
19
26
  {{jtdToTypeScript outputSchema}}
20
27
  ```
21
28
  {{/if}}
22
- - If you cannot complete the task, call submit_result exactly once with a result that explicitly indicates failure or abort status (use a failure/notes field if available). Do not claim success.
29
+ - If you cannot complete the task, call `submit_result` exactly once with a result that explicitly indicates failure or abort status (use a failure/notes field if available). Do not claim success.
23
30
  - Keep going until request is fully fulfilled. This matters.
24
31
  </critical>
@@ -20,13 +20,6 @@
20
20
  {{/unless}}
21
21
  {{/each}}
22
22
 
23
- {{#if schemaOverridden}}
24
- <schema-note>
25
- Note: Agent '{{agentName}}' has a fixed output schema:
26
- {{requiredSchema}}
27
- </schema-note>
28
- {{/if}}
29
-
30
23
  {{#if patchApplySummary}}
31
24
  <patch-summary>
32
25
  {{patchApplySummary}}
package/src/sdk.ts CHANGED
@@ -760,6 +760,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
760
760
  return undefined;
761
761
  },
762
762
  getPlanModeState: () => session.getPlanModeState(),
763
+ getCompactContext: () => session.formatCompactContext(),
763
764
  settings: settingsManager,
764
765
  settingsManager,
765
766
  authStorage,
@@ -3916,6 +3916,69 @@ Be thorough - include exact file paths, function names, error messages, and tech
3916
3916
  return lines.join("\n").trim();
3917
3917
  }
3918
3918
 
3919
+ /**
3920
+ * Format the conversation as compact context for subagents.
3921
+ * Includes only user messages and assistant text responses.
3922
+ * Excludes: system prompt, tool definitions, tool calls/results, thinking blocks.
3923
+ */
3924
+ formatCompactContext(): string {
3925
+ const lines: string[] = [];
3926
+ lines.push("# Conversation Context");
3927
+ lines.push("");
3928
+ lines.push(
3929
+ "This is a summary of the parent conversation. Read this if you need additional context about what was discussed or decided.",
3930
+ );
3931
+ lines.push("");
3932
+
3933
+ for (const msg of this.messages) {
3934
+ if (msg.role === "user") {
3935
+ lines.push("## User");
3936
+ lines.push("");
3937
+ if (typeof msg.content === "string") {
3938
+ lines.push(msg.content);
3939
+ } else {
3940
+ for (const c of msg.content) {
3941
+ if (c.type === "text") {
3942
+ lines.push(c.text);
3943
+ } else if (c.type === "image") {
3944
+ lines.push("[Image attached]");
3945
+ }
3946
+ }
3947
+ }
3948
+ lines.push("");
3949
+ } else if (msg.role === "assistant") {
3950
+ const assistantMsg = msg as AssistantMessage;
3951
+ // Only include text content, skip tool calls and thinking
3952
+ const textParts: string[] = [];
3953
+ for (const c of assistantMsg.content) {
3954
+ if (c.type === "text" && c.text.trim()) {
3955
+ textParts.push(c.text);
3956
+ }
3957
+ }
3958
+ if (textParts.length > 0) {
3959
+ lines.push("## Assistant");
3960
+ lines.push("");
3961
+ lines.push(textParts.join("\n\n"));
3962
+ lines.push("");
3963
+ }
3964
+ } else if (msg.role === "fileMention") {
3965
+ const fileMsg = msg as FileMentionMessage;
3966
+ const paths = fileMsg.files.map(f => f.path).join(", ");
3967
+ lines.push(`[Files referenced: ${paths}]`);
3968
+ lines.push("");
3969
+ } else if (msg.role === "compactionSummary") {
3970
+ const compactMsg = msg as CompactionSummaryMessage;
3971
+ lines.push("## Earlier Context (Summarized)");
3972
+ lines.push("");
3973
+ lines.push(compactMsg.summary);
3974
+ lines.push("");
3975
+ }
3976
+ // Skip: toolResult, bashExecution, pythonExecution, branchSummary, custom, hookMessage
3977
+ }
3978
+
3979
+ return lines.join("\n").trim();
3980
+ }
3981
+
3919
3982
  // =========================================================================
3920
3983
  // Extension System
3921
3984
  // =========================================================================
@@ -196,6 +196,8 @@ export interface ExecutorOptions {
196
196
  sessionFile?: string | null;
197
197
  persistArtifacts?: boolean;
198
198
  artifactsDir?: string;
199
+ /** Path to parent conversation context file */
200
+ contextFile?: string;
199
201
  eventBus?: EventBus;
200
202
  contextFiles?: ContextFileEntry[];
201
203
  skills?: Skill[];
@@ -948,6 +950,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
948
950
  agent: agent.systemPrompt,
949
951
  worktree: worktree ?? "",
950
952
  outputSchema: normalizedOutputSchema,
953
+ contextFile: options.contextFile,
951
954
  }),
952
955
  sessionManager,
953
956
  hasUI: false,
package/src/task/index.ts CHANGED
@@ -211,7 +211,6 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
211
211
  const thinkingLevelOverride = effectiveAgent.thinkingLevel;
212
212
 
213
213
  // Output schema priority: agent frontmatter > params > inherited from parent session
214
- const schemaOverridden = outputSchema !== undefined && effectiveAgent.output !== undefined;
215
214
  const effectiveOutputSchema = effectiveAgent.output ?? outputSchema ?? this.session.outputSchema;
216
215
 
217
216
  // Handle empty or missing tasks
@@ -382,6 +381,15 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
382
381
  };
383
382
  }
384
383
 
384
+ // Write parent conversation context for subagents
385
+ await fs.mkdir(effectiveArtifactsDir, { recursive: true });
386
+ const compactContext = this.session.getCompactContext?.();
387
+ let contextFilePath: string | undefined;
388
+ if (compactContext) {
389
+ contextFilePath = path.join(effectiveArtifactsDir, "context.md");
390
+ await Bun.write(contextFilePath, compactContext);
391
+ }
392
+
385
393
  // Build full prompts with context prepended
386
394
  // Allocate unique IDs across the session to prevent artifact collisions
387
395
  const outputManager =
@@ -478,6 +486,7 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
478
486
  sessionFile,
479
487
  persistArtifacts: !!artifactsDir,
480
488
  artifactsDir: effectiveArtifactsDir,
489
+ contextFile: contextFilePath,
481
490
  enableLsp: false,
482
491
  signal,
483
492
  eventBus: undefined,
@@ -522,6 +531,7 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
522
531
  sessionFile,
523
532
  persistArtifacts: !!artifactsDir,
524
533
  artifactsDir: effectiveArtifactsDir,
534
+ contextFile: contextFilePath,
525
535
  enableLsp: false,
526
536
  signal,
527
537
  eventBus: undefined,
@@ -735,9 +745,7 @@ export class TaskTool implements AgentTool<typeof taskSchema, TaskToolDetails, T
735
745
  duration: formatDuration(totalDuration),
736
746
  summaries,
737
747
  outputIds,
738
- schemaOverridden,
739
748
  agentName,
740
- requiredSchema: agent.output ? JSON.stringify(agent.output) : "",
741
749
  patchApplySummary,
742
750
  });
743
751
 
@@ -173,6 +173,8 @@ export interface ToolSession {
173
173
  };
174
174
  /** Plan mode state (if active) */
175
175
  getPlanModeState?: () => PlanModeState | undefined;
176
+ /** Get compact conversation context for subagents (excludes tool results, system prompts) */
177
+ getCompactContext?: () => string;
176
178
  }
177
179
 
178
180
  type ToolFactory = (session: ToolSession) => Tool | null | Promise<Tool | null>;