@oh-my-pi/pi-coding-agent 15.10.12 → 15.11.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.
Files changed (125) hide show
  1. package/CHANGELOG.md +60 -3
  2. package/dist/cli.js +841 -803
  3. package/dist/types/async/index.d.ts +0 -1
  4. package/dist/types/cli/gallery-fixtures/types.d.ts +5 -0
  5. package/dist/types/config/keybindings.d.ts +6 -1
  6. package/dist/types/config/settings-schema.d.ts +56 -33
  7. package/dist/types/export/html/template.generated.d.ts +1 -1
  8. package/dist/types/extensibility/custom-tools/types.d.ts +2 -2
  9. package/dist/types/extensibility/shared-events.d.ts +2 -2
  10. package/dist/types/internal-urls/history-protocol.d.ts +14 -0
  11. package/dist/types/internal-urls/index.d.ts +1 -0
  12. package/dist/types/internal-urls/types.d.ts +1 -1
  13. package/dist/types/irc/bus.d.ts +66 -0
  14. package/dist/types/modes/components/agent-hub.d.ts +30 -0
  15. package/dist/types/modes/components/compaction-summary-message.d.ts +10 -4
  16. package/dist/types/modes/components/custom-editor.d.ts +2 -0
  17. package/dist/types/modes/components/tool-execution.d.ts +8 -0
  18. package/dist/types/modes/components/ttsr-notification.d.ts +5 -1
  19. package/dist/types/modes/components/welcome.d.ts +3 -9
  20. package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
  21. package/dist/types/modes/interactive-mode.d.ts +3 -2
  22. package/dist/types/modes/theme/theme.d.ts +2 -1
  23. package/dist/types/modes/types.d.ts +3 -2
  24. package/dist/types/modes/utils/ui-helpers.d.ts +1 -1
  25. package/dist/types/registry/agent-lifecycle.d.ts +51 -0
  26. package/dist/types/registry/agent-registry.d.ts +16 -5
  27. package/dist/types/session/agent-session.d.ts +35 -30
  28. package/dist/types/session/messages.d.ts +2 -4
  29. package/dist/types/session/session-history-format.d.ts +12 -0
  30. package/dist/types/session/session-manager.d.ts +21 -3
  31. package/dist/types/session/streaming-output.d.ts +23 -0
  32. package/dist/types/task/executor.d.ts +11 -2
  33. package/dist/types/task/index.d.ts +11 -4
  34. package/dist/types/task/output-manager.d.ts +0 -7
  35. package/dist/types/task/repair-args.d.ts +8 -7
  36. package/dist/types/task/types.d.ts +55 -51
  37. package/dist/types/tools/browser/tab-worker.d.ts +3 -1
  38. package/dist/types/tools/find.d.ts +0 -11
  39. package/dist/types/tools/grouped-file-output.d.ts +0 -49
  40. package/dist/types/tools/index.d.ts +1 -3
  41. package/dist/types/tools/irc.d.ts +76 -38
  42. package/dist/types/tools/job.d.ts +7 -1
  43. package/examples/extensions/with-deps/package.json +1 -0
  44. package/package.json +11 -10
  45. package/scripts/bundle-dist.ts +28 -19
  46. package/src/async/index.ts +0 -1
  47. package/src/cli/gallery-cli.ts +1 -1
  48. package/src/cli/gallery-fixtures/agentic.ts +230 -115
  49. package/src/cli/gallery-fixtures/types.ts +5 -0
  50. package/src/cli.ts +20 -6
  51. package/src/commit/agentic/tools/analyze-file.ts +38 -19
  52. package/src/config/keybindings.ts +6 -1
  53. package/src/config/settings-schema.ts +56 -40
  54. package/src/config/settings.ts +7 -0
  55. package/src/eval/__tests__/agent-bridge.test.ts +5 -3
  56. package/src/eval/agent-bridge.ts +3 -16
  57. package/src/eval/js/shared/prelude.txt +1 -1
  58. package/src/eval/py/prelude.py +5 -6
  59. package/src/export/html/template.generated.ts +1 -1
  60. package/src/export/html/template.js +38 -13
  61. package/src/extensibility/custom-tools/types.ts +2 -2
  62. package/src/extensibility/shared-events.ts +2 -2
  63. package/src/internal-urls/docs-index.generated.ts +8 -8
  64. package/src/internal-urls/history-protocol.ts +113 -0
  65. package/src/internal-urls/index.ts +1 -0
  66. package/src/internal-urls/router.ts +3 -1
  67. package/src/internal-urls/types.ts +1 -1
  68. package/src/irc/bus.ts +292 -0
  69. package/src/main.ts +8 -60
  70. package/src/modes/components/{session-observer-overlay.ts → agent-hub.ts} +586 -367
  71. package/src/modes/components/compaction-summary-message.ts +68 -32
  72. package/src/modes/components/custom-editor.ts +10 -0
  73. package/src/modes/components/tool-execution.ts +31 -1
  74. package/src/modes/components/ttsr-notification.ts +72 -30
  75. package/src/modes/components/welcome.ts +9 -33
  76. package/src/modes/controllers/event-controller.ts +65 -0
  77. package/src/modes/controllers/extension-ui-controller.ts +8 -8
  78. package/src/modes/controllers/input-controller.ts +18 -2
  79. package/src/modes/controllers/selector-controller.ts +21 -17
  80. package/src/modes/interactive-mode.ts +8 -13
  81. package/src/modes/theme/theme.ts +18 -5
  82. package/src/modes/types.ts +3 -5
  83. package/src/modes/utils/hotkeys-markdown.ts +1 -0
  84. package/src/modes/utils/ui-helpers.ts +51 -49
  85. package/src/prompts/system/irc-incoming.md +3 -4
  86. package/src/prompts/system/orchestrate-notice.md +2 -2
  87. package/src/prompts/system/subagent-system-prompt.md +0 -5
  88. package/src/prompts/system/system-prompt.md +1 -0
  89. package/src/prompts/system/workflow-notice.md +2 -2
  90. package/src/prompts/tools/eval.md +3 -3
  91. package/src/prompts/tools/irc.md +29 -19
  92. package/src/prompts/tools/read.md +2 -2
  93. package/src/prompts/tools/task-summary.md +5 -16
  94. package/src/prompts/tools/task.md +38 -29
  95. package/src/registry/agent-lifecycle.ts +218 -0
  96. package/src/registry/agent-registry.ts +16 -5
  97. package/src/sdk.ts +29 -9
  98. package/src/session/agent-session.ts +243 -237
  99. package/src/session/messages.ts +11 -78
  100. package/src/session/session-history-format.ts +246 -0
  101. package/src/session/session-manager.ts +59 -5
  102. package/src/session/streaming-output.ts +60 -0
  103. package/src/task/executor.ts +855 -466
  104. package/src/task/index.ts +718 -794
  105. package/src/task/output-manager.ts +0 -11
  106. package/src/task/render.ts +133 -63
  107. package/src/task/repair-args.ts +21 -9
  108. package/src/task/types.ts +73 -66
  109. package/src/tools/ask.ts +4 -2
  110. package/src/tools/bash.ts +15 -5
  111. package/src/tools/browser/tab-worker.ts +26 -7
  112. package/src/tools/browser.ts +28 -1
  113. package/src/tools/find.ts +2 -27
  114. package/src/tools/grouped-file-output.ts +1 -118
  115. package/src/tools/index.ts +4 -12
  116. package/src/tools/irc.ts +596 -171
  117. package/src/tools/job.ts +41 -7
  118. package/src/tools/read.ts +57 -1
  119. package/src/tools/renderers.ts +2 -0
  120. package/src/tools/resolve.ts +4 -1
  121. package/dist/types/async/support.d.ts +0 -2
  122. package/dist/types/modes/components/session-observer-overlay.d.ts +0 -11
  123. package/dist/types/task/simple-mode.d.ts +0 -8
  124. package/src/async/support.ts +0 -5
  125. package/src/task/simple-mode.ts +0 -27
package/src/tools/job.ts CHANGED
@@ -3,7 +3,7 @@ import type { Component } from "@oh-my-pi/pi-tui";
3
3
  import { Text } from "@oh-my-pi/pi-tui";
4
4
  import { prompt } from "@oh-my-pi/pi-utils";
5
5
  import * as z from "zod/v4";
6
- import { type AsyncJob, type AsyncJobManager, isBackgroundJobSupportEnabled } from "../async";
6
+ import type { AsyncJob, AsyncJobManager } from "../async";
7
7
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
8
8
  import type { Theme } from "../modes/theme/theme";
9
9
  import jobDescription from "../prompts/tools/job.md" with { type: "text" };
@@ -65,6 +65,19 @@ export interface JobToolDetails {
65
65
  cancelled?: { id: string; status: CancelStatus }[];
66
66
  }
67
67
 
68
+ /**
69
+ * A poll snapshot where every watched job is still running and nothing was
70
+ * cancelled — pure "still waiting" noise once a newer poll exists. The TUI
71
+ * keeps such a block un-finalized (displaceable) so a follow-up `job` call
72
+ * replaces it instead of stacking another waiting frame in the transcript.
73
+ */
74
+ export function isWaitingPollDetails(details: unknown): boolean {
75
+ const d = details as JobToolDetails | undefined;
76
+ if (!d || !Array.isArray(d.jobs) || d.jobs.length === 0) return false;
77
+ if (d.cancelled?.length) return false;
78
+ return d.jobs.every(job => job?.status === "running");
79
+ }
80
+
68
81
  export class JobTool implements AgentTool<typeof jobSchema, JobToolDetails> {
69
82
  readonly name = "job";
70
83
  readonly approval = "read" as const;
@@ -78,11 +91,6 @@ export class JobTool implements AgentTool<typeof jobSchema, JobToolDetails> {
78
91
  this.description = prompt.render(jobDescription);
79
92
  }
80
93
 
81
- static createIf(session: ToolSession): JobTool | null {
82
- if (!isBackgroundJobSupportEnabled(session.settings)) return null;
83
- return new JobTool(session);
84
- }
85
-
86
94
  async execute(
87
95
  _toolCallId: string,
88
96
  params: JobParams,
@@ -378,6 +386,30 @@ function statusToColor(status: JobSnapshot["status"]): ToolUIColor {
378
386
  }
379
387
  }
380
388
 
389
+ /**
390
+ * Task job results are delivered in the model-facing `<task-result>` envelope
391
+ * (prompts/tools/task-summary.md) so the parent agent can parse status and the
392
+ * `agent://` pointer. The wrapper markup is noise to a human — preview the
393
+ * inner <output>/<preview> body instead.
394
+ */
395
+ function stripTaskResultEnvelope(text: string): string {
396
+ if (!text.startsWith("<task-result")) return text;
397
+ const body = /<(output|preview)(?:\s[^>]*)?>\n?([\s\S]*?)\n?<\/\1>/.exec(text)?.[2];
398
+ return body?.trim() || text;
399
+ }
400
+
401
+ /**
402
+ * Pretty-printed JSON output wastes the collapsed one-line preview on a lone
403
+ * "{" — flatten structured-looking bodies onto a single line. Slice first:
404
+ * downstream truncation keeps at most a few hundred columns, so collapsing
405
+ * whitespace across a multi-KB body would be pure waste.
406
+ */
407
+ function flattenStructuredPreview(text: string): string {
408
+ const first = text[0];
409
+ if (first !== "{" && first !== "[") return text;
410
+ return text.slice(0, PREVIEW_LINES_EXPANDED * PREVIEW_LINE_WIDTH * 2).replace(/\s+/g, " ");
411
+ }
412
+
381
413
  function describeTarget(args: JobRenderArgs | undefined): string {
382
414
  const poll = args?.poll ?? [];
383
415
  const cancel = args?.cancel ?? [];
@@ -494,7 +526,9 @@ export const jobToolRenderer = {
494
526
  lines.push(` ${uiTheme.fg("toolOutput", visibleLabelLines[i]!)}`);
495
527
  }
496
528
 
497
- const preview = job.errorText?.trim() || job.resultText?.trim();
529
+ const preview = flattenStructuredPreview(
530
+ stripTaskResultEnvelope(job.errorText?.trim() || job.resultText?.trim() || ""),
531
+ );
498
532
  if (preview) {
499
533
  const maxLines = expanded ? PREVIEW_LINES_EXPANDED : PREVIEW_LINES_COLLAPSED;
500
534
  const previewLines = getPreviewLines(preview, maxLines, PREVIEW_LINE_WIDTH, Ellipsis.Unicode);
package/src/tools/read.ts CHANGED
@@ -736,6 +736,17 @@ interface ResolvedSqliteReadPath {
736
736
  /** Per-execute memo of suffix-glob lookups; `null` records a confirmed miss. */
737
737
  type SuffixMatchCache = Map<string, { absolutePath: string; displayPath: string } | null>;
738
738
 
739
+ /**
740
+ * Repeated whole-file reads of the same path pin stale copies in context.
741
+ * From this per-session read count onward, file reads carry a trailing nudge
742
+ * to prefer narrower re-reads.
743
+ */
744
+ const REPEAT_READ_NOTICE_THRESHOLD = 3;
745
+
746
+ function formatRepeatReadNotice(count: number): string {
747
+ return `[note: read #${count} of this file this session — after edits, prefer the context echoed in the edit result or a narrow range re-read]`;
748
+ }
749
+
739
750
  /**
740
751
  * Read tool implementation.
741
752
  *
@@ -754,6 +765,8 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
754
765
  readonly #autoResizeImages: boolean;
755
766
  readonly #defaultLimit: number;
756
767
  readonly #inspectImageEnabled: boolean;
768
+ /** Successful file reads per resolved base path (selector stripped) this session. */
769
+ readonly #readCounts = new Map<string, number>();
757
770
 
758
771
  constructor(private readonly session: ToolSession) {
759
772
  const displayMode = resolveFileDisplayMode(session);
@@ -772,6 +785,19 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
772
785
  });
773
786
  }
774
787
 
788
+ /**
789
+ * Count a file read of `absolutePath` and return the repeat-read nudge once
790
+ * the per-session count reaches {@link REPEAT_READ_NOTICE_THRESHOLD}.
791
+ * Non-file sources (URLs, internal resources, directories, archives,
792
+ * SQLite, images) are never counted.
793
+ */
794
+ #repeatReadNotice(absolutePath: string): string | undefined {
795
+ const count = (this.#readCounts.get(absolutePath) ?? 0) + 1;
796
+ this.#readCounts.set(absolutePath, count);
797
+ if (count < REPEAT_READ_NOTICE_THRESHOLD) return undefined;
798
+ return formatRepeatReadNotice(count);
799
+ }
800
+
775
801
  async #tryReadDelimitedPaths(
776
802
  readPath: string,
777
803
  signal?: AbortSignal,
@@ -948,6 +974,8 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
948
974
  ignoreResultLimits?: boolean;
949
975
  raw?: boolean;
950
976
  immutable?: boolean;
977
+ /** Trailing repeat-read nudge; appended at the very end of the text. */
978
+ repeatNotice?: string;
951
979
  },
952
980
  ): AgentToolResult<ReadToolDetails> {
953
981
  const displayMode = resolveFileDisplayMode(this.session, { raw: options.raw, immutable: options.immutable });
@@ -1092,6 +1120,9 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1092
1120
  : formatLineEntries(buildLineEntries(endLine), startLineDisplay);
1093
1121
  }
1094
1122
 
1123
+ if (options.repeatNotice) {
1124
+ outputText += `\n${options.repeatNotice}`;
1125
+ }
1095
1126
  resultBuilder.text(outputText);
1096
1127
  if (truncationInfo) {
1097
1128
  resultBuilder.truncation(truncationInfo.result, truncationInfo.options);
@@ -1117,6 +1148,8 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1117
1148
  entityLabel: string;
1118
1149
  raw?: boolean;
1119
1150
  immutable?: boolean;
1151
+ /** Trailing repeat-read nudge; appended at the very end of the text. */
1152
+ repeatNotice?: string;
1120
1153
  },
1121
1154
  ): AgentToolResult<ReadToolDetails> {
1122
1155
  const displayMode = resolveFileDisplayMode(this.session, { raw: options.raw, immutable: options.immutable });
@@ -1177,8 +1210,11 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1177
1210
  const bound = range.endLine !== undefined ? `${range.startLine}-${range.endLine}` : `${range.startLine}`;
1178
1211
  notices.push(`[Range ${bound} is beyond end of ${options.entityLabel} (${totalLines} lines total); skipped]`);
1179
1212
  }
1180
- const finalText =
1213
+ let finalText =
1181
1214
  notices.length > 0 ? (outputText ? `${outputText}\n${notices.join("\n")}` : notices.join("\n")) : outputText;
1215
+ if (options.repeatNotice) {
1216
+ finalText = finalText ? `${finalText}\n${options.repeatNotice}` : options.repeatNotice;
1217
+ }
1182
1218
  resultBuilder.text(finalText);
1183
1219
  return resultBuilder.done();
1184
1220
  }
@@ -1196,6 +1232,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1196
1232
  parsed: ParsedSelector,
1197
1233
  displayMode: { hashLines: boolean; lineNumbers: boolean },
1198
1234
  suffixResolution: { from: string; to: string } | undefined,
1235
+ repeatNotice: string | undefined,
1199
1236
  signal: AbortSignal | undefined,
1200
1237
  ): Promise<{
1201
1238
  outputText: string;
@@ -1215,6 +1252,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1215
1252
  sourcePath: absolutePath,
1216
1253
  entityLabel: "file",
1217
1254
  raw: rawSelector,
1255
+ repeatNotice,
1218
1256
  });
1219
1257
  if (suffixResolution) {
1220
1258
  const notice = `[Path '${suffixResolution.from}' not found; resolved to '${suffixResolution.to}' via suffix match]`;
@@ -1896,6 +1934,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1896
1934
  let details: ReadToolDetails = {};
1897
1935
  let sourcePath: string | undefined;
1898
1936
  let columnTruncated = 0;
1937
+ let repeatNotice: string | undefined;
1899
1938
  let truncationInfo:
1900
1939
  | { result: TruncationResult; options: { direction: "head"; startLine?: number; totalFileLines?: number } }
1901
1940
  | undefined;
@@ -1960,11 +1999,13 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1960
1999
  }
1961
2000
  } else if (isNotebookPath(absolutePath) && !isRawSelector(parsed)) {
1962
2001
  const notebookText = await readEditableNotebookText(absolutePath, localReadPath);
2002
+ repeatNotice = this.#repeatReadNotice(absolutePath);
1963
2003
  if (isMultiRange(parsed) && parsed.kind === "lines") {
1964
2004
  return this.#buildInMemoryMultiRangeResult(notebookText, parsed.ranges, {
1965
2005
  details: { resolvedPath: absolutePath },
1966
2006
  sourcePath: absolutePath,
1967
2007
  entityLabel: "notebook",
2008
+ repeatNotice,
1968
2009
  });
1969
2010
  }
1970
2011
  const { offset, limit } = selToOffsetLimit(parsed);
@@ -1972,11 +2013,13 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1972
2013
  details: { resolvedPath: absolutePath },
1973
2014
  sourcePath: absolutePath,
1974
2015
  entityLabel: "notebook",
2016
+ repeatNotice,
1975
2017
  });
1976
2018
  } else if (shouldConvertWithMarkit) {
1977
2019
  // Convert document via markit.
1978
2020
  const result = await convertFileWithMarkit(absolutePath, signal);
1979
2021
  if (result.ok) {
2022
+ repeatNotice = this.#repeatReadNotice(absolutePath);
1980
2023
  // Route the converted markdown through the in-memory text builder
1981
2024
  // so line-range selectors (`file.pdf:50-100`, `:5-16,40-80`) and
1982
2025
  // raw mode apply against the converted output. Without this,
@@ -1987,6 +2030,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1987
2030
  details: { resolvedPath: absolutePath },
1988
2031
  sourcePath: absolutePath,
1989
2032
  entityLabel: "document",
2033
+ repeatNotice,
1990
2034
  });
1991
2035
  }
1992
2036
  const { offset, limit } = selToOffsetLimit(parsed);
@@ -1995,6 +2039,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
1995
2039
  sourcePath: absolutePath,
1996
2040
  entityLabel: "document",
1997
2041
  raw: isRawSelector(parsed),
2042
+ repeatNotice,
1998
2043
  });
1999
2044
  } else if (result.error) {
2000
2045
  content = [{ type: "text", text: `[Cannot read ${ext} file: ${result.error || "conversion failed"}]` }];
@@ -2002,6 +2047,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
2002
2047
  content = [{ type: "text", text: `[Cannot read ${ext} file: conversion failed]` }];
2003
2048
  }
2004
2049
  } else {
2050
+ repeatNotice = this.#repeatReadNotice(absolutePath);
2005
2051
  if (
2006
2052
  parsed.kind === "none" &&
2007
2053
  this.session.settings.get("read.summarize.enabled") &&
@@ -2043,6 +2089,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
2043
2089
  parsed,
2044
2090
  displayMode,
2045
2091
  suffixResolution,
2092
+ repeatNotice,
2046
2093
  undefined, // plain-file read: deterministic and fast, never abort mid-read
2047
2094
  );
2048
2095
  if (multiResult.bridgeResult) return multiResult.bridgeResult;
@@ -2066,6 +2113,7 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
2066
2113
  sourcePath: absolutePath,
2067
2114
  entityLabel: "file",
2068
2115
  raw: isRawSelector(parsed),
2116
+ repeatNotice,
2069
2117
  });
2070
2118
  if (suffixResolution) {
2071
2119
  const notice = `[Path '${suffixResolution.from}' not found; resolved to '${suffixResolution.to}' via suffix match]`;
@@ -2367,6 +2415,14 @@ export class ReadTool implements AgentTool<typeof readSchema, ReadToolDetails> {
2367
2415
  content = [{ type: "text", text: notice }, ...content];
2368
2416
  }
2369
2417
  }
2418
+ if (repeatNotice) {
2419
+ // Trailing nudge goes at the very end of the textual result so it never
2420
+ // disturbs hashline tag headers or inline notices.
2421
+ const lastText = content.findLast((c): c is TextContent => c.type === "text");
2422
+ if (lastText) {
2423
+ lastText.text = `${lastText.text}\n${repeatNotice}`;
2424
+ }
2425
+ }
2370
2426
  const resultBuilder = toolResult(details).content(content);
2371
2427
  if (sourcePath) {
2372
2428
  resultBuilder.sourcePath(sourcePath);
@@ -21,6 +21,7 @@ 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";
24
+ import { ircToolRenderer } from "./irc";
24
25
  import { jobToolRenderer } from "./job";
25
26
  import { recallToolRenderer, reflectToolRenderer, retainToolRenderer } from "./memory-render";
26
27
  import { readToolRenderer } from "./read";
@@ -58,6 +59,7 @@ export const toolRenderers: Record<string, ToolRenderer> = {
58
59
  search: searchToolRenderer as ToolRenderer,
59
60
  lsp: lspToolRenderer as ToolRenderer,
60
61
  inspect_image: inspectImageToolRenderer as ToolRenderer,
62
+ irc: ircToolRenderer as ToolRenderer,
61
63
  read: readToolRenderer as ToolRenderer,
62
64
  job: jobToolRenderer as ToolRenderer,
63
65
  resolve: resolveToolRenderer as ToolRenderer,
@@ -241,7 +241,10 @@ export const resolveToolRenderer = {
241
241
  const isApply = action === "apply" && !result.isError;
242
242
  const isFailedApply = action === "apply" && result.isError;
243
243
  const bgColor = result.isError ? "error" : isApply ? "success" : "warning";
244
- const icon = isApply ? uiTheme.styledSymbol("tool.resolve", "accent") : uiTheme.status.error;
244
+ // Bare symbol: the line is wrapped in inverse(fg(...)), so any embedded fg
245
+ // reset (styledSymbol/status glyphs carry their own \x1b[39m) would drop the
246
+ // inverse block back to the default background mid-line.
247
+ const icon = uiTheme.symbol(isApply ? "tool.resolve" : "status.error");
245
248
  const verb = isApply ? "Accept" : isFailedApply ? "Failed" : "Discard";
246
249
  const separator = ": ";
247
250
  const separatorIndex = label.indexOf(separator);
@@ -1,2 +0,0 @@
1
- import type { Settings } from "../config/settings";
2
- export declare function isBackgroundJobSupportEnabled(settings: Pick<Settings, "get">): boolean;
@@ -1,11 +0,0 @@
1
- import { Container } from "@oh-my-pi/pi-tui";
2
- import type { KeyId } from "../../config/keybindings";
3
- import type { SessionObserverRegistry } from "../session-observer-registry";
4
- export declare class SessionObserverOverlayComponent extends Container {
5
- #private;
6
- constructor(registry: SessionObserverRegistry, onDone: () => void, observeKeys: KeyId[]);
7
- render(width: number): readonly string[];
8
- /** Rebuild content from live registry data */
9
- refreshFromRegistry(): void;
10
- handleInput(keyData: string): void;
11
- }
@@ -1,8 +0,0 @@
1
- export declare const TASK_SIMPLE_MODES: readonly ["default", "schema-free", "independent"];
2
- export type TaskSimpleMode = (typeof TASK_SIMPLE_MODES)[number];
3
- interface TaskSimpleModeCapabilities {
4
- contextEnabled: boolean;
5
- customSchemaEnabled: boolean;
6
- }
7
- export declare function getTaskSimpleModeCapabilities(mode: TaskSimpleMode): TaskSimpleModeCapabilities;
8
- export {};
@@ -1,5 +0,0 @@
1
- import type { Settings } from "../config/settings";
2
-
3
- export function isBackgroundJobSupportEnabled(settings: Pick<Settings, "get">): boolean {
4
- return settings.get("async.enabled") || settings.get("bash.autoBackground.enabled");
5
- }
@@ -1,27 +0,0 @@
1
- export const TASK_SIMPLE_MODES = ["default", "schema-free", "independent"] as const;
2
-
3
- export type TaskSimpleMode = (typeof TASK_SIMPLE_MODES)[number];
4
-
5
- interface TaskSimpleModeCapabilities {
6
- contextEnabled: boolean;
7
- customSchemaEnabled: boolean;
8
- }
9
-
10
- const TASK_SIMPLE_MODE_CAPABILITIES: Record<TaskSimpleMode, TaskSimpleModeCapabilities> = {
11
- default: {
12
- contextEnabled: true,
13
- customSchemaEnabled: true,
14
- },
15
- "schema-free": {
16
- contextEnabled: true,
17
- customSchemaEnabled: false,
18
- },
19
- independent: {
20
- contextEnabled: false,
21
- customSchemaEnabled: false,
22
- },
23
- };
24
-
25
- export function getTaskSimpleModeCapabilities(mode: TaskSimpleMode): TaskSimpleModeCapabilities {
26
- return TASK_SIMPLE_MODE_CAPABILITIES[mode];
27
- }