coding-tool-x 3.4.11 → 3.4.12
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/dist/web/assets/{Analytics-BT-pLYj8.js → Analytics-Q_QFMM2p.js} +1 -1
- package/dist/web/assets/{ConfigTemplates-BGH9N-xf.js → ConfigTemplates-Ca8C7VtV.js} +1 -1
- package/dist/web/assets/{Home-C_YwC-4M.js → Home-ChIIT4Ew.js} +1 -1
- package/dist/web/assets/{PluginManager-BTb28q0R.js → PluginManager-C3w7p-sj.js} +1 -1
- package/dist/web/assets/{ProjectList-BYm3jQ3S.js → ProjectList-BfJTDXDw.js} +1 -1
- package/dist/web/assets/{SessionList-C6EIsN9j.js → SessionList-a3EoL0hZ.js} +1 -1
- package/dist/web/assets/{SkillManager-B2VKu6_J.js → SkillManager-CohW5iqS.js} +1 -1
- package/dist/web/assets/{WorkspaceManager-LHBQcZIV.js → WorkspaceManager-DxaKsaJK.js} +1 -1
- package/dist/web/assets/index-B02wDWNC.css +1 -0
- package/dist/web/assets/index-EMrm1wk-.js +2 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/server/api/claude-hooks.js +23 -570
- package/src/server/index.js +2 -1
- package/src/server/services/notification-hooks.js +543 -37
- package/dist/web/assets/index-D547X48u.js +0 -2
- package/dist/web/assets/index-NC-fbfg8.css +0 -1
|
@@ -239,40 +239,190 @@ function escapeForXml(value) {
|
|
|
239
239
|
|
|
240
240
|
function buildWindowsPopupCommand(title, message) {
|
|
241
241
|
const script = [
|
|
242
|
+
"$ErrorActionPreference = 'Stop'",
|
|
243
|
+
`$titleText = '${escapeForPowerShellSingleQuote(title)}'`,
|
|
244
|
+
`$messageText = '${escapeForPowerShellSingleQuote(message)}'`,
|
|
245
|
+
"$segments = $messageText -split '\\s*\\|\\s*', 2",
|
|
246
|
+
"$headlineText = if ($segments.Length -ge 1) { $segments[0] } else { $messageText }",
|
|
247
|
+
"$detailText = if ($segments.Length -ge 2) { $segments[1] } else { '' }",
|
|
248
|
+
'try {',
|
|
249
|
+
'Add-Type -AssemblyName PresentationFramework',
|
|
250
|
+
'Add-Type -AssemblyName PresentationCore',
|
|
251
|
+
'Add-Type -AssemblyName WindowsBase',
|
|
252
|
+
'$brushConverter = New-Object System.Windows.Media.BrushConverter',
|
|
253
|
+
'$window = New-Object System.Windows.Window',
|
|
254
|
+
'$window.Width = 372',
|
|
255
|
+
'$window.Height = 118',
|
|
256
|
+
'$window.WindowStyle = [System.Windows.WindowStyle]::None',
|
|
257
|
+
'$window.ResizeMode = [System.Windows.ResizeMode]::NoResize',
|
|
258
|
+
'$window.AllowsTransparency = $true',
|
|
259
|
+
'$window.Background = [System.Windows.Media.Brushes]::Transparent',
|
|
260
|
+
'$window.ShowInTaskbar = $false',
|
|
261
|
+
'$window.Topmost = $true',
|
|
262
|
+
'$window.ShowActivated = $false',
|
|
263
|
+
'$window.Opacity = 0',
|
|
264
|
+
'$window.WindowStartupLocation = [System.Windows.WindowStartupLocation]::Manual',
|
|
265
|
+
'$root = New-Object System.Windows.Controls.Border',
|
|
266
|
+
'$root.CornerRadius = New-Object System.Windows.CornerRadius -ArgumentList 20',
|
|
267
|
+
'$root.Padding = New-Object System.Windows.Thickness -ArgumentList 16',
|
|
268
|
+
"$root.Background = $brushConverter.ConvertFromString('#F3F4F7')",
|
|
269
|
+
"$root.BorderBrush = $brushConverter.ConvertFromString('#D9DBE3')",
|
|
270
|
+
'$root.BorderThickness = New-Object System.Windows.Thickness -ArgumentList 1',
|
|
271
|
+
'$shadow = New-Object System.Windows.Media.Effects.DropShadowEffect',
|
|
272
|
+
"$shadow.Color = [System.Windows.Media.ColorConverter]::ConvertFromString('#22000000')",
|
|
273
|
+
'$shadow.BlurRadius = 26',
|
|
274
|
+
'$shadow.ShadowDepth = 0',
|
|
275
|
+
'$shadow.Opacity = 0.85',
|
|
276
|
+
'$root.Effect = $shadow',
|
|
277
|
+
'$grid = New-Object System.Windows.Controls.Grid',
|
|
278
|
+
'$iconColumn = New-Object System.Windows.Controls.ColumnDefinition',
|
|
279
|
+
'$iconColumn.Width = New-Object System.Windows.GridLength -ArgumentList 44',
|
|
280
|
+
'$contentColumn = New-Object System.Windows.Controls.ColumnDefinition',
|
|
281
|
+
'$grid.ColumnDefinitions.Add($iconColumn) | Out-Null',
|
|
282
|
+
'$grid.ColumnDefinitions.Add($contentColumn) | Out-Null',
|
|
283
|
+
'$iconHolder = New-Object System.Windows.Controls.Border',
|
|
284
|
+
'$iconHolder.Width = 34',
|
|
285
|
+
'$iconHolder.Height = 34',
|
|
286
|
+
'$iconHolder.HorizontalAlignment = [System.Windows.HorizontalAlignment]::Left',
|
|
287
|
+
'$iconHolder.VerticalAlignment = [System.Windows.VerticalAlignment]::Top',
|
|
288
|
+
'$iconHolder.CornerRadius = New-Object System.Windows.CornerRadius -ArgumentList 17',
|
|
289
|
+
"$iconHolder.Background = $brushConverter.ConvertFromString('#DDEBFF')",
|
|
290
|
+
'$iconGlyph = New-Object System.Windows.Controls.TextBlock',
|
|
291
|
+
'$iconGlyph.Text = [char]0x2713',
|
|
292
|
+
'$iconGlyph.FontSize = 18',
|
|
293
|
+
'$iconGlyph.FontWeight = [System.Windows.FontWeights]::Bold',
|
|
294
|
+
"$iconGlyph.Foreground = $brushConverter.ConvertFromString('#0A84FF')",
|
|
295
|
+
'$iconGlyph.HorizontalAlignment = [System.Windows.HorizontalAlignment]::Center',
|
|
296
|
+
'$iconGlyph.VerticalAlignment = [System.Windows.VerticalAlignment]::Center',
|
|
297
|
+
'$iconHolder.Child = $iconGlyph',
|
|
298
|
+
'$contentStack = New-Object System.Windows.Controls.StackPanel',
|
|
299
|
+
'$contentStack.Orientation = [System.Windows.Controls.Orientation]::Vertical',
|
|
300
|
+
'$contentStack.Margin = New-Object System.Windows.Thickness -ArgumentList 4,0,0,0',
|
|
301
|
+
'$metaGrid = New-Object System.Windows.Controls.Grid',
|
|
302
|
+
'$metaGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition)) | Out-Null',
|
|
303
|
+
'$timeColumn = New-Object System.Windows.Controls.ColumnDefinition',
|
|
304
|
+
'$timeColumn.Width = [System.Windows.GridLength]::Auto',
|
|
305
|
+
'$metaGrid.ColumnDefinitions.Add($timeColumn) | Out-Null',
|
|
306
|
+
'$appLabel = New-Object System.Windows.Controls.TextBlock',
|
|
307
|
+
'$appLabel.Text = $titleText',
|
|
308
|
+
'$appLabel.FontSize = 11.5',
|
|
309
|
+
'$appLabel.FontWeight = [System.Windows.FontWeights]::SemiBold',
|
|
310
|
+
"$appLabel.Foreground = $brushConverter.ConvertFromString('#6B6C73')",
|
|
311
|
+
'$appLabel.TextTrimming = [System.Windows.TextTrimming]::CharacterEllipsis',
|
|
312
|
+
'$stampLabel = New-Object System.Windows.Controls.TextBlock',
|
|
313
|
+
"$stampLabel.Text = '刚刚'",
|
|
314
|
+
'$stampLabel.FontSize = 11',
|
|
315
|
+
"$stampLabel.Foreground = $brushConverter.ConvertFromString('#8D8E95')",
|
|
316
|
+
'$stampLabel.Margin = New-Object System.Windows.Thickness -ArgumentList 12,0,0,0',
|
|
317
|
+
'[System.Windows.Controls.Grid]::SetColumn($stampLabel, 1)',
|
|
318
|
+
'$metaGrid.Children.Add($appLabel) | Out-Null',
|
|
319
|
+
'$metaGrid.Children.Add($stampLabel) | Out-Null',
|
|
320
|
+
'$headlineLabel = New-Object System.Windows.Controls.TextBlock',
|
|
321
|
+
'$headlineLabel.Text = $headlineText',
|
|
322
|
+
'$headlineLabel.FontSize = 14',
|
|
323
|
+
'$headlineLabel.FontWeight = [System.Windows.FontWeights]::SemiBold',
|
|
324
|
+
"$headlineLabel.Foreground = $brushConverter.ConvertFromString('#1F2024')",
|
|
325
|
+
'$headlineLabel.TextWrapping = [System.Windows.TextWrapping]::Wrap',
|
|
326
|
+
'$headlineLabel.Margin = New-Object System.Windows.Thickness -ArgumentList 0,6,0,0',
|
|
327
|
+
'$detailLabel = New-Object System.Windows.Controls.TextBlock',
|
|
328
|
+
'$detailLabel.Text = $detailText',
|
|
329
|
+
'$detailLabel.FontSize = 12',
|
|
330
|
+
"$detailLabel.Foreground = $brushConverter.ConvertFromString('#5F6168')",
|
|
331
|
+
'$detailLabel.TextWrapping = [System.Windows.TextWrapping]::Wrap',
|
|
332
|
+
'$detailLabel.Margin = New-Object System.Windows.Thickness -ArgumentList 0,4,0,0',
|
|
333
|
+
'$detailLabel.Visibility = if ([string]::IsNullOrWhiteSpace($detailText)) { [System.Windows.Visibility]::Collapsed } else { [System.Windows.Visibility]::Visible }',
|
|
334
|
+
'$contentStack.Children.Add($metaGrid) | Out-Null',
|
|
335
|
+
'$contentStack.Children.Add($headlineLabel) | Out-Null',
|
|
336
|
+
'$contentStack.Children.Add($detailLabel) | Out-Null',
|
|
337
|
+
'[System.Windows.Controls.Grid]::SetColumn($contentStack, 1)',
|
|
338
|
+
'$grid.Children.Add($iconHolder) | Out-Null',
|
|
339
|
+
'$grid.Children.Add($contentStack) | Out-Null',
|
|
340
|
+
'$root.Child = $grid',
|
|
341
|
+
'$window.Content = $root',
|
|
342
|
+
'$workArea = [System.Windows.SystemParameters]::WorkArea',
|
|
343
|
+
'$window.Left = $workArea.Right - $window.Width - 18',
|
|
344
|
+
'$window.Top = $workArea.Top + 18',
|
|
345
|
+
'$frame = New-Object System.Windows.Threading.DispatcherFrame',
|
|
346
|
+
'$window.Add_Closed({ $frame.Continue = $false })',
|
|
347
|
+
'$closeTimer = New-Object System.Windows.Threading.DispatcherTimer',
|
|
348
|
+
'$closeTimer.Interval = [TimeSpan]::FromMilliseconds(4600)',
|
|
349
|
+
'$closeTimer.Add_Tick({',
|
|
350
|
+
' $closeTimer.Stop()',
|
|
351
|
+
' $fadeOut = New-Object System.Windows.Media.Animation.DoubleAnimation',
|
|
352
|
+
' $fadeOut.From = $window.Opacity',
|
|
353
|
+
' $fadeOut.To = 0',
|
|
354
|
+
' $fadeOut.Duration = [TimeSpan]::FromMilliseconds(220)',
|
|
355
|
+
' $fadeOut.Add_Completed({ $window.Close() })',
|
|
356
|
+
' $window.BeginAnimation([System.Windows.Window]::OpacityProperty, $fadeOut)',
|
|
357
|
+
'})',
|
|
358
|
+
'$window.Show()',
|
|
359
|
+
'$fadeIn = New-Object System.Windows.Media.Animation.DoubleAnimation',
|
|
360
|
+
'$fadeIn.From = 0',
|
|
361
|
+
'$fadeIn.To = 1',
|
|
362
|
+
'$fadeIn.Duration = [TimeSpan]::FromMilliseconds(180)',
|
|
363
|
+
'$window.BeginAnimation([System.Windows.Window]::OpacityProperty, $fadeIn)',
|
|
364
|
+
'$closeTimer.Start()',
|
|
365
|
+
'[System.Windows.Threading.Dispatcher]::PushFrame($frame)',
|
|
366
|
+
'} catch {',
|
|
242
367
|
'Add-Type -AssemblyName System.Windows.Forms',
|
|
243
368
|
'Add-Type -AssemblyName System.Drawing',
|
|
244
369
|
'$form = New-Object System.Windows.Forms.Form',
|
|
245
|
-
|
|
370
|
+
'$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::None',
|
|
371
|
+
'$form.BackColor = [System.Drawing.Color]::FromArgb(247, 247, 250)',
|
|
246
372
|
'$form.Width = 360',
|
|
247
|
-
'$form.Height =
|
|
373
|
+
'$form.Height = 118',
|
|
248
374
|
'$form.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual',
|
|
249
|
-
'$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedToolWindow',
|
|
250
375
|
'$form.ShowInTaskbar = $false',
|
|
251
376
|
'$form.TopMost = $true',
|
|
252
377
|
'$form.MaximizeBox = $false',
|
|
253
378
|
'$form.MinimizeBox = $false',
|
|
254
379
|
'$workingArea = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea',
|
|
255
|
-
'$form.Location = New-Object System.Drawing.Point(($workingArea.Right - $form.Width -
|
|
380
|
+
'$form.Location = New-Object System.Drawing.Point(($workingArea.Right - $form.Width - 18), ($workingArea.Top + 18))',
|
|
381
|
+
'$iconPanel = New-Object System.Windows.Forms.Panel',
|
|
382
|
+
'$iconPanel.Width = 34',
|
|
383
|
+
'$iconPanel.Height = 34',
|
|
384
|
+
'$iconPanel.BackColor = [System.Drawing.Color]::FromArgb(221, 235, 255)',
|
|
385
|
+
'$iconPanel.Location = New-Object System.Drawing.Point(16, 18)',
|
|
386
|
+
'$iconLabel = New-Object System.Windows.Forms.Label',
|
|
387
|
+
'$iconLabel.Text = [char]0x2713',
|
|
388
|
+
"$iconLabel.Font = New-Object System.Drawing.Font('Segoe UI', 14, [System.Drawing.FontStyle]::Bold)",
|
|
389
|
+
'$iconLabel.ForeColor = [System.Drawing.Color]::FromArgb(10, 132, 255)',
|
|
390
|
+
'$iconLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter',
|
|
391
|
+
'$iconLabel.Dock = [System.Windows.Forms.DockStyle]::Fill',
|
|
392
|
+
'$iconPanel.Controls.Add($iconLabel)',
|
|
256
393
|
'$titleLabel = New-Object System.Windows.Forms.Label',
|
|
257
|
-
|
|
258
|
-
"$titleLabel.Font = New-Object System.Drawing.Font('Segoe UI',
|
|
394
|
+
'$titleLabel.Text = $titleText',
|
|
395
|
+
"$titleLabel.Font = New-Object System.Drawing.Font('Segoe UI', 9, [System.Drawing.FontStyle]::Bold)",
|
|
396
|
+
'$titleLabel.ForeColor = [System.Drawing.Color]::FromArgb(109, 110, 115)',
|
|
259
397
|
'$titleLabel.AutoSize = $true',
|
|
260
|
-
'$titleLabel.Location = New-Object System.Drawing.Point(
|
|
261
|
-
'$
|
|
262
|
-
|
|
263
|
-
"$
|
|
264
|
-
'$
|
|
265
|
-
'$
|
|
266
|
-
'$
|
|
398
|
+
'$titleLabel.Location = New-Object System.Drawing.Point(60, 16)',
|
|
399
|
+
'$headlineLabel = New-Object System.Windows.Forms.Label',
|
|
400
|
+
'$headlineLabel.Text = $headlineText',
|
|
401
|
+
"$headlineLabel.Font = New-Object System.Drawing.Font('Segoe UI', 10.5, [System.Drawing.FontStyle]::Bold)",
|
|
402
|
+
'$headlineLabel.ForeColor = [System.Drawing.Color]::FromArgb(31, 32, 36)',
|
|
403
|
+
'$headlineLabel.MaximumSize = New-Object System.Drawing.Size(272, 0)',
|
|
404
|
+
'$headlineLabel.AutoSize = $true',
|
|
405
|
+
'$headlineLabel.Location = New-Object System.Drawing.Point(60, 36)',
|
|
406
|
+
'$detailLabel = New-Object System.Windows.Forms.Label',
|
|
407
|
+
'$detailLabel.Text = $detailText',
|
|
408
|
+
"$detailLabel.Font = New-Object System.Drawing.Font('Segoe UI', 9)",
|
|
409
|
+
'$detailLabel.ForeColor = [System.Drawing.Color]::FromArgb(95, 97, 104)',
|
|
410
|
+
'$detailLabel.MaximumSize = New-Object System.Drawing.Size(272, 0)',
|
|
411
|
+
'$detailLabel.AutoSize = $true',
|
|
412
|
+
'$detailLabel.Location = New-Object System.Drawing.Point(60, 60)',
|
|
413
|
+
'$detailLabel.Visible = -not [string]::IsNullOrWhiteSpace($detailText)',
|
|
414
|
+
'$form.Controls.Add($iconPanel)',
|
|
267
415
|
'$form.Controls.Add($titleLabel)',
|
|
268
|
-
'$form.Controls.Add($
|
|
416
|
+
'$form.Controls.Add($headlineLabel)',
|
|
417
|
+
'$form.Controls.Add($detailLabel)',
|
|
269
418
|
'$timer = New-Object System.Windows.Forms.Timer',
|
|
270
|
-
'$timer.Interval =
|
|
419
|
+
'$timer.Interval = 4800',
|
|
271
420
|
'$timer.Add_Tick({ $timer.Stop(); $form.Close() })',
|
|
272
421
|
'$timer.Start()',
|
|
273
|
-
'[void]$form.ShowDialog()'
|
|
422
|
+
'[void]$form.ShowDialog()',
|
|
423
|
+
'}'
|
|
274
424
|
].join('; ');
|
|
275
|
-
return `powershell -NoProfile -Command ${JSON.stringify(script)}`;
|
|
425
|
+
return `powershell -NoProfile -STA -Command ${JSON.stringify(script)}`;
|
|
276
426
|
}
|
|
277
427
|
|
|
278
428
|
function generateNotifyScript(feishu = {}) {
|
|
@@ -379,7 +529,7 @@ function notify(mode, message) {
|
|
|
379
529
|
const ps = "Add-Type -AssemblyName PresentationFramework; [System.Windows.MessageBox]::Show('" +
|
|
380
530
|
escapeForPowerShellSingleQuote(message) + "', '" +
|
|
381
531
|
escapeForPowerShellSingleQuote(title) + "', 'OK', 'Information')"
|
|
382
|
-
const command = 'powershell -NoProfile -Command ' + JSON.stringify(ps) + ' || ' + popupCommand
|
|
532
|
+
const command = 'powershell -NoProfile -STA -Command ' + JSON.stringify(ps) + ' || ' + popupCommand
|
|
383
533
|
execSync(command, { stdio: 'ignore', windowsHide: true })
|
|
384
534
|
} else {
|
|
385
535
|
execSync(popupCommand, { stdio: 'ignore', windowsHide: true })
|
|
@@ -499,40 +649,190 @@ function escapeForXml(value) {
|
|
|
499
649
|
|
|
500
650
|
function buildWindowsPopupCommand(title, message) {
|
|
501
651
|
const script = [
|
|
652
|
+
"$ErrorActionPreference = 'Stop'",
|
|
653
|
+
\`$titleText = '\${escapeForPowerShellSingleQuote(title)}'\`,
|
|
654
|
+
\`$messageText = '\${escapeForPowerShellSingleQuote(message)}'\`,
|
|
655
|
+
"$segments = $messageText -split '\\\\s*\\\\|\\\\s*', 2",
|
|
656
|
+
"$headlineText = if ($segments.Length -ge 1) { $segments[0] } else { $messageText }",
|
|
657
|
+
"$detailText = if ($segments.Length -ge 2) { $segments[1] } else { '' }",
|
|
658
|
+
'try {',
|
|
659
|
+
'Add-Type -AssemblyName PresentationFramework',
|
|
660
|
+
'Add-Type -AssemblyName PresentationCore',
|
|
661
|
+
'Add-Type -AssemblyName WindowsBase',
|
|
662
|
+
'$brushConverter = New-Object System.Windows.Media.BrushConverter',
|
|
663
|
+
'$window = New-Object System.Windows.Window',
|
|
664
|
+
'$window.Width = 372',
|
|
665
|
+
'$window.Height = 118',
|
|
666
|
+
'$window.WindowStyle = [System.Windows.WindowStyle]::None',
|
|
667
|
+
'$window.ResizeMode = [System.Windows.ResizeMode]::NoResize',
|
|
668
|
+
'$window.AllowsTransparency = $true',
|
|
669
|
+
'$window.Background = [System.Windows.Media.Brushes]::Transparent',
|
|
670
|
+
'$window.ShowInTaskbar = $false',
|
|
671
|
+
'$window.Topmost = $true',
|
|
672
|
+
'$window.ShowActivated = $false',
|
|
673
|
+
'$window.Opacity = 0',
|
|
674
|
+
'$window.WindowStartupLocation = [System.Windows.WindowStartupLocation]::Manual',
|
|
675
|
+
'$root = New-Object System.Windows.Controls.Border',
|
|
676
|
+
'$root.CornerRadius = New-Object System.Windows.CornerRadius -ArgumentList 20',
|
|
677
|
+
'$root.Padding = New-Object System.Windows.Thickness -ArgumentList 16',
|
|
678
|
+
"$root.Background = $brushConverter.ConvertFromString('#F3F4F7')",
|
|
679
|
+
"$root.BorderBrush = $brushConverter.ConvertFromString('#D9DBE3')",
|
|
680
|
+
'$root.BorderThickness = New-Object System.Windows.Thickness -ArgumentList 1',
|
|
681
|
+
'$shadow = New-Object System.Windows.Media.Effects.DropShadowEffect',
|
|
682
|
+
"$shadow.Color = [System.Windows.Media.ColorConverter]::ConvertFromString('#22000000')",
|
|
683
|
+
'$shadow.BlurRadius = 26',
|
|
684
|
+
'$shadow.ShadowDepth = 0',
|
|
685
|
+
'$shadow.Opacity = 0.85',
|
|
686
|
+
'$root.Effect = $shadow',
|
|
687
|
+
'$grid = New-Object System.Windows.Controls.Grid',
|
|
688
|
+
'$iconColumn = New-Object System.Windows.Controls.ColumnDefinition',
|
|
689
|
+
'$iconColumn.Width = New-Object System.Windows.GridLength -ArgumentList 44',
|
|
690
|
+
'$contentColumn = New-Object System.Windows.Controls.ColumnDefinition',
|
|
691
|
+
'$grid.ColumnDefinitions.Add($iconColumn) | Out-Null',
|
|
692
|
+
'$grid.ColumnDefinitions.Add($contentColumn) | Out-Null',
|
|
693
|
+
'$iconHolder = New-Object System.Windows.Controls.Border',
|
|
694
|
+
'$iconHolder.Width = 34',
|
|
695
|
+
'$iconHolder.Height = 34',
|
|
696
|
+
'$iconHolder.HorizontalAlignment = [System.Windows.HorizontalAlignment]::Left',
|
|
697
|
+
'$iconHolder.VerticalAlignment = [System.Windows.VerticalAlignment]::Top',
|
|
698
|
+
'$iconHolder.CornerRadius = New-Object System.Windows.CornerRadius -ArgumentList 17',
|
|
699
|
+
"$iconHolder.Background = $brushConverter.ConvertFromString('#DDEBFF')",
|
|
700
|
+
'$iconGlyph = New-Object System.Windows.Controls.TextBlock',
|
|
701
|
+
'$iconGlyph.Text = [char]0x2713',
|
|
702
|
+
'$iconGlyph.FontSize = 18',
|
|
703
|
+
'$iconGlyph.FontWeight = [System.Windows.FontWeights]::Bold',
|
|
704
|
+
"$iconGlyph.Foreground = $brushConverter.ConvertFromString('#0A84FF')",
|
|
705
|
+
'$iconGlyph.HorizontalAlignment = [System.Windows.HorizontalAlignment]::Center',
|
|
706
|
+
'$iconGlyph.VerticalAlignment = [System.Windows.VerticalAlignment]::Center',
|
|
707
|
+
'$iconHolder.Child = $iconGlyph',
|
|
708
|
+
'$contentStack = New-Object System.Windows.Controls.StackPanel',
|
|
709
|
+
'$contentStack.Orientation = [System.Windows.Controls.Orientation]::Vertical',
|
|
710
|
+
'$contentStack.Margin = New-Object System.Windows.Thickness -ArgumentList 4,0,0,0',
|
|
711
|
+
'$metaGrid = New-Object System.Windows.Controls.Grid',
|
|
712
|
+
'$metaGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition)) | Out-Null',
|
|
713
|
+
'$timeColumn = New-Object System.Windows.Controls.ColumnDefinition',
|
|
714
|
+
'$timeColumn.Width = [System.Windows.GridLength]::Auto',
|
|
715
|
+
'$metaGrid.ColumnDefinitions.Add($timeColumn) | Out-Null',
|
|
716
|
+
'$appLabel = New-Object System.Windows.Controls.TextBlock',
|
|
717
|
+
'$appLabel.Text = $titleText',
|
|
718
|
+
'$appLabel.FontSize = 11.5',
|
|
719
|
+
'$appLabel.FontWeight = [System.Windows.FontWeights]::SemiBold',
|
|
720
|
+
"$appLabel.Foreground = $brushConverter.ConvertFromString('#6B6C73')",
|
|
721
|
+
'$appLabel.TextTrimming = [System.Windows.TextTrimming]::CharacterEllipsis',
|
|
722
|
+
'$stampLabel = New-Object System.Windows.Controls.TextBlock',
|
|
723
|
+
"$stampLabel.Text = '刚刚'",
|
|
724
|
+
'$stampLabel.FontSize = 11',
|
|
725
|
+
"$stampLabel.Foreground = $brushConverter.ConvertFromString('#8D8E95')",
|
|
726
|
+
'$stampLabel.Margin = New-Object System.Windows.Thickness -ArgumentList 12,0,0,0',
|
|
727
|
+
'[System.Windows.Controls.Grid]::SetColumn($stampLabel, 1)',
|
|
728
|
+
'$metaGrid.Children.Add($appLabel) | Out-Null',
|
|
729
|
+
'$metaGrid.Children.Add($stampLabel) | Out-Null',
|
|
730
|
+
'$headlineLabel = New-Object System.Windows.Controls.TextBlock',
|
|
731
|
+
'$headlineLabel.Text = $headlineText',
|
|
732
|
+
'$headlineLabel.FontSize = 14',
|
|
733
|
+
'$headlineLabel.FontWeight = [System.Windows.FontWeights]::SemiBold',
|
|
734
|
+
"$headlineLabel.Foreground = $brushConverter.ConvertFromString('#1F2024')",
|
|
735
|
+
'$headlineLabel.TextWrapping = [System.Windows.TextWrapping]::Wrap',
|
|
736
|
+
'$headlineLabel.Margin = New-Object System.Windows.Thickness -ArgumentList 0,6,0,0',
|
|
737
|
+
'$detailLabel = New-Object System.Windows.Controls.TextBlock',
|
|
738
|
+
'$detailLabel.Text = $detailText',
|
|
739
|
+
'$detailLabel.FontSize = 12',
|
|
740
|
+
"$detailLabel.Foreground = $brushConverter.ConvertFromString('#5F6168')",
|
|
741
|
+
'$detailLabel.TextWrapping = [System.Windows.TextWrapping]::Wrap',
|
|
742
|
+
'$detailLabel.Margin = New-Object System.Windows.Thickness -ArgumentList 0,4,0,0',
|
|
743
|
+
'$detailLabel.Visibility = if ([string]::IsNullOrWhiteSpace($detailText)) { [System.Windows.Visibility]::Collapsed } else { [System.Windows.Visibility]::Visible }',
|
|
744
|
+
'$contentStack.Children.Add($metaGrid) | Out-Null',
|
|
745
|
+
'$contentStack.Children.Add($headlineLabel) | Out-Null',
|
|
746
|
+
'$contentStack.Children.Add($detailLabel) | Out-Null',
|
|
747
|
+
'[System.Windows.Controls.Grid]::SetColumn($contentStack, 1)',
|
|
748
|
+
'$grid.Children.Add($iconHolder) | Out-Null',
|
|
749
|
+
'$grid.Children.Add($contentStack) | Out-Null',
|
|
750
|
+
'$root.Child = $grid',
|
|
751
|
+
'$window.Content = $root',
|
|
752
|
+
'$workArea = [System.Windows.SystemParameters]::WorkArea',
|
|
753
|
+
'$window.Left = $workArea.Right - $window.Width - 18',
|
|
754
|
+
'$window.Top = $workArea.Top + 18',
|
|
755
|
+
'$frame = New-Object System.Windows.Threading.DispatcherFrame',
|
|
756
|
+
'$window.Add_Closed({ $frame.Continue = $false })',
|
|
757
|
+
'$closeTimer = New-Object System.Windows.Threading.DispatcherTimer',
|
|
758
|
+
'$closeTimer.Interval = [TimeSpan]::FromMilliseconds(4600)',
|
|
759
|
+
'$closeTimer.Add_Tick({',
|
|
760
|
+
' $closeTimer.Stop()',
|
|
761
|
+
' $fadeOut = New-Object System.Windows.Media.Animation.DoubleAnimation',
|
|
762
|
+
' $fadeOut.From = $window.Opacity',
|
|
763
|
+
' $fadeOut.To = 0',
|
|
764
|
+
' $fadeOut.Duration = [TimeSpan]::FromMilliseconds(220)',
|
|
765
|
+
' $fadeOut.Add_Completed({ $window.Close() })',
|
|
766
|
+
' $window.BeginAnimation([System.Windows.Window]::OpacityProperty, $fadeOut)',
|
|
767
|
+
'})',
|
|
768
|
+
'$window.Show()',
|
|
769
|
+
'$fadeIn = New-Object System.Windows.Media.Animation.DoubleAnimation',
|
|
770
|
+
'$fadeIn.From = 0',
|
|
771
|
+
'$fadeIn.To = 1',
|
|
772
|
+
'$fadeIn.Duration = [TimeSpan]::FromMilliseconds(180)',
|
|
773
|
+
'$window.BeginAnimation([System.Windows.Window]::OpacityProperty, $fadeIn)',
|
|
774
|
+
'$closeTimer.Start()',
|
|
775
|
+
'[System.Windows.Threading.Dispatcher]::PushFrame($frame)',
|
|
776
|
+
'} catch {',
|
|
502
777
|
'Add-Type -AssemblyName System.Windows.Forms',
|
|
503
778
|
'Add-Type -AssemblyName System.Drawing',
|
|
504
779
|
'$form = New-Object System.Windows.Forms.Form',
|
|
505
|
-
|
|
780
|
+
'$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::None',
|
|
781
|
+
'$form.BackColor = [System.Drawing.Color]::FromArgb(247, 247, 250)',
|
|
506
782
|
'$form.Width = 360',
|
|
507
|
-
'$form.Height =
|
|
783
|
+
'$form.Height = 118',
|
|
508
784
|
'$form.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual',
|
|
509
|
-
'$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedToolWindow',
|
|
510
785
|
'$form.ShowInTaskbar = $false',
|
|
511
786
|
'$form.TopMost = $true',
|
|
512
787
|
'$form.MaximizeBox = $false',
|
|
513
788
|
'$form.MinimizeBox = $false',
|
|
514
789
|
'$workingArea = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea',
|
|
515
|
-
'$form.Location = New-Object System.Drawing.Point(($workingArea.Right - $form.Width -
|
|
790
|
+
'$form.Location = New-Object System.Drawing.Point(($workingArea.Right - $form.Width - 18), ($workingArea.Top + 18))',
|
|
791
|
+
'$iconPanel = New-Object System.Windows.Forms.Panel',
|
|
792
|
+
'$iconPanel.Width = 34',
|
|
793
|
+
'$iconPanel.Height = 34',
|
|
794
|
+
'$iconPanel.BackColor = [System.Drawing.Color]::FromArgb(221, 235, 255)',
|
|
795
|
+
'$iconPanel.Location = New-Object System.Drawing.Point(16, 18)',
|
|
796
|
+
'$iconLabel = New-Object System.Windows.Forms.Label',
|
|
797
|
+
'$iconLabel.Text = [char]0x2713',
|
|
798
|
+
"$iconLabel.Font = New-Object System.Drawing.Font('Segoe UI', 14, [System.Drawing.FontStyle]::Bold)",
|
|
799
|
+
'$iconLabel.ForeColor = [System.Drawing.Color]::FromArgb(10, 132, 255)',
|
|
800
|
+
'$iconLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter',
|
|
801
|
+
'$iconLabel.Dock = [System.Windows.Forms.DockStyle]::Fill',
|
|
802
|
+
'$iconPanel.Controls.Add($iconLabel)',
|
|
516
803
|
'$titleLabel = New-Object System.Windows.Forms.Label',
|
|
517
|
-
|
|
518
|
-
"
|
|
804
|
+
'$titleLabel.Text = $titleText',
|
|
805
|
+
"$titleLabel.Font = New-Object System.Drawing.Font('Segoe UI', 9, [System.Drawing.FontStyle]::Bold)",
|
|
806
|
+
'$titleLabel.ForeColor = [System.Drawing.Color]::FromArgb(109, 110, 115)',
|
|
519
807
|
'$titleLabel.AutoSize = $true',
|
|
520
|
-
'$titleLabel.Location = New-Object System.Drawing.Point(
|
|
521
|
-
'$
|
|
522
|
-
|
|
523
|
-
"
|
|
524
|
-
'$
|
|
525
|
-
'$
|
|
526
|
-
'$
|
|
808
|
+
'$titleLabel.Location = New-Object System.Drawing.Point(60, 16)',
|
|
809
|
+
'$headlineLabel = New-Object System.Windows.Forms.Label',
|
|
810
|
+
'$headlineLabel.Text = $headlineText',
|
|
811
|
+
"$headlineLabel.Font = New-Object System.Drawing.Font('Segoe UI', 10.5, [System.Drawing.FontStyle]::Bold)",
|
|
812
|
+
'$headlineLabel.ForeColor = [System.Drawing.Color]::FromArgb(31, 32, 36)',
|
|
813
|
+
'$headlineLabel.MaximumSize = New-Object System.Drawing.Size(272, 0)',
|
|
814
|
+
'$headlineLabel.AutoSize = $true',
|
|
815
|
+
'$headlineLabel.Location = New-Object System.Drawing.Point(60, 36)',
|
|
816
|
+
'$detailLabel = New-Object System.Windows.Forms.Label',
|
|
817
|
+
'$detailLabel.Text = $detailText',
|
|
818
|
+
"$detailLabel.Font = New-Object System.Drawing.Font('Segoe UI', 9)",
|
|
819
|
+
'$detailLabel.ForeColor = [System.Drawing.Color]::FromArgb(95, 97, 104)',
|
|
820
|
+
'$detailLabel.MaximumSize = New-Object System.Drawing.Size(272, 0)',
|
|
821
|
+
'$detailLabel.AutoSize = $true',
|
|
822
|
+
'$detailLabel.Location = New-Object System.Drawing.Point(60, 60)',
|
|
823
|
+
'$detailLabel.Visible = -not [string]::IsNullOrWhiteSpace($detailText)',
|
|
824
|
+
'$form.Controls.Add($iconPanel)',
|
|
527
825
|
'$form.Controls.Add($titleLabel)',
|
|
528
|
-
'$form.Controls.Add($
|
|
826
|
+
'$form.Controls.Add($headlineLabel)',
|
|
827
|
+
'$form.Controls.Add($detailLabel)',
|
|
529
828
|
'$timer = New-Object System.Windows.Forms.Timer',
|
|
530
|
-
'$timer.Interval =
|
|
829
|
+
'$timer.Interval = 4800',
|
|
531
830
|
'$timer.Add_Tick({ $timer.Stop(); $form.Close() })',
|
|
532
831
|
'$timer.Start()',
|
|
533
|
-
'[void]$form.ShowDialog()'
|
|
832
|
+
'[void]$form.ShowDialog()',
|
|
833
|
+
'}'
|
|
534
834
|
].join('; ')
|
|
535
|
-
return 'powershell -NoProfile -Command ' + JSON.stringify(script)
|
|
835
|
+
return 'powershell -NoProfile -STA -Command ' + JSON.stringify(script)
|
|
536
836
|
}
|
|
537
837
|
`;
|
|
538
838
|
}
|
|
@@ -900,6 +1200,205 @@ function saveNotificationSettings(input = {}) {
|
|
|
900
1200
|
return getNotificationSettings();
|
|
901
1201
|
}
|
|
902
1202
|
|
|
1203
|
+
function parseNotifyTypeMarker(command) {
|
|
1204
|
+
const marker = String(command || '').match(/--cc-notify-type=(['"])?(dialog|notification)\1/i);
|
|
1205
|
+
return marker?.[2] ? normalizeType(marker[2].toLowerCase()) : null;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
function getStopHookCommand(settings = {}) {
|
|
1209
|
+
const hooks = settings?.hooks?.Stop;
|
|
1210
|
+
if (!Array.isArray(hooks) || hooks.length === 0) {
|
|
1211
|
+
return '';
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
let fallbackCommand = '';
|
|
1215
|
+
for (const group of hooks) {
|
|
1216
|
+
const groupHooks = Array.isArray(group?.hooks) ? group.hooks : [];
|
|
1217
|
+
for (const hook of groupHooks) {
|
|
1218
|
+
const command = String(hook?.command || '');
|
|
1219
|
+
if (!command) continue;
|
|
1220
|
+
if (!fallbackCommand) {
|
|
1221
|
+
fallbackCommand = command;
|
|
1222
|
+
}
|
|
1223
|
+
if (command.includes('notify-hook.js')) {
|
|
1224
|
+
return command;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
return fallbackCommand;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
function normalizePathForCompare(rawPath) {
|
|
1233
|
+
return String(rawPath || '').replace(/\\/g, '/');
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
function shouldRepairStopHook(settings, expectedScriptPath = PATHS.notifyHook, fileExists = fs.existsSync) {
|
|
1237
|
+
const command = getStopHookCommand(settings);
|
|
1238
|
+
if (!command || !command.includes('notify-hook.js')) {
|
|
1239
|
+
return false;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
const normalizedCommand = normalizePathForCompare(command);
|
|
1243
|
+
const normalizedExpected = normalizePathForCompare(expectedScriptPath);
|
|
1244
|
+
if (!normalizedCommand.includes(normalizedExpected)) {
|
|
1245
|
+
return true;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
const markerType = parseNotifyTypeMarker(command);
|
|
1249
|
+
if (!markerType) {
|
|
1250
|
+
return true;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
return !fileExists(expectedScriptPath);
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
function buildStopHookCommand(type) {
|
|
1257
|
+
return buildClaudeCommand(type);
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
function parseStopHookStatus(settings = {}) {
|
|
1261
|
+
const stopGroups = Array.isArray(settings?.hooks?.Stop) ? settings.hooks.Stop : [];
|
|
1262
|
+
if (stopGroups.length === 0) {
|
|
1263
|
+
return { enabled: false, type: 'notification' };
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
let sawNotificationLikeCommand = false;
|
|
1267
|
+
for (const group of stopGroups) {
|
|
1268
|
+
const groupHooks = Array.isArray(group?.hooks) ? group.hooks : [];
|
|
1269
|
+
for (const hook of groupHooks) {
|
|
1270
|
+
const command = String(hook?.command || '');
|
|
1271
|
+
if (!command) continue;
|
|
1272
|
+
|
|
1273
|
+
const markerType = parseNotifyTypeMarker(command) || parseManagedType(command);
|
|
1274
|
+
if (markerType) {
|
|
1275
|
+
return { enabled: true, type: markerType };
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
const isDialog = command.includes('display dialog') ||
|
|
1279
|
+
command.includes('MessageBox') ||
|
|
1280
|
+
command.includes('zenity --info');
|
|
1281
|
+
if (isDialog) {
|
|
1282
|
+
return { enabled: true, type: 'dialog' };
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
const isNotification = command.includes('display notification') ||
|
|
1286
|
+
command.includes('Popup') ||
|
|
1287
|
+
command.includes('GraphicsPath') ||
|
|
1288
|
+
command.includes('TransparencyKey') ||
|
|
1289
|
+
command.includes('FormBorderStyle]::None') ||
|
|
1290
|
+
command.includes('AllowsTransparency') ||
|
|
1291
|
+
command.includes('notify-send') ||
|
|
1292
|
+
command.includes('ToastNotificationManager') ||
|
|
1293
|
+
command.includes('CreateToastNotifier') ||
|
|
1294
|
+
command.includes('notify-hook.js');
|
|
1295
|
+
if (isNotification) {
|
|
1296
|
+
sawNotificationLikeCommand = true;
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
return sawNotificationLikeCommand
|
|
1302
|
+
? { enabled: true, type: 'notification' }
|
|
1303
|
+
: { enabled: false, type: 'notification' };
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
function normalizeSavedPlatformStatus(platform = {}) {
|
|
1307
|
+
return {
|
|
1308
|
+
enabled: platform?.enabled === true,
|
|
1309
|
+
type: normalizeType(platform?.type)
|
|
1310
|
+
};
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
function buildLegacyClaudeSaveInput(input = {}, currentSettings = getNotificationSettings()) {
|
|
1314
|
+
return {
|
|
1315
|
+
platforms: {
|
|
1316
|
+
claude: input.stopHook !== undefined
|
|
1317
|
+
? normalizePlatformInput(input.stopHook)
|
|
1318
|
+
: { enabled: false, type: 'notification' },
|
|
1319
|
+
codex: normalizeSavedPlatformStatus(currentSettings?.platforms?.codex),
|
|
1320
|
+
gemini: normalizeSavedPlatformStatus(currentSettings?.platforms?.gemini),
|
|
1321
|
+
opencode: normalizeSavedPlatformStatus(currentSettings?.platforms?.opencode)
|
|
1322
|
+
},
|
|
1323
|
+
feishu: input.feishu !== undefined
|
|
1324
|
+
? {
|
|
1325
|
+
enabled: input.feishu?.enabled === true,
|
|
1326
|
+
webhookUrl: input.feishu?.webhookUrl || ''
|
|
1327
|
+
}
|
|
1328
|
+
: {
|
|
1329
|
+
enabled: currentSettings?.feishu?.enabled === true,
|
|
1330
|
+
webhookUrl: currentSettings?.feishu?.webhookUrl || ''
|
|
1331
|
+
}
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
function getLegacyClaudeHookSettings() {
|
|
1336
|
+
return {
|
|
1337
|
+
success: true,
|
|
1338
|
+
stopHook: parseStopHookStatus(readClaudeSettings()),
|
|
1339
|
+
feishu: getFeishuConfig(),
|
|
1340
|
+
platform: os.platform()
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
function saveLegacyClaudeHookSettings(input = {}) {
|
|
1345
|
+
const currentSettings = getNotificationSettings();
|
|
1346
|
+
saveNotificationSettings(buildLegacyClaudeSaveInput(input, currentSettings));
|
|
1347
|
+
return getLegacyClaudeHookSettings();
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
function initDefaultHooks() {
|
|
1351
|
+
try {
|
|
1352
|
+
const uiConfig = loadUIConfig();
|
|
1353
|
+
if (uiConfig.claudeNotificationDisabledByUser === true) {
|
|
1354
|
+
console.log('[Claude Hooks] 用户已主动关闭通知,跳过自动初始化');
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
const currentClaudeSettings = readClaudeSettings();
|
|
1359
|
+
const currentStatus = parseStopHookStatus(currentClaudeSettings);
|
|
1360
|
+
|
|
1361
|
+
if (currentStatus.enabled) {
|
|
1362
|
+
if (shouldRepairStopHook(currentClaudeSettings)) {
|
|
1363
|
+
const currentSettings = getNotificationSettings();
|
|
1364
|
+
saveNotificationSettings({
|
|
1365
|
+
platforms: {
|
|
1366
|
+
claude: { enabled: true, type: currentStatus.type || 'notification' },
|
|
1367
|
+
codex: normalizeSavedPlatformStatus(currentSettings?.platforms?.codex),
|
|
1368
|
+
gemini: normalizeSavedPlatformStatus(currentSettings?.platforms?.gemini),
|
|
1369
|
+
opencode: normalizeSavedPlatformStatus(currentSettings?.platforms?.opencode)
|
|
1370
|
+
},
|
|
1371
|
+
feishu: {
|
|
1372
|
+
enabled: currentSettings?.feishu?.enabled === true,
|
|
1373
|
+
webhookUrl: currentSettings?.feishu?.webhookUrl || ''
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
1376
|
+
console.log('[Claude Hooks] 检测到旧版 Stop hook 路径,已自动修复');
|
|
1377
|
+
} else {
|
|
1378
|
+
console.log('[Claude Hooks] 已存在 Stop hook 配置,跳过初始化');
|
|
1379
|
+
}
|
|
1380
|
+
return;
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
const currentSettings = getNotificationSettings();
|
|
1384
|
+
saveNotificationSettings({
|
|
1385
|
+
platforms: {
|
|
1386
|
+
claude: { enabled: true, type: 'notification' },
|
|
1387
|
+
codex: normalizeSavedPlatformStatus(currentSettings?.platforms?.codex),
|
|
1388
|
+
gemini: normalizeSavedPlatformStatus(currentSettings?.platforms?.gemini),
|
|
1389
|
+
opencode: normalizeSavedPlatformStatus(currentSettings?.platforms?.opencode)
|
|
1390
|
+
},
|
|
1391
|
+
feishu: {
|
|
1392
|
+
enabled: currentSettings?.feishu?.enabled === true,
|
|
1393
|
+
webhookUrl: currentSettings?.feishu?.webhookUrl || ''
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1396
|
+
console.log('[Claude Hooks] 已自动开启任务完成通知(右上角卡片)');
|
|
1397
|
+
} catch (error) {
|
|
1398
|
+
console.error('[Claude Hooks] 初始化默认配置失败:', error);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
|
|
903
1402
|
function sendFeishuTest(webhookUrl) {
|
|
904
1403
|
return new Promise((resolve, reject) => {
|
|
905
1404
|
try {
|
|
@@ -965,7 +1464,7 @@ function generateSystemNotificationCommand(type, message, platformOverride = os.
|
|
|
965
1464
|
if (platform === 'win32') {
|
|
966
1465
|
const popupCommand = buildWindowsPopupCommand(title, message);
|
|
967
1466
|
if (normalizedType === 'dialog') {
|
|
968
|
-
return `powershell -NoProfile -Command "Add-Type -AssemblyName PresentationFramework; [System.Windows.MessageBox]::Show('${escapeForPowerShellSingleQuote(message)}', '${escapeForPowerShellSingleQuote(title)}', 'OK', 'Information')" || ${popupCommand}`;
|
|
1467
|
+
return `powershell -NoProfile -STA -Command "Add-Type -AssemblyName PresentationFramework; [System.Windows.MessageBox]::Show('${escapeForPowerShellSingleQuote(message)}', '${escapeForPowerShellSingleQuote(title)}', 'OK', 'Information')" || ${popupCommand}`;
|
|
969
1468
|
}
|
|
970
1469
|
return popupCommand;
|
|
971
1470
|
}
|
|
@@ -988,8 +1487,11 @@ function testNotification({ type, testFeishu, webhookUrl } = {}) {
|
|
|
988
1487
|
module.exports = {
|
|
989
1488
|
MANAGED_HOOK_NAME,
|
|
990
1489
|
getNotificationSettings,
|
|
1490
|
+
getLegacyClaudeHookSettings,
|
|
991
1491
|
saveNotificationSettings,
|
|
1492
|
+
saveLegacyClaudeHookSettings,
|
|
992
1493
|
testNotification,
|
|
1494
|
+
initDefaultHooks,
|
|
993
1495
|
getOpenCodeManagedPluginPath,
|
|
994
1496
|
buildOpenCodePluginContent,
|
|
995
1497
|
buildCodexNotifyCommand,
|
|
@@ -999,6 +1501,7 @@ module.exports = {
|
|
|
999
1501
|
applyClaudeDisablePreference,
|
|
1000
1502
|
getManagedCommandType,
|
|
1001
1503
|
parseManagedType,
|
|
1504
|
+
parseNotifyTypeMarker,
|
|
1002
1505
|
getClaudeHookStatus,
|
|
1003
1506
|
getCodexHookStatus,
|
|
1004
1507
|
getGeminiHookStatus,
|
|
@@ -1009,10 +1512,13 @@ module.exports = {
|
|
|
1009
1512
|
validateFeishuWebhookUrl,
|
|
1010
1513
|
buildCodexNotifyCommand,
|
|
1011
1514
|
buildGeminiCommand,
|
|
1515
|
+
buildStopHookCommand,
|
|
1012
1516
|
buildClaudeCommand,
|
|
1013
1517
|
buildOpenCodePluginContent,
|
|
1014
1518
|
getOpenCodeManagedPluginPath,
|
|
1015
1519
|
generateNotifyScript,
|
|
1016
|
-
generateSystemNotificationCommand
|
|
1520
|
+
generateSystemNotificationCommand,
|
|
1521
|
+
parseStopHookStatus,
|
|
1522
|
+
shouldRepairStopHook
|
|
1017
1523
|
}
|
|
1018
1524
|
};
|