mattermost-claude-code 0.2.1 → 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
package/dist/claude/types.d.ts
DELETED
|
@@ -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
|
-
}
|
package/dist/claude/types.js
DELETED
|
@@ -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
|
-
}
|