@yanzc/claude-pro 0.0.0-stage → 0.4.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 (58) hide show
  1. package/.env.example +41 -0
  2. package/LICENSE +21 -0
  3. package/README.md +314 -3
  4. package/bin/claude-pro.js +32 -0
  5. package/package.json +40 -6
  6. package/src/agent.js +752 -0
  7. package/src/agents.js +186 -0
  8. package/src/api.js +529 -0
  9. package/src/cache.js +150 -0
  10. package/src/checkpoints.js +184 -0
  11. package/src/claude-code.js +60 -0
  12. package/src/codex/client.js +307 -0
  13. package/src/codex/translate-request.js +239 -0
  14. package/src/codex/translate-stream.js +328 -0
  15. package/src/commands.js +839 -0
  16. package/src/config.js +453 -0
  17. package/src/context.js +109 -0
  18. package/src/filestate.js +57 -0
  19. package/src/gateway.js +143 -0
  20. package/src/hooks.js +81 -0
  21. package/src/main.js +193 -0
  22. package/src/mcp.js +290 -0
  23. package/src/modes.js +154 -0
  24. package/src/oauth.js +287 -0
  25. package/src/peers.js +157 -0
  26. package/src/print.js +106 -0
  27. package/src/prompts.js +179 -0
  28. package/src/ratelimit.js +244 -0
  29. package/src/restart.js +115 -0
  30. package/src/runtime.js +162 -0
  31. package/src/selfcheck.js +71 -0
  32. package/src/session.js +139 -0
  33. package/src/supervisor.js +110 -0
  34. package/src/tasks.js +76 -0
  35. package/src/tools/bash.js +227 -0
  36. package/src/tools/effort.js +41 -0
  37. package/src/tools/files.js +352 -0
  38. package/src/tools/index.js +52 -0
  39. package/src/tools/interaction.js +157 -0
  40. package/src/tools/notebook.js +91 -0
  41. package/src/tools/peers.js +45 -0
  42. package/src/tools/restart.js +50 -0
  43. package/src/tools/search.js +458 -0
  44. package/src/tools/skill.js +32 -0
  45. package/src/tools/task.js +139 -0
  46. package/src/tools/web.js +283 -0
  47. package/src/ui/ansi.js +228 -0
  48. package/src/ui/dialogs.js +122 -0
  49. package/src/ui/editor.js +389 -0
  50. package/src/ui/markdown.js +249 -0
  51. package/src/ui/render.js +155 -0
  52. package/src/ui/repl.js +1460 -0
  53. package/src/ui/screen.js +259 -0
  54. package/src/updater.js +93 -0
  55. package/src/utils/clipboard.js +197 -0
  56. package/src/utils/diff.js +95 -0
  57. package/src/utils/paths.js +37 -0
  58. package/src/utils/shell.js +251 -0
@@ -0,0 +1,155 @@
1
+ // Formatting of transcript items: user prompts, tool calls and results, diffs, todos.
2
+
3
+ import { c, stringWidth, truncate, padEnd, wordWrap, wrapLine } from './ansi.js';
4
+ import { displayPath } from '../utils/paths.js';
5
+ import { renderMarkdown } from './markdown.js';
6
+
7
+ export const DOT = '⏺';
8
+ const RESULT_PREFIX = ' ⎿ ';
9
+ const RESULT_INDENT = ' ';
10
+
11
+ export function toolLabel(tool, input) {
12
+ return tool.label?.(input) || tool.name;
13
+ }
14
+
15
+ export function toolHeader(tool, input, ctx, { status = 'done', width = 100, dot: showDot = true } = {}) {
16
+ const dot = status === 'error' ? c.red(DOT) : status === 'running' ? (Date.now() % 1000 < 500 ? c.gray(DOT) : ' ') : status === 'rejected' ? c.red(DOT) : c.green(DOT);
17
+ let summary = '';
18
+ try { summary = tool.summarize?.(input || {}, ctx) ?? ''; } catch { summary = ''; }
19
+ summary = summary.replace(/\s*\n\s*/g, ' ');
20
+ const label = c.bold(toolLabel(tool, input));
21
+ const head = showDot ? `${dot} ${label}` : label;
22
+ if (!summary) return head;
23
+ return truncate(`${head}(${summary})`, Math.max(20, width - 2)) + (stringWidth(`${head}(${summary})`) > width - 2 ? ')' : '');
24
+ }
25
+
26
+ export function resultLines(lines) {
27
+ return lines.map((l, i) => (i === 0 ? c.gray(RESULT_PREFIX) : RESULT_INDENT) + l);
28
+ }
29
+
30
+ function numberWidth(hunks) {
31
+ let max = 1;
32
+ for (const h of hunks) for (const l of h.lines) max = Math.max(max, l.oldNo || 0, l.newNo || 0);
33
+ return String(max).length;
34
+ }
35
+
36
+ export function renderDiff(preview, width, maxLines = 40) {
37
+ const out = [];
38
+ const w = Math.max(20, width - RESULT_INDENT.length - 1);
39
+ if (preview.kind === 'create') {
40
+ const nw = String(preview.lines.length).length;
41
+ preview.lines.slice(0, maxLines).forEach((line, i) => {
42
+ out.push(c.diffAdd(padEnd(truncate(`${String(i + 1).padStart(nw)} + ${line.replace(/\t/g, ' ')}`, w), w)));
43
+ });
44
+ if (preview.lines.length > maxLines) out.push(c.dim(`… +${preview.lines.length - maxLines} lines`));
45
+ return out;
46
+ }
47
+ const nw = numberWidth(preview.hunks);
48
+ let count = 0;
49
+ preview.hunks.forEach((h, hi) => {
50
+ if (hi > 0) out.push(c.dim(' '.repeat(nw) + ' ...'));
51
+ for (const l of h.lines) {
52
+ if (count++ >= maxLines) continue;
53
+ const text = l.line.replace(/\t/g, ' ');
54
+ if (l.op === '-') out.push(c.diffDel(padEnd(truncate(`${String(l.oldNo).padStart(nw)} - ${text}`, w), w)));
55
+ else if (l.op === '+') out.push(c.diffAdd(padEnd(truncate(`${String(l.newNo).padStart(nw)} + ${text}`, w), w)));
56
+ else out.push(truncate(`${c.dim(String(l.newNo).padStart(nw))} ${text}`, w));
57
+ }
58
+ });
59
+ if (count > maxLines) out.push(c.dim(`… +${count - maxLines} more diff lines`));
60
+ return out;
61
+ }
62
+
63
+ export function renderTodos(todos, { prefix = true } = {}) {
64
+ const lines = todos.map((t) => {
65
+ if (t.status === 'completed') return c.dim(c.strike(`☒ ${t.content}`));
66
+ if (t.status === 'in_progress') return c.bold(`◼ ${t.content}`);
67
+ return `☐ ${t.content}`;
68
+ });
69
+ if (!lines.length) lines.push(c.dim('(todo list cleared)'));
70
+ return prefix ? resultLines(lines) : lines;
71
+ }
72
+
73
+ function contentText(content) {
74
+ if (typeof content === 'string') return content;
75
+ return (content || []).map((b) => (b.type === 'text' ? b.text : b.type === 'image' ? '[image]' : '')).join('\n');
76
+ }
77
+
78
+ // Lines shown under a tool header once it has finished.
79
+ export function renderToolResult(entry, { verbose = false, width = 100, cwd }) {
80
+ const { tool, result } = entry;
81
+ const r = result || {};
82
+ const d = r.display || {};
83
+ const w = Math.max(20, width - RESULT_INDENT.length - 1);
84
+ if (entry.rejected) {
85
+ return resultLines([c.red(entry.rejectMessage ? truncate(entry.rejectMessage.split('\n')[0], w) : 'Rejected by user')]);
86
+ }
87
+ if (r.interrupted) {
88
+ const partial = d.output ? d.output.trimEnd().split('\n').slice(-3) : [];
89
+ return resultLines([...partial.map((l) => c.dim(truncate(l, w))), c.red('Interrupted by user')]);
90
+ }
91
+ if (d.todos) return renderTodos(d.todos);
92
+ if (d.plan !== undefined) {
93
+ const md = renderMarkdown(d.plan, { width: w });
94
+ return resultLines([d.approved ? c.green('User approved the plan') : c.yellow('User asked to keep planning'), ...(verbose ? md : [])]);
95
+ }
96
+ if (d.preview && !r.isError) {
97
+ const lines = [d.summary ? `${d.summary}` : ''];
98
+ if (d.preview.kind === 'create' && !verbose) return resultLines([d.summary || `Created ${displayPath(d.preview.path, cwd)}`]);
99
+ lines.push(...renderDiff(d.preview, width - RESULT_INDENT.length, verbose ? 400 : 30));
100
+ return resultLines(lines);
101
+ }
102
+ if (tool.name === 'Bash' && !r.isError && d.output !== undefined) {
103
+ const all = d.output ? d.output.split('\n') : [];
104
+ if (!all.length) return resultLines([c.dim('(No content)')]);
105
+ const max = verbose ? 200 : 5;
106
+ const shown = all.slice(0, max).flatMap((l) => wrapLine(l, w)).slice(0, verbose ? 400 : 8);
107
+ if (all.length > max) shown.push(c.dim(`… +${all.length - max} lines`));
108
+ return resultLines(shown);
109
+ }
110
+ if (r.isError) {
111
+ const text = contentText(r.content).trim() || 'Error';
112
+ const all = text.split('\n');
113
+ const max = verbose ? 100 : 6;
114
+ const shown = all.slice(0, max).flatMap((l) => wordWrap(l, w)).map((l) => c.red(l));
115
+ if (all.length > max) shown.push(c.dim(`… +${all.length - max} lines`));
116
+ return resultLines(shown);
117
+ }
118
+ if (d.summary) {
119
+ const lines = [d.summary];
120
+ if (verbose && typeof r.content === 'string') lines.push(...r.content.split('\n').slice(0, 60).map((l) => c.dim(truncate(l, w))));
121
+ return resultLines(lines);
122
+ }
123
+ const text = contentText(r.content).trim();
124
+ const all = text ? text.split('\n') : [];
125
+ if (!all.length) return resultLines([c.dim('(No content)')]);
126
+ const max = verbose ? 100 : 3;
127
+ const shown = all.slice(0, max).map((l) => truncate(l, w));
128
+ if (all.length > max) shown.push(c.dim(`… +${all.length - max} lines`));
129
+ return resultLines(shown);
130
+ }
131
+
132
+ export function renderUserMessage(text, width) {
133
+ const lines = text.replace(/\r\n/g, '\n').split('\n');
134
+ const out = [];
135
+ lines.forEach((l, i) => {
136
+ const wrapped = wordWrap(l, Math.max(10, width - 3));
137
+ wrapped.forEach((wl, j) => out.push((i === 0 && j === 0 ? c.gray('> ') : ' ') + c.gray(wl)));
138
+ });
139
+ if (out.length > 30) return [...out.slice(0, 25), c.dim(` … +${out.length - 25} lines`)];
140
+ return out;
141
+ }
142
+
143
+ export function formatTokens(n) {
144
+ if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
145
+ if (n >= 1000) return `${(n / 1000).toFixed(1)}k`;
146
+ return String(n);
147
+ }
148
+
149
+ export function formatDuration(ms) {
150
+ const s = Math.floor(ms / 1000);
151
+ if (s < 60) return `${s}s`;
152
+ const m = Math.floor(s / 60);
153
+ if (m < 60) return `${m}m ${s % 60}s`;
154
+ return `${Math.floor(m / 60)}h ${m % 60}m`;
155
+ }