mu-coding 0.5.0 → 0.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 (84) hide show
  1. package/README.md +49 -3
  2. package/package.json +9 -4
  3. package/prompts/SYSTEM.md +16 -0
  4. package/src/app/shutdown.ts +1 -1
  5. package/src/app/startApp.ts +11 -8
  6. package/src/cli/args.ts +14 -11
  7. package/src/cli/install.ts +18 -3
  8. package/src/config/index.test.ts +26 -0
  9. package/src/config/index.ts +25 -7
  10. package/src/plugin.ts +124 -0
  11. package/src/runtime/codingTools/bash.ts +114 -0
  12. package/src/runtime/codingTools/edit-file.ts +60 -0
  13. package/src/runtime/codingTools/index.ts +39 -0
  14. package/src/runtime/codingTools/read-file.ts +83 -0
  15. package/src/runtime/codingTools/utils.ts +21 -0
  16. package/src/runtime/codingTools/write-file.ts +42 -0
  17. package/src/runtime/createRegistry.test.ts +147 -0
  18. package/src/runtime/createRegistry.ts +160 -23
  19. package/src/runtime/fileMentionProvider.ts +116 -0
  20. package/src/runtime/messageBus.test.ts +62 -0
  21. package/src/runtime/messageBus.ts +78 -0
  22. package/src/runtime/pluginLoader.ts +59 -15
  23. package/src/sessions/index.ts +2 -9
  24. package/src/tui/channel/tuiChannel.test.ts +107 -0
  25. package/src/tui/channel/tuiChannel.ts +62 -0
  26. package/src/tui/chat/MessageRendererContext.ts +44 -0
  27. package/src/tui/chat/ToolDisplayContext.ts +1 -1
  28. package/src/tui/chat/useAbort.ts +5 -0
  29. package/src/tui/chat/useAttachment.ts +1 -1
  30. package/src/tui/chat/useChat.ts +38 -3
  31. package/src/tui/chat/useChatPanel.ts +29 -6
  32. package/src/tui/chat/useChatSession.ts +324 -57
  33. package/src/tui/chat/useModels.ts +26 -1
  34. package/src/tui/chat/usePluginStatus.ts +1 -1
  35. package/src/tui/chat/useSessionPersistence.ts +48 -21
  36. package/src/tui/chat/useStatusSegments.ts +38 -5
  37. package/src/tui/chat/useSubagentBrowser.ts +133 -0
  38. package/src/tui/components/chat/ChatPanel.tsx +25 -4
  39. package/src/tui/components/chat/ChatPanelBody.tsx +22 -1
  40. package/src/tui/components/chat/SubagentBrowserPanel.tsx +145 -0
  41. package/src/tui/components/messageView.tsx +4 -2
  42. package/src/tui/components/messages/EditOutput.tsx +17 -9
  43. package/src/tui/components/messages/ReadOutput.tsx +1 -1
  44. package/src/tui/components/messages/ToolHeader.tsx +8 -4
  45. package/src/tui/components/messages/WriteOutput.tsx +12 -4
  46. package/src/tui/components/messages/assistantMessage.tsx +55 -7
  47. package/src/tui/components/messages/markdown.tsx +402 -0
  48. package/src/tui/components/messages/messageItem.tsx +19 -1
  49. package/src/tui/components/messages/reasoningBlock.tsx +10 -6
  50. package/src/tui/components/messages/streamingOutput.tsx +6 -2
  51. package/src/tui/components/messages/toolCallBlock.tsx +7 -6
  52. package/src/tui/components/messages/userMessage.tsx +22 -7
  53. package/src/tui/components/primitives/dropdown.tsx +8 -4
  54. package/src/tui/components/primitives/modal.tsx +4 -2
  55. package/src/tui/components/primitives/pickerModal.tsx +3 -1
  56. package/src/tui/components/primitives/toast.tsx +43 -10
  57. package/src/tui/components/statusBar.tsx +26 -10
  58. package/src/tui/components/ui/dialogLayer.tsx +11 -6
  59. package/src/tui/context/ThemeContext.tsx +18 -0
  60. package/src/tui/hooks/useChordKeyboard.ts +87 -0
  61. package/src/tui/hooks/useInputInfoSegments.ts +22 -0
  62. package/src/tui/input/InputBoxView.tsx +191 -26
  63. package/src/tui/input/commands.test.ts +3 -1
  64. package/src/tui/input/commands.ts +11 -1
  65. package/src/tui/input/cursor.test.ts +136 -0
  66. package/src/tui/input/cursor.ts +214 -0
  67. package/src/tui/input/dumpContext.ts +107 -0
  68. package/src/tui/input/sanitize.ts +1 -1
  69. package/src/tui/input/useCommandExecutor.ts +1 -1
  70. package/src/tui/input/useInputBox.ts +160 -15
  71. package/src/tui/input/useInputHandler.ts +317 -126
  72. package/src/tui/input/useMentionPicker.ts +133 -0
  73. package/src/tui/input/usePluginShortcuts.ts +29 -0
  74. package/src/tui/plugins/InkApprovalChannel.test.ts +51 -0
  75. package/src/tui/plugins/InkApprovalChannel.ts +30 -0
  76. package/src/tui/plugins/InkUIService.ts +1 -1
  77. package/src/tui/renderApp.tsx +47 -13
  78. package/src/tui/theme/index.ts +1 -0
  79. package/src/tui/theme/merge.test.ts +49 -0
  80. package/src/tui/theme/merge.ts +43 -0
  81. package/src/tui/theme/presets.ts +90 -0
  82. package/src/tui/theme/types.ts +138 -0
  83. package/src/utils/clipboard.ts +1 -1
  84. package/src/tui/chat/useStreamConsumer.ts +0 -118
@@ -1,118 +0,0 @@
1
- import { type AgentEvent, type PluginRegistry, runAgent } from 'mu-agents';
2
- import type { ChatMessage, ProviderConfig } from 'mu-provider';
3
- import { useCallback, useState } from 'react';
4
-
5
- export interface StreamState {
6
- text: string;
7
- reasoning: string;
8
- tps: number;
9
- }
10
-
11
- const EMPTY_STREAM: StreamState = { text: '', reasoning: '', tps: 0 };
12
- const TPS_WARMUP_SEC = 0.5;
13
-
14
- export interface StreamConsumerState {
15
- streaming: boolean;
16
- error: string | null;
17
- stream: StreamState;
18
- /**
19
- * Run the agent against `messages` and stream events into local state.
20
- * Returns the final message array (or null if the agent didn't produce one,
21
- * e.g. on abort). Throws are caught and reported via `error`.
22
- */
23
- runStream: (
24
- messages: ChatMessage[],
25
- config: ProviderConfig,
26
- model: string,
27
- signal: AbortSignal,
28
- registry: PluginRegistry,
29
- onMessages: (messages: ChatMessage[]) => void,
30
- ) => Promise<ChatMessage[] | null>;
31
- resetError: () => void;
32
- }
33
-
34
- function applyEvent(prev: StreamState, event: AgentEvent, tps: number): StreamState {
35
- switch (event.type) {
36
- case 'content':
37
- return { ...prev, text: event.text, tps };
38
- case 'reasoning':
39
- return { ...prev, reasoning: event.text, tps };
40
- case 'turn_end':
41
- return { ...prev, text: '', reasoning: '' };
42
- default:
43
- return prev;
44
- }
45
- }
46
-
47
- async function consumeAgent(
48
- events: AsyncGenerator<AgentEvent>,
49
- onStream: (updater: (prev: StreamState) => StreamState) => void,
50
- onMessages: (messages: ChatMessage[]) => void,
51
- ): Promise<ChatMessage[] | null> {
52
- let final: ChatMessage[] | null = null;
53
- const start = Date.now();
54
- let tokenCount = 0;
55
-
56
- for await (const event of events) {
57
- if (event.type === 'content' || event.type === 'reasoning') {
58
- tokenCount++;
59
- const elapsed = (Date.now() - start) / 1000;
60
- const tps = elapsed > TPS_WARMUP_SEC ? Math.round(tokenCount / elapsed) : 0;
61
- onStream((prev) => applyEvent(prev, event, tps));
62
- } else if (event.type === 'messages') {
63
- final = event.messages;
64
- onMessages(event.messages);
65
- } else {
66
- onStream((prev) => applyEvent(prev, event, 0));
67
- }
68
- }
69
- return final;
70
- }
71
-
72
- /**
73
- * Owns the in-flight streaming view: which tokens have been received, the
74
- * tokens-per-second meter, error text, and the streaming flag. Decoupled
75
- * from message persistence so it can be reused by single-shot agents or
76
- * test harnesses.
77
- */
78
- export function useStreamConsumer(): StreamConsumerState {
79
- const [streaming, setStreaming] = useState(false);
80
- const [error, setError] = useState<string | null>(null);
81
- const [stream, setStream] = useState<StreamState>(EMPTY_STREAM);
82
-
83
- const resetError = useCallback(() => setError(null), []);
84
-
85
- const runStream = useCallback(
86
- async (
87
- messages: ChatMessage[],
88
- config: ProviderConfig,
89
- model: string,
90
- signal: AbortSignal,
91
- registry: PluginRegistry,
92
- onMessages: (messages: ChatMessage[]) => void,
93
- ): Promise<ChatMessage[] | null> => {
94
- setStream(EMPTY_STREAM);
95
- setError(null);
96
- setStreaming(true);
97
- try {
98
- return await consumeAgent(runAgent(messages, config, model, signal, registry), setStream, onMessages);
99
- } catch (err) {
100
- if (!(err instanceof Error && err.name === 'AbortError')) {
101
- setError(err instanceof Error ? err.message : 'Unknown error');
102
- }
103
- return null;
104
- } finally {
105
- setStreaming(false);
106
- // Preserve partial output on abort so the user can see what arrived;
107
- // clear it on clean completion so the persisted assistant message
108
- // doesn't render twice.
109
- if (!signal.aborted) {
110
- setStream((s) => ({ ...s, text: '', reasoning: '' }));
111
- }
112
- }
113
- },
114
- [],
115
- );
116
-
117
- return { streaming, error, stream, runStream, resetError };
118
- }