mu-coding 0.4.0 → 0.8.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 (104) hide show
  1. package/README.md +49 -5
  2. package/bin/mu.js +1 -1
  3. package/package.json +17 -4
  4. package/prompts/SYSTEM.md +16 -0
  5. package/src/app/shutdown.ts +94 -0
  6. package/src/app/startApp.ts +43 -0
  7. package/src/cli/args.ts +131 -0
  8. package/src/{install.ts → cli/install.ts} +19 -15
  9. package/src/config/index.test.ts +77 -0
  10. package/src/config/index.ts +199 -0
  11. package/src/main.ts +4 -0
  12. package/src/plugin.ts +96 -0
  13. package/src/runtime/codingTools/bash.ts +114 -0
  14. package/src/runtime/codingTools/edit-file.ts +60 -0
  15. package/src/runtime/codingTools/index.ts +39 -0
  16. package/src/runtime/codingTools/read-file.ts +83 -0
  17. package/src/runtime/codingTools/utils.ts +21 -0
  18. package/src/runtime/codingTools/write-file.ts +42 -0
  19. package/src/runtime/createRegistry.test.ts +146 -0
  20. package/src/runtime/createRegistry.ts +163 -0
  21. package/src/runtime/messageBus.test.ts +62 -0
  22. package/src/runtime/messageBus.ts +78 -0
  23. package/src/runtime/pluginLoader.ts +122 -0
  24. package/src/sessions/index.test.ts +66 -0
  25. package/src/sessions/index.ts +183 -0
  26. package/src/sessions/peek.test.ts +88 -0
  27. package/src/sessions/project.ts +51 -0
  28. package/src/tui/channel/tuiChannel.test.ts +107 -0
  29. package/src/tui/channel/tuiChannel.ts +49 -0
  30. package/src/tui/{context/chat.ts → chat/ChatContext.ts} +1 -1
  31. package/src/tui/chat/MessageRendererContext.ts +44 -0
  32. package/src/tui/chat/ToolDisplayContext.ts +33 -0
  33. package/src/tui/{useAbort.ts → chat/useAbort.ts} +16 -7
  34. package/src/tui/chat/useAttachment.ts +74 -0
  35. package/src/tui/chat/useChat.ts +106 -0
  36. package/src/tui/chat/useChatPanel.ts +98 -0
  37. package/src/tui/chat/useChatSession.ts +284 -0
  38. package/src/tui/{useModelList.ts → chat/useModels.ts} +12 -2
  39. package/src/tui/chat/usePluginStatus.ts +44 -0
  40. package/src/tui/chat/useSessionPersistence.ts +68 -0
  41. package/src/tui/chat/useStatusSegments.ts +62 -0
  42. package/src/tui/components/chat/ChatPanel.tsx +20 -40
  43. package/src/tui/components/chat/ChatPanelBody.tsx +30 -52
  44. package/src/tui/components/chat/Pickers.tsx +2 -2
  45. package/src/tui/components/messageView.tsx +72 -0
  46. package/src/tui/components/messages/EditOutput.tsx +47 -30
  47. package/src/tui/components/messages/ReadOutput.tsx +27 -22
  48. package/src/tui/components/messages/ToolHeader.tsx +28 -0
  49. package/src/tui/components/messages/WriteOutput.tsx +12 -24
  50. package/src/tui/components/messages/assistantMessage.tsx +17 -2
  51. package/src/tui/components/messages/messageItem.tsx +23 -16
  52. package/src/tui/components/messages/reasoningBlock.tsx +4 -2
  53. package/src/tui/components/messages/streamingOutput.tsx +5 -1
  54. package/src/tui/components/messages/toolCallBlock.tsx +61 -38
  55. package/src/tui/components/messages/userMessage.tsx +21 -6
  56. package/src/tui/components/{ui → primitives}/dropdown.tsx +40 -11
  57. package/src/tui/components/{ui → primitives}/modal.tsx +4 -2
  58. package/src/tui/components/primitives/pickerModal.tsx +47 -0
  59. package/src/tui/components/primitives/scrollbar.tsx +27 -0
  60. package/src/tui/components/{ui → primitives}/toast.tsx +5 -3
  61. package/src/tui/components/statusBar.tsx +32 -0
  62. package/src/tui/components/ui/dialogLayer.tsx +32 -13
  63. package/src/tui/context/ThemeContext.tsx +18 -0
  64. package/src/tui/hooks/useScroll.ts +11 -3
  65. package/src/tui/input/InputBox.tsx +6 -0
  66. package/src/tui/input/InputBoxView.tsx +237 -0
  67. package/src/tui/input/commands.test.ts +51 -0
  68. package/src/tui/input/commands.ts +44 -0
  69. package/src/tui/input/cursor.test.ts +136 -0
  70. package/src/tui/input/cursor.ts +214 -0
  71. package/src/tui/input/dumpContext.ts +107 -0
  72. package/src/tui/input/sanitize.ts +33 -0
  73. package/src/tui/input/useCommandExecutor.ts +32 -0
  74. package/src/tui/input/useInputBox.ts +207 -0
  75. package/src/tui/input/useInputHandler.ts +453 -0
  76. package/src/tui/input/useMentionPicker.ts +121 -0
  77. package/src/tui/input/usePluginShortcuts.ts +29 -0
  78. package/src/tui/plugins/InkApprovalChannel.test.ts +51 -0
  79. package/src/tui/plugins/InkApprovalChannel.ts +30 -0
  80. package/src/tui/{services/uiService.ts → plugins/InkUIService.ts} +68 -35
  81. package/src/tui/renderApp.tsx +43 -0
  82. package/src/tui/theme/index.ts +1 -0
  83. package/src/tui/theme/merge.test.ts +49 -0
  84. package/src/tui/theme/merge.ts +43 -0
  85. package/src/tui/theme/presets.ts +79 -0
  86. package/src/tui/theme/types.ts +116 -0
  87. package/src/utils/clipboard.ts +97 -0
  88. package/src/utils/diff.test.ts +56 -0
  89. package/src/cli.ts +0 -96
  90. package/src/clipboard.ts +0 -62
  91. package/src/config.ts +0 -116
  92. package/src/main.tsx +0 -147
  93. package/src/project.ts +0 -32
  94. package/src/session.ts +0 -95
  95. package/src/tui/commands.ts +0 -33
  96. package/src/tui/components/chatLayout.tsx +0 -192
  97. package/src/tui/components/inputBox.tsx +0 -153
  98. package/src/tui/hooks/useInputHandler.ts +0 -268
  99. package/src/tui/useChat.ts +0 -52
  100. package/src/tui/useChatSession.ts +0 -155
  101. package/src/tui/useChatUI.ts +0 -51
  102. package/tsconfig.json +0 -10
  103. /package/src/{subcommands.ts → cli/subcommands.ts} +0 -0
  104. /package/src/{diff.ts → utils/diff.ts} +0 -0
@@ -1,155 +0,0 @@
1
- import { type AgentEvent, type PluginRegistry, runAgent } from 'mu-agents';
2
- import type { ChatMessage, ProviderConfig } from 'mu-provider';
3
- import { useCallback, useRef, useState } from 'react';
4
- import { generateSessionPath, loadSession, saveSession } from '../session';
5
- import type { AttachmentState } from './useChatUI';
6
-
7
- export interface StreamState {
8
- text: string;
9
- reasoning: string;
10
- totalTokens: number;
11
- tps: number;
12
- }
13
-
14
- const EMPTY_STREAM: StreamState = { text: '', reasoning: '', totalTokens: 0, tps: 0 };
15
-
16
- export interface ChatSessionState {
17
- messages: ChatMessage[];
18
- streaming: boolean;
19
- error: string | null;
20
- stream: StreamState;
21
- inputHistory: string[];
22
- onSend: (text: string) => Promise<void>;
23
- onNew: () => void;
24
- onLoadSession: (path: string) => void;
25
- }
26
-
27
- interface SessionDeps {
28
- config: ProviderConfig;
29
- currentModel: string;
30
- attachment: AttachmentState;
31
- controllerRef: React.RefObject<AbortController | null>;
32
- initialMessages?: ChatMessage[];
33
- registry: PluginRegistry;
34
- }
35
-
36
- function applyEvent(prev: StreamState, event: AgentEvent, tps: number): StreamState {
37
- switch (event.type) {
38
- case 'content':
39
- return { ...prev, text: event.text, tps };
40
- case 'reasoning':
41
- return { ...prev, reasoning: event.text, tps };
42
- case 'usage':
43
- return { ...prev, totalTokens: prev.totalTokens + event.totalTokens };
44
- case 'turn_end':
45
- return { ...prev, text: '', reasoning: '' };
46
- default:
47
- return prev;
48
- }
49
- }
50
-
51
- async function consumeAgent(
52
- events: AsyncGenerator<AgentEvent>,
53
- onStream: (updater: (prev: StreamState) => StreamState) => void,
54
- onMessages: (messages: ChatMessage[]) => void,
55
- ): Promise<ChatMessage[] | null> {
56
- let final: ChatMessage[] | null = null;
57
- const start = Date.now();
58
- let tokenCount = 0;
59
-
60
- for await (const event of events) {
61
- if (event.type === 'content' || event.type === 'reasoning') {
62
- tokenCount++;
63
- const elapsed = (Date.now() - start) / 1000;
64
- const tps = elapsed > 0.5 ? Math.round(tokenCount / elapsed) : 0;
65
- onStream((prev) => applyEvent(prev, event, tps));
66
- } else if (event.type === 'messages') {
67
- final = event.messages;
68
- onMessages(event.messages);
69
- } else {
70
- onStream((prev) => applyEvent(prev, event, 0));
71
- }
72
- }
73
- return final;
74
- }
75
-
76
- export function useChatSession(deps: SessionDeps): ChatSessionState {
77
- const { config, currentModel, attachment, controllerRef, initialMessages, registry } = deps;
78
- const [messages, setMessages] = useState<ChatMessage[]>(initialMessages ?? []);
79
- const [streaming, setStreaming] = useState(false);
80
- const [error, setError] = useState<string | null>(null);
81
- const [stream, setStream] = useState<StreamState>(EMPTY_STREAM);
82
- const [inputHistory, setInputHistory] = useState<string[]>(
83
- initialMessages?.filter((m) => m.role === 'user').map((m) => m.content) ?? [],
84
- );
85
- const sessionPathRef = useRef(generateSessionPath());
86
-
87
- const reset = useCallback(() => {
88
- setStream(EMPTY_STREAM);
89
- setError(null);
90
- }, []);
91
-
92
- const onSend = useCallback(
93
- async (text: string) => {
94
- if (streaming) {
95
- return;
96
- }
97
- const userMsg: ChatMessage = {
98
- role: 'user',
99
- content: text,
100
- ...(attachment.attachment ? { images: [attachment.attachment] } : {}),
101
- };
102
- setMessages((prev) => [...prev, userMsg]);
103
- setInputHistory((prev) => [...prev, text]);
104
- reset();
105
- setStreaming(true);
106
- attachment.clear();
107
-
108
- const controller = new AbortController();
109
- controllerRef.current = controller;
110
-
111
- try {
112
- const final = await consumeAgent(
113
- runAgent([...messages, userMsg], config, currentModel, controller.signal, registry),
114
- setStream,
115
- setMessages,
116
- );
117
- if (final) {
118
- saveSession(sessionPathRef.current, final);
119
- }
120
- } catch (err) {
121
- if (!(err instanceof Error && err.name === 'AbortError')) {
122
- setError(err instanceof Error ? err.message : 'Unknown error');
123
- }
124
- } finally {
125
- setStreaming(false);
126
- controllerRef.current = null;
127
- if (!controller.signal.aborted) {
128
- setStream((s) => ({ ...s, text: '', reasoning: '' }));
129
- }
130
- }
131
- },
132
- [streaming, messages, config, currentModel, attachment, controllerRef, reset, registry],
133
- );
134
-
135
- const onNew = useCallback(() => {
136
- setMessages([]);
137
- reset();
138
- sessionPathRef.current = generateSessionPath();
139
- attachment.clear();
140
- }, [attachment, reset]);
141
-
142
- const onLoadSession = useCallback(
143
- (path: string) => {
144
- const msgs = loadSession(path);
145
- if (msgs.length > 0) {
146
- setMessages(msgs);
147
- sessionPathRef.current = path;
148
- reset();
149
- }
150
- },
151
- [reset],
152
- );
153
-
154
- return { messages, streaming, error, stream, inputHistory, onSend, onNew, onLoadSession };
155
- }
@@ -1,51 +0,0 @@
1
- import type { ImageAttachment } from 'mu-provider';
2
- import { useCallback, useState } from 'react';
3
- import { readClipboardImage } from '../clipboard';
4
-
5
- export interface AttachmentState {
6
- attachment: ImageAttachment | null;
7
- attachmentError: string | null;
8
- onPaste: () => void;
9
- clear: () => void;
10
- }
11
-
12
- export function useAttachment(): AttachmentState {
13
- const [attachment, setAttachment] = useState<ImageAttachment | null>(null);
14
- const [attachmentError, setAttachmentError] = useState<string | null>(null);
15
-
16
- const onPaste = useCallback(() => {
17
- const img = readClipboardImage();
18
- if (img) {
19
- setAttachment(img);
20
- setAttachmentError(null);
21
- return;
22
- }
23
- setAttachmentError('No image on clipboard');
24
- setTimeout(() => setAttachmentError(null), 3000);
25
- }, []);
26
-
27
- const clear = useCallback(() => {
28
- setAttachment(null);
29
- setAttachmentError(null);
30
- }, []);
31
-
32
- return { attachment, attachmentError, onPaste, clear };
33
- }
34
-
35
- export interface TogglesState {
36
- showModelPicker: boolean;
37
- showSessionPicker: boolean;
38
- onTogglePicker: () => void;
39
- onToggleSessionPicker: () => void;
40
- }
41
-
42
- export function useToggles(): TogglesState {
43
- const [showModelPicker, setShowModelPicker] = useState(false);
44
- const [showSessionPicker, setShowSessionPicker] = useState(false);
45
- return {
46
- showModelPicker,
47
- showSessionPicker,
48
- onTogglePicker: useCallback(() => setShowModelPicker((p) => !p), []),
49
- onToggleSessionPicker: useCallback(() => setShowSessionPicker((p) => !p), []),
50
- };
51
- }
package/tsconfig.json DELETED
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "rootDir": "src"
6
- },
7
- "include": ["src/**/*"],
8
- "exclude": ["node_modules", "dist"],
9
- "references": [{ "path": "../mu-provider" }, { "path": "../mu-agents" }, { "path": "../mu-repomap" }]
10
- }
File without changes
File without changes