mirror of
https://github.com/aljazceru/claude-code-viewer.git
synced 2025-12-21 23:34:20 +01:00
fix: disable tool approve for old claude code version
This commit is contained in:
@@ -167,7 +167,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
"query",
|
"query",
|
||||||
z.object({
|
z.object({
|
||||||
basePath: z.string().optional().default("/"),
|
basePath: z.string().optional().default("/"),
|
||||||
})
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const { projectId } = c.req.param();
|
const { projectId } = c.req.param();
|
||||||
@@ -182,14 +182,14 @@ export const routes = (app: HonoAppType) => {
|
|||||||
try {
|
try {
|
||||||
const result = await getFileCompletion(
|
const result = await getFileCompletion(
|
||||||
project.meta.projectPath,
|
project.meta.projectPath,
|
||||||
basePath
|
basePath,
|
||||||
);
|
);
|
||||||
return c.json(result);
|
return c.json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("File completion error:", error);
|
console.error("File completion error:", error);
|
||||||
return c.json({ error: "Failed to get file completion" }, 500);
|
return c.json({ error: "Failed to get file completion" }, 500);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
.get("/projects/:projectId/claude-commands", async (c) => {
|
.get("/projects/:projectId/claude-commands", async (c) => {
|
||||||
@@ -202,18 +202,18 @@ export const routes = (app: HonoAppType) => {
|
|||||||
}).then((dirents) =>
|
}).then((dirents) =>
|
||||||
dirents
|
dirents
|
||||||
.filter((d) => d.isFile() && d.name.endsWith(".md"))
|
.filter((d) => d.isFile() && d.name.endsWith(".md"))
|
||||||
.map((d) => d.name.replace(/\.md$/, ""))
|
.map((d) => d.name.replace(/\.md$/, "")),
|
||||||
),
|
),
|
||||||
project.meta.projectPath !== null
|
project.meta.projectPath !== null
|
||||||
? readdir(
|
? readdir(
|
||||||
resolve(project.meta.projectPath, ".claude", "commands"),
|
resolve(project.meta.projectPath, ".claude", "commands"),
|
||||||
{
|
{
|
||||||
withFileTypes: true,
|
withFileTypes: true,
|
||||||
}
|
},
|
||||||
).then((dirents) =>
|
).then((dirents) =>
|
||||||
dirents
|
dirents
|
||||||
.filter((d) => d.isFile() && d.name.endsWith(".md"))
|
.filter((d) => d.isFile() && d.name.endsWith(".md"))
|
||||||
.map((d) => d.name.replace(/\.md$/, ""))
|
.map((d) => d.name.replace(/\.md$/, "")),
|
||||||
)
|
)
|
||||||
: [],
|
: [],
|
||||||
]);
|
]);
|
||||||
@@ -274,7 +274,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
z.object({
|
z.object({
|
||||||
fromRef: z.string().min(1, "fromRef is required"),
|
fromRef: z.string().min(1, "fromRef is required"),
|
||||||
toRef: z.string().min(1, "toRef is required"),
|
toRef: z.string().min(1, "toRef is required"),
|
||||||
})
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const { projectId } = c.req.param();
|
const { projectId } = c.req.param();
|
||||||
@@ -289,7 +289,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
const result = await getDiff(
|
const result = await getDiff(
|
||||||
project.meta.projectPath,
|
project.meta.projectPath,
|
||||||
fromRef,
|
fromRef,
|
||||||
toRef
|
toRef,
|
||||||
);
|
);
|
||||||
return c.json(result);
|
return c.json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -299,7 +299,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
}
|
}
|
||||||
return c.json({ error: "Failed to get diff" }, 500);
|
return c.json({ error: "Failed to get diff" }, 500);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
.get("/mcp/list", async (c) => {
|
.get("/mcp/list", async (c) => {
|
||||||
@@ -313,7 +313,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
"json",
|
"json",
|
||||||
z.object({
|
z.object({
|
||||||
message: z.string(),
|
message: z.string(),
|
||||||
})
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const { projectId } = c.req.param();
|
const { projectId } = c.req.param();
|
||||||
@@ -325,13 +325,13 @@ export const routes = (app: HonoAppType) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const task = await getTaskController(
|
const task = await getTaskController(
|
||||||
c.get("config")
|
c.get("config"),
|
||||||
).startOrContinueTask(
|
).startOrContinueTask(
|
||||||
{
|
{
|
||||||
projectId,
|
projectId,
|
||||||
cwd: project.meta.projectPath,
|
cwd: project.meta.projectPath,
|
||||||
},
|
},
|
||||||
message
|
message,
|
||||||
);
|
);
|
||||||
|
|
||||||
return c.json({
|
return c.json({
|
||||||
@@ -339,7 +339,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
sessionId: task.sessionId,
|
sessionId: task.sessionId,
|
||||||
userMessageId: task.userMessageId,
|
userMessageId: task.userMessageId,
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
.post(
|
.post(
|
||||||
@@ -348,7 +348,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
"json",
|
"json",
|
||||||
z.object({
|
z.object({
|
||||||
resumeMessage: z.string(),
|
resumeMessage: z.string(),
|
||||||
})
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const { projectId, sessionId } = c.req.param();
|
const { projectId, sessionId } = c.req.param();
|
||||||
@@ -360,14 +360,14 @@ export const routes = (app: HonoAppType) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const task = await getTaskController(
|
const task = await getTaskController(
|
||||||
c.get("config")
|
c.get("config"),
|
||||||
).startOrContinueTask(
|
).startOrContinueTask(
|
||||||
{
|
{
|
||||||
projectId,
|
projectId,
|
||||||
sessionId,
|
sessionId,
|
||||||
cwd: project.meta.projectPath,
|
cwd: project.meta.projectPath,
|
||||||
},
|
},
|
||||||
resumeMessage
|
resumeMessage,
|
||||||
);
|
);
|
||||||
|
|
||||||
return c.json({
|
return c.json({
|
||||||
@@ -375,7 +375,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
sessionId: task.sessionId,
|
sessionId: task.sessionId,
|
||||||
userMessageId: task.userMessageId,
|
userMessageId: task.userMessageId,
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
.get("/tasks/alive", async (c) => {
|
.get("/tasks/alive", async (c) => {
|
||||||
@@ -386,7 +386,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
status: task.status,
|
status: task.status,
|
||||||
sessionId: task.sessionId,
|
sessionId: task.sessionId,
|
||||||
userMessageId: task.userMessageId,
|
userMessageId: task.userMessageId,
|
||||||
})
|
}),
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -398,7 +398,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
const { sessionId } = c.req.valid("json");
|
const { sessionId } = c.req.valid("json");
|
||||||
getTaskController(c.get("config")).abortTask(sessionId);
|
getTaskController(c.get("config")).abortTask(sessionId);
|
||||||
return c.json({ message: "Task aborted" });
|
return c.json({ message: "Task aborted" });
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
.post(
|
.post(
|
||||||
@@ -408,15 +408,15 @@ export const routes = (app: HonoAppType) => {
|
|||||||
z.object({
|
z.object({
|
||||||
permissionRequestId: z.string(),
|
permissionRequestId: z.string(),
|
||||||
decision: z.enum(["allow", "deny"]),
|
decision: z.enum(["allow", "deny"]),
|
||||||
})
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const permissionResponse = c.req.valid("json");
|
const permissionResponse = c.req.valid("json");
|
||||||
getTaskController(c.get("config")).respondToPermissionRequest(
|
getTaskController(c.get("config")).respondToPermissionRequest(
|
||||||
permissionResponse
|
permissionResponse,
|
||||||
);
|
);
|
||||||
return c.json({ message: "Permission response received" });
|
return c.json({ message: "Permission response received" });
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
.get("/sse", async (c) => {
|
.get("/sse", async (c) => {
|
||||||
@@ -426,7 +426,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
const stream = writeTypeSafeSSE(rawStream);
|
const stream = writeTypeSafeSSE(rawStream);
|
||||||
|
|
||||||
const onSessionListChanged = (
|
const onSessionListChanged = (
|
||||||
event: InternalEventDeclaration["sessionListChanged"]
|
event: InternalEventDeclaration["sessionListChanged"],
|
||||||
) => {
|
) => {
|
||||||
stream.writeSSE("sessionListChanged", {
|
stream.writeSSE("sessionListChanged", {
|
||||||
projectId: event.projectId,
|
projectId: event.projectId,
|
||||||
@@ -434,7 +434,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onSessionChanged = (
|
const onSessionChanged = (
|
||||||
event: InternalEventDeclaration["sessionChanged"]
|
event: InternalEventDeclaration["sessionChanged"],
|
||||||
) => {
|
) => {
|
||||||
stream.writeSSE("sessionChanged", {
|
stream.writeSSE("sessionChanged", {
|
||||||
projectId: event.projectId,
|
projectId: event.projectId,
|
||||||
@@ -443,7 +443,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onTaskChanged = (
|
const onTaskChanged = (
|
||||||
event: InternalEventDeclaration["taskChanged"]
|
event: InternalEventDeclaration["taskChanged"],
|
||||||
) => {
|
) => {
|
||||||
stream.writeSSE("taskChanged", {
|
stream.writeSSE("taskChanged", {
|
||||||
aliveTasks: event.aliveTasks,
|
aliveTasks: event.aliveTasks,
|
||||||
@@ -467,7 +467,7 @@ export const routes = (app: HonoAppType) => {
|
|||||||
},
|
},
|
||||||
async (err) => {
|
async (err) => {
|
||||||
console.error("Streaming error:", err);
|
console.error("Streaming error:", err);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export class ClaudeCodeExecutor {
|
|||||||
? resolve(executablePath)
|
? resolve(executablePath)
|
||||||
: execSync("which claude", {}).toString().trim();
|
: execSync("which claude", {}).toString().trim();
|
||||||
this.claudeCodeVersion = ClaudeCodeVersion.fromCLIString(
|
this.claudeCodeVersion = ClaudeCodeVersion.fromCLIString(
|
||||||
execSync(`${this.pathToClaudeCodeExecutable} --version`, {}).toString()
|
execSync(`${this.pathToClaudeCodeExecutable} --version`, {}).toString(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,11 +27,11 @@ export class ClaudeCodeExecutor {
|
|||||||
return {
|
return {
|
||||||
enableToolApproval:
|
enableToolApproval:
|
||||||
this.claudeCodeVersion?.greaterThanOrEqual(
|
this.claudeCodeVersion?.greaterThanOrEqual(
|
||||||
new ClaudeCodeVersion({ major: 1, minor: 0, patch: 82 })
|
new ClaudeCodeVersion({ major: 1, minor: 0, patch: 82 }),
|
||||||
) ?? false,
|
) ?? false,
|
||||||
extractUuidFromSDKMessage:
|
extractUuidFromSDKMessage:
|
||||||
this.claudeCodeVersion?.greaterThanOrEqual(
|
this.claudeCodeVersion?.greaterThanOrEqual(
|
||||||
new ClaudeCodeVersion({ major: 1, minor: 0, patch: 86 })
|
new ClaudeCodeVersion({ major: 1, minor: 0, patch: 86 }),
|
||||||
) ?? false,
|
) ?? false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export class ClaudeCodeTaskController {
|
|||||||
return async (
|
return async (
|
||||||
toolName: string,
|
toolName: string,
|
||||||
toolInput: Record<string, unknown>,
|
toolInput: Record<string, unknown>,
|
||||||
_options: { signal: AbortSignal }
|
_options: { signal: AbortSignal },
|
||||||
) => {
|
) => {
|
||||||
// If not in default mode, use the configured permission mode behavior
|
// If not in default mode, use the configured permission mode behavior
|
||||||
if (this.config.permissionMode !== "default") {
|
if (this.config.permissionMode !== "default") {
|
||||||
@@ -81,7 +81,7 @@ export class ClaudeCodeTaskController {
|
|||||||
// Store the request
|
// Store the request
|
||||||
this.pendingPermissionRequests.set(
|
this.pendingPermissionRequests.set(
|
||||||
permissionRequest.id,
|
permissionRequest.id,
|
||||||
permissionRequest
|
permissionRequest,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Emit event to notify UI
|
// Emit event to notify UI
|
||||||
@@ -92,7 +92,7 @@ export class ClaudeCodeTaskController {
|
|||||||
// Wait for user response with timeout
|
// Wait for user response with timeout
|
||||||
const response = await this.waitForPermissionResponse(
|
const response = await this.waitForPermissionResponse(
|
||||||
permissionRequest.id,
|
permissionRequest.id,
|
||||||
60000
|
60000,
|
||||||
); // 60 second timeout
|
); // 60 second timeout
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
@@ -120,7 +120,7 @@ export class ClaudeCodeTaskController {
|
|||||||
|
|
||||||
private async waitForPermissionResponse(
|
private async waitForPermissionResponse(
|
||||||
permissionRequestId: string,
|
permissionRequestId: string,
|
||||||
timeoutMs: number
|
timeoutMs: number,
|
||||||
): Promise<PermissionResponse | null> {
|
): Promise<PermissionResponse | null> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const checkResponse = () => {
|
const checkResponse = () => {
|
||||||
@@ -153,7 +153,7 @@ export class ClaudeCodeTaskController {
|
|||||||
|
|
||||||
public get aliveTasks() {
|
public get aliveTasks() {
|
||||||
return this.tasks.filter(
|
return this.tasks.filter(
|
||||||
(task) => task.status === "running" || task.status === "paused"
|
(task) => task.status === "running" || task.status === "paused",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,10 +163,10 @@ export class ClaudeCodeTaskController {
|
|||||||
projectId: string;
|
projectId: string;
|
||||||
sessionId?: string;
|
sessionId?: string;
|
||||||
},
|
},
|
||||||
message: string
|
message: string,
|
||||||
): Promise<AliveClaudeCodeTask> {
|
): Promise<AliveClaudeCodeTask> {
|
||||||
const existingTask = this.aliveTasks.find(
|
const existingTask = this.aliveTasks.find(
|
||||||
(task) => task.sessionId === currentSession.sessionId
|
(task) => task.sessionId === currentSession.sessionId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (existingTask) {
|
if (existingTask) {
|
||||||
@@ -190,7 +190,7 @@ export class ClaudeCodeTaskController {
|
|||||||
projectId: string;
|
projectId: string;
|
||||||
sessionId?: string;
|
sessionId?: string;
|
||||||
},
|
},
|
||||||
message: string
|
message: string,
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
generateMessages,
|
generateMessages,
|
||||||
@@ -221,7 +221,7 @@ export class ClaudeCodeTaskController {
|
|||||||
(resolve, reject) => {
|
(resolve, reject) => {
|
||||||
aliveTaskResolve = resolve;
|
aliveTaskResolve = resolve;
|
||||||
aliveTaskReject = reject;
|
aliveTaskReject = reject;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let resolved = false;
|
let resolved = false;
|
||||||
@@ -240,10 +240,10 @@ export class ClaudeCodeTaskController {
|
|||||||
permissionMode: this.config.permissionMode,
|
permissionMode: this.config.permissionMode,
|
||||||
canUseTool: this.createCanUseToolCallback(
|
canUseTool: this.createCanUseToolCallback(
|
||||||
task.id,
|
task.id,
|
||||||
task.baseSessionId
|
task.baseSessionId,
|
||||||
),
|
),
|
||||||
abortController: abortController,
|
abortController: abortController,
|
||||||
}
|
},
|
||||||
)) {
|
)) {
|
||||||
currentTask ??= this.aliveTasks.find((t) => t.id === task.id);
|
currentTask ??= this.aliveTasks.find((t) => t.id === task.id);
|
||||||
|
|
||||||
@@ -257,13 +257,9 @@ export class ClaudeCodeTaskController {
|
|||||||
// 初回の system message だとまだ history ファイルが作成されていないので
|
// 初回の system message だとまだ history ファイルが作成されていないので
|
||||||
if (message.type === "user" || message.type === "assistant") {
|
if (message.type === "user" || message.type === "assistant") {
|
||||||
// 本来は message.uuid の存在チェックをしたいが、古いバージョンでは存在しないことがある
|
// 本来は message.uuid の存在チェックをしたいが、古いバージョンでは存在しないことがある
|
||||||
console.log(
|
|
||||||
"[DEBUG startTask] 9. Processing user/assistant message"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!resolved) {
|
if (!resolved) {
|
||||||
console.log(
|
console.log(
|
||||||
"[DEBUG startTask] 10. Resolving task for first time"
|
"[DEBUG startTask] 10. Resolving task for first time",
|
||||||
);
|
);
|
||||||
|
|
||||||
const runningTask: RunningClaudeCodeTask = {
|
const runningTask: RunningClaudeCodeTask = {
|
||||||
@@ -283,12 +279,12 @@ export class ClaudeCodeTaskController {
|
|||||||
};
|
};
|
||||||
this.tasks.push(runningTask);
|
this.tasks.push(runningTask);
|
||||||
console.log(
|
console.log(
|
||||||
"[DEBUG startTask] 11. About to call aliveTaskResolve"
|
"[DEBUG startTask] 11. About to call aliveTaskResolve",
|
||||||
);
|
);
|
||||||
aliveTaskResolve(runningTask);
|
aliveTaskResolve(runningTask);
|
||||||
resolved = true;
|
resolved = true;
|
||||||
console.log(
|
console.log(
|
||||||
"[DEBUG startTask] 12. aliveTaskResolve called, resolved=true"
|
"[DEBUG startTask] 12. aliveTaskResolve called, resolved=true",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,13 +294,10 @@ export class ClaudeCodeTaskController {
|
|||||||
await Promise.all(
|
await Promise.all(
|
||||||
task.onMessageHandlers.map(async (onMessageHandler) => {
|
task.onMessageHandlers.map(async (onMessageHandler) => {
|
||||||
await onMessageHandler(message);
|
await onMessageHandler(message);
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (currentTask !== undefined && message.type === "result") {
|
if (currentTask !== undefined && message.type === "result") {
|
||||||
console.log(
|
|
||||||
"[DEBUG startTask] 15. Result message received, pausing task"
|
|
||||||
);
|
|
||||||
this.upsertExistingTask({
|
this.upsertExistingTask({
|
||||||
...currentTask,
|
...currentTask,
|
||||||
status: "paused",
|
status: "paused",
|
||||||
@@ -318,12 +311,12 @@ export class ClaudeCodeTaskController {
|
|||||||
|
|
||||||
if (updatedTask === undefined) {
|
if (updatedTask === undefined) {
|
||||||
console.log(
|
console.log(
|
||||||
"[DEBUG startTask] 17. ERROR: Task not found in aliveTasks"
|
"[DEBUG startTask] 17. ERROR: Task not found in aliveTasks",
|
||||||
);
|
);
|
||||||
const error = new Error(
|
const error = new Error(
|
||||||
`illegal state: task is not running, task: ${JSON.stringify(
|
`illegal state: task is not running, task: ${JSON.stringify(
|
||||||
updatedTask
|
updatedTask,
|
||||||
)}`
|
)}`,
|
||||||
);
|
);
|
||||||
aliveTaskReject(error);
|
aliveTaskReject(error);
|
||||||
throw error;
|
throw error;
|
||||||
@@ -336,7 +329,7 @@ export class ClaudeCodeTaskController {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!resolved) {
|
if (!resolved) {
|
||||||
console.log(
|
console.log(
|
||||||
"[DEBUG startTask] 20. Rejecting task (not yet resolved)"
|
"[DEBUG startTask] 20. Rejecting task (not yet resolved)",
|
||||||
);
|
);
|
||||||
aliveTaskReject(error);
|
aliveTaskReject(error);
|
||||||
resolved = true;
|
resolved = true;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class EventBus {
|
|||||||
|
|
||||||
public emit<EventName extends keyof InternalEventDeclaration>(
|
public emit<EventName extends keyof InternalEventDeclaration>(
|
||||||
event: EventName,
|
event: EventName,
|
||||||
data: InternalEventDeclaration[EventName]
|
data: InternalEventDeclaration[EventName],
|
||||||
): void {
|
): void {
|
||||||
this.emitter.emit(event, {
|
this.emitter.emit(event, {
|
||||||
...data,
|
...data,
|
||||||
@@ -20,8 +20,8 @@ class EventBus {
|
|||||||
public on<EventName extends keyof InternalEventDeclaration>(
|
public on<EventName extends keyof InternalEventDeclaration>(
|
||||||
event: EventName,
|
event: EventName,
|
||||||
listener: (
|
listener: (
|
||||||
data: InternalEventDeclaration[EventName]
|
data: InternalEventDeclaration[EventName],
|
||||||
) => void | Promise<void>
|
) => void | Promise<void>,
|
||||||
): void {
|
): void {
|
||||||
this.emitter.on(event, listener);
|
this.emitter.on(event, listener);
|
||||||
}
|
}
|
||||||
@@ -29,8 +29,8 @@ class EventBus {
|
|||||||
public off<EventName extends keyof InternalEventDeclaration>(
|
public off<EventName extends keyof InternalEventDeclaration>(
|
||||||
event: EventName,
|
event: EventName,
|
||||||
listener: (
|
listener: (
|
||||||
data: InternalEventDeclaration[EventName]
|
data: InternalEventDeclaration[EventName],
|
||||||
) => void | Promise<void>
|
) => void | Promise<void>,
|
||||||
): void {
|
): void {
|
||||||
this.emitter.off(event, listener);
|
this.emitter.off(event, listener);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user