@oh-my-pi/pi-coding-agent 15.7.5 → 15.7.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.
Files changed (74) hide show
  1. package/CHANGELOG.md +30 -1
  2. package/dist/types/config/settings-schema.d.ts +9 -0
  3. package/dist/types/eval/__tests__/heartbeat.test.d.ts +1 -0
  4. package/dist/types/eval/heartbeat.d.ts +45 -0
  5. package/dist/types/extensibility/extensions/loader.d.ts +2 -2
  6. package/dist/types/extensibility/extensions/runner.d.ts +2 -1
  7. package/dist/types/extensibility/extensions/types.d.ts +24 -5
  8. package/dist/types/lsp/diagnostics-ledger.d.ts +10 -0
  9. package/dist/types/lsp/index.d.ts +2 -0
  10. package/dist/types/lsp/utils.d.ts +4 -0
  11. package/dist/types/modes/acp/acp-agent.d.ts +1 -1
  12. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  13. package/dist/types/modes/components/custom-editor.d.ts +0 -1
  14. package/dist/types/modes/components/hook-selector.d.ts +7 -1
  15. package/dist/types/modes/controllers/extension-ui-controller.d.ts +2 -2
  16. package/dist/types/modes/interactive-mode.d.ts +2 -2
  17. package/dist/types/modes/rpc/rpc-mode.d.ts +1 -1
  18. package/dist/types/modes/theme/theme.d.ts +1 -1
  19. package/dist/types/modes/types.d.ts +2 -2
  20. package/dist/types/session/agent-session.d.ts +8 -1
  21. package/dist/types/tools/ask.d.ts +8 -6
  22. package/dist/types/tools/eval-backends.d.ts +12 -0
  23. package/dist/types/tools/eval-render.d.ts +52 -0
  24. package/dist/types/tools/eval.d.ts +2 -35
  25. package/dist/types/tools/index.d.ts +4 -11
  26. package/dist/types/tui/output-block.d.ts +4 -3
  27. package/examples/extensions/README.md +1 -0
  28. package/examples/extensions/thinking-note.ts +13 -0
  29. package/package.json +9 -9
  30. package/src/config/model-registry.ts +33 -4
  31. package/src/config/settings-schema.ts +10 -0
  32. package/src/discovery/claude.ts +41 -22
  33. package/src/edit/index.ts +23 -3
  34. package/src/eval/__tests__/agent-bridge.test.ts +90 -0
  35. package/src/eval/__tests__/heartbeat.test.ts +84 -0
  36. package/src/eval/__tests__/llm-bridge.test.ts +30 -0
  37. package/src/eval/agent-bridge.ts +44 -38
  38. package/src/eval/heartbeat.ts +74 -0
  39. package/src/eval/js/executor.ts +13 -9
  40. package/src/eval/llm-bridge.ts +20 -14
  41. package/src/eval/py/executor.ts +14 -18
  42. package/src/exec/bash-executor.ts +31 -5
  43. package/src/extensibility/extensions/loader.ts +16 -18
  44. package/src/extensibility/extensions/runner.ts +22 -17
  45. package/src/extensibility/extensions/types.ts +39 -5
  46. package/src/internal-urls/docs-index.generated.ts +3 -3
  47. package/src/lsp/diagnostics-ledger.ts +51 -0
  48. package/src/lsp/index.ts +9 -22
  49. package/src/lsp/utils.ts +21 -0
  50. package/src/modes/acp/acp-agent.ts +8 -4
  51. package/src/modes/components/assistant-message.ts +28 -1
  52. package/src/modes/components/custom-editor.ts +9 -7
  53. package/src/modes/components/hook-selector.ts +159 -32
  54. package/src/modes/components/tool-execution.ts +20 -4
  55. package/src/modes/controllers/event-controller.ts +5 -2
  56. package/src/modes/controllers/extension-ui-controller.ts +3 -2
  57. package/src/modes/controllers/input-controller.ts +0 -15
  58. package/src/modes/interactive-mode.ts +2 -1
  59. package/src/modes/rpc/rpc-mode.ts +17 -6
  60. package/src/modes/theme/theme-schema.json +30 -0
  61. package/src/modes/theme/theme.ts +39 -2
  62. package/src/modes/types.ts +2 -1
  63. package/src/modes/utils/ui-helpers.ts +5 -2
  64. package/src/prompts/tools/ask.md +2 -1
  65. package/src/prompts/tools/eval.md +1 -1
  66. package/src/session/agent-session.ts +65 -11
  67. package/src/tools/ask.ts +74 -32
  68. package/src/tools/eval-backends.ts +38 -0
  69. package/src/tools/eval-render.ts +750 -0
  70. package/src/tools/eval.ts +27 -754
  71. package/src/tools/index.ts +7 -37
  72. package/src/tools/renderers.ts +1 -1
  73. package/src/tools/write.ts +9 -1
  74. package/src/tui/output-block.ts +5 -4
@@ -1,7 +1,7 @@
1
1
  import type { InMemorySnapshotStore } from "@oh-my-pi/hashline";
2
2
  import type { AgentTelemetryConfig, AgentTool } from "@oh-my-pi/pi-agent-core";
3
3
  import type { ToolChoice } from "@oh-my-pi/pi-ai";
4
- import { $env, $flag, logger } from "@oh-my-pi/pi-utils";
4
+ import { logger } from "@oh-my-pi/pi-utils";
5
5
  import type { PromptTemplate } from "../config/prompt-templates";
6
6
  import type { Settings } from "../config/settings";
7
7
  import { EditTool } from "../edit";
@@ -34,6 +34,7 @@ import { BrowserTool } from "./browser";
34
34
  import { type CheckpointState, CheckpointTool, RewindTool } from "./checkpoint";
35
35
  import { DebugTool } from "./debug";
36
36
  import { EvalTool } from "./eval";
37
+ import { resolveEvalBackends } from "./eval-backends";
37
38
  import { FindTool } from "./find";
38
39
  import { GithubTool } from "./gh";
39
40
  import { InspectImageTool } from "./inspect-image";
@@ -74,6 +75,7 @@ export * from "./browser";
74
75
  export * from "./checkpoint";
75
76
  export * from "./debug";
76
77
  export * from "./eval";
78
+ export * from "./eval-backends";
77
79
  export * from "./find";
78
80
  export * from "./gh";
79
81
  export * from "./image-gen";
@@ -257,6 +259,10 @@ export interface ToolSession {
257
259
  * by `getConflictHistory`. */
258
260
  conflictHistory?: import("./conflict-detect").ConflictHistory;
259
261
 
262
+ /** Per-session ledger of post-edit LSP diagnostics already surfaced to the
263
+ * model for each file. Lazily initialized by `getDiagnosticsLedger`. */
264
+ diagnosticsLedger?: import("../lsp/diagnostics-ledger").DiagnosticsLedger;
265
+
260
266
  /** Queue a hidden message to be injected at the next agent turn. */
261
267
  queueDeferredMessage?(message: CustomMessage): void;
262
268
  /** Get the active OpenTelemetry config so subagent dispatch can forward
@@ -331,42 +337,6 @@ export const HIDDEN_TOOLS: Record<string, ToolFactory> = {
331
337
 
332
338
  export type ToolName = keyof typeof BUILTIN_TOOLS;
333
339
 
334
- export interface EvalBackendsAllowance {
335
- python: boolean;
336
- js: boolean;
337
- }
338
-
339
- /**
340
- * Parse PI_PY / PI_JS environment variables. Each is a boolean flag; unset
341
- * means "not specified, defer to settings". Returns null when neither is set
342
- * so the caller can fall through to `readEvalBackendsAllowance` per key.
343
- */
344
- function getEvalBackendsFromEnv(): EvalBackendsAllowance | null {
345
- const pyEnv = $env.PI_PY;
346
- const jsEnv = $env.PI_JS;
347
- if (pyEnv === undefined && jsEnv === undefined) return null;
348
- return {
349
- python: pyEnv === undefined ? true : $flag("PI_PY"),
350
- js: jsEnv === undefined ? true : $flag("PI_JS"),
351
- };
352
- }
353
-
354
- /** Read per-backend allowance from settings (defaults true). */
355
- export function readEvalBackendsAllowance(session: ToolSession): EvalBackendsAllowance {
356
- return {
357
- python: session.settings.get("eval.py") ?? true,
358
- js: session.settings.get("eval.js") ?? true,
359
- };
360
- }
361
-
362
- /**
363
- * Materialize the active eval backend allowance: PI_PY / PI_JS env flags
364
- * override the per-key settings; otherwise settings (defaults true) win.
365
- */
366
- export function resolveEvalBackends(session: ToolSession): EvalBackendsAllowance {
367
- return getEvalBackendsFromEnv() ?? readEvalBackendsAllowance(session);
368
- }
369
-
370
340
  /**
371
341
  * Create tools from BUILTIN_TOOLS registry.
372
342
  */
@@ -17,7 +17,7 @@ import { astGrepToolRenderer } from "./ast-grep";
17
17
  import { bashToolRenderer } from "./bash";
18
18
  import { browserToolRenderer } from "./browser/render";
19
19
  import { debugToolRenderer } from "./debug";
20
- import { evalToolRenderer } from "./eval";
20
+ import { evalToolRenderer } from "./eval-render";
21
21
  import { findToolRenderer } from "./find";
22
22
  import { githubToolRenderer } from "./gh-renderer";
23
23
  import { inspectImageToolRenderer } from "./inspect-image-renderer";
@@ -15,6 +15,7 @@ import type { RenderResultOptions } from "../extensibility/custom-tools/types";
15
15
  import { InternalUrlRouter } from "../internal-urls";
16
16
  import { parseInternalUrl } from "../internal-urls/parse";
17
17
  import { createLspWritethrough, type FileDiagnosticsResult, type WritethroughCallback, writethroughNoop } from "../lsp";
18
+ import { getDiagnosticsLedger } from "../lsp/diagnostics-ledger";
18
19
  import { getLanguageFromPath, highlightCode, type Theme } from "../modes/theme/theme";
19
20
  import writeDescription from "../prompts/tools/write.md" with { type: "text" };
20
21
  import type { ToolSession } from "../sdk";
@@ -278,8 +279,15 @@ export class WriteTool implements AgentTool<typeof writeSchema, WriteToolDetails
278
279
  const enableLsp = session.enableLsp ?? true;
279
280
  const enableFormat = enableLsp && session.settings.get("lsp.formatOnWrite");
280
281
  const enableDiagnostics = enableLsp && session.settings.get("lsp.diagnosticsOnWrite");
282
+ const dedup = enableDiagnostics && session.settings.get("lsp.diagnosticsDeduplicate");
281
283
  this.#writethrough = enableLsp
282
- ? createLspWritethrough(session.cwd, { enableFormat, enableDiagnostics })
284
+ ? createLspWritethrough(session.cwd, {
285
+ enableFormat,
286
+ enableDiagnostics,
287
+ transformDiagnostics: dedup
288
+ ? (path, result) => getDiagnosticsLedger(session).reduce(path, result)
289
+ : undefined,
290
+ })
283
291
  : writethroughNoop;
284
292
  this.description = prompt.render(writeDescription);
285
293
  }
@@ -19,7 +19,7 @@ export interface OutputBlockOptions {
19
19
  animate?: boolean;
20
20
  }
21
21
 
22
- const BORDER_SHIMMER_TICK_MS = 50;
22
+ const BORDER_SHIMMER_TICK_MS = 16;
23
23
  /** Duration of one full left↔right↔left bounce of the bottom-edge segment, in
24
24
  * ms. Position is derived from the wall clock against this fixed cycle so a
25
25
  * resize only nudges the segment proportionally instead of teleporting it. */
@@ -28,9 +28,10 @@ const BORDER_BOUNCE_MS = 3000;
28
28
  const BORDER_SEGMENT_LEN = 8;
29
29
 
30
30
  /**
31
- * Monotonic frame counter for animated borders. Quantized coarse enough to
32
- * coalesce multiple render passes inside one frame, fine enough to advance on
33
- * every spinner interval so cached blocks re-render while the segment travels.
31
+ * Monotonic frame counter for animated borders, quantized to the TUI's ~16ms
32
+ * render cap so the cache key advances once per ~60fps frame fine enough for a
33
+ * smooth segment sweep, coarse enough to coalesce multiple render passes that
34
+ * land inside the same frame.
34
35
  */
35
36
  export function borderShimmerTick(): number {
36
37
  return Math.floor(Date.now() / BORDER_SHIMMER_TICK_MS);