mattermost-claude-code 0.2.2 → 0.2.3

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.
package/dist/index.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mattermost-claude-code",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Share Claude Code sessions live in a Mattermost channel with interactive features",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -1,76 +0,0 @@
1
- export type ClaudeStreamEvent = SystemEvent | AssistantEvent | UserEvent | ToolUseEvent | ToolResultEvent | ResultEvent;
2
- export interface SystemEvent {
3
- type: 'system';
4
- subtype: 'init' | 'error';
5
- session_id?: string;
6
- message?: string;
7
- error?: string;
8
- }
9
- export interface AssistantEvent {
10
- type: 'assistant';
11
- message: {
12
- id: string;
13
- type: 'message';
14
- role: 'assistant';
15
- content: ContentBlock[];
16
- model: string;
17
- stop_reason: string | null;
18
- stop_sequence: string | null;
19
- };
20
- session_id: string;
21
- }
22
- export interface UserEvent {
23
- type: 'user';
24
- message: {
25
- role: 'user';
26
- content: string;
27
- };
28
- session_id: string;
29
- }
30
- export interface ToolUseEvent {
31
- type: 'tool_use';
32
- tool_use: {
33
- id: string;
34
- name: string;
35
- input: Record<string, unknown>;
36
- };
37
- session_id: string;
38
- }
39
- export interface ToolResultEvent {
40
- type: 'tool_result';
41
- tool_result: {
42
- tool_use_id: string;
43
- content: string | ContentBlock[];
44
- is_error?: boolean;
45
- };
46
- session_id: string;
47
- }
48
- export interface ResultEvent {
49
- type: 'result';
50
- result: string;
51
- session_id: string;
52
- cost_usd?: number;
53
- duration_ms?: number;
54
- is_error?: boolean;
55
- }
56
- export type ContentBlock = TextBlock | ToolUseBlock | ToolResultBlock;
57
- export interface TextBlock {
58
- type: 'text';
59
- text: string;
60
- }
61
- export interface ToolUseBlock {
62
- type: 'tool_use';
63
- id: string;
64
- name: string;
65
- input: Record<string, unknown>;
66
- }
67
- export interface ToolResultBlock {
68
- type: 'tool_result';
69
- tool_use_id: string;
70
- content: string;
71
- is_error?: boolean;
72
- }
73
- export interface ClaudeUserInput {
74
- type: 'user';
75
- content: string;
76
- }
@@ -1,3 +0,0 @@
1
- // Claude Code stream-json output types
2
- // Based on https://code.claude.com/docs/en/cli-reference
3
- export {};
@@ -1,28 +0,0 @@
1
- import type { AssistantEvent, ToolUseEvent, ToolResultEvent, ResultEvent } from '../claude/types.js';
2
- /**
3
- * Format Claude events into Mattermost-friendly messages
4
- * Styled to look similar to Claude Code CLI output
5
- */
6
- export declare class MessageFormatter {
7
- private pendingToolUses;
8
- formatUserPrompt(username: string, prompt: string): string;
9
- formatSessionStart(workingDir: string): string;
10
- formatSessionEnd(result?: ResultEvent): string;
11
- formatAssistantMessage(event: AssistantEvent): string;
12
- formatToolUse(event: ToolUseEvent): string;
13
- private formatReadTool;
14
- private formatEditTool;
15
- private formatWriteTool;
16
- private formatBashTool;
17
- private formatGlobTool;
18
- private formatGrepTool;
19
- private formatTaskTool;
20
- private formatWebSearchTool;
21
- private formatWebFetchTool;
22
- private formatTodoWriteTool;
23
- formatToolResult(event: ToolResultEvent): string | null;
24
- formatUnauthorized(username: string): string;
25
- formatError(error: string): string;
26
- private truncate;
27
- private shortenPath;
28
- }
@@ -1,244 +0,0 @@
1
- /**
2
- * Format Claude events into Mattermost-friendly messages
3
- * Styled to look similar to Claude Code CLI output
4
- */
5
- export class MessageFormatter {
6
- // Store tool results to show line counts, etc.
7
- pendingToolUses = new Map();
8
- // Format a user's prompt for display (like Claude Code's user input)
9
- formatUserPrompt(username, prompt) {
10
- return `> **${username}:** ${prompt}`;
11
- }
12
- // Format session start
13
- formatSessionStart(workingDir) {
14
- const shortPath = this.shortenPath(workingDir);
15
- return [
16
- '```',
17
- `🚀 Session started`,
18
- ` Working directory: ${shortPath}`,
19
- '```',
20
- ].join('\n');
21
- }
22
- // Format session end with stats
23
- formatSessionEnd(result) {
24
- if (result?.cost_usd) {
25
- const duration = result.duration_ms
26
- ? `${(result.duration_ms / 1000).toFixed(1)}s`
27
- : '';
28
- const cost = `$${result.cost_usd.toFixed(4)}`;
29
- return [
30
- '```',
31
- `✓ Session completed`,
32
- ` Duration: ${duration} | Cost: ${cost}`,
33
- '```',
34
- ].join('\n');
35
- }
36
- return '```\n✓ Session completed\n```';
37
- }
38
- // Format assistant message content
39
- formatAssistantMessage(event) {
40
- const content = event.message.content;
41
- const parts = [];
42
- for (const block of content) {
43
- if (block.type === 'text') {
44
- parts.push(block.text);
45
- }
46
- }
47
- return parts.join('\n');
48
- }
49
- // Format tool use - Claude Code style: ● ToolName(args)
50
- formatToolUse(event) {
51
- const { id, name, input } = event.tool_use;
52
- // Store for later when we get the result
53
- this.pendingToolUses.set(id, event);
54
- switch (name) {
55
- case 'Read':
56
- return this.formatReadTool(input);
57
- case 'Edit':
58
- return this.formatEditTool(input);
59
- case 'Write':
60
- return this.formatWriteTool(input);
61
- case 'Bash':
62
- return this.formatBashTool(input);
63
- case 'Glob':
64
- return this.formatGlobTool(input);
65
- case 'Grep':
66
- return this.formatGrepTool(input);
67
- case 'Task':
68
- return this.formatTaskTool(input);
69
- case 'WebSearch':
70
- return this.formatWebSearchTool(input);
71
- case 'WebFetch':
72
- return this.formatWebFetchTool(input);
73
- case 'TodoWrite':
74
- return this.formatTodoWriteTool(input);
75
- default:
76
- return `● **${name}**`;
77
- }
78
- }
79
- formatReadTool(input) {
80
- const path = input.file_path;
81
- const shortPath = this.shortenPath(path);
82
- return `● **Read**(\`${shortPath}\`)`;
83
- }
84
- formatEditTool(input) {
85
- const path = input.file_path;
86
- const shortPath = this.shortenPath(path);
87
- const oldStr = input.old_string;
88
- const newStr = input.new_string;
89
- // Count lines changed
90
- const oldLines = oldStr.split('\n').length;
91
- const newLines = newStr.split('\n').length;
92
- // Create diff preview
93
- const diffLines = [];
94
- const oldPreview = oldStr.split('\n').slice(0, 3);
95
- const newPreview = newStr.split('\n').slice(0, 3);
96
- for (const line of oldPreview) {
97
- diffLines.push(`- ${line}`);
98
- }
99
- if (oldLines > 3)
100
- diffLines.push(` ... (${oldLines - 3} more lines)`);
101
- for (const line of newPreview) {
102
- diffLines.push(`+ ${line}`);
103
- }
104
- if (newLines > 3)
105
- diffLines.push(` ... (${newLines - 3} more lines)`);
106
- return [
107
- `● **Edit**(\`${shortPath}\`)`,
108
- '```diff',
109
- ...diffLines,
110
- '```',
111
- ].join('\n');
112
- }
113
- formatWriteTool(input) {
114
- const path = input.file_path;
115
- const shortPath = this.shortenPath(path);
116
- const content = input.content;
117
- const lines = content.split('\n').length;
118
- return `● **Write**(\`${shortPath}\`) - ${lines} lines`;
119
- }
120
- formatBashTool(input) {
121
- const command = input.command;
122
- const desc = input.description;
123
- // Truncate long commands
124
- const cmdPreview = command.length > 80
125
- ? command.substring(0, 77) + '...'
126
- : command;
127
- if (desc) {
128
- return [
129
- `● **Bash**(${desc})`,
130
- '```bash',
131
- cmdPreview,
132
- '```',
133
- ].join('\n');
134
- }
135
- return [
136
- `● **Bash**`,
137
- '```bash',
138
- cmdPreview,
139
- '```',
140
- ].join('\n');
141
- }
142
- formatGlobTool(input) {
143
- const pattern = input.pattern;
144
- return `● **Glob**(\`${pattern}\`)`;
145
- }
146
- formatGrepTool(input) {
147
- const pattern = input.pattern;
148
- const path = input.path;
149
- if (path) {
150
- return `● **Grep**(\`${pattern}\` in \`${this.shortenPath(path)}\`)`;
151
- }
152
- return `● **Grep**(\`${pattern}\`)`;
153
- }
154
- formatTaskTool(input) {
155
- const desc = input.description;
156
- const type = input.subagent_type;
157
- if (desc) {
158
- return `● **Task**(${type || 'agent'}: ${desc})`;
159
- }
160
- return `● **Task**(${type || 'agent'})`;
161
- }
162
- formatWebSearchTool(input) {
163
- const query = input.query;
164
- return `● **WebSearch**(\`${query}\`)`;
165
- }
166
- formatWebFetchTool(input) {
167
- const url = input.url;
168
- const shortUrl = url.length > 50 ? url.substring(0, 47) + '...' : url;
169
- return `● **WebFetch**(\`${shortUrl}\`)`;
170
- }
171
- formatTodoWriteTool(input) {
172
- const todos = input.todos;
173
- if (todos && todos.length > 0) {
174
- const summary = todos.slice(0, 2).map(t => t.content).join(', ');
175
- const more = todos.length > 2 ? ` +${todos.length - 2} more` : '';
176
- return `● **TodoWrite**(${summary}${more})`;
177
- }
178
- return `● **TodoWrite**`;
179
- }
180
- // Format tool result with line counts, etc.
181
- formatToolResult(event) {
182
- const { tool_use_id, content, is_error } = event.tool_result;
183
- const toolUse = this.pendingToolUses.get(tool_use_id);
184
- if (is_error) {
185
- const errorMsg = typeof content === 'string'
186
- ? content
187
- : JSON.stringify(content);
188
- return ` ↳ ❌ ${this.truncate(errorMsg, 150)}`;
189
- }
190
- // Get result as string
191
- const resultStr = typeof content === 'string'
192
- ? content
193
- : JSON.stringify(content, null, 2);
194
- // For Read tool, show line count
195
- if (toolUse?.tool_use.name === 'Read') {
196
- const lines = resultStr.split('\n').length;
197
- return ` ↳ Read ${lines} lines`;
198
- }
199
- // For Glob, show file count
200
- if (toolUse?.tool_use.name === 'Glob') {
201
- const files = resultStr.split('\n').filter(l => l.trim()).length;
202
- return ` ↳ Found ${files} files`;
203
- }
204
- // For Grep, show match count
205
- if (toolUse?.tool_use.name === 'Grep') {
206
- const matches = resultStr.split('\n').filter(l => l.trim()).length;
207
- return ` ↳ Found ${matches} matches`;
208
- }
209
- // For Bash, show truncated output if not too long
210
- if (toolUse?.tool_use.name === 'Bash' && resultStr.length > 0) {
211
- const lines = resultStr.split('\n');
212
- if (lines.length <= 5 && resultStr.length < 300) {
213
- return ' ↳ ```\n' + resultStr + '\n ```';
214
- }
215
- return ` ↳ Output: ${lines.length} lines`;
216
- }
217
- // Skip showing most results to avoid noise
218
- return null;
219
- }
220
- // Format unauthorized user message
221
- formatUnauthorized(username) {
222
- return `⚠️ Sorry @${username}, you're not authorized to use this bot.`;
223
- }
224
- // Format error message
225
- formatError(error) {
226
- return `❌ **Error:** ${error}`;
227
- }
228
- // Helper to truncate strings
229
- truncate(str, maxLength) {
230
- const clean = str.replace(/\n/g, ' ').trim();
231
- if (clean.length <= maxLength)
232
- return clean;
233
- return clean.substring(0, maxLength - 3) + '...';
234
- }
235
- // Helper to shorten file paths
236
- shortenPath(path) {
237
- // Replace home directory with ~
238
- const home = process.env.HOME || '/Users/anneschuth';
239
- if (path.startsWith(home)) {
240
- return '~' + path.substring(home.length);
241
- }
242
- return path;
243
- }
244
- }