opencode-discord-presence 0.1.5 → 0.2.0

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 (53) hide show
  1. package/dist/index.d.ts +9 -3
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +117 -3
  4. package/dist/index.js.map +1 -1
  5. package/package.json +1 -1
  6. package/dist/config.d.ts +0 -45
  7. package/dist/config.d.ts.map +0 -1
  8. package/dist/config.js +0 -65
  9. package/dist/config.js.map +0 -1
  10. package/dist/i18n/index.d.ts +0 -10
  11. package/dist/i18n/index.d.ts.map +0 -1
  12. package/dist/i18n/index.js +0 -32
  13. package/dist/i18n/index.js.map +0 -1
  14. package/dist/i18n/locales/en.d.ts +0 -3
  15. package/dist/i18n/locales/en.d.ts.map +0 -1
  16. package/dist/i18n/locales/en.js +0 -13
  17. package/dist/i18n/locales/en.js.map +0 -1
  18. package/dist/i18n/locales/ja.d.ts +0 -3
  19. package/dist/i18n/locales/ja.d.ts.map +0 -1
  20. package/dist/i18n/locales/ja.js +0 -13
  21. package/dist/i18n/locales/ja.js.map +0 -1
  22. package/dist/i18n/locales/ko.d.ts +0 -14
  23. package/dist/i18n/locales/ko.d.ts.map +0 -1
  24. package/dist/i18n/locales/ko.js +0 -14
  25. package/dist/i18n/locales/ko.js.map +0 -1
  26. package/dist/i18n/locales/zh.d.ts +0 -3
  27. package/dist/i18n/locales/zh.d.ts.map +0 -1
  28. package/dist/i18n/locales/zh.js +0 -13
  29. package/dist/i18n/locales/zh.js.map +0 -1
  30. package/dist/plugin.d.ts +0 -38
  31. package/dist/plugin.d.ts.map +0 -1
  32. package/dist/plugin.js +0 -144
  33. package/dist/plugin.js.map +0 -1
  34. package/dist/services/discord-rpc.d.ts +0 -83
  35. package/dist/services/discord-rpc.d.ts.map +0 -1
  36. package/dist/services/discord-rpc.js +0 -200
  37. package/dist/services/discord-rpc.js.map +0 -1
  38. package/dist/types/index.d.ts +0 -68
  39. package/dist/types/index.d.ts.map +0 -1
  40. package/dist/types/index.js +0 -6
  41. package/dist/types/index.js.map +0 -1
  42. package/dist/utils/format.d.ts +0 -45
  43. package/dist/utils/format.d.ts.map +0 -1
  44. package/dist/utils/format.js +0 -103
  45. package/dist/utils/format.js.map +0 -1
  46. package/dist/utils/particle.d.ts +0 -34
  47. package/dist/utils/particle.d.ts.map +0 -1
  48. package/dist/utils/particle.js +0 -83
  49. package/dist/utils/particle.js.map +0 -1
  50. package/dist/utils/project.d.ts +0 -32
  51. package/dist/utils/project.d.ts.map +0 -1
  52. package/dist/utils/project.js +0 -81
  53. package/dist/utils/project.js.map +0 -1
@@ -1,83 +0,0 @@
1
- /**
2
- * @fileoverview Discord RPC Service for Rich Presence
3
- * @module opencode-discord-presence/services/discord-rpc
4
- *
5
- * Provides a singleton service for managing Discord Rich Presence connection.
6
- * Features:
7
- * - Singleton pattern for single connection per application
8
- * - Automatic reconnection with exponential backoff
9
- * - Debounced presence updates to avoid rate limiting
10
- * - Event-driven connection management
11
- */
12
- import type { PresenceState } from "../types/index.js";
13
- /**
14
- * Singleton service for managing Discord Rich Presence
15
- *
16
- * @example
17
- * ```typescript
18
- * const rpc = DiscordRPCService.getInstance("your-client-id")
19
- * await rpc.connect()
20
- * await rpc.updatePresence({
21
- * details: "Working on project",
22
- * state: "Using Claude",
23
- * largeImageKey: "opencode-logo"
24
- * })
25
- * ```
26
- */
27
- export declare class DiscordRPCService {
28
- private static instance;
29
- private static currentClientId;
30
- private client;
31
- private _isConnected;
32
- private reconnectAttempts;
33
- private debounceTimer;
34
- private pendingPresence;
35
- /**
36
- * Private constructor - use getInstance() instead
37
- */
38
- private constructor();
39
- /**
40
- * Get the singleton instance of DiscordRPCService
41
- *
42
- * @param clientId - Discord Application ID
43
- * @returns The singleton instance
44
- */
45
- static getInstance(clientId: string): DiscordRPCService;
46
- /**
47
- * Reset the singleton instance (mainly for testing)
48
- */
49
- static resetInstance(): void;
50
- /**
51
- * Whether the service is currently connected to Discord
52
- */
53
- get isConnected(): boolean;
54
- /**
55
- * Set up event handlers for the Discord RPC client
56
- */
57
- private setupEventHandlers;
58
- /**
59
- * Attempt to reconnect with exponential backoff
60
- */
61
- private attemptReconnect;
62
- /**
63
- * Connect to Discord RPC
64
- *
65
- * @throws Error if connection fails and not retrying
66
- */
67
- connect(): Promise<void>;
68
- /**
69
- * Disconnect from Discord RPC
70
- */
71
- disconnect(): Promise<void>;
72
- /**
73
- * Update the Rich Presence with debouncing
74
- *
75
- * @param presence - The presence state to set
76
- */
77
- updatePresence(presence: PresenceState): Promise<void>;
78
- /**
79
- * Clear the Rich Presence
80
- */
81
- clearPresence(): Promise<void>;
82
- }
83
- //# sourceMappingURL=discord-rpc.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"discord-rpc.d.ts","sourceRoot":"","sources":["../../src/services/discord-rpc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAStD;;;;;;;;;;;;;GAaG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAiC;IACxD,OAAO,CAAC,MAAM,CAAC,eAAe,CAAsB;IAEpD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,aAAa,CAA6C;IAClE,OAAO,CAAC,eAAe,CAA2B;IAElD;;OAEG;IACH,OAAO;IAKP;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB;IAQvD;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI;IAQ5B;;OAEG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAc1B;;OAEG;YACW,gBAAgB;IAwB9B;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAe9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAcjC;;;;OAIG;IACG,cAAc,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAkC5D;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAgBrC"}
@@ -1,200 +0,0 @@
1
- /**
2
- * @fileoverview Discord RPC Service for Rich Presence
3
- * @module opencode-discord-presence/services/discord-rpc
4
- *
5
- * Provides a singleton service for managing Discord Rich Presence connection.
6
- * Features:
7
- * - Singleton pattern for single connection per application
8
- * - Automatic reconnection with exponential backoff
9
- * - Debounced presence updates to avoid rate limiting
10
- * - Event-driven connection management
11
- */
12
- import { Client } from "@xhayper/discord-rpc";
13
- /** Reconnection configuration */
14
- const RECONNECT_BASE_DELAY_MS = 5000;
15
- const RECONNECT_MAX_ATTEMPTS = 10;
16
- /** Debounce configuration */
17
- const DEBOUNCE_DELAY_MS = 100; // Short debounce for batching rapid updates
18
- /**
19
- * Singleton service for managing Discord Rich Presence
20
- *
21
- * @example
22
- * ```typescript
23
- * const rpc = DiscordRPCService.getInstance("your-client-id")
24
- * await rpc.connect()
25
- * await rpc.updatePresence({
26
- * details: "Working on project",
27
- * state: "Using Claude",
28
- * largeImageKey: "opencode-logo"
29
- * })
30
- * ```
31
- */
32
- export class DiscordRPCService {
33
- static instance = null;
34
- static currentClientId = null;
35
- client;
36
- _isConnected = false;
37
- reconnectAttempts = 0;
38
- debounceTimer = null;
39
- pendingPresence = null;
40
- /**
41
- * Private constructor - use getInstance() instead
42
- */
43
- constructor(clientId) {
44
- this.client = new Client({ clientId });
45
- this.setupEventHandlers();
46
- }
47
- /**
48
- * Get the singleton instance of DiscordRPCService
49
- *
50
- * @param clientId - Discord Application ID
51
- * @returns The singleton instance
52
- */
53
- static getInstance(clientId) {
54
- if (!DiscordRPCService.instance || DiscordRPCService.currentClientId !== clientId) {
55
- DiscordRPCService.instance = new DiscordRPCService(clientId);
56
- DiscordRPCService.currentClientId = clientId;
57
- }
58
- return DiscordRPCService.instance;
59
- }
60
- /**
61
- * Reset the singleton instance (mainly for testing)
62
- */
63
- static resetInstance() {
64
- if (DiscordRPCService.instance) {
65
- DiscordRPCService.instance.disconnect().catch(() => { });
66
- }
67
- DiscordRPCService.instance = null;
68
- DiscordRPCService.currentClientId = null;
69
- }
70
- /**
71
- * Whether the service is currently connected to Discord
72
- */
73
- get isConnected() {
74
- return this._isConnected;
75
- }
76
- /**
77
- * Set up event handlers for the Discord RPC client
78
- */
79
- setupEventHandlers() {
80
- this.client.on("ready", () => {
81
- console.log("[discord-rpc] Connected to Discord");
82
- this._isConnected = true;
83
- this.reconnectAttempts = 0;
84
- });
85
- this.client.on("disconnected", () => {
86
- console.log("[discord-rpc] Disconnected from Discord");
87
- this._isConnected = false;
88
- this.attemptReconnect();
89
- });
90
- }
91
- /**
92
- * Attempt to reconnect with exponential backoff
93
- */
94
- async attemptReconnect() {
95
- if (this.reconnectAttempts >= RECONNECT_MAX_ATTEMPTS) {
96
- console.warn(`[discord-rpc] Max reconnection attempts (${RECONNECT_MAX_ATTEMPTS}) reached. Giving up.`);
97
- return;
98
- }
99
- this.reconnectAttempts++;
100
- const delay = RECONNECT_BASE_DELAY_MS * 2 ** (this.reconnectAttempts - 1);
101
- console.log(`[discord-rpc] Attempting reconnect ${this.reconnectAttempts}/${RECONNECT_MAX_ATTEMPTS} in ${delay}ms`);
102
- await new Promise((resolve) => setTimeout(resolve, delay));
103
- try {
104
- await this.connect();
105
- }
106
- catch (error) {
107
- console.error("[discord-rpc] Reconnection failed:", error);
108
- }
109
- }
110
- /**
111
- * Connect to Discord RPC
112
- *
113
- * @throws Error if connection fails and not retrying
114
- */
115
- async connect() {
116
- if (this._isConnected) {
117
- return;
118
- }
119
- try {
120
- await this.client.login();
121
- this._isConnected = true;
122
- }
123
- catch (error) {
124
- console.warn("[discord-rpc] Failed to connect:", error);
125
- // Don't throw - Discord might not be running
126
- this._isConnected = false;
127
- }
128
- }
129
- /**
130
- * Disconnect from Discord RPC
131
- */
132
- async disconnect() {
133
- if (this.debounceTimer) {
134
- clearTimeout(this.debounceTimer);
135
- this.debounceTimer = null;
136
- }
137
- try {
138
- await this.client.destroy();
139
- }
140
- catch (_error) {
141
- // Ignore errors during disconnect
142
- }
143
- this._isConnected = false;
144
- }
145
- /**
146
- * Update the Rich Presence with debouncing
147
- *
148
- * @param presence - The presence state to set
149
- */
150
- async updatePresence(presence) {
151
- if (!this._isConnected || !this.client.user) {
152
- return;
153
- }
154
- // Store pending presence and debounce
155
- this.pendingPresence = {
156
- details: presence.details,
157
- state: presence.state,
158
- startTimestamp: presence.startTimestamp,
159
- largeImageKey: presence.largeImageKey,
160
- largeImageText: presence.largeImageText,
161
- smallImageKey: presence.smallImageKey,
162
- smallImageText: presence.smallImageText,
163
- };
164
- // Clear existing debounce timer
165
- if (this.debounceTimer) {
166
- clearTimeout(this.debounceTimer);
167
- }
168
- // Set new debounce timer
169
- this.debounceTimer = setTimeout(async () => {
170
- if (this.pendingPresence && this._isConnected && this.client.user) {
171
- try {
172
- await this.client.user.setActivity(this.pendingPresence);
173
- }
174
- catch (error) {
175
- console.warn("[discord-rpc] Failed to update presence:", error);
176
- }
177
- }
178
- this.pendingPresence = null;
179
- }, DEBOUNCE_DELAY_MS);
180
- }
181
- /**
182
- * Clear the Rich Presence
183
- */
184
- async clearPresence() {
185
- if (!this._isConnected || !this.client.user) {
186
- return;
187
- }
188
- if (this.debounceTimer) {
189
- clearTimeout(this.debounceTimer);
190
- this.debounceTimer = null;
191
- }
192
- try {
193
- await this.client.user.clearActivity();
194
- }
195
- catch (error) {
196
- console.warn("[discord-rpc] Failed to clear presence:", error);
197
- }
198
- }
199
- }
200
- //# sourceMappingURL=discord-rpc.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"discord-rpc.js","sourceRoot":"","sources":["../../src/services/discord-rpc.ts"],"names":[],"mappings":"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"}
@@ -1,68 +0,0 @@
1
- /**
2
- * @fileoverview Type definitions for OpenCode Discord Presence plugin
3
- * @module opencode-discord-presence/types
4
- */
5
- /**
6
- * Supported languages for the plugin UI
7
- * - "auto": Detect from system locale
8
- * - "ko": Korean
9
- * - "en": English
10
- * - "ja": Japanese
11
- * - "zh": Chinese (Simplified)
12
- */
13
- export type SupportedLanguage = "auto" | "ko" | "en" | "ja" | "zh";
14
- /**
15
- * Configuration options for the Discord Rich Presence plugin
16
- */
17
- export interface DiscordPresenceConfig {
18
- /** Whether the plugin is enabled */
19
- enabled: boolean;
20
- /** Discord Application ID for Rich Presence */
21
- applicationId: string;
22
- /** Show elapsed time since session started */
23
- showSessionTime: boolean;
24
- /** Show token usage count */
25
- showTokenUsage: boolean;
26
- /** Show current project name */
27
- showProjectName: boolean;
28
- /** Language for presence messages (default: "auto") */
29
- language: SupportedLanguage;
30
- }
31
- /**
32
- * Token count structure for tracking usage
33
- */
34
- export interface TokenCount {
35
- /** Input tokens consumed */
36
- input: number;
37
- /** Output tokens generated */
38
- output: number;
39
- }
40
- /**
41
- * Model information from OpenCode
42
- */
43
- export interface ModelInfo {
44
- /** Provider ID (e.g., "anthropic", "openai") */
45
- providerID: string;
46
- /** Model ID (e.g., "claude-sonnet-4-20250514") */
47
- modelID: string;
48
- }
49
- /**
50
- * Presence state for Discord Rich Presence
51
- */
52
- export interface PresenceState {
53
- /** Main text line (details) */
54
- details: string;
55
- /** Secondary text line (state) */
56
- state?: string;
57
- /** Timestamp when activity started */
58
- startTimestamp?: number;
59
- /** Large image asset key */
60
- largeImageKey: string;
61
- /** Tooltip for large image */
62
- largeImageText?: string;
63
- /** Small image asset key */
64
- smallImageKey?: string;
65
- /** Tooltip for small image */
66
- smallImageText?: string;
67
- }
68
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAElE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,oCAAoC;IACpC,OAAO,EAAE,OAAO,CAAA;IAChB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,CAAA;IACrB,8CAA8C;IAC9C,eAAe,EAAE,OAAO,CAAA;IACxB,6BAA6B;IAC7B,cAAc,EAAE,OAAO,CAAA;IACvB,gCAAgC;IAChC,eAAe,EAAE,OAAO,CAAA;IACxB,uDAAuD;IACvD,QAAQ,EAAE,iBAAiB,CAAA;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAA;IAClB,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,sCAAsC;IACtC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,4BAA4B;IAC5B,aAAa,EAAE,MAAM,CAAA;IACrB,8BAA8B;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,4BAA4B;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,8BAA8B;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB"}
@@ -1,6 +0,0 @@
1
- /**
2
- * @fileoverview Type definitions for OpenCode Discord Presence plugin
3
- * @module opencode-discord-presence/types
4
- */
5
- export {};
6
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -1,45 +0,0 @@
1
- /**
2
- * @fileoverview Formatting utilities for tokens and model names
3
- * @module opencode-discord-presence/utils/format
4
- *
5
- * Provides formatting functions for displaying token counts and model names
6
- * in a user-friendly way for Discord Rich Presence.
7
- */
8
- import type { ModelInfo, TokenCount } from "../types/index.js";
9
- /**
10
- * Format token count for display
11
- *
12
- * @param tokens - Token count object with input and output
13
- * @returns Formatted string like "12.5k tokens" or "700 tokens"
14
- *
15
- * @example
16
- * ```typescript
17
- * formatTokens({ input: 8200, output: 4300 }) // "12.5k tokens"
18
- * formatTokens({ input: 500, output: 200 }) // "700 tokens"
19
- * formatTokens({ input: 0, output: 0 }) // "0 tokens"
20
- * ```
21
- */
22
- export declare function formatTokens(tokens: TokenCount): string;
23
- /**
24
- * Format model name for display
25
- *
26
- * Converts model IDs like "claude-sonnet-4-20250514" to human-readable
27
- * names like "Claude Sonnet 4".
28
- *
29
- * @param model - Model info with providerID and modelID
30
- * @returns Human-readable model name
31
- *
32
- * @example
33
- * ```typescript
34
- * formatModelName({ providerID: "anthropic", modelID: "claude-sonnet-4-20250514" })
35
- * // "Claude Sonnet 4"
36
- *
37
- * formatModelName({ providerID: "openai", modelID: "gpt-4o" })
38
- * // "GPT-4o"
39
- *
40
- * formatModelName({ providerID: "unknown", modelID: "custom-model" })
41
- * // "custom-model"
42
- * ```
43
- */
44
- export declare function formatModelName(model: ModelInfo | undefined): string;
45
- //# sourceMappingURL=format.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9D;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAevD;AAgCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAuBpE"}
@@ -1,103 +0,0 @@
1
- /**
2
- * @fileoverview Formatting utilities for tokens and model names
3
- * @module opencode-discord-presence/utils/format
4
- *
5
- * Provides formatting functions for displaying token counts and model names
6
- * in a user-friendly way for Discord Rich Presence.
7
- */
8
- /**
9
- * Format token count for display
10
- *
11
- * @param tokens - Token count object with input and output
12
- * @returns Formatted string like "12.5k tokens" or "700 tokens"
13
- *
14
- * @example
15
- * ```typescript
16
- * formatTokens({ input: 8200, output: 4300 }) // "12.5k tokens"
17
- * formatTokens({ input: 500, output: 200 }) // "700 tokens"
18
- * formatTokens({ input: 0, output: 0 }) // "0 tokens"
19
- * ```
20
- */
21
- export function formatTokens(tokens) {
22
- const total = tokens.input + tokens.output;
23
- if (total === 0) {
24
- return "0 tokens";
25
- }
26
- if (total >= 1000) {
27
- const k = total / 1000;
28
- // Round to 1 decimal place
29
- const rounded = Math.round(k * 10) / 10;
30
- return `${rounded}k tokens`;
31
- }
32
- return `${total} tokens`;
33
- }
34
- /**
35
- * Model name mappings for common providers
36
- */
37
- const MODEL_NAME_MAPPINGS = {
38
- anthropic: {
39
- "claude-opus-4-20250514": "Claude Opus 4",
40
- "claude-sonnet-4-20250514": "Claude Sonnet 4",
41
- "claude-3-5-sonnet-20241022": "Claude 3.5 Sonnet",
42
- "claude-3-5-haiku-20241022": "Claude 3.5 Haiku",
43
- "claude-3-opus-20240229": "Claude 3 Opus",
44
- "claude-3-sonnet-20240229": "Claude 3 Sonnet",
45
- "claude-3-haiku-20240307": "Claude 3 Haiku",
46
- },
47
- openai: {
48
- "gpt-4o": "GPT-4o",
49
- "gpt-4o-mini": "GPT-4o Mini",
50
- "gpt-4-turbo": "GPT-4 Turbo",
51
- "gpt-4": "GPT-4",
52
- "gpt-3.5-turbo": "GPT-3.5 Turbo",
53
- o1: "o1",
54
- "o1-mini": "o1 Mini",
55
- "o1-preview": "o1 Preview",
56
- },
57
- google: {
58
- "gemini-2.0-flash": "Gemini 2.0 Flash",
59
- "gemini-1.5-pro": "Gemini 1.5 Pro",
60
- "gemini-1.5-flash": "Gemini 1.5 Flash",
61
- },
62
- };
63
- /**
64
- * Format model name for display
65
- *
66
- * Converts model IDs like "claude-sonnet-4-20250514" to human-readable
67
- * names like "Claude Sonnet 4".
68
- *
69
- * @param model - Model info with providerID and modelID
70
- * @returns Human-readable model name
71
- *
72
- * @example
73
- * ```typescript
74
- * formatModelName({ providerID: "anthropic", modelID: "claude-sonnet-4-20250514" })
75
- * // "Claude Sonnet 4"
76
- *
77
- * formatModelName({ providerID: "openai", modelID: "gpt-4o" })
78
- * // "GPT-4o"
79
- *
80
- * formatModelName({ providerID: "unknown", modelID: "custom-model" })
81
- * // "custom-model"
82
- * ```
83
- */
84
- export function formatModelName(model) {
85
- if (!model) {
86
- return "Unknown Model";
87
- }
88
- const { providerID, modelID } = model;
89
- const providerMappings = MODEL_NAME_MAPPINGS[providerID];
90
- if (providerMappings?.[modelID]) {
91
- return providerMappings[modelID];
92
- }
93
- // Try to make the model ID more readable
94
- // Remove version suffixes like -20250514
95
- let readable = modelID.replace(/-\d{8}$/, "");
96
- // Capitalize first letter of each word
97
- readable = readable
98
- .split("-")
99
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
100
- .join(" ");
101
- return readable || modelID;
102
- }
103
- //# sourceMappingURL=format.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,MAAkB;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAA;IAE1C,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,MAAM,CAAC,GAAG,KAAK,GAAG,IAAI,CAAA;QACtB,2BAA2B;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAA;QACvC,OAAO,GAAG,OAAO,UAAU,CAAA;IAC7B,CAAC;IAED,OAAO,GAAG,KAAK,SAAS,CAAA;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,mBAAmB,GAA2C;IAClE,SAAS,EAAE;QACT,wBAAwB,EAAE,eAAe;QACzC,0BAA0B,EAAE,iBAAiB;QAC7C,4BAA4B,EAAE,mBAAmB;QACjD,2BAA2B,EAAE,kBAAkB;QAC/C,wBAAwB,EAAE,eAAe;QACzC,0BAA0B,EAAE,iBAAiB;QAC7C,yBAAyB,EAAE,gBAAgB;KAC5C;IACD,MAAM,EAAE;QACN,QAAQ,EAAE,QAAQ;QAClB,aAAa,EAAE,aAAa;QAC5B,aAAa,EAAE,aAAa;QAC5B,OAAO,EAAE,OAAO;QAChB,eAAe,EAAE,eAAe;QAChC,EAAE,EAAE,IAAI;QACR,SAAS,EAAE,SAAS;QACpB,YAAY,EAAE,YAAY;KAC3B;IACD,MAAM,EAAE;QACN,kBAAkB,EAAE,kBAAkB;QACtC,gBAAgB,EAAE,gBAAgB;QAClC,kBAAkB,EAAE,kBAAkB;KACvC;CACF,CAAA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAAC,KAA4B;IAC1D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,eAAe,CAAA;IACxB,CAAC;IAED,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,KAAK,CAAA;IACrC,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAA;IAExD,IAAI,gBAAgB,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAClC,CAAC;IAED,yCAAyC;IACzC,yCAAyC;IACzC,IAAI,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;IAE7C,uCAAuC;IACvC,QAAQ,GAAG,QAAQ;SAChB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,GAAG,CAAC,CAAA;IAEZ,OAAO,QAAQ,IAAI,OAAO,CAAA;AAC5B,CAAC"}
@@ -1,34 +0,0 @@
1
- /**
2
- * @fileoverview Korean particle utility for proper grammar
3
- * @module opencode-discord-presence/utils/particle
4
- *
5
- * Korean particles (조사) change based on whether the preceding syllable
6
- * ends with a consonant (받침) or not.
7
- *
8
- * - 을/를 (object marker): 을 after 받침, 를 after no 받침
9
- * - 은/는 (topic marker): 은 after 받침, 는 after no 받침
10
- *
11
- * @example
12
- * ```typescript
13
- * withParticle("빌드", "을/를") // "빌드를" (ㄷ has 받침)
14
- * withParticle("프로메테우스", "을/를") // "프로메테우스를" (스 has no 받침)
15
- * withParticle("oracle", "은/는") // "oracle은" (e is consonant-like)
16
- * ```
17
- */
18
- /** Supported particle types */
19
- export type ParticleType = "을/를" | "은/는";
20
- /**
21
- * Adds the correct Korean particle to a word based on its final character
22
- *
23
- * @param word - The word to add a particle to
24
- * @param particle - The particle type ("을/를" or "은/는")
25
- * @returns The word with the correct particle appended
26
- *
27
- * @example
28
- * ```typescript
29
- * withParticle("Prometheus", "을/를") // "Prometheus를"
30
- * withParticle("build", "은/는") // "build는"
31
- * ```
32
- */
33
- export declare function withParticle(word: string, particle: ParticleType): string;
34
- //# sourceMappingURL=particle.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"particle.d.ts","sourceRoot":"","sources":["../../src/utils/particle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,+BAA+B;AAC/B,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,KAAK,CAAA;AAExC;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,MAAM,CAOzE"}
@@ -1,83 +0,0 @@
1
- /**
2
- * @fileoverview Korean particle utility for proper grammar
3
- * @module opencode-discord-presence/utils/particle
4
- *
5
- * Korean particles (조사) change based on whether the preceding syllable
6
- * ends with a consonant (받침) or not.
7
- *
8
- * - 을/를 (object marker): 을 after 받침, 를 after no 받침
9
- * - 은/는 (topic marker): 은 after 받침, 는 after no 받침
10
- *
11
- * @example
12
- * ```typescript
13
- * withParticle("빌드", "을/를") // "빌드를" (ㄷ has 받침)
14
- * withParticle("프로메테우스", "을/를") // "프로메테우스를" (스 has no 받침)
15
- * withParticle("oracle", "은/는") // "oracle은" (e is consonant-like)
16
- * ```
17
- */
18
- /**
19
- * Adds the correct Korean particle to a word based on its final character
20
- *
21
- * @param word - The word to add a particle to
22
- * @param particle - The particle type ("을/를" or "은/는")
23
- * @returns The word with the correct particle appended
24
- *
25
- * @example
26
- * ```typescript
27
- * withParticle("Prometheus", "을/를") // "Prometheus를"
28
- * withParticle("build", "은/는") // "build는"
29
- * ```
30
- */
31
- export function withParticle(word, particle) {
32
- const hasBatchim = checkBatchim(word);
33
- if (particle === "을/를") {
34
- return word + (hasBatchim ? "을" : "를");
35
- }
36
- return word + (hasBatchim ? "은" : "는");
37
- }
38
- /**
39
- * Checks if the last character of a word has a 받침 (final consonant)
40
- *
41
- * For Korean characters (Hangul), we check if the Unicode code point
42
- * indicates a final consonant. Korean syllables in Unicode are structured as:
43
- * (initial * 21 + medial) * 28 + final + 0xAC00
44
- * where final = 0 means no 받침.
45
- *
46
- * For English and other characters, we use a heuristic based on
47
- * whether the character sounds like it ends with a consonant.
48
- *
49
- * @param word - The word to check
50
- * @returns true if the last character has a 받침-like ending
51
- */
52
- function checkBatchim(word) {
53
- if (word.length === 0) {
54
- return false;
55
- }
56
- const lastChar = word.charAt(word.length - 1);
57
- const code = lastChar.charCodeAt(0);
58
- // Korean Hangul syllables range: 0xAC00 (가) to 0xD7A3 (힣)
59
- if (code >= 0xac00 && code <= 0xd7a3) {
60
- // Korean syllable structure: (initial * 21 + medial) * 28 + final + 0xAC00
61
- // final = 0 means no 받침
62
- return (code - 0xac00) % 28 !== 0;
63
- }
64
- // For numbers, check if it's a digit that sounds like it ends with a consonant
65
- // 1(일), 3(삼), 6(육), 7(칠), 8(팔), 0(영/공) have 받침
66
- if (/[0-9]/.test(lastChar)) {
67
- return ["1", "3", "6", "7", "8", "0"].includes(lastChar);
68
- }
69
- // For English/Latin characters, consonants that typically sound like 받침
70
- // when pronounced in Korean context:
71
- // - l, m, n, ng, r (liquid/nasal sounds) -> 받침
72
- // - b, c, d, g, k, p, t (stop consonants) -> 받침
73
- // - vowels (a, e, i, o, u) -> no 받침
74
- // - s, x, z -> can be either, but typically no 받침 in Korean pronunciation
75
- const consonantsWithBatchim = "lmnrbcdgkpt";
76
- const lowerChar = lastChar.toLowerCase();
77
- if (/[a-z]/i.test(lastChar)) {
78
- return consonantsWithBatchim.includes(lowerChar);
79
- }
80
- // Default: no 받침 for other characters
81
- return false;
82
- }
83
- //# sourceMappingURL=particle.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"particle.js","sourceRoot":"","sources":["../../src/utils/particle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,QAAsB;IAC/D,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;IAErC,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;QACvB,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACxC,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;AACxC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;IAEnC,0DAA0D;IAC1D,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC;QACrC,2EAA2E;QAC3E,wBAAwB;QACxB,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACnC,CAAC;IAED,+EAA+E;IAC/E,+CAA+C;IAC/C,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC1D,CAAC;IAED,wEAAwE;IACxE,qCAAqC;IACrC,+CAA+C;IAC/C,gDAAgD;IAChD,oCAAoC;IACpC,0EAA0E;IAC1E,MAAM,qBAAqB,GAAG,aAAa,CAAA;IAC3C,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAA;IAExC,IAAI,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,OAAO,qBAAqB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;IAClD,CAAC;IAED,sCAAsC;IACtC,OAAO,KAAK,CAAA;AACd,CAAC"}