claude-threads 0.14.1 → 0.16.2
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 +47 -0
- package/LICENSE +190 -21
- package/README.md +9 -5
- package/dist/index.js +20397 -387
- package/dist/mcp/permission-server.js +34039 -139
- package/package.json +16 -20
- 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
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User reaction handling module
|
|
3
|
-
*
|
|
4
|
-
* Handles emoji reactions on posts: plan approval, question answers,
|
|
5
|
-
* message approval, cancel/escape actions.
|
|
6
|
-
*/
|
|
7
|
-
import { isApprovalEmoji, isDenialEmoji, isAllowAllEmoji, getNumberEmojiIndex, } from '../utils/emoji.js';
|
|
8
|
-
import { postCurrentQuestion } from './events.js';
|
|
9
|
-
// ---------------------------------------------------------------------------
|
|
10
|
-
// Question reaction handling
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
/**
|
|
13
|
-
* Handle a reaction on a question post (number emoji to select an option).
|
|
14
|
-
*/
|
|
15
|
-
export async function handleQuestionReaction(session, postId, emojiName, username, ctx) {
|
|
16
|
-
if (!session.pendingQuestionSet)
|
|
17
|
-
return;
|
|
18
|
-
const { currentIndex, questions } = session.pendingQuestionSet;
|
|
19
|
-
const question = questions[currentIndex];
|
|
20
|
-
if (!question)
|
|
21
|
-
return;
|
|
22
|
-
const optionIndex = getNumberEmojiIndex(emojiName);
|
|
23
|
-
if (optionIndex < 0 || optionIndex >= question.options.length)
|
|
24
|
-
return;
|
|
25
|
-
const selectedOption = question.options[optionIndex];
|
|
26
|
-
question.answer = selectedOption.label;
|
|
27
|
-
if (ctx.debug)
|
|
28
|
-
console.log(` 💬 @${username} answered "${question.header}": ${selectedOption.label}`);
|
|
29
|
-
// Update the post to show answer
|
|
30
|
-
try {
|
|
31
|
-
await session.platform.updatePost(postId, `✅ **${question.header}**: ${selectedOption.label}`);
|
|
32
|
-
}
|
|
33
|
-
catch (err) {
|
|
34
|
-
console.error(' ⚠️ Failed to update answered question:', err);
|
|
35
|
-
}
|
|
36
|
-
// Move to next question or finish
|
|
37
|
-
session.pendingQuestionSet.currentIndex++;
|
|
38
|
-
if (session.pendingQuestionSet.currentIndex < questions.length) {
|
|
39
|
-
// Post next question
|
|
40
|
-
await postCurrentQuestion(session, {
|
|
41
|
-
debug: ctx.debug,
|
|
42
|
-
registerPost: () => { }, // Will be called by events module
|
|
43
|
-
flush: async () => { },
|
|
44
|
-
startTyping: ctx.startTyping,
|
|
45
|
-
stopTyping: ctx.stopTyping,
|
|
46
|
-
appendContent: () => { },
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
// All questions answered - send tool result
|
|
51
|
-
let answersText = 'Here are my answers:\n';
|
|
52
|
-
for (const q of questions) {
|
|
53
|
-
answersText += `- **${q.header}**: ${q.answer}\n`;
|
|
54
|
-
}
|
|
55
|
-
if (ctx.debug)
|
|
56
|
-
console.log(' ✅ All questions answered');
|
|
57
|
-
// Get the toolUseId before clearing
|
|
58
|
-
const toolUseId = session.pendingQuestionSet.toolUseId;
|
|
59
|
-
// Clear pending questions
|
|
60
|
-
session.pendingQuestionSet = null;
|
|
61
|
-
// Send tool result to Claude (AskUserQuestion expects a tool_result, not a user message)
|
|
62
|
-
if (session.claude.isRunning()) {
|
|
63
|
-
session.claude.sendToolResult(toolUseId, answersText);
|
|
64
|
-
ctx.startTyping(session);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
// ---------------------------------------------------------------------------
|
|
69
|
-
// Plan approval reaction handling
|
|
70
|
-
// ---------------------------------------------------------------------------
|
|
71
|
-
/**
|
|
72
|
-
* Handle a reaction on a plan approval post (thumbs up/down).
|
|
73
|
-
*/
|
|
74
|
-
export async function handleApprovalReaction(session, emojiName, username, ctx) {
|
|
75
|
-
if (!session.pendingApproval)
|
|
76
|
-
return;
|
|
77
|
-
const isApprove = isApprovalEmoji(emojiName);
|
|
78
|
-
const isReject = isDenialEmoji(emojiName);
|
|
79
|
-
if (!isApprove && !isReject)
|
|
80
|
-
return;
|
|
81
|
-
const { postId, toolUseId } = session.pendingApproval;
|
|
82
|
-
const shortId = session.threadId.substring(0, 8);
|
|
83
|
-
console.log(` ${isApprove ? '✅' : '❌'} Plan ${isApprove ? 'approved' : 'rejected'} (${shortId}…) by @${username}`);
|
|
84
|
-
// Update the post to show the decision
|
|
85
|
-
try {
|
|
86
|
-
const statusMessage = isApprove
|
|
87
|
-
? `✅ **Plan approved** by @${username} - starting implementation...`
|
|
88
|
-
: `❌ **Changes requested** by @${username}`;
|
|
89
|
-
await session.platform.updatePost(postId, statusMessage);
|
|
90
|
-
}
|
|
91
|
-
catch (err) {
|
|
92
|
-
console.error(' ⚠️ Failed to update approval post:', err);
|
|
93
|
-
}
|
|
94
|
-
// Clear pending approval and mark as approved
|
|
95
|
-
session.pendingApproval = null;
|
|
96
|
-
if (isApprove) {
|
|
97
|
-
session.planApproved = true;
|
|
98
|
-
}
|
|
99
|
-
// Send tool result to Claude (ExitPlanMode expects a tool_result, not a user message)
|
|
100
|
-
if (session.claude.isRunning()) {
|
|
101
|
-
const response = isApprove
|
|
102
|
-
? 'Approved. Please proceed with the implementation.'
|
|
103
|
-
: 'Please revise the plan. I would like some changes.';
|
|
104
|
-
session.claude.sendToolResult(toolUseId, response);
|
|
105
|
-
ctx.startTyping(session);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
// ---------------------------------------------------------------------------
|
|
109
|
-
// Message approval reaction handling
|
|
110
|
-
// ---------------------------------------------------------------------------
|
|
111
|
-
/**
|
|
112
|
-
* Handle a reaction on a message approval post (approve/invite/deny).
|
|
113
|
-
*/
|
|
114
|
-
export async function handleMessageApprovalReaction(session, emoji, approver, ctx) {
|
|
115
|
-
const pending = session.pendingMessageApproval;
|
|
116
|
-
if (!pending)
|
|
117
|
-
return;
|
|
118
|
-
// Only session owner or globally allowed users can approve
|
|
119
|
-
if (session.startedBy !== approver && !session.platform.isUserAllowed(approver)) {
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
const isAllow = isApprovalEmoji(emoji);
|
|
123
|
-
const isInvite = isAllowAllEmoji(emoji);
|
|
124
|
-
const isDeny = isDenialEmoji(emoji);
|
|
125
|
-
if (!isAllow && !isInvite && !isDeny)
|
|
126
|
-
return;
|
|
127
|
-
if (isAllow) {
|
|
128
|
-
// Allow this single message
|
|
129
|
-
await session.platform.updatePost(pending.postId, `✅ Message from @${pending.fromUser} approved by @${approver}`);
|
|
130
|
-
session.claude.sendMessage(pending.originalMessage);
|
|
131
|
-
session.lastActivityAt = new Date();
|
|
132
|
-
ctx.startTyping(session);
|
|
133
|
-
console.log(` ✅ Message from @${pending.fromUser} approved by @${approver}`);
|
|
134
|
-
}
|
|
135
|
-
else if (isInvite) {
|
|
136
|
-
// Invite user to session
|
|
137
|
-
session.sessionAllowedUsers.add(pending.fromUser);
|
|
138
|
-
await session.platform.updatePost(pending.postId, `✅ @${pending.fromUser} invited to session by @${approver}`);
|
|
139
|
-
await ctx.updateSessionHeader(session);
|
|
140
|
-
session.claude.sendMessage(pending.originalMessage);
|
|
141
|
-
session.lastActivityAt = new Date();
|
|
142
|
-
ctx.startTyping(session);
|
|
143
|
-
console.log(` 👋 @${pending.fromUser} invited to session by @${approver}`);
|
|
144
|
-
}
|
|
145
|
-
else if (isDeny) {
|
|
146
|
-
// Deny
|
|
147
|
-
await session.platform.updatePost(pending.postId, `❌ Message from @${pending.fromUser} denied by @${approver}`);
|
|
148
|
-
console.log(` ❌ Message from @${pending.fromUser} denied by @${approver}`);
|
|
149
|
-
}
|
|
150
|
-
session.pendingMessageApproval = null;
|
|
151
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Message streaming and flushing utilities
|
|
3
|
-
*
|
|
4
|
-
* Handles buffering, formatting, and posting Claude responses to the platform.
|
|
5
|
-
*/
|
|
6
|
-
import type { PlatformClient, PlatformFile } from '../platform/index.js';
|
|
7
|
-
import type { Session } from './types.js';
|
|
8
|
-
import type { ContentBlock } from '../claude/cli.js';
|
|
9
|
-
/**
|
|
10
|
-
* Schedule a delayed flush of the session's pending content.
|
|
11
|
-
* If an update is already scheduled, this is a no-op.
|
|
12
|
-
*
|
|
13
|
-
* Used during streaming to batch updates and avoid excessive API calls.
|
|
14
|
-
*/
|
|
15
|
-
export declare function scheduleUpdate(session: Session, onFlush: (session: Session) => Promise<void>): void;
|
|
16
|
-
/**
|
|
17
|
-
* Build message content for Claude, including images if present.
|
|
18
|
-
* Returns either a string or an array of content blocks.
|
|
19
|
-
*
|
|
20
|
-
* @param text - The text message
|
|
21
|
-
* @param platform - Platform client for downloading images
|
|
22
|
-
* @param files - Optional files attached to the message
|
|
23
|
-
* @param debug - Whether to log debug info
|
|
24
|
-
* @returns Plain string or content blocks array with images
|
|
25
|
-
*/
|
|
26
|
-
export declare function buildMessageContent(text: string, platform: PlatformClient, files?: PlatformFile[], debug?: boolean): Promise<string | ContentBlock[]>;
|
|
27
|
-
/**
|
|
28
|
-
* Start sending typing indicators to the platform.
|
|
29
|
-
* Sends immediately, then every 3 seconds until stopped.
|
|
30
|
-
*/
|
|
31
|
-
export declare function startTyping(session: Session): void;
|
|
32
|
-
/**
|
|
33
|
-
* Stop sending typing indicators.
|
|
34
|
-
*/
|
|
35
|
-
export declare function stopTyping(session: Session): void;
|
|
36
|
-
/**
|
|
37
|
-
* Flush pending content to the platform.
|
|
38
|
-
*
|
|
39
|
-
* Handles:
|
|
40
|
-
* - Message length limits (splits into multiple posts if needed)
|
|
41
|
-
* - Creating vs updating posts
|
|
42
|
-
* - Post registration for reaction routing
|
|
43
|
-
*
|
|
44
|
-
* @param session - The session to flush
|
|
45
|
-
* @param registerPost - Callback to register post for reaction routing
|
|
46
|
-
*/
|
|
47
|
-
export declare function flush(session: Session, registerPost: (postId: string, threadId: string) => void): Promise<void>;
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Message streaming and flushing utilities
|
|
3
|
-
*
|
|
4
|
-
* Handles buffering, formatting, and posting Claude responses to the platform.
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Schedule a delayed flush of the session's pending content.
|
|
8
|
-
* If an update is already scheduled, this is a no-op.
|
|
9
|
-
*
|
|
10
|
-
* Used during streaming to batch updates and avoid excessive API calls.
|
|
11
|
-
*/
|
|
12
|
-
export function scheduleUpdate(session, onFlush) {
|
|
13
|
-
if (session.updateTimer)
|
|
14
|
-
return;
|
|
15
|
-
session.updateTimer = setTimeout(() => {
|
|
16
|
-
session.updateTimer = null;
|
|
17
|
-
onFlush(session);
|
|
18
|
-
}, 500);
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Build message content for Claude, including images if present.
|
|
22
|
-
* Returns either a string or an array of content blocks.
|
|
23
|
-
*
|
|
24
|
-
* @param text - The text message
|
|
25
|
-
* @param platform - Platform client for downloading images
|
|
26
|
-
* @param files - Optional files attached to the message
|
|
27
|
-
* @param debug - Whether to log debug info
|
|
28
|
-
* @returns Plain string or content blocks array with images
|
|
29
|
-
*/
|
|
30
|
-
export async function buildMessageContent(text, platform, files, debug = false) {
|
|
31
|
-
// Filter to only image files
|
|
32
|
-
const imageFiles = files?.filter(f => f.mimeType.startsWith('image/') &&
|
|
33
|
-
['image/jpeg', 'image/png', 'image/gif', 'image/webp'].includes(f.mimeType)) || [];
|
|
34
|
-
// If no images, return plain text
|
|
35
|
-
if (imageFiles.length === 0) {
|
|
36
|
-
return text;
|
|
37
|
-
}
|
|
38
|
-
// Build content blocks with images
|
|
39
|
-
const blocks = [];
|
|
40
|
-
// Download and add each image
|
|
41
|
-
for (const file of imageFiles) {
|
|
42
|
-
try {
|
|
43
|
-
if (!platform.downloadFile) {
|
|
44
|
-
console.warn(` ⚠️ Platform does not support file downloads, skipping ${file.name}`);
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
const buffer = await platform.downloadFile(file.id);
|
|
48
|
-
const base64 = buffer.toString('base64');
|
|
49
|
-
blocks.push({
|
|
50
|
-
type: 'image',
|
|
51
|
-
source: {
|
|
52
|
-
type: 'base64',
|
|
53
|
-
media_type: file.mimeType,
|
|
54
|
-
data: base64,
|
|
55
|
-
},
|
|
56
|
-
});
|
|
57
|
-
if (debug) {
|
|
58
|
-
console.log(` 📷 Attached image: ${file.name} (${file.mimeType}, ${Math.round(buffer.length / 1024)}KB)`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
catch (err) {
|
|
62
|
-
console.error(` ⚠️ Failed to download image ${file.name}:`, err);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
// Add the text message
|
|
66
|
-
if (text) {
|
|
67
|
-
blocks.push({
|
|
68
|
-
type: 'text',
|
|
69
|
-
text,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
return blocks;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Start sending typing indicators to the platform.
|
|
76
|
-
* Sends immediately, then every 3 seconds until stopped.
|
|
77
|
-
*/
|
|
78
|
-
export function startTyping(session) {
|
|
79
|
-
if (session.typingTimer)
|
|
80
|
-
return;
|
|
81
|
-
// Send typing immediately, then every 3 seconds
|
|
82
|
-
session.platform.sendTyping(session.threadId);
|
|
83
|
-
session.typingTimer = setInterval(() => {
|
|
84
|
-
session.platform.sendTyping(session.threadId);
|
|
85
|
-
}, 3000);
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Stop sending typing indicators.
|
|
89
|
-
*/
|
|
90
|
-
export function stopTyping(session) {
|
|
91
|
-
if (session.typingTimer) {
|
|
92
|
-
clearInterval(session.typingTimer);
|
|
93
|
-
session.typingTimer = null;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Flush pending content to the platform.
|
|
98
|
-
*
|
|
99
|
-
* Handles:
|
|
100
|
-
* - Message length limits (splits into multiple posts if needed)
|
|
101
|
-
* - Creating vs updating posts
|
|
102
|
-
* - Post registration for reaction routing
|
|
103
|
-
*
|
|
104
|
-
* @param session - The session to flush
|
|
105
|
-
* @param registerPost - Callback to register post for reaction routing
|
|
106
|
-
*/
|
|
107
|
-
export async function flush(session, registerPost) {
|
|
108
|
-
if (!session.pendingContent.trim())
|
|
109
|
-
return;
|
|
110
|
-
let content = session.pendingContent.replace(/\n{3,}/g, '\n\n').trim();
|
|
111
|
-
// Most chat platforms have post length limits (~16K for Mattermost/Slack)
|
|
112
|
-
const MAX_POST_LENGTH = 16000; // Leave some margin
|
|
113
|
-
const CONTINUATION_THRESHOLD = 14000; // Start new message before we hit the limit
|
|
114
|
-
// Check if we need to start a new message due to length
|
|
115
|
-
if (session.currentPostId && content.length > CONTINUATION_THRESHOLD) {
|
|
116
|
-
// Finalize the current post with what we have up to the threshold
|
|
117
|
-
// Find a good break point (end of line) near the threshold
|
|
118
|
-
let breakPoint = content.lastIndexOf('\n', CONTINUATION_THRESHOLD);
|
|
119
|
-
if (breakPoint < CONTINUATION_THRESHOLD * 0.7) {
|
|
120
|
-
// If we can't find a good line break, just break at the threshold
|
|
121
|
-
breakPoint = CONTINUATION_THRESHOLD;
|
|
122
|
-
}
|
|
123
|
-
const firstPart = content.substring(0, breakPoint).trim() + '\n\n*... (continued below)*';
|
|
124
|
-
const remainder = content.substring(breakPoint).trim();
|
|
125
|
-
// Update the current post with the first part
|
|
126
|
-
await session.platform.updatePost(session.currentPostId, firstPart);
|
|
127
|
-
// Start a new post for the continuation
|
|
128
|
-
session.currentPostId = null;
|
|
129
|
-
session.pendingContent = remainder;
|
|
130
|
-
// Create the continuation post if there's content
|
|
131
|
-
if (remainder) {
|
|
132
|
-
const post = await session.platform.createPost('*(continued)*\n\n' + remainder, session.threadId);
|
|
133
|
-
session.currentPostId = post.id;
|
|
134
|
-
registerPost(post.id, session.threadId);
|
|
135
|
-
}
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
// Normal case: content fits in current post
|
|
139
|
-
if (content.length > MAX_POST_LENGTH) {
|
|
140
|
-
// Safety truncation if we somehow got content that's still too long
|
|
141
|
-
content = content.substring(0, MAX_POST_LENGTH - 50) + '\n\n*... (truncated)*';
|
|
142
|
-
}
|
|
143
|
-
if (session.currentPostId) {
|
|
144
|
-
await session.platform.updatePost(session.currentPostId, content);
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
const post = await session.platform.createPost(content, session.threadId);
|
|
148
|
-
session.currentPostId = post.id;
|
|
149
|
-
// Register post for reaction routing
|
|
150
|
-
registerPost(post.id, session.threadId);
|
|
151
|
-
}
|
|
152
|
-
}
|
package/dist/session/types.d.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session management types and interfaces
|
|
3
|
-
*/
|
|
4
|
-
import type { ClaudeCli } from '../claude/cli.js';
|
|
5
|
-
import type { PlatformClient } from '../platform/index.js';
|
|
6
|
-
import type { WorktreeInfo } from '../persistence/session-store.js';
|
|
7
|
-
export interface QuestionOption {
|
|
8
|
-
label: string;
|
|
9
|
-
description: string;
|
|
10
|
-
}
|
|
11
|
-
export interface PendingQuestionSet {
|
|
12
|
-
toolUseId: string;
|
|
13
|
-
currentIndex: number;
|
|
14
|
-
currentPostId: string | null;
|
|
15
|
-
questions: Array<{
|
|
16
|
-
header: string;
|
|
17
|
-
question: string;
|
|
18
|
-
options: QuestionOption[];
|
|
19
|
-
answer: string | null;
|
|
20
|
-
}>;
|
|
21
|
-
}
|
|
22
|
-
export interface PendingApproval {
|
|
23
|
-
postId: string;
|
|
24
|
-
type: 'plan' | 'action';
|
|
25
|
-
toolUseId: string;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Pending message from unauthorized user awaiting approval
|
|
29
|
-
*/
|
|
30
|
-
export interface PendingMessageApproval {
|
|
31
|
-
postId: string;
|
|
32
|
-
originalMessage: string;
|
|
33
|
-
fromUser: string;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Represents a single Claude Code session tied to a platform thread.
|
|
37
|
-
* Each session has its own Claude CLI process and state.
|
|
38
|
-
*/
|
|
39
|
-
export interface Session {
|
|
40
|
-
platformId: string;
|
|
41
|
-
threadId: string;
|
|
42
|
-
sessionId: string;
|
|
43
|
-
claudeSessionId: string;
|
|
44
|
-
startedBy: string;
|
|
45
|
-
startedAt: Date;
|
|
46
|
-
lastActivityAt: Date;
|
|
47
|
-
sessionNumber: number;
|
|
48
|
-
platform: PlatformClient;
|
|
49
|
-
workingDir: string;
|
|
50
|
-
claude: ClaudeCli;
|
|
51
|
-
currentPostId: string | null;
|
|
52
|
-
pendingContent: string;
|
|
53
|
-
pendingApproval: PendingApproval | null;
|
|
54
|
-
pendingQuestionSet: PendingQuestionSet | null;
|
|
55
|
-
pendingMessageApproval: PendingMessageApproval | null;
|
|
56
|
-
planApproved: boolean;
|
|
57
|
-
sessionAllowedUsers: Set<string>;
|
|
58
|
-
forceInteractivePermissions: boolean;
|
|
59
|
-
sessionStartPostId: string | null;
|
|
60
|
-
tasksPostId: string | null;
|
|
61
|
-
activeSubagents: Map<string, string>;
|
|
62
|
-
updateTimer: ReturnType<typeof setTimeout> | null;
|
|
63
|
-
typingTimer: ReturnType<typeof setInterval> | null;
|
|
64
|
-
timeoutWarningPosted: boolean;
|
|
65
|
-
isRestarting: boolean;
|
|
66
|
-
isResumed: boolean;
|
|
67
|
-
wasInterrupted: boolean;
|
|
68
|
-
inProgressTaskStart: number | null;
|
|
69
|
-
activeToolStarts: Map<string, number>;
|
|
70
|
-
worktreeInfo?: WorktreeInfo;
|
|
71
|
-
pendingWorktreePrompt?: boolean;
|
|
72
|
-
worktreePromptDisabled?: boolean;
|
|
73
|
-
queuedPrompt?: string;
|
|
74
|
-
worktreePromptPostId?: string;
|
|
75
|
-
}
|
|
76
|
-
export declare const MAX_SESSIONS: number;
|
|
77
|
-
export declare const SESSION_TIMEOUT_MS: number;
|
|
78
|
-
export declare const SESSION_WARNING_MS: number;
|
package/dist/session/types.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session management types and interfaces
|
|
3
|
-
*/
|
|
4
|
-
// =============================================================================
|
|
5
|
-
// Configuration Constants
|
|
6
|
-
// =============================================================================
|
|
7
|
-
export const MAX_SESSIONS = parseInt(process.env.MAX_SESSIONS || '5', 10);
|
|
8
|
-
export const SESSION_TIMEOUT_MS = parseInt(process.env.SESSION_TIMEOUT_MS || '1800000', 10); // 30 min
|
|
9
|
-
export const SESSION_WARNING_MS = 5 * 60 * 1000; // Warn 5 minutes before timeout
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Git worktree management utilities
|
|
3
|
-
*
|
|
4
|
-
* Handles worktree prompts, creation, switching, and cleanup.
|
|
5
|
-
*/
|
|
6
|
-
import type { Session } from './types.js';
|
|
7
|
-
import type { WorktreeMode } from '../config.js';
|
|
8
|
-
import type { ClaudeEvent } from '../claude/cli.js';
|
|
9
|
-
/**
|
|
10
|
-
* Check if we should prompt the user to create a worktree.
|
|
11
|
-
* Returns the reason for prompting, or null if we shouldn't prompt.
|
|
12
|
-
*/
|
|
13
|
-
export declare function shouldPromptForWorktree(session: Session, worktreeMode: WorktreeMode, hasOtherSessionInRepo: (repoRoot: string, excludeThreadId: string) => boolean): Promise<string | null>;
|
|
14
|
-
/**
|
|
15
|
-
* Post the worktree prompt message to the user.
|
|
16
|
-
*/
|
|
17
|
-
export declare function postWorktreePrompt(session: Session, reason: string, registerPost: (postId: string, threadId: string) => void): Promise<void>;
|
|
18
|
-
/**
|
|
19
|
-
* Handle user providing a branch name in response to worktree prompt.
|
|
20
|
-
* Returns true if handled (whether successful or not).
|
|
21
|
-
*/
|
|
22
|
-
export declare function handleWorktreeBranchResponse(session: Session, branchName: string, username: string, createAndSwitch: (threadId: string, branch: string, username: string) => Promise<void>): Promise<boolean>;
|
|
23
|
-
/**
|
|
24
|
-
* Handle ❌ reaction on worktree prompt - skip worktree and continue in main repo.
|
|
25
|
-
*/
|
|
26
|
-
export declare function handleWorktreeSkip(session: Session, username: string, persistSession: (session: Session) => void, startTyping: (session: Session) => void): Promise<void>;
|
|
27
|
-
/**
|
|
28
|
-
* Create a new worktree and switch the session to it.
|
|
29
|
-
*/
|
|
30
|
-
export declare function createAndSwitchToWorktree(session: Session, branch: string, username: string, options: {
|
|
31
|
-
skipPermissions: boolean;
|
|
32
|
-
chromeEnabled: boolean;
|
|
33
|
-
handleEvent: (sessionId: string, event: ClaudeEvent) => void;
|
|
34
|
-
handleExit: (sessionId: string, code: number) => Promise<void>;
|
|
35
|
-
updateSessionHeader: (session: Session) => Promise<void>;
|
|
36
|
-
flush: (session: Session) => Promise<void>;
|
|
37
|
-
persistSession: (session: Session) => void;
|
|
38
|
-
startTyping: (session: Session) => void;
|
|
39
|
-
stopTyping: (session: Session) => void;
|
|
40
|
-
}): Promise<void>;
|
|
41
|
-
/**
|
|
42
|
-
* Switch to an existing worktree.
|
|
43
|
-
*/
|
|
44
|
-
export declare function switchToWorktree(session: Session, branchOrPath: string, username: string, changeDirectory: (threadId: string, newDir: string, username: string) => Promise<void>): Promise<void>;
|
|
45
|
-
/**
|
|
46
|
-
* List all worktrees for the current repository.
|
|
47
|
-
*/
|
|
48
|
-
export declare function listWorktreesCommand(session: Session): Promise<void>;
|
|
49
|
-
/**
|
|
50
|
-
* Remove a worktree.
|
|
51
|
-
*/
|
|
52
|
-
export declare function removeWorktreeCommand(session: Session, branchOrPath: string, username: string): Promise<void>;
|
|
53
|
-
/**
|
|
54
|
-
* Disable worktree prompts for a session.
|
|
55
|
-
*/
|
|
56
|
-
export declare function disableWorktreePrompt(session: Session, username: string, persistSession: (session: Session) => void): Promise<void>;
|