poi-plugin-mcp 0.2.16 → 0.2.21

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.
@@ -26,6 +26,8 @@ function renderStatefulSettings(React, controller) {
26
26
  const [busy, setBusy] = React.useState(false)
27
27
  const [message, setMessage] = React.useState('')
28
28
 
29
+ React.useEffect(() => startStatusPolling(controller, setStatus), [controller])
30
+
29
31
  async function run(action, successMessage) {
30
32
  setBusy(true)
31
33
  setMessage('')
@@ -58,6 +60,8 @@ function renderStatefulSettings(React, controller) {
58
60
  port,
59
61
  enabled: status.enabled,
60
62
  inputEnabled: status.inputEnabled,
63
+ recordingEnabled: status.recordingEnabled,
64
+ debugEvalEnabled: status.debugEvalEnabled,
61
65
  }),
62
66
  'Port saved',
63
67
  ),
@@ -68,6 +72,22 @@ function renderStatefulSettings(React, controller) {
68
72
  inputEnabled ? 'WebView input enabled' : 'WebView input disabled',
69
73
  )
70
74
  },
75
+ onRecordingToggle: (event) => {
76
+ const recordingEnabled = event.target.checked
77
+ return run(
78
+ () => controller.applySettings({ recordingEnabled }),
79
+ recordingEnabled ? 'Play recording enabled' : 'Play recording disabled',
80
+ )
81
+ },
82
+ onDebugEvalToggle: (event) => {
83
+ const debugEvalEnabled = event.target.checked
84
+ return run(
85
+ () => controller.applySettings({ debugEvalEnabled }),
86
+ debugEvalEnabled
87
+ ? 'Dangerous WebView eval enabled'
88
+ : 'Dangerous WebView eval disabled',
89
+ )
90
+ },
71
91
  onToggle: () => run(
72
92
  () => (status.running ? controller.stopBridge() : controller.startBridge()),
73
93
  status.running ? 'Stopped' : 'Started',
@@ -75,6 +95,15 @@ function renderStatefulSettings(React, controller) {
75
95
  })
76
96
  }
77
97
 
98
+ function startStatusPolling(controller, setStatus, options = {}) {
99
+ const setIntervalFn = options.setInterval || setInterval
100
+ const clearIntervalFn = options.clearInterval || clearInterval
101
+ const timer = setIntervalFn(() => {
102
+ setStatus(controller.getStatus())
103
+ }, 1000)
104
+ return () => clearIntervalFn(timer)
105
+ }
106
+
78
107
  function renderStaticSettings(e, controller) {
79
108
  const status = controller.getStatus()
80
109
  const port = status.port
@@ -94,12 +123,30 @@ function renderStaticSettings(e, controller) {
94
123
  port: nextPort,
95
124
  enabled: status.enabled,
96
125
  inputEnabled: status.inputEnabled,
126
+ recordingEnabled: status.recordingEnabled,
127
+ debugEvalEnabled: status.debugEvalEnabled,
97
128
  })
98
129
  },
99
130
  onInputToggle: (event) => controller.applySettings({
100
131
  port,
101
132
  enabled: status.enabled,
102
133
  inputEnabled: event.target.checked,
134
+ recordingEnabled: status.recordingEnabled,
135
+ debugEvalEnabled: status.debugEvalEnabled,
136
+ }),
137
+ onRecordingToggle: (event) => controller.applySettings({
138
+ port,
139
+ enabled: status.enabled,
140
+ inputEnabled: status.inputEnabled,
141
+ recordingEnabled: event.target.checked,
142
+ debugEvalEnabled: status.debugEvalEnabled,
143
+ }),
144
+ onDebugEvalToggle: (event) => controller.applySettings({
145
+ port,
146
+ enabled: status.enabled,
147
+ inputEnabled: status.inputEnabled,
148
+ recordingEnabled: status.recordingEnabled,
149
+ debugEvalEnabled: event.target.checked,
103
150
  }),
104
151
  onToggle: () => (status.running ? controller.stopBridge() : controller.startBridge()),
105
152
  })
@@ -155,6 +202,57 @@ function renderSettings(e, props) {
155
202
  props.status.inputEnabled ? 'Enabled' : 'Disabled',
156
203
  ),
157
204
  ),
205
+ e('div', { style: styles.row },
206
+ e('label', { style: styles.label, htmlFor: 'poi-mcp-recording-enabled' }, 'Record play'),
207
+ e('input', {
208
+ id: 'poi-mcp-recording-enabled',
209
+ type: 'checkbox',
210
+ checked: props.onPortChange ? props.status.recordingEnabled : undefined,
211
+ defaultChecked: props.onPortChange ? undefined : props.status.recordingEnabled,
212
+ disabled: props.busy,
213
+ onChange: props.onRecordingToggle,
214
+ }),
215
+ e('span', { style: styles.status },
216
+ props.status.recordingLimitReached
217
+ ? `Paused: ${
218
+ props.status.recordingLimitReached.message ||
219
+ props.status.recordingLimitReached.reason
220
+ }`
221
+ : props.status.recording
222
+ ? 'Recording - splits after 5 min idle'
223
+ : props.status.recordingStarting
224
+ ? 'Starting recording session'
225
+ : props.status.recordingArmed
226
+ ? props.status.recordingAttached
227
+ ? 'Armed - starts on game mouse activity'
228
+ : 'Armed - waiting for game WebView'
229
+ : 'Disabled',
230
+ ),
231
+ ),
232
+ props.status.recordingSessionDir
233
+ ? e('div', { style: styles.note }, `Recording: ${props.status.recordingSessionDir}`)
234
+ : null,
235
+ e('div', { style: styles.warningRow },
236
+ e('label', {
237
+ style: styles.label,
238
+ htmlFor: 'poi-mcp-debug-eval-enabled',
239
+ }, 'Debug eval'),
240
+ e('input', {
241
+ id: 'poi-mcp-debug-eval-enabled',
242
+ type: 'checkbox',
243
+ checked: props.onPortChange ? props.status.debugEvalEnabled : undefined,
244
+ defaultChecked: props.onPortChange
245
+ ? undefined
246
+ : props.status.debugEvalEnabled,
247
+ disabled: props.busy,
248
+ onChange: props.onDebugEvalToggle,
249
+ }),
250
+ e('span', { style: styles.warning },
251
+ props.status.debugEvalEnabled
252
+ ? 'DANGEROUS: authenticated arbitrary code can run in the game WebView'
253
+ : 'Disabled (recommended)',
254
+ ),
255
+ ),
158
256
  e('div', { style: styles.note },
159
257
  'Pi extension defaults to 127.0.0.1:17777; keep this port unless you also update Pi.',
160
258
  ),
@@ -189,6 +287,14 @@ const styles = {
189
287
  display: 'flex',
190
288
  gap: 8,
191
289
  },
290
+ warningRow: {
291
+ alignItems: 'center',
292
+ display: 'flex',
293
+ gap: 8,
294
+ padding: 8,
295
+ border: '1px solid #cf222e',
296
+ borderRadius: 4,
297
+ },
192
298
  label: {
193
299
  flex: '0 0 80px',
194
300
  fontWeight: 600,
@@ -202,6 +308,11 @@ const styles = {
202
308
  status: {
203
309
  color: '#59636e',
204
310
  },
311
+ warning: {
312
+ color: '#cf222e',
313
+ fontSize: 12,
314
+ fontWeight: 600,
315
+ },
205
316
  note: {
206
317
  color: '#59636e',
207
318
  fontSize: 12,
@@ -215,4 +326,5 @@ const styles = {
215
326
 
216
327
  module.exports = {
217
328
  createSettingsClass,
329
+ startStatusPolling,
218
330
  }
package/lib/settings.js CHANGED
@@ -6,6 +6,8 @@ const DEFAULT_SETTINGS = Object.freeze({
6
6
  port: 17777,
7
7
  enabled: true,
8
8
  inputEnabled: false,
9
+ recordingEnabled: false,
10
+ debugEvalEnabled: false,
9
11
  })
10
12
 
11
13
  const DEFAULT_SETTINGS_FILE = path.join(os.homedir(), '.poi-mcp', 'settings.json')
@@ -18,6 +20,12 @@ function normalizeSettings(input = {}) {
18
20
  inputEnabled: typeof input.inputEnabled === 'boolean'
19
21
  ? input.inputEnabled
20
22
  : DEFAULT_SETTINGS.inputEnabled,
23
+ recordingEnabled: typeof input.recordingEnabled === 'boolean'
24
+ ? input.recordingEnabled
25
+ : DEFAULT_SETTINGS.recordingEnabled,
26
+ debugEvalEnabled: typeof input.debugEvalEnabled === 'boolean'
27
+ ? input.debugEvalEnabled
28
+ : DEFAULT_SETTINGS.debugEvalEnabled,
21
29
  }
22
30
  }
23
31