mattermost-claude-code 0.5.2 â 0.5.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/README.md +10 -0
- package/dist/claude/session.d.ts +8 -0
- package/dist/claude/session.js +43 -1
- package/dist/index.js +13 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -146,6 +146,16 @@ React đ to allow this message, â
to invite them to the session, đ to den
|
|
|
146
146
|
|
|
147
147
|
Messages starting with `@someone-else` are ignored by the bot, allowing side conversations in the thread without triggering Claude.
|
|
148
148
|
|
|
149
|
+
### Downgrade Permissions
|
|
150
|
+
|
|
151
|
+
If the bot is running with `--skip-permissions` (auto mode), you can enable interactive permissions for a specific session:
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
/permissions interactive
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
This allows collaboration by requiring approval for Claude's actions. Note: you can only downgrade (auto â interactive), not upgrade - this ensures security.
|
|
158
|
+
|
|
149
159
|
## Interactive Features
|
|
150
160
|
|
|
151
161
|
### Permission Approval
|
package/dist/claude/session.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ interface Session {
|
|
|
45
45
|
pendingMessageApproval: PendingMessageApproval | null;
|
|
46
46
|
planApproved: boolean;
|
|
47
47
|
sessionAllowedUsers: Set<string>;
|
|
48
|
+
forceInteractivePermissions: boolean;
|
|
48
49
|
sessionStartPostId: string | null;
|
|
49
50
|
tasksPostId: string | null;
|
|
50
51
|
activeSubagents: Map<string, string>;
|
|
@@ -111,6 +112,13 @@ export declare class SessionManager {
|
|
|
111
112
|
inviteUser(threadId: string, invitedUser: string, invitedBy: string): Promise<void>;
|
|
112
113
|
/** Kick a user from a specific session */
|
|
113
114
|
kickUser(threadId: string, kickedUser: string, kickedBy: string): Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* Enable interactive permissions for a session.
|
|
117
|
+
* Can only downgrade (skip â interactive), not upgrade.
|
|
118
|
+
*/
|
|
119
|
+
enableInteractivePermissions(threadId: string, username: string): Promise<void>;
|
|
120
|
+
/** Check if a session should use interactive permissions */
|
|
121
|
+
isSessionInteractive(threadId: string): boolean;
|
|
114
122
|
/** Update the session header post with current participants */
|
|
115
123
|
private updateSessionHeader;
|
|
116
124
|
/** Request approval for a message from an unauthorized user */
|
package/dist/claude/session.js
CHANGED
|
@@ -121,6 +121,7 @@ export class SessionManager {
|
|
|
121
121
|
pendingMessageApproval: null,
|
|
122
122
|
planApproved: false,
|
|
123
123
|
sessionAllowedUsers: new Set([username]), // Owner is always allowed
|
|
124
|
+
forceInteractivePermissions: false, // Can be enabled via /permissions interactive
|
|
124
125
|
sessionStartPostId: post.id, // Track for updating participants
|
|
125
126
|
tasksPostId: null,
|
|
126
127
|
activeSubagents: new Map(),
|
|
@@ -813,12 +814,53 @@ export class SessionManager {
|
|
|
813
814
|
await this.mattermost.createPost(`â ī¸ @${kickedUser} was not in this session`, threadId);
|
|
814
815
|
}
|
|
815
816
|
}
|
|
817
|
+
/**
|
|
818
|
+
* Enable interactive permissions for a session.
|
|
819
|
+
* Can only downgrade (skip â interactive), not upgrade.
|
|
820
|
+
*/
|
|
821
|
+
async enableInteractivePermissions(threadId, username) {
|
|
822
|
+
const session = this.sessions.get(threadId);
|
|
823
|
+
if (!session)
|
|
824
|
+
return;
|
|
825
|
+
// Only session owner or globally allowed users can change permissions
|
|
826
|
+
if (session.startedBy !== username && !this.mattermost.isUserAllowed(username)) {
|
|
827
|
+
await this.mattermost.createPost(`â ī¸ Only @${session.startedBy} or allowed users can change permissions`, threadId);
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
// Can only downgrade, not upgrade
|
|
831
|
+
if (!this.skipPermissions) {
|
|
832
|
+
await this.mattermost.createPost(`âšī¸ Permissions are already interactive for this session`, threadId);
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
// Already enabled for this session
|
|
836
|
+
if (session.forceInteractivePermissions) {
|
|
837
|
+
await this.mattermost.createPost(`âšī¸ Interactive permissions already enabled for this session`, threadId);
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
session.forceInteractivePermissions = true;
|
|
841
|
+
await this.mattermost.createPost(`đ Interactive permissions enabled for this session by @${username}`, threadId);
|
|
842
|
+
console.log(` đ Interactive permissions enabled for session by @${username}`);
|
|
843
|
+
await this.updateSessionHeader(session);
|
|
844
|
+
}
|
|
845
|
+
/** Check if a session should use interactive permissions */
|
|
846
|
+
isSessionInteractive(threadId) {
|
|
847
|
+
const session = this.sessions.get(threadId);
|
|
848
|
+
if (!session)
|
|
849
|
+
return !this.skipPermissions;
|
|
850
|
+
// If global is interactive, always interactive
|
|
851
|
+
if (!this.skipPermissions)
|
|
852
|
+
return true;
|
|
853
|
+
// If session has forced interactive, use that
|
|
854
|
+
return session.forceInteractivePermissions;
|
|
855
|
+
}
|
|
816
856
|
/** Update the session header post with current participants */
|
|
817
857
|
async updateSessionHeader(session) {
|
|
818
858
|
if (!session.sessionStartPostId)
|
|
819
859
|
return;
|
|
820
860
|
const shortDir = this.workingDir.replace(process.env.HOME || '', '~');
|
|
821
|
-
|
|
861
|
+
// Check session-level permission override
|
|
862
|
+
const isInteractive = !this.skipPermissions || session.forceInteractivePermissions;
|
|
863
|
+
const permMode = isInteractive ? 'đ Interactive' : '⥠Auto';
|
|
822
864
|
// Build participants list (excluding owner who is shown in "Started by")
|
|
823
865
|
const otherParticipants = [...session.sessionAllowedUsers]
|
|
824
866
|
.filter(u => u !== session.startedBy)
|
package/dist/index.js
CHANGED
|
@@ -102,6 +102,19 @@ async function main() {
|
|
|
102
102
|
await session.kickUser(threadRoot, kickMatch[1], username);
|
|
103
103
|
return;
|
|
104
104
|
}
|
|
105
|
+
// Check for /permissions command
|
|
106
|
+
const permMatch = content.match(/^\/permissions?\s+(interactive|auto)/i);
|
|
107
|
+
if (permMatch) {
|
|
108
|
+
const mode = permMatch[1].toLowerCase();
|
|
109
|
+
if (mode === 'interactive') {
|
|
110
|
+
await session.enableInteractivePermissions(threadRoot, username);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// Can't upgrade to auto - that would be less secure
|
|
114
|
+
await mattermost.createPost(`â ī¸ Cannot upgrade to auto permissions - can only downgrade to interactive`, threadRoot);
|
|
115
|
+
}
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
105
118
|
// Check if user is allowed in this session
|
|
106
119
|
if (!session.isUserAllowedInSession(threadRoot, username)) {
|
|
107
120
|
// Request approval for their message
|