opencode-discord 1.4.0 → 1.5.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.
- package/README.md +38 -0
- package/index.ts +82 -23
- package/package.json +3 -2
package/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# opencode-discord
|
|
2
|
+
|
|
3
|
+
Discord Rich Presence plugin for [OpenCode](https://opencode.ai). Shows your AI coding activity in Discord.
|
|
4
|
+
|
|
5
|
+
> **Note:** This project is not built by the OpenCode team and is not affiliated with them in any way.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Add to your `opencode.json`:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"plugin": ["opencode-discord"]
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Make sure Discord desktop is running. Your status will show contextual info like:
|
|
18
|
+
|
|
19
|
+
- **Waiting for response...** — AI is generating
|
|
20
|
+
- **Editing main.ts** — editing a file
|
|
21
|
+
- **Running terminal commands** — using bash
|
|
22
|
+
- **Reading config.json** — reading files
|
|
23
|
+
- **No active session** — idle
|
|
24
|
+
|
|
25
|
+
## Rich Presence Assets
|
|
26
|
+
|
|
27
|
+
Upload these assets to your [Discord Application](https://discord.com/developers/applications) under Rich Presence > Art Assets:
|
|
28
|
+
|
|
29
|
+
| Name | Description |
|
|
30
|
+
|------|-------------|
|
|
31
|
+
| `opencode` | Large image (main logo) |
|
|
32
|
+
| `thinking` | Small image (AI generating) |
|
|
33
|
+
| `active` | Small image (session active) |
|
|
34
|
+
| `idle` | Small image (idle) |
|
|
35
|
+
|
|
36
|
+
## License
|
|
37
|
+
|
|
38
|
+
MIT
|
package/index.ts
CHANGED
|
@@ -3,31 +3,60 @@ import { Client } from "@xhayper/discord-rpc"
|
|
|
3
3
|
|
|
4
4
|
const CLIENT_ID = process.env.DISCORD_CLIENT_ID ?? "1369345745815339008"
|
|
5
5
|
|
|
6
|
+
type Activity = "idle" | "thinking" | "editing" | "running" | "reading"
|
|
7
|
+
|
|
6
8
|
export const DiscordStatus: Plugin = async ({ project }) => {
|
|
7
9
|
const client = new Client({ clientId: CLIENT_ID })
|
|
8
10
|
let connected = false
|
|
9
11
|
let sessionActive = false
|
|
10
|
-
let currentProject = project?.name ?? ""
|
|
12
|
+
let currentProject = project?.name ?? "Unknown Project"
|
|
11
13
|
let startTimestamp = Date.now()
|
|
12
14
|
let lastEditedFile: string | undefined
|
|
15
|
+
let activity: Activity = "idle"
|
|
16
|
+
let sessionCount = 0
|
|
17
|
+
let lastTool: string | undefined
|
|
13
18
|
|
|
14
19
|
console.log(`[opencode-discord] init clientId=${CLIENT_ID} project=${currentProject}`)
|
|
15
20
|
|
|
16
21
|
async function updatePresence() {
|
|
17
|
-
console.log(`[opencode-discord] updatePresence connected=${connected} session=${sessionActive}`)
|
|
18
22
|
if (!connected) return
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
let details: string
|
|
25
|
+
let state: string
|
|
26
|
+
let smallImageKey: string
|
|
27
|
+
let smallImageText: string
|
|
28
|
+
|
|
29
|
+
if (!sessionActive) {
|
|
30
|
+
details = "No active session"
|
|
31
|
+
state = currentProject
|
|
32
|
+
smallImageKey = "idle"
|
|
33
|
+
smallImageText = "Idle"
|
|
34
|
+
} else {
|
|
35
|
+
switch (activity) {
|
|
36
|
+
case "thinking":
|
|
37
|
+
details = "Waiting for response..."
|
|
38
|
+
break
|
|
39
|
+
case "editing":
|
|
40
|
+
details = lastEditedFile
|
|
41
|
+
? `Editing ${lastEditedFile}`
|
|
42
|
+
: `Editing files`
|
|
43
|
+
break
|
|
44
|
+
case "running":
|
|
45
|
+
details = "Running terminal commands"
|
|
46
|
+
break
|
|
47
|
+
case "reading":
|
|
48
|
+
details = lastEditedFile
|
|
49
|
+
? `Reading ${lastEditedFile}`
|
|
50
|
+
: "Reading files"
|
|
51
|
+
break
|
|
52
|
+
default:
|
|
53
|
+
details = "Session active"
|
|
54
|
+
}
|
|
25
55
|
|
|
26
|
-
|
|
27
|
-
?
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
: "Idle"
|
|
56
|
+
state = currentProject
|
|
57
|
+
smallImageKey = activity === "thinking" ? "thinking" : "active"
|
|
58
|
+
smallImageText = activity === "thinking" ? "Generating" : "Active"
|
|
59
|
+
}
|
|
31
60
|
|
|
32
61
|
try {
|
|
33
62
|
await client.user?.setActivity({
|
|
@@ -35,11 +64,14 @@ export const DiscordStatus: Plugin = async ({ project }) => {
|
|
|
35
64
|
state,
|
|
36
65
|
startTimestamp,
|
|
37
66
|
largeImageKey: "opencode",
|
|
38
|
-
largeImageText:
|
|
39
|
-
smallImageKey
|
|
40
|
-
smallImageText
|
|
67
|
+
largeImageText: `OpenCode · ${sessionCount} session${sessionCount !== 1 ? "s" : ""}`,
|
|
68
|
+
smallImageKey,
|
|
69
|
+
smallImageText,
|
|
70
|
+
buttons: [
|
|
71
|
+
{ label: "OpenCode", url: "https://opencode.ai" },
|
|
72
|
+
],
|
|
41
73
|
})
|
|
42
|
-
console.log(`[opencode-discord] presence
|
|
74
|
+
console.log(`[opencode-discord] presence: ${details} / ${state}`)
|
|
43
75
|
} catch (e) {
|
|
44
76
|
console.error(`[opencode-discord] presence failed:`, e)
|
|
45
77
|
}
|
|
@@ -72,27 +104,37 @@ export const DiscordStatus: Plugin = async ({ project }) => {
|
|
|
72
104
|
|
|
73
105
|
return {
|
|
74
106
|
event: async ({ event }) => {
|
|
75
|
-
console.log(`[opencode-discord] event: ${event.type}`)
|
|
76
|
-
|
|
77
107
|
switch (event.type) {
|
|
78
108
|
case "session.created":
|
|
79
109
|
sessionActive = true
|
|
110
|
+
sessionCount++
|
|
80
111
|
startTimestamp = Date.now()
|
|
81
112
|
lastEditedFile = undefined
|
|
113
|
+
activity = "thinking"
|
|
82
114
|
break
|
|
83
115
|
|
|
84
116
|
case "session.idle":
|
|
117
|
+
sessionActive = true
|
|
118
|
+
activity = "idle"
|
|
119
|
+
break
|
|
120
|
+
|
|
85
121
|
case "session.error":
|
|
86
122
|
sessionActive = false
|
|
87
|
-
|
|
123
|
+
activity = "idle"
|
|
88
124
|
break
|
|
89
125
|
|
|
90
126
|
case "session.deleted":
|
|
91
127
|
sessionActive = false
|
|
92
128
|
lastEditedFile = undefined
|
|
129
|
+
activity = "idle"
|
|
130
|
+
break
|
|
131
|
+
|
|
132
|
+
case "session.compacted":
|
|
133
|
+
activity = "thinking"
|
|
93
134
|
break
|
|
94
135
|
|
|
95
136
|
case "file.edited":
|
|
137
|
+
activity = "editing"
|
|
96
138
|
lastEditedFile =
|
|
97
139
|
(event as any).file?.split("/").pop() ??
|
|
98
140
|
(event as any).file
|
|
@@ -102,14 +144,31 @@ export const DiscordStatus: Plugin = async ({ project }) => {
|
|
|
102
144
|
await updatePresence()
|
|
103
145
|
},
|
|
104
146
|
|
|
147
|
+
"tool.execute.before": async (input) => {
|
|
148
|
+
lastTool = input.tool
|
|
149
|
+
|
|
150
|
+
if (input.tool === "bash") {
|
|
151
|
+
activity = "running"
|
|
152
|
+
} else if (input.tool === "edit" || input.tool === "write") {
|
|
153
|
+
activity = "editing"
|
|
154
|
+
const path = input.args?.filePath as string | undefined
|
|
155
|
+
if (path) lastEditedFile = path.split("/").pop() ?? path
|
|
156
|
+
} else if (input.tool === "read") {
|
|
157
|
+
activity = "reading"
|
|
158
|
+
const path = input.args?.filePath as string | undefined
|
|
159
|
+
if (path) lastEditedFile = path.split("/").pop() ?? path
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
await updatePresence()
|
|
163
|
+
},
|
|
164
|
+
|
|
105
165
|
"tool.execute.after": async (input) => {
|
|
106
166
|
if (input.tool === "edit" || input.tool === "write") {
|
|
167
|
+
activity = "editing"
|
|
107
168
|
const path = input.args?.filePath as string | undefined
|
|
108
|
-
if (path)
|
|
109
|
-
lastEditedFile = path.split("/").pop() ?? path
|
|
110
|
-
}
|
|
111
|
-
await updatePresence()
|
|
169
|
+
if (path) lastEditedFile = path.split("/").pop() ?? path
|
|
112
170
|
}
|
|
171
|
+
await updatePresence()
|
|
113
172
|
},
|
|
114
173
|
}
|
|
115
174
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-discord",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.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",
|
|
7
7
|
"files": [
|
|
8
|
-
"index.ts"
|
|
8
|
+
"index.ts",
|
|
9
|
+
"README.md"
|
|
9
10
|
],
|
|
10
11
|
"keywords": [
|
|
11
12
|
"opencode",
|