@oh-my-pi/pi-coding-agent 13.3.4 → 13.3.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/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [13.3.6] - 2026-02-26
6
+ ### Breaking Changes
7
+
8
+ - Changed `submit_result` tool parameter structure from top-level `data` or `error` fields to nested `result` object containing either `result.data` or `result.error`
9
+
10
+ ## [13.3.5] - 2026-02-26
11
+ ### Added
12
+
13
+ - Added support for setting array and record configuration values using JSON syntax
14
+
15
+ ### Changed
16
+
17
+ - Increased default async max jobs limit from 15 to 100 for improved concurrent task handling
18
+
19
+ ### Fixed
20
+
21
+ - Improved config display formatting to properly render arrays and objects as JSON instead of `[object Object]`
22
+ - Enhanced type display in config list output to show correct type indicators for number, array, and record settings
23
+
5
24
  ## [13.3.3] - 2026-02-26
6
25
  ### Added
7
26
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-coding-agent",
4
- "version": "13.3.4",
4
+ "version": "13.3.6",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://github.com/can1357/oh-my-pi",
7
7
  "author": "Can Boluk",
@@ -41,12 +41,12 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@mozilla/readability": "^0.6",
44
- "@oh-my-pi/omp-stats": "13.3.4",
45
- "@oh-my-pi/pi-agent-core": "13.3.4",
46
- "@oh-my-pi/pi-ai": "13.3.4",
47
- "@oh-my-pi/pi-natives": "13.3.4",
48
- "@oh-my-pi/pi-tui": "13.3.4",
49
- "@oh-my-pi/pi-utils": "13.3.4",
44
+ "@oh-my-pi/omp-stats": "13.3.6",
45
+ "@oh-my-pi/pi-agent-core": "13.3.6",
46
+ "@oh-my-pi/pi-ai": "13.3.6",
47
+ "@oh-my-pi/pi-natives": "13.3.6",
48
+ "@oh-my-pi/pi-tui": "13.3.6",
49
+ "@oh-my-pi/pi-utils": "13.3.6",
50
50
  "@sinclair/typebox": "^0.34",
51
51
  "@xterm/headless": "^6.0",
52
52
  "ajv": "^8.18",
@@ -134,18 +134,36 @@ function formatValue(value: unknown): string {
134
134
  if (typeof value === "number") {
135
135
  return chalk.cyan(String(value));
136
136
  }
137
+ if (typeof value === "string") {
138
+ return chalk.yellow(value);
139
+ }
140
+ if (Array.isArray(value) || typeof value === "object") {
141
+ try {
142
+ return chalk.yellow(JSON.stringify(value));
143
+ } catch {
144
+ return chalk.yellow(String(value));
145
+ }
146
+ }
137
147
  return chalk.yellow(String(value));
138
148
  }
139
149
 
140
150
  function getTypeDisplay(def: CliSettingDef): string {
141
- if (def.type === "boolean") {
142
- return "(boolean)";
143
- }
144
151
  const values = getSettingValues(def);
145
152
  if (values && values.length > 0) {
146
153
  return `(${values.join("|")})`;
147
154
  }
148
- return "(string)";
155
+ switch (def.type) {
156
+ case "boolean":
157
+ return "(boolean)";
158
+ case "number":
159
+ return "(number)";
160
+ case "array":
161
+ return "(array)";
162
+ case "record":
163
+ return "(record)";
164
+ default:
165
+ return "(string)";
166
+ }
149
167
  }
150
168
 
151
169
  // =============================================================================
@@ -177,6 +195,32 @@ function parseAndSetValue(path: SettingPath, rawValue: string): void {
177
195
  parsedValue = trimmed;
178
196
  break;
179
197
  }
198
+ case "array": {
199
+ let parsed: unknown;
200
+ try {
201
+ parsed = JSON.parse(trimmed);
202
+ } catch {
203
+ throw new Error(`Invalid array JSON: ${rawValue}`);
204
+ }
205
+ if (!Array.isArray(parsed)) {
206
+ throw new Error(`Invalid array JSON: ${rawValue}`);
207
+ }
208
+ parsedValue = parsed;
209
+ break;
210
+ }
211
+ case "record": {
212
+ let parsed: unknown;
213
+ try {
214
+ parsed = JSON.parse(trimmed);
215
+ } catch {
216
+ throw new Error(`Invalid record JSON: ${rawValue}`);
217
+ }
218
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
219
+ throw new Error(`Invalid record JSON: ${rawValue}`);
220
+ }
221
+ parsedValue = parsed;
222
+ break;
223
+ }
180
224
  default:
181
225
  parsedValue = trimmed;
182
226
  }
@@ -522,7 +522,7 @@ export const SETTINGS_SCHEMA = {
522
522
  },
523
523
  "async.maxJobs": {
524
524
  type: "number",
525
- default: 15,
525
+ default: 100,
526
526
  ui: {
527
527
  tab: "tools",
528
528
  label: "Async max jobs",
@@ -112,11 +112,11 @@ Each `report_finding` requires:
112
112
  - `file_path`: Absolute path
113
113
  - `line_start`, `line_end`: Range ≤10 lines, must overlap diff
114
114
 
115
- Final `submit_result` call (payload under `data`):
116
- - `data.overall_correctness`: "correct" (no bugs/blockers) or "incorrect"
117
- - `data.explanation`: Plain text, 1-3 sentences summarizing verdict. Don't repeat findings (captured via `report_finding`).
118
- - `data.confidence`: 0.0-1.0
119
- - `data.findings`: Optional; **MUST** omit (auto-populated from `report_finding`)
115
+ Final `submit_result` call (payload under `result.data`):
116
+ - `result.data.overall_correctness`: "correct" (no bugs/blockers) or "incorrect"
117
+ - `result.data.explanation`: Plain text, 1-3 sentences summarizing verdict. Don't repeat findings (captured via `report_finding`).
118
+ - `result.data.confidence`: 0.0-1.0
119
+ - `result.data.findings`: Optional; **MUST** omit (auto-populated from `report_finding`)
120
120
 
121
121
  You **MUST NOT** output JSON or code blocks.
122
122
 
@@ -2,8 +2,8 @@
2
2
  You stopped without calling submit_result. This is reminder {{retryCount}} of {{maxRetries}}.
3
3
 
4
4
  You **MUST** call submit_result as your only action now. Choose one:
5
- - If task is complete: call submit_result with your result in the `data` field
6
- - If task failed: call submit_result with an `error` field describing what happened
5
+ - If task is complete: call submit_result with your result in `result.data`
6
+ - If task failed: call submit_result with `result.error` describing what happened
7
7
 
8
8
  You **MUST NOT** give up if you can still complete the task through exploration (using available tools or repo context). If you submit an error, you **MUST** include what you tried and the exact blocker.
9
9
 
@@ -19,7 +19,7 @@ No TODO tracking, no progress updates. Execute, call `submit_result`, done.
19
19
 
20
20
  When finished, you **MUST** call `submit_result` exactly once. This is like writing to a ticket, provide what is required, and close it.
21
21
 
22
- This is your only way to return a result. You **MUST NOT** put JSON in plain text, and you **MUST NOT** substitute a text summary for the structured `data` parameter.
22
+ This is your only way to return a result. You **MUST NOT** put JSON in plain text, and you **MUST NOT** substitute a text summary for the structured `result.data` parameter.
23
23
 
24
24
  {{#if outputSchema}}
25
25
  Your result **MUST** match this TypeScript interface:
@@ -29,7 +29,7 @@ Your result **MUST** match this TypeScript interface:
29
29
  {{/if}}
30
30
 
31
31
  {{SECTION_SEPERATOR "Giving Up"}}
32
- If you cannot complete the assignment, you **MUST** call `submit_result` exactly once with an `error` message describing what you tried and the exact blocker.
32
+ If you cannot complete the assignment, you **MUST** call `submit_result` exactly once with `result.error` describing what you tried and the exact blocker.
33
33
 
34
34
  Giving up is a last resort.
35
35
  You **MUST NOT** give up due to uncertainty or missing information obtainable via tools or repo context.
package/src/sdk.ts CHANGED
@@ -729,7 +729,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
729
729
 
730
730
  const enableLsp = options.enableLsp ?? true;
731
731
  const asyncEnabled = settings.get("async.enabled");
732
- const asyncMaxJobs = Math.min(100, Math.max(1, settings.get("async.maxJobs") ?? 15));
732
+ const asyncMaxJobs = Math.min(100, Math.max(1, settings.get("async.maxJobs") ?? 100));
733
733
  const ASYNC_INLINE_RESULT_MAX_CHARS = 12_000;
734
734
  const ASYNC_PREVIEW_MAX_CHARS = 4_000;
735
735
  const formatAsyncResultForFollowUp = async (result: string): Promise<string> => {
@@ -89,16 +89,20 @@ export class SubmitResultTool implements AgentTool<TSchema, SubmitResultDetails>
89
89
  ...(normalizedSchema as object),
90
90
  description: `Structured output matching the schema:\n${schemaHint}`,
91
91
  })
92
- : Type.Object({}, { additionalProperties: true, description: "Structured JSON output (no schema specified)" });
93
-
94
- this.parameters = Type.Union([
95
- Type.Object({
96
- data: dataSchema,
97
- }),
98
- Type.Object({
99
- error: Type.String({ description: "Error message when the task cannot be completed" }),
100
- }),
101
- ]);
92
+ : Type.Record(Type.String(), Type.Any(), { description: "Structured JSON output (no schema specified)" });
93
+
94
+ this.parameters = Type.Object(
95
+ {
96
+ result: Type.Union([
97
+ Type.Object({ data: dataSchema }, { description: "Successfully completed the task" }),
98
+ Type.Object({ error: Type.String({ description: "Error message when the task cannot be completed" }) }),
99
+ ]),
100
+ },
101
+ {
102
+ additionalProperties: false,
103
+ description: "Submit either `data` for success or `error` for failure",
104
+ },
105
+ );
102
106
  }
103
107
 
104
108
  async execute(
@@ -109,10 +113,23 @@ export class SubmitResultTool implements AgentTool<TSchema, SubmitResultDetails>
109
113
  _context?: AgentToolContext,
110
114
  ): Promise<AgentToolResult<SubmitResultDetails>> {
111
115
  const raw = params as Record<string, unknown>;
112
- const errorMessage = typeof raw.error === "string" ? raw.error : undefined;
113
- const status = errorMessage !== undefined ? "aborted" : "success";
114
- const data = raw.data;
116
+ const rawResult = raw.result;
117
+ if (!rawResult || typeof rawResult !== "object" || Array.isArray(rawResult)) {
118
+ throw new Error("result must be an object containing either data or error");
119
+ }
115
120
 
121
+ const resultRecord = rawResult as Record<string, unknown>;
122
+ const errorMessage = typeof resultRecord.error === "string" ? resultRecord.error : undefined;
123
+ const data = resultRecord.data;
124
+
125
+ if (errorMessage !== undefined && data !== undefined) {
126
+ throw new Error("result cannot contain both data and error");
127
+ }
128
+ if (errorMessage === undefined && data === undefined) {
129
+ throw new Error("result must contain either data or error");
130
+ }
131
+
132
+ const status = errorMessage !== undefined ? "aborted" : "success";
116
133
  if (status === "success") {
117
134
  if (data === undefined || data === null) {
118
135
  throw new Error("data is required when submit_result indicates success");