@oh-my-pi/pi-coding-agent 13.3.3 → 13.3.5

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,20 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [13.3.5] - 2026-02-26
6
+ ### Added
7
+
8
+ - Added support for setting array and record configuration values using JSON syntax
9
+
10
+ ### Changed
11
+
12
+ - Increased default async max jobs limit from 15 to 100 for improved concurrent task handling
13
+
14
+ ### Fixed
15
+
16
+ - Improved config display formatting to properly render arrays and objects as JSON instead of `[object Object]`
17
+ - Enhanced type display in config list output to show correct type indicators for number, array, and record settings
18
+
5
19
  ## [13.3.3] - 2026-02-26
6
20
  ### Added
7
21
 
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.3",
4
+ "version": "13.3.5",
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.3",
45
- "@oh-my-pi/pi-agent-core": "13.3.3",
46
- "@oh-my-pi/pi-ai": "13.3.3",
47
- "@oh-my-pi/pi-natives": "13.3.3",
48
- "@oh-my-pi/pi-tui": "13.3.3",
49
- "@oh-my-pi/pi-utils": "13.3.3",
44
+ "@oh-my-pi/omp-stats": "13.3.5",
45
+ "@oh-my-pi/pi-agent-core": "13.3.5",
46
+ "@oh-my-pi/pi-ai": "13.3.5",
47
+ "@oh-my-pi/pi-natives": "13.3.5",
48
+ "@oh-my-pi/pi-tui": "13.3.5",
49
+ "@oh-my-pi/pi-utils": "13.3.5",
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",
@@ -22,7 +22,20 @@ Returns the output, and an exit code from command execution.
22
22
  </output>
23
23
 
24
24
  <critical>
25
+ You **MUST** use specialized tools instead of bash for ALL file operations:
26
+
27
+ |Instead of (WRONG)|Use (CORRECT)|
28
+ |---|---|
29
+ |`cat file`, `head -n N file`|`read(path="file", limit=N)`|
30
+ |`cat -n file \|sed -n '50,150p'`|`read(path="file", offset=50, limit=100)`|
31
+ |`grep -A 20 'pat' file`|`grep(pattern="pat", path="file", post=20)`|
32
+ |`grep -rn 'pat' dir/`|`grep(pattern="pat", path="dir/")`|
33
+ |`rg 'pattern' dir/`|`grep(pattern="pattern", path="dir/")`|
34
+ |`find dir -name '*.ts'`|`find(pattern="dir/**/*.ts")`|
35
+ |`ls dir/`|`read(path="dir/")`|
36
+ |`cat <<'EOF' > file`|`write(path="file", content="...")`|
37
+ |`sed -i 's/old/new/' file`|`edit(path="file", edits=[...])`|
25
38
  - You **MUST NOT** use Bash for these operations like read, grep, find, edit, write, where specialized tools exist.
26
- - You **MUST NOT** use `2>&1` pattern, stdout and stderr are already merged.
39
+ - You **MUST NOT** use `2>&1` | `2>/dev/null` pattern, stdout and stderr are already merged.
27
40
  - You **MUST NOT** use `| head -n 50` or `| tail -n 100` pattern, use `head` and `tail` parameters instead.
28
41
  </critical>
@@ -18,4 +18,11 @@ Reads files from local filesystem or internal URLs.
18
18
  <output>
19
19
  - Returns file content as text; images return visual content; PDFs return extracted text
20
20
  - Missing files: returns closest filename matches for correction
21
- </output>
21
+ </output>
22
+
23
+ <critical>
24
+ - You **MUST** use `read` instead of bash for ALL file reading: `cat`, `head`, `tail`, `less`, `more` are FORBIDDEN.
25
+ - You **MUST** use `read(path="dir/")` instead of `ls dir/` for directory listings.
26
+ - You **MUST** always include the `path` parameter — NEVER call `read` with empty arguments `{}`.
27
+ - When reading specific line ranges, use `offset` and `limit`: `read(path="file", offset=50, limit=100)` not `cat -n file | sed`.
28
+ </critical>
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> => {
@@ -92,12 +92,12 @@ function buildCommonArgs(host: SSHConnectionTarget): string[] {
92
92
  }
93
93
 
94
94
  async function runSshSync(args: string[]): Promise<{ exitCode: number | null; stderr: string }> {
95
- const result = await $`ssh ${args}`.nothrow();
95
+ const result = await $`ssh ${args}`.quiet().nothrow();
96
96
  return { exitCode: result.exitCode, stderr: result.stderr.toString().trim() };
97
97
  }
98
98
 
99
99
  async function runSshCaptureSync(args: string[]): Promise<{ exitCode: number | null; stdout: string; stderr: string }> {
100
- const result = await $`ssh ${args}`.nothrow();
100
+ const result = await $`ssh ${args}`.quiet().nothrow();
101
101
  return {
102
102
  exitCode: result.exitCode,
103
103
  stdout: result.stdout.toString().trim(),
@@ -79,6 +79,7 @@ export async function executeSSH(
79
79
  using child = ptree.spawn(["ssh", ...(await buildRemoteCommand(host, resolvedCommand))], {
80
80
  signal: options?.signal,
81
81
  timeout: options?.timeout,
82
+ stdin: "pipe",
82
83
  stderr: "full",
83
84
  });
84
85