@oh-my-pi/pi-coding-agent 11.8.2 → 11.9.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 (141) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/docs/tui.md +9 -9
  3. package/package.json +7 -7
  4. package/src/capability/mcp.ts +9 -0
  5. package/src/cli/file-processor.ts +8 -13
  6. package/src/cli/oclif-help.ts +1 -1
  7. package/src/cli.ts +14 -0
  8. package/src/commit/git/index.ts +16 -16
  9. package/src/config/file-lock.ts +1 -1
  10. package/src/config/keybindings.ts +11 -11
  11. package/src/config/model-registry.ts +31 -66
  12. package/src/config/settings.ts +88 -95
  13. package/src/config.ts +2 -2
  14. package/src/cursor.ts +4 -4
  15. package/src/debug/index.ts +28 -28
  16. package/src/discovery/builtin.ts +48 -0
  17. package/src/discovery/codex.ts +5 -13
  18. package/src/discovery/cursor.ts +2 -7
  19. package/src/discovery/mcp-json.ts +33 -0
  20. package/src/exa/mcp-client.ts +2 -2
  21. package/src/exa/websets.ts +2 -2
  22. package/src/export/html/index.ts +3 -3
  23. package/src/export/ttsr.ts +27 -27
  24. package/src/extensibility/custom-tools/loader.ts +9 -9
  25. package/src/extensibility/extensions/runner.ts +64 -64
  26. package/src/extensibility/hooks/runner.ts +46 -46
  27. package/src/extensibility/plugins/manager.ts +49 -49
  28. package/src/extensibility/slash-commands.ts +1 -0
  29. package/src/index.ts +0 -3
  30. package/src/internal-urls/router.ts +5 -5
  31. package/src/ipy/kernel.ts +61 -57
  32. package/src/lsp/client.ts +1 -1
  33. package/src/lsp/clients/biome-client.ts +2 -2
  34. package/src/lsp/clients/lsp-linter-client.ts +7 -7
  35. package/src/lsp/index.ts +9 -9
  36. package/src/mcp/config-writer.ts +194 -0
  37. package/src/mcp/config.ts +20 -6
  38. package/src/mcp/index.ts +4 -0
  39. package/src/mcp/loader.ts +6 -0
  40. package/src/mcp/manager.ts +139 -50
  41. package/src/mcp/oauth-discovery.ts +274 -0
  42. package/src/mcp/oauth-flow.ts +229 -0
  43. package/src/mcp/tool-bridge.ts +20 -20
  44. package/src/mcp/transports/http.ts +107 -66
  45. package/src/mcp/transports/stdio.ts +74 -59
  46. package/src/mcp/types.ts +15 -1
  47. package/src/modes/components/assistant-message.ts +25 -25
  48. package/src/modes/components/bash-execution.ts +51 -51
  49. package/src/modes/components/bordered-loader.ts +7 -7
  50. package/src/modes/components/branch-summary-message.ts +7 -7
  51. package/src/modes/components/compaction-summary-message.ts +7 -7
  52. package/src/modes/components/countdown-timer.ts +15 -15
  53. package/src/modes/components/custom-editor.ts +22 -22
  54. package/src/modes/components/custom-message.ts +21 -21
  55. package/src/modes/components/dynamic-border.ts +3 -3
  56. package/src/modes/components/extensions/extension-dashboard.ts +72 -72
  57. package/src/modes/components/extensions/extension-list.ts +99 -97
  58. package/src/modes/components/extensions/inspector-panel.ts +26 -26
  59. package/src/modes/components/footer.ts +36 -36
  60. package/src/modes/components/history-search.ts +52 -52
  61. package/src/modes/components/hook-editor.ts +20 -20
  62. package/src/modes/components/hook-input.ts +20 -20
  63. package/src/modes/components/hook-message.ts +22 -22
  64. package/src/modes/components/hook-selector.ts +52 -52
  65. package/src/modes/components/index.ts +0 -1
  66. package/src/modes/components/login-dialog.ts +57 -57
  67. package/src/modes/components/mcp-add-wizard.ts +1286 -0
  68. package/src/modes/components/model-selector.ts +173 -173
  69. package/src/modes/components/oauth-selector.ts +45 -45
  70. package/src/modes/components/plugin-settings.ts +52 -52
  71. package/src/modes/components/python-execution.ts +53 -53
  72. package/src/modes/components/queue-mode-selector.ts +7 -7
  73. package/src/modes/components/read-tool-group.ts +23 -23
  74. package/src/modes/components/session-selector.ts +40 -37
  75. package/src/modes/components/settings-selector.ts +80 -80
  76. package/src/modes/components/show-images-selector.ts +7 -7
  77. package/src/modes/components/skill-message.ts +27 -27
  78. package/src/modes/components/status-line-segment-editor.ts +81 -81
  79. package/src/modes/components/status-line.ts +73 -73
  80. package/src/modes/components/theme-selector.ts +11 -11
  81. package/src/modes/components/thinking-selector.ts +7 -7
  82. package/src/modes/components/todo-display.ts +19 -19
  83. package/src/modes/components/todo-reminder.ts +9 -9
  84. package/src/modes/components/tool-execution.ts +212 -216
  85. package/src/modes/components/tree-selector.ts +144 -144
  86. package/src/modes/components/ttsr-notification.ts +17 -17
  87. package/src/modes/components/user-message-selector.ts +18 -18
  88. package/src/modes/components/welcome.ts +10 -10
  89. package/src/modes/controllers/command-controller.ts +0 -7
  90. package/src/modes/controllers/event-controller.ts +23 -23
  91. package/src/modes/controllers/extension-ui-controller.ts +13 -13
  92. package/src/modes/controllers/input-controller.ts +12 -9
  93. package/src/modes/controllers/mcp-command-controller.ts +1223 -0
  94. package/src/modes/interactive-mode.ts +240 -241
  95. package/src/modes/rpc/rpc-client.ts +77 -77
  96. package/src/modes/rpc/rpc-mode.ts +5 -5
  97. package/src/modes/theme/theme.ts +113 -113
  98. package/src/modes/types.ts +1 -1
  99. package/src/patch/index.ts +45 -45
  100. package/src/prompts/tools/task.md +22 -2
  101. package/src/sdk.ts +1 -0
  102. package/src/session/agent-session.ts +512 -476
  103. package/src/session/agent-storage.ts +72 -75
  104. package/src/session/auth-storage.ts +186 -252
  105. package/src/session/history-storage.ts +36 -38
  106. package/src/session/session-manager.ts +300 -299
  107. package/src/session/session-storage.ts +65 -90
  108. package/src/ssh/connection-manager.ts +9 -9
  109. package/src/system-prompt.ts +2 -3
  110. package/src/task/agents.ts +1 -1
  111. package/src/task/executor.ts +28 -40
  112. package/src/task/index.ts +13 -12
  113. package/src/task/subprocess-tool-registry.ts +5 -5
  114. package/src/task/worktree.ts +8 -5
  115. package/src/tools/ask.ts +7 -7
  116. package/src/tools/bash.ts +15 -10
  117. package/src/tools/browser.ts +130 -127
  118. package/src/tools/calculator.ts +46 -46
  119. package/src/tools/context.ts +9 -9
  120. package/src/tools/exit-plan-mode.ts +5 -5
  121. package/src/tools/fetch.ts +5 -5
  122. package/src/tools/find.ts +16 -16
  123. package/src/tools/grep.ts +12 -24
  124. package/src/tools/index.ts +1 -1
  125. package/src/tools/notebook.ts +6 -6
  126. package/src/tools/output-meta.ts +10 -2
  127. package/src/tools/python.ts +12 -11
  128. package/src/tools/read.ts +17 -17
  129. package/src/tools/ssh.ts +9 -9
  130. package/src/tools/submit-result.ts +13 -13
  131. package/src/tools/todo-write.ts +6 -6
  132. package/src/tools/write.ts +10 -10
  133. package/src/tui/output-block.ts +6 -6
  134. package/src/tui/utils.ts +9 -9
  135. package/src/utils/event-bus.ts +13 -11
  136. package/src/utils/frontmatter.ts +1 -1
  137. package/src/utils/ignore-files.ts +1 -1
  138. package/src/web/search/index.ts +5 -5
  139. package/src/web/search/providers/anthropic.ts +7 -2
  140. package/examples/hooks/snake.ts +0 -342
  141. package/src/modes/components/armin.ts +0 -379
@@ -7,8 +7,8 @@ import { DynamicBorder } from "./dynamic-border";
7
7
  * Themes must be pre-loaded and passed to the constructor.
8
8
  */
9
9
  export class ThemeSelectorComponent extends Container {
10
- private selectList: SelectList;
11
- private onPreview: (themeName: string) => void;
10
+ #selectList: SelectList;
11
+ #onPreview: (themeName: string) => void;
12
12
 
13
13
  constructor(
14
14
  currentTheme: string,
@@ -18,7 +18,7 @@ export class ThemeSelectorComponent extends Container {
18
18
  onPreview: (themeName: string) => void,
19
19
  ) {
20
20
  super();
21
- this.onPreview = onPreview;
21
+ this.#onPreview = onPreview;
22
22
 
23
23
  // Create select items from provided themes
24
24
  const themeItems: SelectItem[] = themes.map(name => ({
@@ -31,33 +31,33 @@ export class ThemeSelectorComponent extends Container {
31
31
  this.addChild(new DynamicBorder());
32
32
 
33
33
  // Create selector
34
- this.selectList = new SelectList(themeItems, 10, getSelectListTheme());
34
+ this.#selectList = new SelectList(themeItems, 10, getSelectListTheme());
35
35
 
36
36
  // Preselect current theme
37
37
  const currentIndex = themes.indexOf(currentTheme);
38
38
  if (currentIndex !== -1) {
39
- this.selectList.setSelectedIndex(currentIndex);
39
+ this.#selectList.setSelectedIndex(currentIndex);
40
40
  }
41
41
 
42
- this.selectList.onSelect = item => {
42
+ this.#selectList.onSelect = item => {
43
43
  onSelect(item.value);
44
44
  };
45
45
 
46
- this.selectList.onCancel = () => {
46
+ this.#selectList.onCancel = () => {
47
47
  onCancel();
48
48
  };
49
49
 
50
- this.selectList.onSelectionChange = item => {
51
- this.onPreview(item.value);
50
+ this.#selectList.onSelectionChange = item => {
51
+ this.#onPreview(item.value);
52
52
  };
53
53
 
54
- this.addChild(this.selectList);
54
+ this.addChild(this.#selectList);
55
55
 
56
56
  // Add bottom border
57
57
  this.addChild(new DynamicBorder());
58
58
  }
59
59
 
60
60
  getSelectList(): SelectList {
61
- return this.selectList;
61
+ return this.#selectList;
62
62
  }
63
63
  }
@@ -16,7 +16,7 @@ const LEVEL_DESCRIPTIONS: Record<ThinkingLevel, string> = {
16
16
  * Component that renders a thinking level selector with borders
17
17
  */
18
18
  export class ThinkingSelectorComponent extends Container {
19
- private selectList: SelectList;
19
+ #selectList: SelectList;
20
20
 
21
21
  constructor(
22
22
  currentLevel: ThinkingLevel,
@@ -36,29 +36,29 @@ export class ThinkingSelectorComponent extends Container {
36
36
  this.addChild(new DynamicBorder());
37
37
 
38
38
  // Create selector
39
- this.selectList = new SelectList(thinkingLevels, thinkingLevels.length, getSelectListTheme());
39
+ this.#selectList = new SelectList(thinkingLevels, thinkingLevels.length, getSelectListTheme());
40
40
 
41
41
  // Preselect current level
42
42
  const currentIndex = thinkingLevels.findIndex(item => item.value === currentLevel);
43
43
  if (currentIndex !== -1) {
44
- this.selectList.setSelectedIndex(currentIndex);
44
+ this.#selectList.setSelectedIndex(currentIndex);
45
45
  }
46
46
 
47
- this.selectList.onSelect = item => {
47
+ this.#selectList.onSelect = item => {
48
48
  onSelect(item.value as ThinkingLevel);
49
49
  };
50
50
 
51
- this.selectList.onCancel = () => {
51
+ this.#selectList.onCancel = () => {
52
52
  onCancel();
53
53
  };
54
54
 
55
- this.addChild(this.selectList);
55
+ this.addChild(this.#selectList);
56
56
 
57
57
  // Add bottom border
58
58
  this.addChild(new DynamicBorder());
59
59
  }
60
60
 
61
61
  getSelectList(): SelectList {
62
- return this.selectList;
62
+ return this.#selectList;
63
63
  }
64
64
  }
@@ -27,17 +27,17 @@ async function loadTodoFile(filePath: string): Promise<TodoFile | null> {
27
27
  }
28
28
 
29
29
  export class TodoDisplayComponent {
30
- public todos: TodoItem[] = [];
31
- private expanded = false;
32
- private visible = false;
33
- private cached: RenderCache | undefined;
30
+ todos: TodoItem[] = [];
31
+ #expanded = false;
32
+ #visible = false;
33
+ #cached: RenderCache | undefined;
34
34
 
35
35
  constructor(private readonly sessionFile: string | null) {}
36
36
 
37
37
  async loadTodos(): Promise<void> {
38
38
  if (!this.sessionFile) {
39
39
  this.todos = [];
40
- this.visible = false;
40
+ this.#visible = false;
41
41
  return;
42
42
  }
43
43
 
@@ -45,36 +45,36 @@ export class TodoDisplayComponent {
45
45
  const todoPath = path.join(artifactsDir, TODO_FILE_NAME);
46
46
  const data = await loadTodoFile(todoPath);
47
47
  this.todos = data?.todos ?? [];
48
- this.visible = this.todos.length > 0;
49
- this.cached = undefined;
48
+ this.#visible = this.todos.length > 0;
49
+ this.#cached = undefined;
50
50
  }
51
51
 
52
52
  setTodos(todos: TodoItem[]): void {
53
53
  this.todos = todos;
54
- this.visible = this.todos.length > 0;
55
- this.cached = undefined;
54
+ this.#visible = this.todos.length > 0;
55
+ this.#cached = undefined;
56
56
  }
57
57
 
58
58
  setExpanded(expanded: boolean): void {
59
- this.expanded = expanded;
60
- this.cached = undefined;
59
+ this.#expanded = expanded;
60
+ this.#cached = undefined;
61
61
  }
62
62
 
63
63
  isVisible(): boolean {
64
- return this.visible;
64
+ return this.#visible;
65
65
  }
66
66
 
67
67
  render(width: number): string[] {
68
- if (!this.visible || this.todos.length === 0) {
68
+ if (!this.#visible || this.todos.length === 0) {
69
69
  return [];
70
70
  }
71
71
 
72
- const key = new Hasher().bool(this.expanded).u32(width).digest();
73
- if (this.cached?.key === key) return this.cached.lines;
72
+ const key = new Hasher().bool(this.#expanded).u32(width).digest();
73
+ if (this.#cached?.key === key) return this.#cached.lines;
74
74
 
75
75
  const lines: string[] = [];
76
- const maxItems = this.expanded ? this.todos.length : Math.min(5, this.todos.length);
77
- const hasMore = !this.expanded && this.todos.length > 5;
76
+ const maxItems = this.#expanded ? this.todos.length : Math.min(5, this.todos.length);
77
+ const hasMore = !this.#expanded && this.todos.length > 5;
78
78
 
79
79
  for (let i = 0; i < maxItems; i++) {
80
80
  const todo = this.todos[i];
@@ -102,12 +102,12 @@ export class TodoDisplayComponent {
102
102
  }
103
103
 
104
104
  const result = lines.map(l => truncateToWidth(l, width, Ellipsis.Omit));
105
- this.cached = { key, lines: result };
105
+ this.#cached = { key, lines: result };
106
106
  return result;
107
107
  }
108
108
 
109
109
  getRenderedComponent(): Text | null {
110
- if (!this.visible) return null;
110
+ if (!this.#visible) return null;
111
111
  const lines = this.render(80);
112
112
  return new Text(lines.join("\n"), 0, 0);
113
113
  }
@@ -7,7 +7,7 @@ import type { TodoItem } from "../../tools/todo-write";
7
7
  * Shows when the agent stops with incomplete todos.
8
8
  */
9
9
  export class TodoReminderComponent extends Container {
10
- private box: Box;
10
+ #box: Box;
11
11
 
12
12
  constructor(
13
13
  private readonly todos: TodoItem[],
@@ -18,23 +18,23 @@ export class TodoReminderComponent extends Container {
18
18
 
19
19
  this.addChild(new Spacer(1));
20
20
 
21
- this.box = new Box(1, 1, t => theme.inverse(theme.fg("warning", t)));
22
- this.addChild(this.box);
21
+ this.#box = new Box(1, 1, t => theme.inverse(theme.fg("warning", t)));
22
+ this.addChild(this.#box);
23
23
 
24
- this.rebuild();
24
+ this.#rebuild();
25
25
  }
26
26
 
27
- private rebuild(): void {
28
- this.box.clear();
27
+ #rebuild(): void {
28
+ this.#box.clear();
29
29
 
30
30
  const count = this.todos.length;
31
31
  const label = count === 1 ? "todo" : "todos";
32
32
  const header = `${theme.icon.warning} ${count} incomplete ${label} - reminder ${this.attempt}/${this.maxAttempts}`;
33
33
 
34
- this.box.addChild(new Text(header, 0, 0));
35
- this.box.addChild(new Spacer(1));
34
+ this.#box.addChild(new Text(header, 0, 0));
35
+ this.#box.addChild(new Spacer(1));
36
36
 
37
37
  const todoList = this.todos.map(t => ` ${theme.checkbox.unchecked} ${t.content}`).join("\n");
38
- this.box.addChild(new Text(theme.italic(todoList), 0, 0));
38
+ this.#box.addChild(new Text(theme.italic(todoList), 0, 0));
39
39
  }
40
40
  }