mini-coder 0.5.14 → 0.6.1

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 (70) hide show
  1. package/README.md +26 -109
  2. package/bin/mc.ts +8 -11
  3. package/bun.lock +79 -269
  4. package/nono-mini-coder.json +42 -0
  5. package/package.json +17 -22
  6. package/src/agent.ts +243 -1403
  7. package/src/args.ts +289 -0
  8. package/src/headless.ts +41 -359
  9. package/src/index.ts +29 -1016
  10. package/src/oauth.ts +117 -0
  11. package/src/prompt.ts +219 -284
  12. package/src/session.ts +55 -1306
  13. package/src/shared.ts +117 -38
  14. package/src/tool-bash.ts +110 -0
  15. package/src/tool-edit.ts +133 -0
  16. package/src/tool-read.ts +80 -293
  17. package/src/tui-components.ts +150 -0
  18. package/src/tui-conversation.ts +271 -0
  19. package/src/tui-editor.ts +29 -0
  20. package/src/tui-overlay.ts +403 -0
  21. package/src/tui.ts +228 -0
  22. package/src/types.ts +164 -0
  23. package/tsconfig.json +17 -0
  24. package/BENCHMARK.md +0 -107
  25. package/LICENSE +0 -9
  26. package/PROGRESS.md +0 -5
  27. package/assets/icon-1-minimal.svg +0 -31
  28. package/assets/icon-2-dark-terminal.svg +0 -48
  29. package/assets/icon-3-gradient-modern.svg +0 -45
  30. package/assets/icon-4-filled-bold.svg +0 -54
  31. package/assets/icon-5-community-badge.svg +0 -63
  32. package/assets/mc-claude-smart.png +0 -0
  33. package/assets/mc-gpt-smart.png +0 -0
  34. package/assets/preview-0-5-0.png +0 -0
  35. package/assets/preview.gif +0 -0
  36. package/benchmark-baseline.sh +0 -15
  37. package/benchmark-loop.sh +0 -19
  38. package/skills-lock.json +0 -15
  39. package/src/assistant-output.ts +0 -73
  40. package/src/cli.ts +0 -134
  41. package/src/delegation.ts +0 -238
  42. package/src/errors.ts +0 -15
  43. package/src/git.ts +0 -247
  44. package/src/input.ts +0 -168
  45. package/src/mcp.ts +0 -609
  46. package/src/paths.ts +0 -37
  47. package/src/session-message.ts +0 -385
  48. package/src/settings.ts +0 -449
  49. package/src/skills.ts +0 -271
  50. package/src/submit.ts +0 -376
  51. package/src/text.ts +0 -71
  52. package/src/theme.ts +0 -330
  53. package/src/tool-common.ts +0 -93
  54. package/src/tool-delegate.ts +0 -125
  55. package/src/tool-grep.ts +0 -606
  56. package/src/tool-shell.ts +0 -1051
  57. package/src/tools.ts +0 -1179
  58. package/src/ui/agent.ts +0 -320
  59. package/src/ui/commands.test.ts +0 -957
  60. package/src/ui/commands.ts +0 -848
  61. package/src/ui/conversation.test.ts +0 -585
  62. package/src/ui/conversation.ts +0 -1836
  63. package/src/ui/help.ts +0 -158
  64. package/src/ui/input.test.ts +0 -64
  65. package/src/ui/input.ts +0 -138
  66. package/src/ui/overlay.ts +0 -59
  67. package/src/ui/runtime.ts +0 -69
  68. package/src/ui/status.ts +0 -220
  69. package/src/ui.ts +0 -1190
  70. package/src/version.ts +0 -48
package/src/ui/status.ts DELETED
@@ -1,220 +0,0 @@
1
- /**
2
- * Status-bar formatting and rendering for the terminal UI.
3
- *
4
- * Computes the cumulative usage pill, abbreviates the working directory, and
5
- * formats the cached current-context estimate maintained on application state.
6
- *
7
- * @module
8
- */
9
-
10
- import { homedir } from "node:os";
11
- import { Spacer } from "@cel-tui/components";
12
- import { HStack, Text, visibleWidth } from "@cel-tui/core";
13
- import type { Node } from "@cel-tui/types";
14
- import type { AppState } from "../index.ts";
15
- import type { StatusTone, Theme } from "../theme.ts";
16
-
17
- /**
18
- * Abbreviate a path with `~` for the home directory.
19
- *
20
- * @param path - Absolute path to abbreviate.
21
- * @returns The abbreviated display path.
22
- */
23
- export function abbreviatePath(path: string): string {
24
- const home = homedir();
25
- if (path === home) {
26
- return "~";
27
- }
28
- if (path.startsWith(`${home}/`)) {
29
- return `~${path.slice(home.length)}`;
30
- }
31
- return path;
32
- }
33
-
34
- /** Format a token count with human-friendly units (1.2k, 45k, 1.2M). */
35
- function formatTokens(n: number): string {
36
- if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
37
- if (n >= 1_000) return `${(n / 1_000).toFixed(1)}k`;
38
- return String(n);
39
- }
40
-
41
- /** Format a token capacity, trimming unnecessary trailing `.0`. */
42
- function formatTokenCapacity(n: number): string {
43
- return formatTokens(n).replace(/\.0([kM])$/, "$1");
44
- }
45
-
46
- /** Format a dollar cost. */
47
- function formatCost(cost: number): string {
48
- return `$${cost.toFixed(2)}`;
49
- }
50
-
51
- /** Format the effort level for display. */
52
- function formatEffort(effort: string): string {
53
- const map: Record<string, string> = {
54
- minimal: "min",
55
- low: "low",
56
- medium: "med",
57
- high: "high",
58
- xhigh: "xhigh",
59
- };
60
- return map[effort] ?? effort;
61
- }
62
-
63
- /** Format git status for the status bar right side. */
64
- function formatGitStatus(state: AppState): string {
65
- if (!state.git) return "";
66
- const parts: string[] = [state.git.branch];
67
- if (state.git.staged > 0) parts.push(`+${state.git.staged}`);
68
- if (state.git.modified > 0) parts.push(`~${state.git.modified}`);
69
- if (state.git.untracked > 0) parts.push(`?${state.git.untracked}`);
70
- if (state.git.ahead > 0) parts.push(`▲ ${state.git.ahead}`);
71
- if (state.git.behind > 0) parts.push(`▼ ${state.git.behind}`);
72
- return parts.join(" ");
73
- }
74
-
75
- /** Format model info for the status bar left side. */
76
- function formatModelInfo(state: AppState): string {
77
- if (!state.model) return "no model";
78
- return `${state.model.provider}/${state.model.id} · ${formatEffort(state.effort)}`;
79
- }
80
-
81
- /** Estimate current context usage as a percentage of the active model window. */
82
- function getContextPercentage(state: AppState): number {
83
- if (!state.model || state.model.contextWindow <= 0) {
84
- return 0;
85
- }
86
- return (state.contextTokens / state.model.contextWindow) * 100;
87
- }
88
-
89
- /** Format cumulative session totals plus estimated current context usage for the status bar. */
90
- function formatUsage(state: AppState, contextPct: number): string {
91
- if (!state.model) return "";
92
- const input = formatTokens(state.stats.totalInput);
93
- const output = formatTokens(state.stats.totalOutput);
94
- const contextWindow = formatTokenCapacity(state.model.contextWindow);
95
- return `in:${input} out:${output} · ${contextPct.toFixed(1)}%/${contextWindow} · ${formatCost(state.stats.totalCost)}`;
96
- }
97
-
98
- /** Select the model/effort pill tone for the current reasoning effort. */
99
- function getEffortTone(theme: Theme, effort: string): StatusTone {
100
- switch (effort) {
101
- case "xhigh":
102
- return theme.statusEffortScale[3];
103
- case "high":
104
- return theme.statusEffortScale[2];
105
- case "medium":
106
- return theme.statusEffortScale[1];
107
- default:
108
- return theme.statusEffortScale[0];
109
- }
110
- }
111
-
112
- /** Select the usage/context pill tone for the current context pressure. */
113
- function getContextTone(theme: Theme, contextPct: number): StatusTone {
114
- if (contextPct >= 90) {
115
- return theme.statusContextScale[4];
116
- }
117
- if (contextPct >= 75) {
118
- return theme.statusContextScale[3];
119
- }
120
- if (contextPct >= 50) {
121
- return theme.statusContextScale[2];
122
- }
123
- if (contextPct >= 25) {
124
- return theme.statusContextScale[1];
125
- }
126
- return theme.statusContextScale[0];
127
- }
128
-
129
- /** Render a single compact status pill. */
130
- function renderStatusPill(text: string, tone: StatusTone): Node {
131
- return HStack({ bgColor: tone.bg, padding: { x: 1 } }, [
132
- Text(text, { fgColor: tone.fg }),
133
- ]);
134
- }
135
-
136
- function measureStatusPill(text: string): number {
137
- return visibleWidth(text) + 2;
138
- }
139
-
140
- function leftTruncate(text: string, maxWidth: number): string {
141
- if (maxWidth <= 0) {
142
- return "";
143
- }
144
- if (visibleWidth(text) <= maxWidth) {
145
- return text;
146
- }
147
- if (maxWidth === 1) {
148
- return "…";
149
- }
150
-
151
- for (let i = text.lastIndexOf("/"); i > 0; i = text.lastIndexOf("/", i - 1)) {
152
- const candidate = text.slice(i);
153
- if (visibleWidth(candidate) <= maxWidth - 1) {
154
- return `…${candidate}`;
155
- }
156
- }
157
-
158
- let suffix = "";
159
- for (const char of Array.from(text).reverse()) {
160
- const next = `${char}${suffix}`;
161
- if (visibleWidth(next) > maxWidth - 1) {
162
- break;
163
- }
164
- suffix = next;
165
- }
166
-
167
- return `…${suffix}`;
168
- }
169
-
170
- /**
171
- * Render the one-line status bar as compact padded pills.
172
- *
173
- * The inner pills use the neutral secondary tone. The model pill uses a
174
- * reasoning-effort tone scale, and the usage pill uses an independent
175
- * context-pressure tone scale. The git pill is omitted outside repositories.
176
- *
177
- * @param state - Application state.
178
- * @param cols - Current terminal width in columns.
179
- * @returns The rendered status bar node.
180
- */
181
- export function renderStatusBar(
182
- state: AppState,
183
- cols = Number.POSITIVE_INFINITY,
184
- ): Node {
185
- const fullCwd = abbreviatePath(state.cwd);
186
- const gitStatus = formatGitStatus(state);
187
- const modelInfo = formatModelInfo(state);
188
- const contextPct = getContextPercentage(state);
189
- const usage = formatUsage(state, contextPct);
190
- const reservedWidth =
191
- 2 +
192
- measureStatusPill(modelInfo) +
193
- measureStatusPill(usage) +
194
- (gitStatus ? measureStatusPill(gitStatus) : 0) +
195
- 2;
196
- const cwd = Number.isFinite(cols)
197
- ? leftTruncate(fullCwd, Math.max(Math.floor(cols) - reservedWidth, 1))
198
- : fullCwd;
199
-
200
- const secondaryTone = state.theme.statusSecondary;
201
- const children: Node[] = [
202
- renderStatusPill(modelInfo, getEffortTone(state.theme, state.effort)),
203
- renderStatusPill(cwd, secondaryTone),
204
- Spacer(),
205
- ];
206
- if (gitStatus) {
207
- children.push(renderStatusPill(gitStatus, secondaryTone));
208
- }
209
- children.push(
210
- renderStatusPill(usage, getContextTone(state.theme, contextPct)),
211
- );
212
-
213
- return HStack(
214
- {
215
- height: 1,
216
- padding: { x: 1 },
217
- },
218
- children,
219
- );
220
- }