@oh-my-pi/pi-coding-agent 16.4.4 → 16.4.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 (109) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/dist/cli.js +3799 -3729
  3. package/dist/types/async/job-manager.d.ts +8 -0
  4. package/dist/types/cli/bench-cli.d.ts +1 -7
  5. package/dist/types/cli/usage-cli.d.ts +1 -0
  6. package/dist/types/commands/usage.d.ts +7 -0
  7. package/dist/types/config/settings-schema.d.ts +19 -9
  8. package/dist/types/config/settings.d.ts +3 -2
  9. package/dist/types/discovery/helpers.d.ts +2 -2
  10. package/dist/types/extensibility/extensions/types.d.ts +36 -0
  11. package/dist/types/irc/bus.d.ts +4 -0
  12. package/dist/types/modes/components/__tests__/pause-screen.test.d.ts +1 -0
  13. package/dist/types/modes/components/ask-dialog.d.ts +27 -0
  14. package/dist/types/modes/components/custom-editor.d.ts +3 -8
  15. package/dist/types/modes/components/index.d.ts +2 -1
  16. package/dist/types/modes/components/model-browser.d.ts +100 -0
  17. package/dist/types/modes/components/model-hub.d.ts +52 -0
  18. package/dist/types/modes/components/pause-screen.d.ts +43 -0
  19. package/dist/types/modes/components/session-selector.d.ts +13 -0
  20. package/dist/types/modes/components/tool-execution.d.ts +2 -0
  21. package/dist/types/modes/controllers/extension-ui-controller.d.ts +2 -1
  22. package/dist/types/modes/controllers/input-controller.d.ts +2 -0
  23. package/dist/types/modes/interactive-mode.d.ts +3 -0
  24. package/dist/types/modes/queue-input.d.ts +8 -0
  25. package/dist/types/modes/shared.d.ts +1 -1
  26. package/dist/types/modes/types.d.ts +4 -0
  27. package/dist/types/session/agent-session.d.ts +1 -1
  28. package/dist/types/session/agent-storage.d.ts +57 -0
  29. package/dist/types/session/session-context.d.ts +9 -0
  30. package/dist/types/task/executor.d.ts +26 -13
  31. package/dist/types/task/index.d.ts +12 -11
  32. package/dist/types/task/label.d.ts +4 -0
  33. package/dist/types/task/repair-args.d.ts +8 -8
  34. package/dist/types/task/types.d.ts +31 -56
  35. package/dist/types/tools/ask.d.ts +12 -0
  36. package/dist/types/tools/conflict-detect.d.ts +17 -1
  37. package/dist/types/tools/job.d.ts +16 -0
  38. package/package.json +12 -12
  39. package/scripts/build-binary.ts +0 -1
  40. package/scripts/compile-binary.ts +4 -3
  41. package/src/async/job-manager.ts +9 -0
  42. package/src/cli/bench-cli.ts +7 -26
  43. package/src/cli/usage-cli.ts +11 -0
  44. package/src/commands/usage.ts +13 -2
  45. package/src/commit/agentic/tools/analyze-file.ts +2 -3
  46. package/src/config/settings-schema.ts +18 -7
  47. package/src/config/settings.ts +13 -4
  48. package/src/discovery/helpers.ts +3 -4
  49. package/src/extensibility/custom-tools/loader.ts +70 -37
  50. package/src/extensibility/extensions/types.ts +46 -0
  51. package/src/irc/bus.ts +61 -20
  52. package/src/modes/components/__tests__/pause-screen.test.ts +143 -0
  53. package/src/modes/components/advisor-config.ts +32 -22
  54. package/src/modes/components/ask-dialog.ts +888 -0
  55. package/src/modes/components/custom-editor.test.ts +58 -1
  56. package/src/modes/components/custom-editor.ts +42 -11
  57. package/src/modes/components/index.ts +2 -1
  58. package/src/modes/components/model-browser.ts +769 -0
  59. package/src/modes/components/model-hub.ts +2002 -0
  60. package/src/modes/components/pause-screen.ts +208 -0
  61. package/src/modes/components/session-selector.ts +299 -42
  62. package/src/modes/components/tool-execution.ts +2 -0
  63. package/src/modes/components/usage-row.ts +5 -6
  64. package/src/modes/controllers/event-controller.ts +8 -2
  65. package/src/modes/controllers/extension-ui-controller.ts +252 -5
  66. package/src/modes/controllers/input-controller.ts +140 -6
  67. package/src/modes/controllers/selector-controller.ts +160 -97
  68. package/src/modes/controllers/tan-command-controller.ts +1 -1
  69. package/src/modes/controllers/todo-command-controller.ts +1 -2
  70. package/src/modes/interactive-mode.ts +8 -0
  71. package/src/modes/queue-input.ts +132 -0
  72. package/src/modes/shared.ts +1 -1
  73. package/src/modes/theme/theme.ts +3 -3
  74. package/src/modes/types.ts +4 -0
  75. package/src/modes/utils/ui-helpers.ts +50 -24
  76. package/src/prompts/agents/scout.md +0 -1
  77. package/src/prompts/agents/task.md +1 -1
  78. package/src/prompts/system/subagent-system-prompt.md +1 -5
  79. package/src/prompts/system/subagent-yield-reminder.md +10 -0
  80. package/src/prompts/system/task-label.md +23 -0
  81. package/src/prompts/tools/job.md +1 -1
  82. package/src/prompts/tools/task-summary.md +3 -0
  83. package/src/prompts/tools/task.md +17 -18
  84. package/src/session/agent-session.ts +186 -49
  85. package/src/session/agent-storage.ts +330 -3
  86. package/src/session/history-storage.ts +1 -34
  87. package/src/session/session-context.test.ts +73 -0
  88. package/src/session/session-context.ts +43 -26
  89. package/src/slash-commands/builtin-registry.ts +18 -0
  90. package/src/task/agents.ts +2 -0
  91. package/src/task/executor.ts +159 -46
  92. package/src/task/index.ts +377 -239
  93. package/src/task/label.ts +38 -0
  94. package/src/task/render.ts +74 -22
  95. package/src/task/repair-args.ts +20 -31
  96. package/src/task/spawn-policy.test.ts +4 -4
  97. package/src/task/types.ts +46 -66
  98. package/src/tools/ask.ts +233 -40
  99. package/src/tools/conflict-detect.ts +102 -5
  100. package/src/tools/index.ts +1 -0
  101. package/src/tools/irc.ts +20 -11
  102. package/src/tools/job.ts +158 -18
  103. package/src/tools/write.ts +70 -6
  104. package/src/vibe/runtime.ts +1 -1
  105. package/src/web/search/providers/browser-headers.ts +30 -13
  106. package/dist/types/modes/components/model-selector.d.ts +0 -37
  107. package/dist/types/tools/bash-command-fixup.d.ts +0 -3
  108. package/src/modes/components/model-selector.ts +0 -1291
  109. package/src/tools/bash-command-fixup.ts +0 -4
@@ -1,8 +1,9 @@
1
1
  import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "bun:test";
2
+ import { CURSOR_MARKER } from "@oh-my-pi/pi-tui";
2
3
  import { setKittyProtocolActive } from "@oh-my-pi/pi-tui/keys";
3
4
  import { $ } from "bun";
4
5
  import { getDefaultPasteImageKeys } from "../../config/keybindings";
5
- import { getEditorTheme, initTheme } from "../theme/theme";
6
+ import { getEditorTheme, initTheme, theme } from "../theme/theme";
6
7
  import {
7
8
  CustomEditor,
8
9
  extractBracketedImagePastePaths,
@@ -78,6 +79,62 @@ describe("CustomEditor placeholder decoration", () => {
78
79
  });
79
80
  });
80
81
 
82
+ describe("CustomEditor queue shorthand decoration", () => {
83
+ beforeAll(async () => {
84
+ await initTheme();
85
+ });
86
+
87
+ it("reserves the first line as soon as either queue prefix is completed", () => {
88
+ for (const prefix of ["->", "=>"]) {
89
+ const editor = new CustomEditor(getEditorTheme());
90
+ editor.handleInput(prefix[0] ?? "");
91
+ expect(editor.getText()).toBe(prefix[0]);
92
+
93
+ editor.handleInput(prefix[1] ?? "");
94
+ expect(editor.getText()).toBe(`${prefix}\n`);
95
+ expect(editor.getCursor()).toEqual({ line: 1, col: 0 });
96
+
97
+ editor.handleInput("\x7f");
98
+ expect(editor.getText()).toBe(`${prefix}\n`);
99
+ expect(editor.getCursor()).toEqual({ line: 1, col: 0 });
100
+ }
101
+ });
102
+
103
+ it("renders the reserved line as a dim Queueing header", () => {
104
+ for (const prefix of ["->", "=>"]) {
105
+ const editor = new CustomEditor(getEditorTheme());
106
+ editor.setText(`${prefix}\nqueue this`);
107
+
108
+ expect(editor.decorateText(prefix)).toBe(theme.fg("dim", `Queueing ${theme.nav.selected}`));
109
+ editor.focused = true;
110
+ const rendered = editor.render(40).map(line => Bun.stripANSI(line.replace(CURSOR_MARKER, "")));
111
+ expect(rendered.some(line => line.includes(`Queueing ${theme.nav.selected}`))).toBe(true);
112
+ expect(rendered.every(line => Bun.stringWidth(line) === 40)).toBe(true);
113
+ expect(rendered.some(line => line.includes("queue this"))).toBe(true);
114
+ }
115
+ });
116
+
117
+ it("highlights dot and parenthesis markers only for detected queue lists", () => {
118
+ for (const [input, marker] of [
119
+ ["=>\n1. first\n2. second", "1."],
120
+ ["=>\n1) first\n2) second", "1)"],
121
+ ]) {
122
+ const editor = new CustomEditor(getEditorTheme());
123
+ editor.setText(input);
124
+ expect(editor.decorateText(`${marker} first`).startsWith(theme.fg("accent", marker))).toBe(true);
125
+ }
126
+
127
+ const unfinished = new CustomEditor(getEditorTheme());
128
+ unfinished.setText("=>\n1. first\n2. second\n3. third\n4.");
129
+ expect(unfinished.decorateText("1. first").startsWith(theme.fg("accent", "1."))).toBe(true);
130
+ expect(unfinished.decorateText("4.").startsWith(theme.fg("accent", "4."))).toBe(true);
131
+
132
+ const editor = new CustomEditor(getEditorTheme());
133
+ editor.setText("=>\n1. first\n3. third");
134
+ expect(editor.decorateText("1. first")).toBe("1. first");
135
+ });
136
+ });
137
+
81
138
  describe("CustomEditor bracketed path paste", () => {
82
139
  it("leaves a pasted bare .png filename on the normal text path", () => {
83
140
  expect(extractBracketedImagePastePaths(bracketedPaste("icon-photo-default.png"))).toBeUndefined();
@@ -6,7 +6,8 @@ import type { AppKeybinding } from "../../config/keybindings";
6
6
  import { isSettingsInitialized, settings } from "../../config/settings";
7
7
  import { imageReferenceHyperlink, PLACEHOLDER_REGEX, renderPlaceholders } from "../image-references";
8
8
  import { hasMagicKeyword, highlightMagicKeywords } from "../magic-keywords";
9
- import { fgOrPlain } from "../theme/theme";
9
+ import { isQueuedMessageList, parseQueueShorthand, QUEUE_LIST_MARKER_RE } from "../queue-input";
10
+ import { fgOrPlain, theme } from "../theme/theme";
10
11
 
11
12
  type ConfigurableEditorAction = Extract<
12
13
  AppKeybinding,
@@ -326,21 +327,41 @@ export class CustomEditor extends Editor {
326
327
  * timer to request the next animation frame. Undefined when nobody is
327
328
  * listening (tests, headless callers); the timer chain still self-cleans. */
328
329
  #requestShimmerRepaint: (() => void) | undefined;
330
+ #queueDecorationText: string | undefined;
331
+ #queueShorthandActive = false;
332
+ #queueListActive = false;
329
333
 
330
- /** Gradient-highlight the "ultrathink" / "orchestrate" / "workflowz" keywords as the user types
331
- * them, skipping any occurrence inside code spans, fenced blocks, or XML sections. Also make
332
- * pasted image placeholders visually distinct and hyperlink them once their blob file exists.
333
- * When the editor is focused, the buffer contains a magic keyword, and `magicKeywords.enabled`
334
- * is on, the gradient shifts every frame to produce a Claude-Code-style shimmer; each render
335
- * schedules the next frame, so losing focus, deleting the keyword, or flipping the setting
336
- * stops the animation on its own. The static glow itself runs even when shimmering is gated
337
- * off, matching existing behavior for the editor and sent bubbles. */
334
+ /** Decorate magic keywords, attachments, and the queue-composer header/list markers.
335
+ * Queue shorthand reserves its first logical line as a dim `Queueing` label; sequential
336
+ * item markers use the accent color so separate follow-ups remain visible while composing. */
338
337
  decorateText = (text: string): string => {
339
- const animated = this.focused && this.#shimmerEnabled() && hasMagicKeyword(this.getText());
338
+ const editorText = this.getText();
339
+ const animated = this.focused && this.#shimmerEnabled() && hasMagicKeyword(editorText);
340
340
  const phase = animated ? (Date.now() % CustomEditor.SHIMMER_PERIOD_MS) / CustomEditor.SHIMMER_PERIOD_MS : 0;
341
341
  if (animated) this.#scheduleShimmerFrame();
342
+ if (this.#queueDecorationText !== editorText) {
343
+ this.#queueDecorationText = editorText;
344
+ const queueBody = parseQueueShorthand(editorText);
345
+ this.#queueShorthandActive = queueBody !== undefined;
346
+ this.#queueListActive = queueBody !== undefined && isQueuedMessageList(queueBody);
347
+ }
342
348
  return renderPlaceholders(text, {
343
- renderText: value => highlightMagicKeywords(value, undefined, phase),
349
+ renderText: value => {
350
+ const highlighted = highlightMagicKeywords(value, undefined, phase);
351
+ if (this.#queueShorthandActive && (value.startsWith("->") || value.startsWith("=>"))) {
352
+ const icon = typeof theme === "undefined" ? "➤" : theme.nav.selected;
353
+ return `${fgOrPlain("dim", `Queueing ${icon}`)}${highlighted.slice(2)}`;
354
+ }
355
+ if (this.#queueListActive) {
356
+ const markerMatch = QUEUE_LIST_MARKER_RE.exec(value);
357
+ if (markerMatch) {
358
+ const indent = markerMatch[1] ?? "";
359
+ const markerEnd = markerMatch[0].length;
360
+ return `${indent}${fgOrPlain("accent", value.slice(indent.length, markerEnd))}${highlighted.slice(markerEnd)}`;
361
+ }
362
+ }
363
+ return highlighted;
364
+ },
344
365
  renderReference: (value, kind, index) =>
345
366
  kind === "image"
346
367
  ? imageReferenceHyperlink(value, index, this.imageLinks, label =>
@@ -628,6 +649,7 @@ export class CustomEditor extends Editor {
628
649
  this.#pendingInput.push(data);
629
650
  return;
630
651
  }
652
+ const hadBareQueuePrefix = this.getText() === "->" || this.getText() === "=>";
631
653
  const kittyParsed = parseKittySequence(data);
632
654
  if (kittyParsed && (kittyParsed.modifier & 64) !== 0 && this.onCapsLock) {
633
655
  // Caps Lock is modifier bit 64
@@ -831,5 +853,14 @@ export class CustomEditor extends Editor {
831
853
 
832
854
  // Pass to parent for normal handling
833
855
  super.handleInput(data);
856
+ const cursor = this.getCursor();
857
+ if (
858
+ !hadBareQueuePrefix &&
859
+ (this.getText() === "->" || this.getText() === "=>") &&
860
+ cursor.line === 0 &&
861
+ cursor.col === 2
862
+ ) {
863
+ this.insertText("\n");
864
+ }
834
865
  }
835
866
  }
@@ -18,7 +18,8 @@ export * from "./hook-selector";
18
18
  export * from "./keybinding-hints";
19
19
  export * from "./login-dialog";
20
20
  export * from "./logout-account-selector";
21
- export * from "./model-selector";
21
+ export * from "./model-browser";
22
+ export * from "./model-hub";
22
23
  export * from "./oauth-selector";
23
24
  export * from "./queue-mode-selector";
24
25
  export * from "./read-tool-group";