claude-threads 0.15.0 → 0.16.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/CHANGELOG.md +28 -0
- package/README.md +5 -5
- package/dist/index.js +20410 -387
- package/dist/mcp/permission-server.js +34038 -139
- package/package.json +14 -18
- package/dist/changelog.d.ts +0 -20
- package/dist/changelog.js +0 -134
- package/dist/claude/cli.d.ts +0 -50
- package/dist/claude/cli.js +0 -181
- package/dist/config/migration.d.ts +0 -45
- package/dist/config/migration.js +0 -35
- package/dist/config.d.ts +0 -21
- package/dist/config.js +0 -7
- package/dist/git/worktree.d.ts +0 -46
- package/dist/git/worktree.js +0 -228
- package/dist/index.d.ts +0 -2
- package/dist/logo.d.ts +0 -14
- package/dist/logo.js +0 -41
- package/dist/mattermost/api.d.ts +0 -85
- package/dist/mattermost/api.js +0 -124
- package/dist/mattermost/api.test.d.ts +0 -1
- package/dist/mattermost/api.test.js +0 -319
- package/dist/mcp/permission-server.d.ts +0 -2
- package/dist/onboarding.d.ts +0 -1
- package/dist/onboarding.js +0 -318
- package/dist/persistence/session-store.d.ts +0 -71
- package/dist/persistence/session-store.js +0 -152
- package/dist/platform/client.d.ts +0 -140
- package/dist/platform/client.js +0 -1
- package/dist/platform/formatter.d.ts +0 -74
- package/dist/platform/formatter.js +0 -1
- package/dist/platform/index.d.ts +0 -11
- package/dist/platform/index.js +0 -8
- package/dist/platform/mattermost/client.d.ts +0 -70
- package/dist/platform/mattermost/client.js +0 -404
- package/dist/platform/mattermost/formatter.d.ts +0 -20
- package/dist/platform/mattermost/formatter.js +0 -46
- package/dist/platform/mattermost/permission-api.d.ts +0 -10
- package/dist/platform/mattermost/permission-api.js +0 -139
- package/dist/platform/mattermost/types.d.ts +0 -71
- package/dist/platform/mattermost/types.js +0 -1
- package/dist/platform/permission-api-factory.d.ts +0 -11
- package/dist/platform/permission-api-factory.js +0 -21
- package/dist/platform/permission-api.d.ts +0 -67
- package/dist/platform/permission-api.js +0 -8
- package/dist/platform/types.d.ts +0 -70
- package/dist/platform/types.js +0 -7
- package/dist/session/commands.d.ts +0 -52
- package/dist/session/commands.js +0 -323
- package/dist/session/events.d.ts +0 -25
- package/dist/session/events.js +0 -368
- package/dist/session/index.d.ts +0 -7
- package/dist/session/index.js +0 -6
- package/dist/session/lifecycle.d.ts +0 -70
- package/dist/session/lifecycle.js +0 -456
- package/dist/session/manager.d.ts +0 -96
- package/dist/session/manager.js +0 -537
- package/dist/session/reactions.d.ts +0 -25
- package/dist/session/reactions.js +0 -151
- package/dist/session/streaming.d.ts +0 -47
- package/dist/session/streaming.js +0 -152
- package/dist/session/types.d.ts +0 -78
- package/dist/session/types.js +0 -9
- package/dist/session/worktree.d.ts +0 -56
- package/dist/session/worktree.js +0 -339
- package/dist/update-notifier.d.ts +0 -3
- package/dist/update-notifier.js +0 -41
- package/dist/utils/emoji.d.ts +0 -43
- package/dist/utils/emoji.js +0 -65
- package/dist/utils/emoji.test.d.ts +0 -1
- package/dist/utils/emoji.test.js +0 -131
- package/dist/utils/logger.d.ts +0 -34
- package/dist/utils/logger.js +0 -42
- package/dist/utils/logger.test.d.ts +0 -1
- package/dist/utils/logger.test.js +0 -121
- package/dist/utils/tool-formatter.d.ts +0 -53
- package/dist/utils/tool-formatter.js +0 -252
- package/dist/utils/tool-formatter.test.d.ts +0 -1
- package/dist/utils/tool-formatter.test.js +0 -372
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-threads",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.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",
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
"claude-threads-mcp": "./dist/mcp/permission-server.js"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
|
-
"dev": "
|
|
13
|
-
"build": "
|
|
14
|
-
"start": "
|
|
15
|
-
"test": "
|
|
16
|
-
"test:watch": "
|
|
17
|
-
"test:coverage": "
|
|
12
|
+
"dev": "bun --watch src/index.ts",
|
|
13
|
+
"build": "bun build src/index.ts --outdir dist --target node && bun build src/mcp/permission-server.ts --outdir dist/mcp --target node",
|
|
14
|
+
"start": "bun dist/index.js",
|
|
15
|
+
"test": "bun test",
|
|
16
|
+
"test:watch": "bun test --watch",
|
|
17
|
+
"test:coverage": "bun test --coverage",
|
|
18
18
|
"lint": "eslint src/",
|
|
19
19
|
"lint:fix": "eslint src/ --fix",
|
|
20
20
|
"typecheck": "tsc --noEmit",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"ai",
|
|
29
29
|
"cli",
|
|
30
30
|
"anthropic",
|
|
31
|
-
"chat"
|
|
31
|
+
"chat",
|
|
32
|
+
"bun"
|
|
32
33
|
],
|
|
33
34
|
"author": "Anne Schuth",
|
|
34
35
|
"license": "Apache-2.0",
|
|
@@ -54,33 +55,28 @@
|
|
|
54
55
|
"prompts": "^2.4.2",
|
|
55
56
|
"semver": "^7.7.3",
|
|
56
57
|
"update-notifier": "^7.3.1",
|
|
57
|
-
"
|
|
58
|
-
"yaml": "^2.8.2",
|
|
59
|
-
"zod": "^4.2.1"
|
|
58
|
+
"zod": "4.2.1"
|
|
60
59
|
},
|
|
61
60
|
"devDependencies": {
|
|
62
61
|
"@eslint/js": "^9.39.2",
|
|
62
|
+
"@types/bun": "latest",
|
|
63
63
|
"@types/node": "^25.0.3",
|
|
64
64
|
"@types/prompts": "^2.4.9",
|
|
65
65
|
"@types/semver": "^7.7.1",
|
|
66
66
|
"@types/update-notifier": "^6.0.8",
|
|
67
|
-
"@types/ws": "^8.5.13",
|
|
68
|
-
"@vitest/coverage-v8": "^4.0.16",
|
|
69
67
|
"eslint": "^9.39.2",
|
|
70
68
|
"husky": "^9.1.7",
|
|
71
69
|
"lint-staged": "^16.2.7",
|
|
72
|
-
"tsx": "^4.19.2",
|
|
73
70
|
"typescript": "^5.7.2",
|
|
74
|
-
"typescript-eslint": "^8.50.1"
|
|
75
|
-
"vitest": "^4.0.16"
|
|
71
|
+
"typescript-eslint": "^8.50.1"
|
|
76
72
|
},
|
|
77
73
|
"engines": {
|
|
78
|
-
"
|
|
74
|
+
"bun": ">=1.2.21"
|
|
79
75
|
},
|
|
80
76
|
"lint-staged": {
|
|
81
77
|
"*.ts": [
|
|
82
78
|
"eslint --fix",
|
|
83
|
-
"
|
|
79
|
+
"bun test --bail"
|
|
84
80
|
]
|
|
85
81
|
}
|
|
86
82
|
}
|
package/dist/changelog.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
interface ReleaseNotes {
|
|
2
|
-
version: string;
|
|
3
|
-
date: string;
|
|
4
|
-
sections: {
|
|
5
|
-
[key: string]: string[];
|
|
6
|
-
};
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Parse CHANGELOG.md and extract release notes for a specific version.
|
|
10
|
-
*/
|
|
11
|
-
export declare function getReleaseNotes(version?: string): ReleaseNotes | null;
|
|
12
|
-
/**
|
|
13
|
-
* Format release notes as a Mattermost message.
|
|
14
|
-
*/
|
|
15
|
-
export declare function formatReleaseNotes(notes: ReleaseNotes): string;
|
|
16
|
-
/**
|
|
17
|
-
* Get a short summary of what's new (for session header).
|
|
18
|
-
*/
|
|
19
|
-
export declare function getWhatsNewSummary(notes: ReleaseNotes): string;
|
|
20
|
-
export {};
|
package/dist/changelog.js
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { readFileSync, existsSync } from 'fs';
|
|
2
|
-
import { dirname, resolve } from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
5
|
-
/**
|
|
6
|
-
* Parse CHANGELOG.md and extract release notes for a specific version.
|
|
7
|
-
*/
|
|
8
|
-
export function getReleaseNotes(version) {
|
|
9
|
-
// Try to find CHANGELOG.md in various locations
|
|
10
|
-
const possiblePaths = [
|
|
11
|
-
resolve(__dirname, '..', 'CHANGELOG.md'), // dist/../CHANGELOG.md (installed)
|
|
12
|
-
resolve(__dirname, '..', '..', 'CHANGELOG.md'), // src/../CHANGELOG.md (dev)
|
|
13
|
-
];
|
|
14
|
-
let changelogPath = null;
|
|
15
|
-
for (const p of possiblePaths) {
|
|
16
|
-
if (existsSync(p)) {
|
|
17
|
-
changelogPath = p;
|
|
18
|
-
break;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
if (!changelogPath) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
try {
|
|
25
|
-
const content = readFileSync(changelogPath, 'utf-8');
|
|
26
|
-
return parseChangelog(content, version);
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Parse changelog content and extract notes for a version.
|
|
34
|
-
* If no version specified, returns the latest (first) version.
|
|
35
|
-
*/
|
|
36
|
-
function parseChangelog(content, targetVersion) {
|
|
37
|
-
const lines = content.split('\n');
|
|
38
|
-
let currentVersion = null;
|
|
39
|
-
let currentDate = null;
|
|
40
|
-
let currentSection = null;
|
|
41
|
-
let sections = {};
|
|
42
|
-
let foundTarget = false;
|
|
43
|
-
for (const line of lines) {
|
|
44
|
-
// Match version header: ## [0.8.0] - 2025-12-28
|
|
45
|
-
const versionMatch = line.match(/^## \[(\d+\.\d+\.\d+)\](?: - (\d{4}-\d{2}-\d{2}))?/);
|
|
46
|
-
if (versionMatch) {
|
|
47
|
-
// If we already found our target, we're done
|
|
48
|
-
if (foundTarget) {
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
currentVersion = versionMatch[1];
|
|
52
|
-
currentDate = versionMatch[2] || '';
|
|
53
|
-
sections = {};
|
|
54
|
-
currentSection = null;
|
|
55
|
-
// Check if this is the version we want
|
|
56
|
-
if (!targetVersion || currentVersion === targetVersion) {
|
|
57
|
-
foundTarget = true;
|
|
58
|
-
}
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
// Only process if we're in the target version
|
|
62
|
-
if (!foundTarget)
|
|
63
|
-
continue;
|
|
64
|
-
// Match section header: ### Added, ### Fixed, ### Changed
|
|
65
|
-
const sectionMatch = line.match(/^### (\w+)/);
|
|
66
|
-
if (sectionMatch) {
|
|
67
|
-
currentSection = sectionMatch[1];
|
|
68
|
-
sections[currentSection] = [];
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
// Match list item: - Item text
|
|
72
|
-
const itemMatch = line.match(/^- (.+)/);
|
|
73
|
-
if (itemMatch && currentSection) {
|
|
74
|
-
sections[currentSection].push(itemMatch[1]);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (!foundTarget || !currentVersion) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
return {
|
|
81
|
-
version: currentVersion,
|
|
82
|
-
date: currentDate || '',
|
|
83
|
-
sections,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Format release notes as a Mattermost message.
|
|
88
|
-
*/
|
|
89
|
-
export function formatReleaseNotes(notes) {
|
|
90
|
-
let msg = `### 📋 Release Notes - v${notes.version}`;
|
|
91
|
-
if (notes.date) {
|
|
92
|
-
msg += ` (${notes.date})`;
|
|
93
|
-
}
|
|
94
|
-
msg += '\n\n';
|
|
95
|
-
for (const [section, items] of Object.entries(notes.sections)) {
|
|
96
|
-
if (items.length === 0)
|
|
97
|
-
continue;
|
|
98
|
-
const emoji = section === 'Added' ? '✨' :
|
|
99
|
-
section === 'Fixed' ? '🐛' :
|
|
100
|
-
section === 'Changed' ? '🔄' :
|
|
101
|
-
section === 'Removed' ? '🗑️' : '•';
|
|
102
|
-
msg += `**${emoji} ${section}**\n`;
|
|
103
|
-
for (const item of items) {
|
|
104
|
-
msg += `- ${item}\n`;
|
|
105
|
-
}
|
|
106
|
-
msg += '\n';
|
|
107
|
-
}
|
|
108
|
-
return msg.trim();
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Get a short summary of what's new (for session header).
|
|
112
|
-
*/
|
|
113
|
-
export function getWhatsNewSummary(notes) {
|
|
114
|
-
const items = [];
|
|
115
|
-
// Prioritize: Added > Fixed > Changed
|
|
116
|
-
for (const section of ['Added', 'Fixed', 'Changed']) {
|
|
117
|
-
const sectionItems = notes.sections[section] || [];
|
|
118
|
-
for (const item of sectionItems) {
|
|
119
|
-
// Extract just the first part (before any dash or detail)
|
|
120
|
-
const short = item.split(' - ')[0].replace(/\*\*/g, '');
|
|
121
|
-
if (short.length <= 50) {
|
|
122
|
-
items.push(short);
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
items.push(short.substring(0, 47) + '...');
|
|
126
|
-
}
|
|
127
|
-
if (items.length >= 2)
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
if (items.length >= 2)
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
return items.join(', ');
|
|
134
|
-
}
|
package/dist/claude/cli.d.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from 'events';
|
|
2
|
-
export interface ClaudeEvent {
|
|
3
|
-
type: string;
|
|
4
|
-
[key: string]: unknown;
|
|
5
|
-
}
|
|
6
|
-
export interface TextContentBlock {
|
|
7
|
-
type: 'text';
|
|
8
|
-
text: string;
|
|
9
|
-
}
|
|
10
|
-
export interface ImageContentBlock {
|
|
11
|
-
type: 'image';
|
|
12
|
-
source: {
|
|
13
|
-
type: 'base64';
|
|
14
|
-
media_type: string;
|
|
15
|
-
data: string;
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
export type ContentBlock = TextContentBlock | ImageContentBlock;
|
|
19
|
-
export interface PlatformMcpConfig {
|
|
20
|
-
type: string;
|
|
21
|
-
url: string;
|
|
22
|
-
token: string;
|
|
23
|
-
channelId: string;
|
|
24
|
-
allowedUsers: string[];
|
|
25
|
-
}
|
|
26
|
-
export interface ClaudeCliOptions {
|
|
27
|
-
workingDir: string;
|
|
28
|
-
threadId?: string;
|
|
29
|
-
skipPermissions?: boolean;
|
|
30
|
-
sessionId?: string;
|
|
31
|
-
resume?: boolean;
|
|
32
|
-
chrome?: boolean;
|
|
33
|
-
platformConfig?: PlatformMcpConfig;
|
|
34
|
-
}
|
|
35
|
-
export declare class ClaudeCli extends EventEmitter {
|
|
36
|
-
private process;
|
|
37
|
-
private options;
|
|
38
|
-
private buffer;
|
|
39
|
-
debug: boolean;
|
|
40
|
-
constructor(options: ClaudeCliOptions);
|
|
41
|
-
start(): void;
|
|
42
|
-
sendMessage(content: string | ContentBlock[]): void;
|
|
43
|
-
sendToolResult(toolUseId: string, content: unknown): void;
|
|
44
|
-
private parseOutput;
|
|
45
|
-
isRunning(): boolean;
|
|
46
|
-
kill(): void;
|
|
47
|
-
/** Interrupt current processing (like Escape in CLI) - keeps process alive */
|
|
48
|
-
interrupt(): boolean;
|
|
49
|
-
private getMcpServerPath;
|
|
50
|
-
}
|
package/dist/claude/cli.js
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
2
|
-
import { EventEmitter } from 'events';
|
|
3
|
-
import { resolve, dirname } from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
export class ClaudeCli extends EventEmitter {
|
|
6
|
-
process = null;
|
|
7
|
-
options;
|
|
8
|
-
buffer = '';
|
|
9
|
-
debug = process.env.DEBUG === '1' || process.argv.includes('--debug');
|
|
10
|
-
constructor(options) {
|
|
11
|
-
super();
|
|
12
|
-
this.options = options;
|
|
13
|
-
}
|
|
14
|
-
start() {
|
|
15
|
-
if (this.process)
|
|
16
|
-
throw new Error('Already running');
|
|
17
|
-
const claudePath = process.env.CLAUDE_PATH || 'claude';
|
|
18
|
-
const args = [
|
|
19
|
-
'--input-format', 'stream-json',
|
|
20
|
-
'--output-format', 'stream-json',
|
|
21
|
-
'--verbose',
|
|
22
|
-
];
|
|
23
|
-
// Add session ID for persistence/resume support
|
|
24
|
-
if (this.options.sessionId) {
|
|
25
|
-
if (this.options.resume) {
|
|
26
|
-
args.push('--resume', this.options.sessionId);
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
args.push('--session-id', this.options.sessionId);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
// Either use skip permissions or the MCP-based permission system
|
|
33
|
-
if (this.options.skipPermissions) {
|
|
34
|
-
args.push('--dangerously-skip-permissions');
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
// Configure the permission MCP server
|
|
38
|
-
const mcpServerPath = this.getMcpServerPath();
|
|
39
|
-
// Platform config is required for MCP permission server
|
|
40
|
-
const platformConfig = this.options.platformConfig;
|
|
41
|
-
if (!platformConfig) {
|
|
42
|
-
throw new Error('platformConfig is required when skipPermissions is false');
|
|
43
|
-
}
|
|
44
|
-
// Platform-agnostic environment variables for MCP permission server
|
|
45
|
-
const mcpEnv = {
|
|
46
|
-
PLATFORM_TYPE: platformConfig.type,
|
|
47
|
-
PLATFORM_URL: platformConfig.url,
|
|
48
|
-
PLATFORM_TOKEN: platformConfig.token,
|
|
49
|
-
PLATFORM_CHANNEL_ID: platformConfig.channelId,
|
|
50
|
-
PLATFORM_THREAD_ID: this.options.threadId || '',
|
|
51
|
-
ALLOWED_USERS: platformConfig.allowedUsers.join(','),
|
|
52
|
-
DEBUG: this.debug ? '1' : '',
|
|
53
|
-
};
|
|
54
|
-
const mcpConfig = {
|
|
55
|
-
mcpServers: {
|
|
56
|
-
'claude-threads-permissions': {
|
|
57
|
-
type: 'stdio',
|
|
58
|
-
command: 'node',
|
|
59
|
-
args: [mcpServerPath],
|
|
60
|
-
env: mcpEnv,
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
args.push('--mcp-config', JSON.stringify(mcpConfig));
|
|
65
|
-
args.push('--permission-prompt-tool', 'mcp__claude-threads-permissions__permission_prompt');
|
|
66
|
-
}
|
|
67
|
-
// Chrome integration
|
|
68
|
-
if (this.options.chrome) {
|
|
69
|
-
args.push('--chrome');
|
|
70
|
-
}
|
|
71
|
-
if (this.debug) {
|
|
72
|
-
console.log(` [claude] Starting: ${claudePath} ${args.slice(0, 5).join(' ')}...`);
|
|
73
|
-
}
|
|
74
|
-
this.process = spawn(claudePath, args, {
|
|
75
|
-
cwd: this.options.workingDir,
|
|
76
|
-
env: process.env,
|
|
77
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
78
|
-
});
|
|
79
|
-
this.process.stdout?.on('data', (chunk) => {
|
|
80
|
-
this.parseOutput(chunk.toString());
|
|
81
|
-
});
|
|
82
|
-
this.process.stderr?.on('data', (chunk) => {
|
|
83
|
-
if (this.debug) {
|
|
84
|
-
console.error(` [claude:err] ${chunk.toString().trim()}`);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
this.process.on('error', (err) => {
|
|
88
|
-
console.error(' ❌ Claude error:', err);
|
|
89
|
-
this.emit('error', err);
|
|
90
|
-
});
|
|
91
|
-
this.process.on('exit', (code) => {
|
|
92
|
-
if (this.debug) {
|
|
93
|
-
console.log(` [claude] Exited ${code}`);
|
|
94
|
-
}
|
|
95
|
-
this.process = null;
|
|
96
|
-
this.buffer = '';
|
|
97
|
-
this.emit('exit', code);
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
// Send a user message via JSON stdin
|
|
101
|
-
// content can be a string or an array of content blocks (for images)
|
|
102
|
-
sendMessage(content) {
|
|
103
|
-
if (!this.process?.stdin)
|
|
104
|
-
throw new Error('Not running');
|
|
105
|
-
const msg = JSON.stringify({
|
|
106
|
-
type: 'user',
|
|
107
|
-
message: { role: 'user', content }
|
|
108
|
-
}) + '\n';
|
|
109
|
-
if (this.debug) {
|
|
110
|
-
const preview = typeof content === 'string'
|
|
111
|
-
? content.substring(0, 50)
|
|
112
|
-
: `[${content.length} blocks]`;
|
|
113
|
-
console.log(` [claude] Sending: ${preview}...`);
|
|
114
|
-
}
|
|
115
|
-
this.process.stdin.write(msg);
|
|
116
|
-
}
|
|
117
|
-
// Send a tool result response
|
|
118
|
-
sendToolResult(toolUseId, content) {
|
|
119
|
-
if (!this.process?.stdin)
|
|
120
|
-
throw new Error('Not running');
|
|
121
|
-
const msg = JSON.stringify({
|
|
122
|
-
type: 'user',
|
|
123
|
-
message: {
|
|
124
|
-
role: 'user',
|
|
125
|
-
content: [{
|
|
126
|
-
type: 'tool_result',
|
|
127
|
-
tool_use_id: toolUseId,
|
|
128
|
-
content: typeof content === 'string' ? content : JSON.stringify(content)
|
|
129
|
-
}]
|
|
130
|
-
}
|
|
131
|
-
}) + '\n';
|
|
132
|
-
if (this.debug) {
|
|
133
|
-
console.log(` [claude] Sending tool_result for ${toolUseId}`);
|
|
134
|
-
}
|
|
135
|
-
this.process.stdin.write(msg);
|
|
136
|
-
}
|
|
137
|
-
parseOutput(data) {
|
|
138
|
-
this.buffer += data;
|
|
139
|
-
const lines = this.buffer.split('\n');
|
|
140
|
-
this.buffer = lines.pop() || '';
|
|
141
|
-
for (const line of lines) {
|
|
142
|
-
const trimmed = line.trim();
|
|
143
|
-
if (!trimmed)
|
|
144
|
-
continue;
|
|
145
|
-
try {
|
|
146
|
-
const event = JSON.parse(trimmed);
|
|
147
|
-
if (this.debug) {
|
|
148
|
-
console.log(`[DEBUG] Event: ${event.type}`, JSON.stringify(event).substring(0, 200));
|
|
149
|
-
}
|
|
150
|
-
this.emit('event', event);
|
|
151
|
-
}
|
|
152
|
-
catch {
|
|
153
|
-
if (this.debug) {
|
|
154
|
-
console.log(`[DEBUG] Raw: ${trimmed.substring(0, 200)}`);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
isRunning() {
|
|
160
|
-
return this.process !== null;
|
|
161
|
-
}
|
|
162
|
-
kill() {
|
|
163
|
-
this.process?.kill('SIGTERM');
|
|
164
|
-
this.process = null;
|
|
165
|
-
}
|
|
166
|
-
/** Interrupt current processing (like Escape in CLI) - keeps process alive */
|
|
167
|
-
interrupt() {
|
|
168
|
-
if (!this.process)
|
|
169
|
-
return false;
|
|
170
|
-
this.process.kill('SIGINT');
|
|
171
|
-
return true;
|
|
172
|
-
}
|
|
173
|
-
getMcpServerPath() {
|
|
174
|
-
// Get the path to the MCP permission server
|
|
175
|
-
// When running from source: src/mcp/permission-server.ts -> dist/mcp/permission-server.js
|
|
176
|
-
// When installed globally: the bin entry points to dist/mcp/permission-server.js
|
|
177
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
178
|
-
const __dirname = dirname(__filename);
|
|
179
|
-
return resolve(__dirname, '..', 'mcp', 'permission-server.js');
|
|
180
|
-
}
|
|
181
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
export declare const CONFIG_PATH: string;
|
|
2
|
-
export type WorktreeMode = 'off' | 'prompt' | 'require';
|
|
3
|
-
export interface NewConfig {
|
|
4
|
-
version: number;
|
|
5
|
-
workingDir: string;
|
|
6
|
-
chrome: boolean;
|
|
7
|
-
worktreeMode: WorktreeMode;
|
|
8
|
-
platforms: PlatformInstanceConfig[];
|
|
9
|
-
}
|
|
10
|
-
export interface PlatformInstanceConfig {
|
|
11
|
-
id: string;
|
|
12
|
-
type: 'mattermost' | 'slack';
|
|
13
|
-
displayName: string;
|
|
14
|
-
[key: string]: unknown;
|
|
15
|
-
}
|
|
16
|
-
export interface MattermostPlatformConfig extends PlatformInstanceConfig {
|
|
17
|
-
type: 'mattermost';
|
|
18
|
-
url: string;
|
|
19
|
-
token: string;
|
|
20
|
-
channelId: string;
|
|
21
|
-
botName: string;
|
|
22
|
-
allowedUsers: string[];
|
|
23
|
-
skipPermissions: boolean;
|
|
24
|
-
}
|
|
25
|
-
export interface SlackPlatformConfig extends PlatformInstanceConfig {
|
|
26
|
-
type: 'slack';
|
|
27
|
-
botToken: string;
|
|
28
|
-
appToken: string;
|
|
29
|
-
channelId: string;
|
|
30
|
-
botName: string;
|
|
31
|
-
allowedUsers: string[];
|
|
32
|
-
skipPermissions: boolean;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Load config from YAML file
|
|
36
|
-
*/
|
|
37
|
-
export declare function loadConfigWithMigration(): NewConfig | null;
|
|
38
|
-
/**
|
|
39
|
-
* Save config to YAML file
|
|
40
|
-
*/
|
|
41
|
-
export declare function saveConfig(config: NewConfig): void;
|
|
42
|
-
/**
|
|
43
|
-
* Check if config exists
|
|
44
|
-
*/
|
|
45
|
-
export declare function configExists(): boolean;
|
package/dist/config/migration.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
2
|
-
import YAML from 'yaml';
|
|
3
|
-
import { resolve, dirname } from 'path';
|
|
4
|
-
import { homedir } from 'os';
|
|
5
|
-
// YAML config path
|
|
6
|
-
export const CONFIG_PATH = resolve(homedir(), '.config', 'claude-threads', 'config.yaml');
|
|
7
|
-
// =============================================================================
|
|
8
|
-
// Config Loading
|
|
9
|
-
// =============================================================================
|
|
10
|
-
/**
|
|
11
|
-
* Load config from YAML file
|
|
12
|
-
*/
|
|
13
|
-
export function loadConfigWithMigration() {
|
|
14
|
-
if (existsSync(CONFIG_PATH)) {
|
|
15
|
-
const content = readFileSync(CONFIG_PATH, 'utf-8');
|
|
16
|
-
return YAML.parse(content);
|
|
17
|
-
}
|
|
18
|
-
return null; // No config found
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Save config to YAML file
|
|
22
|
-
*/
|
|
23
|
-
export function saveConfig(config) {
|
|
24
|
-
const configDir = dirname(CONFIG_PATH);
|
|
25
|
-
if (!existsSync(configDir)) {
|
|
26
|
-
mkdirSync(configDir, { recursive: true });
|
|
27
|
-
}
|
|
28
|
-
writeFileSync(CONFIG_PATH, YAML.stringify(config), 'utf-8');
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Check if config exists
|
|
32
|
-
*/
|
|
33
|
-
export function configExists() {
|
|
34
|
-
return existsSync(CONFIG_PATH);
|
|
35
|
-
}
|
package/dist/config.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configuration type exports
|
|
3
|
-
*
|
|
4
|
-
* Re-exports types from config/migration.ts for convenience.
|
|
5
|
-
* The actual config loading and migration logic is in config/migration.ts.
|
|
6
|
-
*/
|
|
7
|
-
import type { WorktreeMode as WorktreeModeType } from './config/migration.js';
|
|
8
|
-
export type { NewConfig, PlatformInstanceConfig, MattermostPlatformConfig, WorktreeMode, } from './config/migration.js';
|
|
9
|
-
/**
|
|
10
|
-
* CLI arguments that can override config
|
|
11
|
-
*/
|
|
12
|
-
export interface CliArgs {
|
|
13
|
-
url?: string;
|
|
14
|
-
token?: string;
|
|
15
|
-
channel?: string;
|
|
16
|
-
botName?: string;
|
|
17
|
-
allowedUsers?: string;
|
|
18
|
-
skipPermissions?: boolean;
|
|
19
|
-
chrome?: boolean;
|
|
20
|
-
worktreeMode?: WorktreeModeType;
|
|
21
|
-
}
|
package/dist/config.js
DELETED
package/dist/git/worktree.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
export interface WorktreeInfo {
|
|
2
|
-
path: string;
|
|
3
|
-
branch: string;
|
|
4
|
-
commit: string;
|
|
5
|
-
isMain: boolean;
|
|
6
|
-
isBare: boolean;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Check if a directory is inside a git repository
|
|
10
|
-
*/
|
|
11
|
-
export declare function isGitRepository(dir: string): Promise<boolean>;
|
|
12
|
-
/**
|
|
13
|
-
* Get the root directory of the git repository
|
|
14
|
-
*/
|
|
15
|
-
export declare function getRepositoryRoot(dir: string): Promise<string>;
|
|
16
|
-
/**
|
|
17
|
-
* Check if there are uncommitted changes (staged or unstaged)
|
|
18
|
-
*/
|
|
19
|
-
export declare function hasUncommittedChanges(dir: string): Promise<boolean>;
|
|
20
|
-
/**
|
|
21
|
-
* List all worktrees for a repository
|
|
22
|
-
*/
|
|
23
|
-
export declare function listWorktrees(repoRoot: string): Promise<WorktreeInfo[]>;
|
|
24
|
-
/**
|
|
25
|
-
* Generate the worktree directory path
|
|
26
|
-
* Creates path like: /path/to/repo-worktrees/branch-name-abc123
|
|
27
|
-
*/
|
|
28
|
-
export declare function getWorktreeDir(repoRoot: string, branch: string): string;
|
|
29
|
-
/**
|
|
30
|
-
* Create a new worktree for a branch
|
|
31
|
-
* If the branch doesn't exist, creates it from the current HEAD
|
|
32
|
-
*/
|
|
33
|
-
export declare function createWorktree(repoRoot: string, branch: string, targetDir: string): Promise<string>;
|
|
34
|
-
/**
|
|
35
|
-
* Remove a worktree
|
|
36
|
-
*/
|
|
37
|
-
export declare function removeWorktree(repoRoot: string, worktreePath: string): Promise<void>;
|
|
38
|
-
/**
|
|
39
|
-
* Find a worktree by branch name
|
|
40
|
-
*/
|
|
41
|
-
export declare function findWorktreeByBranch(repoRoot: string, branch: string): Promise<WorktreeInfo | null>;
|
|
42
|
-
/**
|
|
43
|
-
* Validate a git branch name
|
|
44
|
-
* Based on git-check-ref-format rules
|
|
45
|
-
*/
|
|
46
|
-
export declare function isValidBranchName(name: string): boolean;
|