@icaruk/zai-peak-hours 0.0.1 → 0.0.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 +19 -59
- package/dist/index.d.ts +2 -7
- package/dist/index.js +93 -82
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
# @icaruk/zai-peak-hours
|
|
2
2
|
|
|
3
|
-
OpenCode
|
|
3
|
+
OpenCode plugin that displays z.ai peak hours information with automatic timezone detection via toast notifications.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
Add
|
|
7
|
+
Add to your `~/.config/opencode/opencode.json`:
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
```jsonc
|
|
9
|
+
```json
|
|
11
10
|
{
|
|
12
11
|
"plugin": ["@icaruk/zai-peak-hours"]
|
|
13
12
|
}
|
|
14
13
|
```
|
|
15
14
|
|
|
16
|
-
**Local development (before npm publication):**
|
|
17
|
-
```jsonc
|
|
18
|
-
{
|
|
19
|
-
"plugin": ["file://D:/Dev/zai-peak-hours/dist/index.js"]
|
|
20
|
-
}
|
|
21
|
-
```
|
|
22
|
-
|
|
23
15
|
## Features
|
|
24
16
|
|
|
25
17
|
- 🌍 Automatic timezone detection (UTC+8 / Asia/Shanghai)
|
|
@@ -29,51 +21,14 @@ Add this to your `~/.config/opencode/tui.json`:
|
|
|
29
21
|
- ⚙️ Configurable update interval
|
|
30
22
|
- 🛠️ Manual commands for on-demand status checks
|
|
31
23
|
|
|
32
|
-
## TUI vs Regular Plugins
|
|
33
|
-
|
|
34
|
-
This is a **TUI plugin** (runs in the OpenCode client/terminal UI), not a regular server-side plugin.
|
|
35
|
-
|
|
36
|
-
| | TUI Plugin (this) | Regular Plugin |
|
|
37
|
-
| ------------- | ------------------------ | -------------------------- |
|
|
38
|
-
| **Config** | `tui.json` | `opencode.jsonc` |
|
|
39
|
-
| **Dónde corre** | Client/TUI | Server/backend |
|
|
40
|
-
| **Acceso UI** | Sí (toasts, comandos) | No |
|
|
41
|
-
| **Custom tools** | No | Sí |
|
|
42
|
-
| **Hook en tools** | No | Sí |
|
|
43
|
-
|
|
44
|
-
TUI plugins can display toasts, register slash commands, and show UI elements directly in the terminal.
|
|
45
|
-
|
|
46
24
|
## Commands
|
|
47
25
|
|
|
48
26
|
- `/peak_hours` - Display current peak hours status
|
|
49
27
|
- `/peak_hours_status` - Display plugin diagnostics and configuration
|
|
50
28
|
|
|
51
|
-
## Configuration
|
|
52
|
-
|
|
53
|
-
Configuration is optional - the plugin works out of the box.
|
|
54
|
-
|
|
55
|
-
To customize, create `~/.config/opencode/peak-hours.json`:
|
|
56
|
-
|
|
57
|
-
```json
|
|
58
|
-
{
|
|
59
|
-
"enabled": true,
|
|
60
|
-
"updateIntervalMinutes": 15
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Options
|
|
65
|
-
|
|
66
|
-
- `enabled` (boolean, default: `true`) - Enable or disable the plugin
|
|
67
|
-
- `updateIntervalMinutes` (number, default: `15`) - Update interval in minutes
|
|
68
|
-
|
|
69
|
-
## Peak Hours Schedule
|
|
70
|
-
|
|
71
|
-
- **Peak Hours**: 14:00-18:00 UTC+8 (Asia/Shanghai timezone)
|
|
72
|
-
- **Off-Peak Hours**: All other times
|
|
73
|
-
|
|
74
29
|
## Messages
|
|
75
30
|
|
|
76
|
-
The plugin displays toast notifications
|
|
31
|
+
The plugin displays toast notifications:
|
|
77
32
|
|
|
78
33
|
**Peak Hours:**
|
|
79
34
|
```
|
|
@@ -87,30 +42,35 @@ Currently in off-peak hours. X hours Y minutes remaining
|
|
|
87
42
|
|
|
88
43
|
## Development
|
|
89
44
|
|
|
90
|
-
For local development and testing:
|
|
91
|
-
|
|
92
45
|
```bash
|
|
93
|
-
# Clone
|
|
46
|
+
# Clone
|
|
94
47
|
git clone https://github.com/Icaruk/zai-peak-hours.git
|
|
95
48
|
cd zai-peak-hours
|
|
96
49
|
|
|
97
|
-
# Install
|
|
50
|
+
# Install
|
|
98
51
|
npm install
|
|
99
52
|
|
|
100
|
-
# Build
|
|
53
|
+
# Build
|
|
101
54
|
npm run build
|
|
102
55
|
|
|
103
|
-
#
|
|
56
|
+
# Watch
|
|
104
57
|
npm run dev
|
|
105
58
|
```
|
|
106
59
|
|
|
107
|
-
|
|
108
|
-
|
|
60
|
+
Add local config in `opencode.json`
|
|
61
|
+
|
|
62
|
+
```json
|
|
109
63
|
{
|
|
110
|
-
"plugin": [
|
|
64
|
+
"plugin": [
|
|
65
|
+
"file:///D:/Dev/zai-peak-hours/dist/index.js"
|
|
66
|
+
]
|
|
111
67
|
}
|
|
112
68
|
```
|
|
113
69
|
|
|
70
|
+
## npm package
|
|
71
|
+
|
|
72
|
+
https://www.npmjs.com/package/@icaruk/zai-peak-hours
|
|
73
|
+
|
|
114
74
|
## License
|
|
115
75
|
|
|
116
76
|
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
declare function tui(api: TuiPluginApi, options: PluginOptions | undefined, meta: TuiPluginMeta): Promise<void>;
|
|
4
|
-
declare const plugin: {
|
|
5
|
-
id: string;
|
|
6
|
-
tui: typeof tui;
|
|
7
|
-
};
|
|
1
|
+
import type { Plugin } from '@opencode-ai/plugin';
|
|
2
|
+
export declare const plugin: Plugin;
|
|
8
3
|
export default plugin;
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { tool } from '@opencode-ai/plugin';
|
|
1
2
|
import { getPeakHoursStatus, formatPeakHoursMessage } from './peak-hours';
|
|
2
3
|
import { DEFAULT_CONFIG } from './config';
|
|
3
4
|
import * as fs from 'fs';
|
|
4
5
|
import * as path from 'path';
|
|
5
6
|
let timerId = null;
|
|
6
|
-
let pluginLoaded = false;
|
|
7
7
|
let configCache = null;
|
|
8
8
|
function getConfigPath() {
|
|
9
9
|
const configDir = process.env.XDG_CONFIG_HOME
|
|
@@ -33,105 +33,116 @@ function loadConfig() {
|
|
|
33
33
|
configCache = DEFAULT_CONFIG;
|
|
34
34
|
return configCache;
|
|
35
35
|
}
|
|
36
|
-
function showPeakHoursToast(
|
|
36
|
+
async function showPeakHoursToast(client) {
|
|
37
37
|
const config = loadConfig();
|
|
38
38
|
if (!config.enabled) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
await client.tui.showToast({
|
|
40
|
+
body: {
|
|
41
|
+
message: 'Peak Hours plugin is disabled in config',
|
|
42
|
+
variant: 'info',
|
|
43
|
+
duration: 3000
|
|
44
|
+
}
|
|
42
45
|
});
|
|
43
46
|
return;
|
|
44
47
|
}
|
|
45
48
|
const status = getPeakHoursStatus();
|
|
46
49
|
const message = formatPeakHoursMessage(status);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
await client.tui.showToast({
|
|
51
|
+
body: {
|
|
52
|
+
message,
|
|
53
|
+
variant: status.inPeakHours ? 'warning' : 'info',
|
|
54
|
+
duration: 5000
|
|
55
|
+
}
|
|
50
56
|
});
|
|
51
57
|
}
|
|
52
|
-
function showDiagnostics(
|
|
58
|
+
async function showDiagnostics(client) {
|
|
53
59
|
const config = loadConfig();
|
|
54
60
|
const status = getPeakHoursStatus();
|
|
55
61
|
const currentTime = new Date().toISOString();
|
|
56
|
-
const diagnostics =
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
const diagnostics = `=== Peak Hours Plugin Diagnostics ===
|
|
63
|
+
Plugin enabled: ${config.enabled}
|
|
64
|
+
Update interval: ${config.updateIntervalMinutes} minutes
|
|
65
|
+
Current time: ${currentTime}
|
|
66
|
+
In peak hours: ${status.inPeakHours}
|
|
67
|
+
Time until ${status.transitionType}: ${status.timeUntilTransition}
|
|
68
|
+
====================================`;
|
|
69
|
+
await client.tui.showToast({
|
|
70
|
+
body: {
|
|
71
|
+
message: diagnostics,
|
|
72
|
+
variant: 'info',
|
|
73
|
+
duration: 8000
|
|
74
|
+
}
|
|
69
75
|
});
|
|
70
76
|
}
|
|
71
|
-
async
|
|
72
|
-
pluginLoaded = true;
|
|
77
|
+
export const plugin = async ({ client }) => {
|
|
73
78
|
const config = loadConfig();
|
|
74
|
-
const updateInterval = config.updateIntervalMinutes * 60 * 1000;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
const updateInterval = config.updateIntervalMinutes * 60 * 1000;
|
|
80
|
+
await client.tui.showToast({
|
|
81
|
+
body: {
|
|
82
|
+
message: 'Peak Hours Plugin loaded successfully',
|
|
83
|
+
variant: 'info',
|
|
84
|
+
duration: 3000
|
|
85
|
+
}
|
|
79
86
|
});
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
description: 'Display current peak hours status
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
return {
|
|
88
|
+
config: async (input) => {
|
|
89
|
+
input.command ?? (input.command = {});
|
|
90
|
+
input.command['peak_hours'] = {
|
|
91
|
+
template: '/peak_hours',
|
|
92
|
+
description: 'Display current peak hours status'
|
|
93
|
+
};
|
|
94
|
+
input.command['peak_hours_status'] = {
|
|
95
|
+
template: '/peak_hours_status',
|
|
96
|
+
description: 'Display peak hours plugin diagnostics'
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
'tool.execute.after': async (input) => {
|
|
100
|
+
if (!config.enabled) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (input.tool === 'peak_hours') {
|
|
104
|
+
await showPeakHoursToast(client);
|
|
105
|
+
}
|
|
106
|
+
else if (input.tool === 'peak_hours_status') {
|
|
107
|
+
await showDiagnostics(client);
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
'session.created': async () => {
|
|
111
|
+
if (!config.enabled) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
await showPeakHoursToast(client);
|
|
115
|
+
timerId = setInterval(async () => {
|
|
116
|
+
await showPeakHoursToast(client);
|
|
117
|
+
}, updateInterval);
|
|
118
|
+
},
|
|
119
|
+
tool: {
|
|
120
|
+
'peak_hours': tool({
|
|
121
|
+
description: 'Display current z.ai peak hours status and time until next transition',
|
|
122
|
+
args: {},
|
|
123
|
+
async execute(_args, context) {
|
|
124
|
+
const status = getPeakHoursStatus();
|
|
125
|
+
const message = formatPeakHoursMessage(status);
|
|
126
|
+
return `Peak Hours Status:\n${message}\n\nIn peak hours: ${status.inPeakHours}\nTime until ${status.transitionType}: ${status.timeUntilTransition}`;
|
|
92
127
|
}
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
128
|
+
}),
|
|
129
|
+
'peak_hours_status': tool({
|
|
130
|
+
description: 'Display peak hours plugin diagnostics and configuration status',
|
|
131
|
+
args: {},
|
|
132
|
+
async execute(_args, context) {
|
|
133
|
+
const config = loadConfig();
|
|
134
|
+
const status = getPeakHoursStatus();
|
|
135
|
+
const currentTime = new Date().toISOString();
|
|
136
|
+
return `=== Peak Hours Plugin Diagnostics ===
|
|
137
|
+
Plugin enabled: ${config.enabled}
|
|
138
|
+
Update interval: ${config.updateIntervalMinutes} minutes
|
|
139
|
+
Current time: ${currentTime}
|
|
140
|
+
In peak hours: ${status.inPeakHours}
|
|
141
|
+
Time until ${status.transitionType}: ${status.timeUntilTransition}
|
|
142
|
+
====================================`;
|
|
104
143
|
}
|
|
105
|
-
}
|
|
106
|
-
];
|
|
107
|
-
api.command.register(() => commands);
|
|
108
|
-
}
|
|
109
|
-
catch (error) {
|
|
110
|
-
api.ui.toast({
|
|
111
|
-
message: `Error registering peak_hours commands: ${error}`,
|
|
112
|
-
duration: 5000
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
if (!config.enabled) {
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const unsubscribe = api.event.on('session.created', () => {
|
|
119
|
-
showPeakHoursToast(api);
|
|
120
|
-
timerId = setInterval(() => {
|
|
121
|
-
showPeakHoursToast(api);
|
|
122
|
-
}, updateInterval);
|
|
123
|
-
});
|
|
124
|
-
api.lifecycle.onDispose(() => {
|
|
125
|
-
unsubscribe();
|
|
126
|
-
if (timerId) {
|
|
127
|
-
clearInterval(timerId);
|
|
128
|
-
timerId = null;
|
|
144
|
+
})
|
|
129
145
|
}
|
|
130
|
-
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
const plugin = {
|
|
134
|
-
id: "icaruk.peak-hours",
|
|
135
|
-
tui
|
|
146
|
+
};
|
|
136
147
|
};
|
|
137
148
|
export default plugin;
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@icaruk/zai-peak-hours",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OpenCode plugin to display z.ai peak hours information with automatic timezone detection",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
-
"tui": "dist/index.js",
|
|
9
8
|
"exports": {
|
|
10
9
|
".": {
|
|
11
10
|
"import": "./dist/index.js",
|