@oh-my-pi/pi-coding-agent 9.6.3 → 9.7.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-coding-agent",
3
- "version": "9.6.3",
3
+ "version": "9.7.0",
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.6.3",
83
- "@oh-my-pi/pi-agent-core": "9.6.3",
84
- "@oh-my-pi/pi-ai": "9.6.3",
85
- "@oh-my-pi/pi-natives": "9.6.3",
86
- "@oh-my-pi/pi-tui": "9.6.3",
87
- "@oh-my-pi/pi-utils": "9.6.3",
82
+ "@oh-my-pi/omp-stats": "9.7.0",
83
+ "@oh-my-pi/pi-agent-core": "9.7.0",
84
+ "@oh-my-pi/pi-ai": "9.7.0",
85
+ "@oh-my-pi/pi-natives": "9.7.0",
86
+ "@oh-my-pi/pi-tui": "9.7.0",
87
+ "@oh-my-pi/pi-utils": "9.7.0",
88
88
  "@openai/agents": "^0.4.4",
89
89
  "@sinclair/typebox": "^0.34.48",
90
90
  "ajv": "^8.17.1",
@@ -105,7 +105,6 @@ async function executeBashOnce(
105
105
  env: finalEnv,
106
106
  signal: options?.signal,
107
107
  timeout: options?.timeout,
108
- detached: true,
109
108
  });
110
109
 
111
110
  // Pump streams - errors during abort/timeout are expected
@@ -254,7 +254,6 @@ class ShellSession {
254
254
  this.#child = ptree.spawn([this.config.shell, ...args], {
255
255
  stdin: "pipe",
256
256
  env: this.config.env,
257
- detached: !IS_WINDOWS,
258
257
  });
259
258
 
260
259
  if (this.#child.proc.exitCode !== null) {
@@ -502,11 +501,7 @@ class ShellSession {
502
501
  child.proc.kill("SIGINT");
503
502
  return;
504
503
  }
505
- if (child.isProcessGroup) {
506
- process.kill(-child.pid, "SIGINT");
507
- } else {
508
- process.kill(child.pid, "SIGINT");
509
- }
504
+ process.kill(child.pid, "SIGINT");
510
505
  } catch {}
511
506
  }
512
507
 
@@ -265,8 +265,8 @@ async function startGatewayProcess(
265
265
  stdin: "ignore",
266
266
  stdout: "pipe",
267
267
  stderr: "pipe",
268
- detached: true,
269
268
  windowsHide: true,
269
+ detached: true,
270
270
  env: kernelEnv,
271
271
  },
272
272
  );
@@ -296,13 +296,13 @@ async function startGatewayProcess(
296
296
  await Bun.sleep(100);
297
297
  }
298
298
 
299
- await procmgr.terminate({ target: gatewayProcess, group: true });
299
+ gatewayProcess.kill();
300
300
  throw new Error("Gateway startup timeout");
301
301
  }
302
302
 
303
303
  async function killGateway(pid: number, context: string): Promise<void> {
304
304
  try {
305
- await procmgr.terminate({ target: pid, group: true });
305
+ await procmgr.terminate({ target: pid });
306
306
  } catch (err) {
307
307
  logger.warn("Failed to kill shared gateway process", {
308
308
  error: err instanceof Error ? err.message : String(err),
package/src/ipy/kernel.ts CHANGED
@@ -490,7 +490,6 @@ export class PythonKernel {
490
490
  {
491
491
  cwd: options.cwd,
492
492
  env: kernelEnv,
493
- detached: true,
494
493
  },
495
494
  );
496
495
 
package/src/lsp/client.ts CHANGED
@@ -411,7 +411,6 @@ export async function getOrCreateClient(config: ServerConfig, cwd: string, initT
411
411
 
412
412
  const proc = ptree.spawn([command, ...args], {
413
413
  cwd,
414
- detached: true,
415
414
  stdin: "pipe",
416
415
  env: env ? { ...process.env, ...env } : undefined,
417
416
  });
package/src/main.ts CHANGED
@@ -385,7 +385,8 @@ async function buildSessionOptions(
385
385
  process.exit(1);
386
386
  }
387
387
  options.model = model;
388
- settings.setModelRole("default", `${model.provider}/${model.id}`);
388
+ const currentRoles = settings.get("modelRoles") as Record<string, string>;
389
+ settings.override("modelRoles", { ...currentRoles, default: `${model.provider}/${model.id}` });
389
390
  } else if (scopedModels.length > 0 && !parsed.continue && !parsed.resume) {
390
391
  const remembered = settings.getModelRole("default");
391
392
  if (remembered) {
@@ -637,9 +638,10 @@ export async function main(args: string[]) {
637
638
  const planModel = parsed.plan ?? process.env.OMP_PLAN_MODEL;
638
639
  if (smolModel || slowModel || planModel) {
639
640
  const currentRoles = settings.get("modelRoles") as Record<string, string>;
640
- if (smolModel) settings.override("modelRoles", { ...currentRoles, smol: smolModel });
641
- if (slowModel) settings.override("modelRoles", { ...currentRoles, slow: slowModel });
642
- if (planModel) settings.override("modelRoles", { ...currentRoles, plan: planModel });
641
+ if (smolModel) currentRoles.smol = smolModel;
642
+ if (slowModel) currentRoles.slow = slowModel;
643
+ if (planModel) currentRoles.plan = planModel;
644
+ settings.override("modelRoles", currentRoles);
643
645
  }
644
646
 
645
647
  await initTheme(settings.get("theme"), isInteractive, settings.get("symbolPreset"), settings.get("colorBlindMode"));
@@ -290,6 +290,31 @@ These are comfort. They are not clarity.
290
290
  {{appendSystemPrompt}}
291
291
  {{/if}}
292
292
 
293
+ {{#if isCoordinator}}
294
+ {{#has tools "task"}}
295
+ <parallel_reflex>
296
+ When the work forks, you fork.
297
+
298
+ Notice the sequential habit:
299
+ - The comfort of doing one thing at a time
300
+ - The illusion that order means correctness
301
+ - The assumption that you must finish A before starting B
302
+ **Triggers requiring Task tool:**
303
+ - Editing 4+ files with no dependencies between edits
304
+ - Investigating 2+ independent subsystems or questions
305
+ - Any work that decomposes into pieces that don't need each other's results
306
+
307
+ <critical>
308
+ Sequential requires justification.
309
+ If you cannot articulate why B depends on A's result, they are parallel.
310
+ </critical>
311
+
312
+ Do not carry the whole problem in one skull.
313
+ Split the load. Bring back facts. Then cut code.
314
+ </parallel_reflex>
315
+ {{/has}}
316
+ {{/if}}
317
+
293
318
  <stakes>
294
319
  This is not practice.
295
320
 
@@ -325,23 +350,4 @@ The question is not "Does this work?"
325
350
  but "Under what conditions does this work, and what happens outside them?"
326
351
 
327
352
  Write what you can defend.
328
- </critical>
329
-
330
- {{#if isCoordinator}}
331
- {{#has tools "task"}}
332
- <critical id="coordinator">
333
- Your context window is limited—especially the output. Work in discrete steps and run each step using Task tool. Avoid putting substantial work in the main context when possible. Run multiple tasks in parallel whenever possible.
334
-
335
- ## Triggers requiring Task tool
336
- - Editing 4+ files with no dependencies → `Task`
337
- - Investigating 2+ independent questions → `Task`
338
- - Any work that decomposes into pieces that don't need each other's results → `Task`
339
-
340
- Sequential requires justification.
341
- If you cannot articulate why B depends on A's result, they are parallel.
342
-
343
- Do not carry the whole problem in one skull.
344
- Split the load. Bring back facts. Then synthesize.
345
- </critical>
346
- {{/has}}
347
- {{/if}}
353
+ </critical>
package/src/tools/find.ts CHANGED
@@ -238,8 +238,8 @@ export class FindTool implements AgentTool<typeof findSchema, FindToolDetails> {
238
238
  });
239
239
  };
240
240
  const onMatch = onUpdate
241
- ? (match: FindMatch) => {
242
- if (signal?.aborted) return;
241
+ ? (match: FindMatch | null) => {
242
+ if (signal?.aborted || !match) return;
243
243
  let relativePath = match.path;
244
244
  if (!relativePath) return;
245
245
  if (match.fileType === "dir" && !relativePath.endsWith("/")) {
package/src/tools/read.ts CHANGED
@@ -497,7 +497,6 @@ async function convertWithMarkitdown(
497
497
  allowNonZero: true,
498
498
  allowAbort: true,
499
499
  stderr: "buffer",
500
- detached: true,
501
500
  });
502
501
 
503
502
  if (result.exitError?.aborted) {
@@ -54,7 +54,6 @@ export async function convertWithMarkitdown(
54
54
  signal,
55
55
  allowNonZero: true,
56
56
  stderr: "full",
57
- detached: true,
58
57
  });
59
58
  if (!result.ok) {
60
59
  return {