@oh-my-pi/pi-coding-agent 17.0.6 → 17.0.8

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.
Files changed (83) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/dist/cli.js +4967 -4948
  3. package/dist/types/config/model-registry.d.ts +1 -1
  4. package/dist/types/config/model-resolver.d.ts +5 -1
  5. package/dist/types/config/settings-schema.d.ts +16 -0
  6. package/dist/types/dap/client.d.ts +19 -0
  7. package/dist/types/extensibility/extensions/runner.d.ts +4 -2
  8. package/dist/types/extensibility/extensions/types.d.ts +3 -0
  9. package/dist/types/extensibility/typebox.d.ts +4 -0
  10. package/dist/types/hindsight/client.d.ts +10 -0
  11. package/dist/types/hindsight/config.d.ts +8 -0
  12. package/dist/types/mcp/tool-bridge.d.ts +9 -0
  13. package/dist/types/mnemopi/state.d.ts +2 -0
  14. package/dist/types/modes/components/user-message.d.ts +25 -1
  15. package/dist/types/modes/controllers/extension-ui-controller.d.ts +8 -0
  16. package/dist/types/modes/interactive-mode.d.ts +7 -1
  17. package/dist/types/modes/types.d.ts +14 -1
  18. package/dist/types/modes/utils/ui-helpers.d.ts +12 -8
  19. package/dist/types/sdk.d.ts +1 -0
  20. package/dist/types/session/agent-session-error-log.test.d.ts +1 -0
  21. package/dist/types/session/agent-session.d.ts +78 -2
  22. package/dist/types/task/executor.d.ts +10 -0
  23. package/dist/types/task/index.d.ts +1 -0
  24. package/dist/types/task/prewalk.d.ts +3 -0
  25. package/dist/types/tools/ask.d.ts +10 -0
  26. package/dist/types/tools/tool-timeouts.d.ts +8 -2
  27. package/dist/types/utils/changelog.d.ts +4 -6
  28. package/package.json +12 -13
  29. package/src/cli/models-cli.ts +37 -17
  30. package/src/cli/update-cli.ts +14 -1
  31. package/src/config/model-discovery.ts +3 -2
  32. package/src/config/model-registry.ts +53 -26
  33. package/src/config/model-resolver.ts +56 -31
  34. package/src/config/settings-schema.ts +5 -0
  35. package/src/config/settings.ts +68 -5
  36. package/src/dap/client.ts +86 -7
  37. package/src/edit/diff.ts +4 -4
  38. package/src/eval/py/prelude.py +5 -5
  39. package/src/export/html/template.js +23 -9
  40. package/src/extensibility/extensions/runner.ts +9 -4
  41. package/src/extensibility/extensions/types.ts +3 -0
  42. package/src/extensibility/typebox.ts +22 -9
  43. package/src/hindsight/client.test.ts +42 -0
  44. package/src/hindsight/client.ts +40 -3
  45. package/src/hindsight/config.ts +18 -0
  46. package/src/launch/broker.ts +31 -5
  47. package/src/lsp/index.ts +1 -1
  48. package/src/main.ts +15 -5
  49. package/src/mcp/tool-bridge.ts +9 -0
  50. package/src/mnemopi/state.ts +70 -3
  51. package/src/modes/components/agent-dashboard.ts +6 -2
  52. package/src/modes/components/chat-transcript-builder.ts +13 -2
  53. package/src/modes/components/diff.ts +2 -2
  54. package/src/modes/components/plan-review-overlay.ts +20 -4
  55. package/src/modes/components/user-message.ts +100 -1
  56. package/src/modes/controllers/command-controller.ts +22 -5
  57. package/src/modes/controllers/event-controller.ts +4 -1
  58. package/src/modes/controllers/extension-ui-controller.ts +18 -0
  59. package/src/modes/controllers/input-controller.ts +47 -12
  60. package/src/modes/controllers/selector-controller.ts +82 -6
  61. package/src/modes/interactive-mode.ts +36 -4
  62. package/src/modes/types.ts +16 -3
  63. package/src/modes/utils/ui-helpers.ts +40 -20
  64. package/src/prompts/system/workflow-notice.md +1 -1
  65. package/src/sdk.ts +134 -48
  66. package/src/session/agent-session-error-log.test.ts +59 -0
  67. package/src/session/agent-session.ts +300 -26
  68. package/src/system-prompt.ts +1 -2
  69. package/src/task/executor.ts +41 -27
  70. package/src/task/index.ts +11 -0
  71. package/src/task/prewalk.ts +6 -0
  72. package/src/task/worktree.ts +25 -11
  73. package/src/tools/ask.ts +15 -0
  74. package/src/tools/bash.ts +14 -6
  75. package/src/tools/browser.ts +1 -1
  76. package/src/tools/debug.ts +1 -1
  77. package/src/tools/eval.ts +4 -5
  78. package/src/tools/fetch.ts +1 -1
  79. package/src/tools/hub/launch.ts +7 -0
  80. package/src/tools/tool-timeouts.ts +10 -3
  81. package/src/tools/write.ts +31 -0
  82. package/src/utils/changelog.ts +54 -58
  83. package/src/utils/git.ts +57 -49
package/src/utils/git.ts CHANGED
@@ -217,6 +217,12 @@ export const GIT_NETWORK_TIMEOUT_MS = 30 * 60 * 1000;
217
217
  export const GIT_COMMAND_OUTPUT_LIMIT_BYTES = 8 * 1024 * 1024;
218
218
 
219
219
  const GIT_COMMAND_TIMEOUT_EXIT_CODE = 124;
220
+ // Exit code returned when the `git` binary cannot be launched at all (spawn
221
+ // ENOENT). Mirrors the POSIX "command not found" code so read-only callers that
222
+ // degrade on any non-zero exit treat a missing git the same as a failed
223
+ // invocation instead of letting the raw spawn ENOENT escape as an unhandled
224
+ // rejection.
225
+ const GIT_SPAWN_ENOENT_EXIT_CODE = 127;
220
226
  const GIT_OUTPUT_TRUNCATED_MARKER = "\n[git subprocess output truncated after 8 MiB]\n";
221
227
  const GIT_COMMAND_TERMINATE_GRACE_MS = 5_000;
222
228
 
@@ -388,6 +394,29 @@ function ensureAvailable(): void {
388
394
  }
389
395
  }
390
396
 
397
+ /**
398
+ * Launch a `git` plumbing command synchronously and decode stdout. Returns the
399
+ * exit code plus trimmed stdout; a missing `git` binary (spawn ENOENT) is
400
+ * reported as {@link GIT_SPAWN_ENOENT_EXIT_CODE} so sync read-only callers
401
+ * degrade to `null` instead of throwing an uncaught error during rendering.
402
+ */
403
+ function gitSpawnSyncText(cwd: string, args: readonly string[]): { exitCode: number; stdout: string } {
404
+ const commandArgs = withShortLivedGitConfig(withNoOptionalLocks(args));
405
+ try {
406
+ const result = Bun.spawnSync(["git", ...commandArgs], {
407
+ cwd,
408
+ env: buildGitEnv(),
409
+ stdout: "pipe",
410
+ stderr: "pipe",
411
+ windowsHide: true,
412
+ });
413
+ return { exitCode: result.exitCode ?? 0, stdout: new TextDecoder().decode(result.stdout).trim() };
414
+ } catch (err) {
415
+ if (isEnoent(err)) return { exitCode: GIT_SPAWN_ENOENT_EXIT_CODE, stdout: "" };
416
+ throw err;
417
+ }
418
+ }
419
+
391
420
  function formatCommandFailure(
392
421
  args: readonly string[],
393
422
  result: Pick<GitCommandResult, "exitCode" | "stdout" | "stderr">,
@@ -401,15 +430,26 @@ function formatCommandFailure(
401
430
 
402
431
  async function git(cwd: string, args: readonly string[], options: CommandOptions = {}): Promise<GitCommandResult> {
403
432
  const commandArgs = withShortLivedGitConfig(options.readOnly ? withNoOptionalLocks(args) : [...args]);
404
- const child = Bun.spawn(["git", ...commandArgs], {
405
- cwd,
406
- env: buildGitEnv(options.env),
407
- signal: options.signal,
408
- stdin: normalizeStdin(options.stdin),
409
- stdout: "pipe",
410
- stderr: "pipe",
411
- windowsHide: true,
412
- });
433
+ let child: Subprocess;
434
+ try {
435
+ child = Bun.spawn(["git", ...commandArgs], {
436
+ cwd,
437
+ env: buildGitEnv(options.env),
438
+ signal: options.signal,
439
+ stdin: normalizeStdin(options.stdin),
440
+ stdout: "pipe",
441
+ stderr: "pipe",
442
+ windowsHide: true,
443
+ });
444
+ } catch (err) {
445
+ if (isEnoent(err)) {
446
+ // A deleted/nonexistent cwd also surfaces as a spawn ENOENT; only blame
447
+ // the binary when the working directory actually exists.
448
+ const stderr = fs.existsSync(cwd) ? "git is not installed." : `working directory does not exist: ${cwd}`;
449
+ return { exitCode: GIT_SPAWN_ENOENT_EXIT_CODE, stdout: "", stderr };
450
+ }
451
+ throw err;
452
+ }
413
453
 
414
454
  return await collectSubprocessResult("git", commandArgs, child, options);
415
455
  }
@@ -890,28 +930,12 @@ async function resolveHeadStateReftable(repository: GitRepository, signal?: Abor
890
930
  }
891
931
 
892
932
  function resolveHeadStateReftableSync(repository: GitRepository): GitHeadState | null {
893
- ensureAvailable();
894
- const symArgs = withShortLivedGitConfig(withNoOptionalLocks(["symbolic-ref", "HEAD"]));
895
- const symResult = Bun.spawnSync(["git", ...symArgs], {
896
- cwd: repository.repoRoot,
897
- env: buildGitEnv(),
898
- stdout: "pipe",
899
- stderr: "pipe",
900
- windowsHide: true,
901
- });
902
-
903
- const revArgs = withShortLivedGitConfig(withNoOptionalLocks(["rev-parse", "--verify", "HEAD"]));
904
- const revResult = Bun.spawnSync(["git", ...revArgs], {
905
- cwd: repository.repoRoot,
906
- env: buildGitEnv(),
907
- stdout: "pipe",
908
- stderr: "pipe",
909
- windowsHide: true,
910
- });
911
- const commit = revResult.exitCode === 0 ? new TextDecoder().decode(revResult.stdout).trim() || null : null;
933
+ const symResult = gitSpawnSyncText(repository.repoRoot, ["symbolic-ref", "HEAD"]);
934
+ const revResult = gitSpawnSyncText(repository.repoRoot, ["rev-parse", "--verify", "HEAD"]);
935
+ const commit = revResult.exitCode === 0 ? revResult.stdout || null : null;
912
936
 
913
937
  if (symResult.exitCode === 0) {
914
- const ref = new TextDecoder().decode(symResult.stdout).trim();
938
+ const ref = symResult.stdout;
915
939
  const branchName = ref.startsWith(LOCAL_BRANCH_PREFIX) ? ref.slice(LOCAL_BRANCH_PREFIX.length) : null;
916
940
  return {
917
941
  ...repository,
@@ -933,29 +957,13 @@ function resolveHeadStateReftableSync(repository: GitRepository): GitHeadState |
933
957
 
934
958
  function readRefSync(repository: GitRepository, targetRef: string): string | null {
935
959
  if (isReftableRepoSync(repository)) {
936
- ensureAvailable();
937
- const symArgs = withShortLivedGitConfig(withNoOptionalLocks(["symbolic-ref", targetRef]));
938
- const symResult = Bun.spawnSync(["git", ...symArgs], {
939
- cwd: repository.repoRoot,
940
- env: buildGitEnv(),
941
- stdout: "pipe",
942
- stderr: "pipe",
943
- windowsHide: true,
944
- });
960
+ const symResult = gitSpawnSyncText(repository.repoRoot, ["symbolic-ref", targetRef]);
945
961
  if (symResult.exitCode === 0) {
946
- const stdoutText = new TextDecoder().decode(symResult.stdout).trim();
947
- return `${HEAD_REF_PREFIX} ${stdoutText}`;
962
+ return `${HEAD_REF_PREFIX} ${symResult.stdout}`;
948
963
  }
949
- const revArgs = withShortLivedGitConfig(withNoOptionalLocks(["rev-parse", "--verify", targetRef]));
950
- const revResult = Bun.spawnSync(["git", ...revArgs], {
951
- cwd: repository.repoRoot,
952
- env: buildGitEnv(),
953
- stdout: "pipe",
954
- stderr: "pipe",
955
- windowsHide: true,
956
- });
964
+ const revResult = gitSpawnSyncText(repository.repoRoot, ["rev-parse", "--verify", targetRef]);
957
965
  if (revResult.exitCode === 0) {
958
- return new TextDecoder().decode(revResult.stdout).trim() || null;
966
+ return revResult.stdout || null;
959
967
  }
960
968
  return null;
961
969
  }