opencode-discord 1.0.0 → 1.1.1

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.
Files changed (2) hide show
  1. package/index.ts +112 -81
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -3,105 +3,136 @@ import { Client } from "@theuntraceable/discord-rpc"
3
3
 
4
4
  const CLIENT_ID = process.env.DISCORD_CLIENT_ID ?? "YOUR_DISCORD_APP_ID"
5
5
 
6
- const client = new Client({ clientId: CLIENT_ID })
7
- let connected = false
8
- let sessionActive = false
9
- let currentProject = ""
10
- let startTimestamp = Date.now()
11
- let lastEditedFile: string | undefined
12
-
13
- async function updatePresence(): Promise<void> {
14
- if (!connected) return
15
-
16
- const details = sessionActive
17
- ? currentProject
18
- ? `Working on ${currentProject}`
19
- : "Working on a project"
20
- : "No active session"
21
-
22
- const state = sessionActive
23
- ? lastEditedFile
24
- ? `Editing ${lastEditedFile}`
25
- : "AI session active"
26
- : "Idle"
27
-
28
- try {
29
- await client.user?.setActivity({
30
- details,
31
- state,
32
- startTimestamp,
33
- largeImageKey: "opencode",
34
- largeImageText: "OpenCode",
35
- smallImageKey: sessionActive ? "ai" : "idle",
36
- smallImageText: sessionActive ? "AI Active" : "Idle",
37
- })
38
- } catch {
39
- // Presence update failed
6
+ export const DiscordStatus: Plugin = async ({ client: sdk, project }) => {
7
+ async function log(level: string, message: string, extra?: any) {
8
+ try {
9
+ await sdk.app.log({
10
+ service: "opencode-discord",
11
+ level,
12
+ message,
13
+ extra,
14
+ })
15
+ } catch (e) {
16
+ console.error(`[opencode-discord] ${message}`, extra ?? "", e)
17
+ }
40
18
  }
41
- }
42
19
 
43
- export const DiscordStatus: Plugin = async ({ project }) => {
44
- currentProject = project?.name ?? ""
20
+ await log("info", "Plugin initializing", { clientId: CLIENT_ID, project: project?.name })
21
+
22
+ const rpc = new Client({ clientId: CLIENT_ID })
23
+ let connected = false
24
+ let sessionActive = false
25
+ let currentProject = project?.name ?? ""
26
+ let startTimestamp = Date.now()
27
+ let lastEditedFile: string | undefined
28
+
29
+ async function updatePresence() {
30
+ await log("debug", "updatePresence called", { connected, sessionActive, lastEditedFile })
31
+ if (!connected) {
32
+ await log("warn", "Skipping presence update - not connected to Discord")
33
+ return
34
+ }
35
+
36
+ const details = sessionActive
37
+ ? currentProject
38
+ ? `Working on ${currentProject}`
39
+ : "Working on a project"
40
+ : "No active session"
41
+
42
+ const state = sessionActive
43
+ ? lastEditedFile
44
+ ? `Editing ${lastEditedFile}`
45
+ : "AI session active"
46
+ : "Idle"
47
+
48
+ try {
49
+ await rpc.user?.setActivity({
50
+ details,
51
+ state,
52
+ startTimestamp,
53
+ largeImageKey: "opencode",
54
+ largeImageText: "OpenCode",
55
+ smallImageKey: sessionActive ? "ai" : "idle",
56
+ smallImageText: sessionActive ? "AI Active" : "Idle",
57
+ })
58
+ await log("info", "Presence updated", { details, state })
59
+ } catch (e) {
60
+ await log("error", "Failed to update presence", { error: String(e) })
61
+ }
62
+ }
45
63
 
46
- client.on("ready", () => {
64
+ rpc.on("ready", async () => {
47
65
  connected = true
48
66
  startTimestamp = Date.now()
49
- updatePresence()
67
+ await log("info", "Discord RPC connected", { user: rpc.user?.username })
68
+ await updatePresence()
50
69
  })
51
70
 
52
- client.login().catch(() => {
71
+ rpc.on("error", async (err: any) => {
72
+ await log("error", "Discord RPC error", { error: String(err) })
73
+ })
74
+
75
+ rpc.on("disconnected", async () => {
53
76
  connected = false
77
+ await log("warn", "Discord RPC disconnected")
54
78
  })
55
79
 
56
- return {
57
- "session.created": async () => {
58
- sessionActive = true
59
- startTimestamp = Date.now()
60
- lastEditedFile = undefined
61
- await updatePresence()
62
- },
80
+ try {
81
+ await log("info", "Attempting Discord RPC login...")
82
+ await rpc.login()
83
+ await log("info", "Discord RPC login successful")
84
+ } catch (e) {
85
+ connected = false
86
+ await log("error", "Discord RPC login failed", { error: String(e) })
87
+ }
63
88
 
64
- "session.updated": async ({ event }) => {
65
- sessionActive = true
66
- if (event.data?.project) {
67
- currentProject = event.data.project
89
+ return {
90
+ event: async ({ event }) => {
91
+ await log("debug", `Event received: ${event.type}`, { event })
92
+
93
+ switch (event.type) {
94
+ case "session.created":
95
+ sessionActive = true
96
+ startTimestamp = Date.now()
97
+ lastEditedFile = undefined
98
+ await log("info", "Session created")
99
+ break
100
+
101
+ case "session.idle":
102
+ case "session.error":
103
+ sessionActive = false
104
+ lastEditedFile = undefined
105
+ await log("info", `Session ${event.type}`)
106
+ break
107
+
108
+ case "session.deleted":
109
+ sessionActive = false
110
+ lastEditedFile = undefined
111
+ await log("info", "Session deleted")
112
+ break
113
+
114
+ case "file.edited":
115
+ lastEditedFile =
116
+ (event as any).file?.split("/").pop() ??
117
+ (event as any).file
118
+ await log("info", "File edited", { file: lastEditedFile })
119
+ break
68
120
  }
69
- await updatePresence()
70
- },
71
-
72
- "session.idle": async () => {
73
- sessionActive = false
74
- lastEditedFile = undefined
75
- await updatePresence()
76
- },
77
-
78
- "session.error": async () => {
79
- sessionActive = false
80
- await updatePresence()
81
- },
82
121
 
83
- "session.deleted": async () => {
84
- sessionActive = false
85
- lastEditedFile = undefined
86
122
  await updatePresence()
87
123
  },
88
124
 
89
- "file.edited": async ({ event }) => {
90
- if (event.data?.file) {
91
- lastEditedFile = event.data.file.split("/").pop() ?? event.data.file
92
- }
93
- await updatePresence()
94
- },
125
+ "tool.execute.after": async (input) => {
126
+ await log("debug", `Tool executed: ${input.tool}`, { args: input.args })
95
127
 
96
- "command.executed": async ({ event }) => {
97
- if (event.data?.command) {
98
- lastEditedFile = undefined
128
+ if (input.tool === "edit" || input.tool === "write") {
129
+ const path = input.args?.filePath as string | undefined
130
+ if (path) {
131
+ lastEditedFile = path.split("/").pop() ?? path
132
+ await log("info", "File tool detected", { file: lastEditedFile })
133
+ }
134
+ await updatePresence()
99
135
  }
100
- await updatePresence()
101
- },
102
-
103
- "session.diff": async () => {
104
- await updatePresence()
105
136
  },
106
137
  }
107
138
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-discord",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Discord Rich Presence plugin for OpenCode — shows your AI coding activity in Discord",
5
5
  "type": "module",
6
6
  "main": "index.ts",