foliko 2.0.11 → 2.0.13

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/install.ps1 CHANGED
@@ -1,129 +1,129 @@
1
- # Foliko Installer
2
-
3
- # Fix execution policy first
4
- Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force -ErrorAction SilentlyContinue
5
-
6
- Write-Host "Foliko Installer"
7
- Write-Host "================="
8
- Write-Host ""
9
-
10
- # Refresh PATH
11
- $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
12
-
13
- # ============ Check/Install Node.js ============
14
- Write-Host "Checking Node.js..."
15
- if (Get-Command node -ErrorAction SilentlyContinue) {
16
- Write-Host "Node.js installed: $(node --version)" -ForegroundColor Green
17
- } else {
18
- Write-Host "Node.js not found, installing..." -ForegroundColor Yellow
19
-
20
- $nodeUrl = "https://nodejs.org/dist/v20.11.0/node-v20.11.0-x64.msi"
21
- $nodeInstaller = "$env:TEMP\node-installer.msi"
22
-
23
- Write-Host "Downloading Node.js..." -ForegroundColor Cyan
24
- Invoke-WebRequest -Uri $nodeUrl -OutFile $nodeInstaller -UseBasicParsing
25
-
26
- Write-Host "Installing Node.js (may require admin)..." -ForegroundColor Cyan
27
- Start-Process msiexec.exe -ArgumentList "/i", $nodeInstaller, "/quiet", "/norestart" -Wait
28
-
29
- $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
30
- Start-Sleep -Seconds 3
31
-
32
- if (Get-Command node -ErrorAction SilentlyContinue) {
33
- Write-Host "Node.js installed: $(node --version)" -ForegroundColor Green
34
- Remove-Item $nodeInstaller -Force -ErrorAction SilentlyContinue
35
- } else {
36
- Write-Host "Node.js installation failed" -ForegroundColor Red
37
- Write-Host "Download manually: https://nodejs.org/" -ForegroundColor Yellow
38
- }
39
- }
40
- Write-Host ""
41
-
42
- # ============ Check/Install Python ============
43
- Write-Host "Checking Python..."
44
- if (Get-Command python -ErrorAction SilentlyContinue) {
45
- Write-Host "Python installed: $(python --version)" -ForegroundColor Green
46
- } else {
47
- Write-Host "Python not found, installing..." -ForegroundColor Yellow
48
-
49
- $pythonUrl = "https://www.python.org/ftp/python/3.12.1/python-3.12.1-amd64.exe"
50
- $pythonInstaller = "$env:TEMP\python-installer.exe"
51
-
52
- Write-Host "Downloading Python..." -ForegroundColor Cyan
53
- Invoke-WebRequest -Uri $pythonUrl -OutFile $pythonInstaller -UseBasicParsing
54
-
55
- Write-Host "Installing Python (may require admin)..." -ForegroundColor Cyan
56
- Start-Process $pythonInstaller -ArgumentList "/quiet", "InstallAllUsers=1", "PrependPath=1", "Include_pip=1" -Wait
57
-
58
- $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
59
- Start-Sleep -Seconds 3
60
-
61
- if (Get-Command python -ErrorAction SilentlyContinue) {
62
- Write-Host "Python installed: $(python --version)" -ForegroundColor Green
63
- Remove-Item $pythonInstaller -Force -ErrorAction SilentlyContinue
64
- } else {
65
- Write-Host "Python installation failed" -ForegroundColor Red
66
- Write-Host "Download manually: https://www.python.org/downloads/" -ForegroundColor Yellow
67
- }
68
- }
69
- Write-Host ""
70
-
71
- # ============ Check/Install uv ============
72
- Write-Host "Checking uv..."
73
- if (Get-Command uv -ErrorAction SilentlyContinue) {
74
- Write-Host "uv installed: $(uv --version)" -ForegroundColor Green
75
- } else {
76
- Write-Host "uv not found, installing..." -ForegroundColor Yellow
77
-
78
- try {
79
- Write-Host "Downloading uv..." -ForegroundColor Cyan
80
- Invoke-WebRequest -Uri "https://astral.sh/uv/install.ps1" -OutFile "$env:TEMP\install-uv.ps1" -UseBasicParsing
81
- powershell -ExecutionPolicy Bypass -File "$env:TEMP\install-uv.ps1" -Version "0.4.0" -PowerShell -Admin
82
- Remove-Item "$env:TEMP\install-uv.ps1" -Force -ErrorAction SilentlyContinue
83
-
84
- $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
85
-
86
- if (Get-Command uv -ErrorAction SilentlyContinue) {
87
- Write-Host "uv installed: $(uv --version)" -ForegroundColor Green
88
- }
89
- } catch {
90
- Write-Host "uv installation failed (optional, can be skipped)" -ForegroundColor Yellow
91
- }
92
- }
93
- Write-Host ""
94
-
95
- # ============ Clean npm cache and install Foliko ============
96
- Write-Host "Cleaning npm cache..." -ForegroundColor Cyan
97
- npm cache clean --force 2>$null | Out-Null
98
-
99
- Write-Host "Installing Foliko..." -ForegroundColor Cyan
100
- npm install -g foliko --ignore-scripts 2>&1 | Out-Null
101
-
102
- # Get npm global bin path
103
- $npmPrefix = npm config get prefix 2>$null
104
- $npmBinPath = $npmPrefix -replace "\\$", ""
105
-
106
- # Add to PATH permanently for current user
107
- $userPath = [Environment]::GetEnvironmentVariable("Path", "User")
108
- if ($userPath -notlike "*$npmBinPath*") {
109
- [Environment]::SetEnvironmentVariable("Path", "$userPath;$npmBinPath", "User")
110
- }
111
-
112
- # Also add to current session PATH
113
- $env:Path = "$npmBinPath;$env:Path"
114
- Start-Sleep -Seconds 2
115
-
116
- # Check if installation succeeded
117
- if (Test-Path "$npmBinPath\foliko.cmd") {
118
- Write-Host ""
119
- Write-Host "Installation complete!" -ForegroundColor Green
120
- Write-Host ""
121
- Write-Host "Please restart your terminal or run:" -ForegroundColor Cyan
122
- Write-Host ' $env:Path = "C:\Users\Administrator\AppData\Roaming\npm;' + '$env:Path"' -ForegroundColor White
123
- Write-Host ""
124
- Write-Host "Then run: foliko chat" -ForegroundColor Yellow
125
- } else {
126
- Write-Host ""
127
- Write-Host "Installation may have failed." -ForegroundColor Yellow
128
- Write-Host "Run: npm install -g foliko"
129
- }
1
+ # Foliko Installer
2
+
3
+ # Fix execution policy first
4
+ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force -ErrorAction SilentlyContinue
5
+
6
+ Write-Host "Foliko Installer"
7
+ Write-Host "================="
8
+ Write-Host ""
9
+
10
+ # Refresh PATH
11
+ $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
12
+
13
+ # ============ Check/Install Node.js ============
14
+ Write-Host "Checking Node.js..."
15
+ if (Get-Command node -ErrorAction SilentlyContinue) {
16
+ Write-Host "Node.js installed: $(node --version)" -ForegroundColor Green
17
+ } else {
18
+ Write-Host "Node.js not found, installing..." -ForegroundColor Yellow
19
+
20
+ $nodeUrl = "https://nodejs.org/dist/v20.11.0/node-v20.11.0-x64.msi"
21
+ $nodeInstaller = "$env:TEMP\node-installer.msi"
22
+
23
+ Write-Host "Downloading Node.js..." -ForegroundColor Cyan
24
+ Invoke-WebRequest -Uri $nodeUrl -OutFile $nodeInstaller -UseBasicParsing
25
+
26
+ Write-Host "Installing Node.js (may require admin)..." -ForegroundColor Cyan
27
+ Start-Process msiexec.exe -ArgumentList "/i", $nodeInstaller, "/quiet", "/norestart" -Wait
28
+
29
+ $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
30
+ Start-Sleep -Seconds 3
31
+
32
+ if (Get-Command node -ErrorAction SilentlyContinue) {
33
+ Write-Host "Node.js installed: $(node --version)" -ForegroundColor Green
34
+ Remove-Item $nodeInstaller -Force -ErrorAction SilentlyContinue
35
+ } else {
36
+ Write-Host "Node.js installation failed" -ForegroundColor Red
37
+ Write-Host "Download manually: https://nodejs.org/" -ForegroundColor Yellow
38
+ }
39
+ }
40
+ Write-Host ""
41
+
42
+ # ============ Check/Install Python ============
43
+ Write-Host "Checking Python..."
44
+ if (Get-Command python -ErrorAction SilentlyContinue) {
45
+ Write-Host "Python installed: $(python --version)" -ForegroundColor Green
46
+ } else {
47
+ Write-Host "Python not found, installing..." -ForegroundColor Yellow
48
+
49
+ $pythonUrl = "https://www.python.org/ftp/python/3.12.1/python-3.12.1-amd64.exe"
50
+ $pythonInstaller = "$env:TEMP\python-installer.exe"
51
+
52
+ Write-Host "Downloading Python..." -ForegroundColor Cyan
53
+ Invoke-WebRequest -Uri $pythonUrl -OutFile $pythonInstaller -UseBasicParsing
54
+
55
+ Write-Host "Installing Python (may require admin)..." -ForegroundColor Cyan
56
+ Start-Process $pythonInstaller -ArgumentList "/quiet", "InstallAllUsers=1", "PrependPath=1", "Include_pip=1" -Wait
57
+
58
+ $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
59
+ Start-Sleep -Seconds 3
60
+
61
+ if (Get-Command python -ErrorAction SilentlyContinue) {
62
+ Write-Host "Python installed: $(python --version)" -ForegroundColor Green
63
+ Remove-Item $pythonInstaller -Force -ErrorAction SilentlyContinue
64
+ } else {
65
+ Write-Host "Python installation failed" -ForegroundColor Red
66
+ Write-Host "Download manually: https://www.python.org/downloads/" -ForegroundColor Yellow
67
+ }
68
+ }
69
+ Write-Host ""
70
+
71
+ # ============ Check/Install uv ============
72
+ Write-Host "Checking uv..."
73
+ if (Get-Command uv -ErrorAction SilentlyContinue) {
74
+ Write-Host "uv installed: $(uv --version)" -ForegroundColor Green
75
+ } else {
76
+ Write-Host "uv not found, installing..." -ForegroundColor Yellow
77
+
78
+ try {
79
+ Write-Host "Downloading uv..." -ForegroundColor Cyan
80
+ Invoke-WebRequest -Uri "https://astral.sh/uv/install.ps1" -OutFile "$env:TEMP\install-uv.ps1" -UseBasicParsing
81
+ powershell -ExecutionPolicy Bypass -File "$env:TEMP\install-uv.ps1" -Version "0.4.0" -PowerShell -Admin
82
+ Remove-Item "$env:TEMP\install-uv.ps1" -Force -ErrorAction SilentlyContinue
83
+
84
+ $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
85
+
86
+ if (Get-Command uv -ErrorAction SilentlyContinue) {
87
+ Write-Host "uv installed: $(uv --version)" -ForegroundColor Green
88
+ }
89
+ } catch {
90
+ Write-Host "uv installation failed (optional, can be skipped)" -ForegroundColor Yellow
91
+ }
92
+ }
93
+ Write-Host ""
94
+
95
+ # ============ Clean npm cache and install Foliko ============
96
+ Write-Host "Cleaning npm cache..." -ForegroundColor Cyan
97
+ npm cache clean --force 2>$null | Out-Null
98
+
99
+ Write-Host "Installing Foliko..." -ForegroundColor Cyan
100
+ npm install -g foliko --ignore-scripts 2>&1 | Out-Null
101
+
102
+ # Get npm global bin path
103
+ $npmPrefix = npm config get prefix 2>$null
104
+ $npmBinPath = $npmPrefix -replace "\\$", ""
105
+
106
+ # Add to PATH permanently for current user
107
+ $userPath = [Environment]::GetEnvironmentVariable("Path", "User")
108
+ if ($userPath -notlike "*$npmBinPath*") {
109
+ [Environment]::SetEnvironmentVariable("Path", "$userPath;$npmBinPath", "User")
110
+ }
111
+
112
+ # Also add to current session PATH
113
+ $env:Path = "$npmBinPath;$env:Path"
114
+ Start-Sleep -Seconds 2
115
+
116
+ # Check if installation succeeded
117
+ if (Test-Path "$npmBinPath\foliko.cmd") {
118
+ Write-Host ""
119
+ Write-Host "Installation complete!" -ForegroundColor Green
120
+ Write-Host ""
121
+ Write-Host "Please restart your terminal or run:" -ForegroundColor Cyan
122
+ Write-Host ' $env:Path = "C:\Users\Administrator\AppData\Roaming\npm;' + '$env:Path"' -ForegroundColor White
123
+ Write-Host ""
124
+ Write-Host "Then run: foliko chat" -ForegroundColor Yellow
125
+ } else {
126
+ Write-Host ""
127
+ Write-Host "Installation may have failed." -ForegroundColor Yellow
128
+ Write-Host "Run: npm install -g foliko"
129
+ }
package/install.sh CHANGED
@@ -1,121 +1,121 @@
1
- #!/bin/bash
2
- # Foliko Installer
3
-
4
- set -e
5
-
6
- echo -e "\033[36mFoliko Installer\033[0m"
7
- echo -e "\033[36m=================\033[0m"
8
- echo ""
9
-
10
- # Detect OS
11
- detect_os() {
12
- if [[ "$OSTYPE" == "darwin"* ]]; then
13
- echo "macOS"
14
- elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
15
- echo "Linux"
16
- else
17
- echo "unknown"
18
- fi
19
- }
20
-
21
- OS=$(detect_os)
22
-
23
- # ============ Check/Install Node.js ============
24
- echo -e "\033[36mChecking Node.js...\033[0m"
25
- if command -v node &> /dev/null; then
26
- echo -e "\033[32mNode.js installed: $(node --version)\033[0m"
27
- else
28
- echo -e "\033[33mNode.js not found, installing...\033[0m"
29
-
30
- if [[ "$OS" == "macOS" ]]; then
31
- if command -v brew &> /dev/null; then
32
- brew install node
33
- else
34
- echo -e "\033[31mHomebrew not found. Install it first:\033[0m"
35
- echo "/bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
36
- exit 1
37
- fi
38
- elif [[ "$OS" == "Linux" ]]; then
39
- if command -v apt-get &> /dev/null; then
40
- sudo apt-get update && sudo apt-get install -y nodejs npm
41
- elif command -v yum &> /dev/null; then
42
- sudo yum install -y nodejs npm
43
- elif command -v pacman &> /dev/null; then
44
- sudo pacman -S nodejs npm
45
- else
46
- echo -e "\033[31mNo package manager found. Install Node.js manually: https://nodejs.org/\033[0m"
47
- exit 1
48
- fi
49
- fi
50
-
51
- if command -v node &> /dev/null; then
52
- echo -e "\033[32mNode.js installed: $(node --version)\033[0m"
53
- else
54
- echo -e "\033[31mNode.js installation failed\033[0m"
55
- exit 1
56
- fi
57
- fi
58
- echo ""
59
-
60
- # ============ Check/Install Python ============
61
- echo -e "\033[36mChecking Python...\033[0m"
62
- if command -v python3 &> /dev/null; then
63
- echo -e "\033[32mPython installed: $(python3 --version)\033[0m"
64
- else
65
- echo -e "\033[33mPython not found, installing...\033[0m"
66
-
67
- if [[ "$OS" == "macOS" ]]; then
68
- if command -v brew &> /dev/null; then
69
- brew install python3
70
- fi
71
- elif [[ "$OS" == "Linux" ]]; then
72
- if command -v apt-get &> /dev/null; then
73
- sudo apt-get update && sudo apt-get install -y python3 python3-venv python3-pip
74
- elif command -v yum &> /dev/null; then
75
- sudo yum install -y python3
76
- elif command -v pacman &> /dev/null; then
77
- sudo pacman -S python python-pip
78
- fi
79
- fi
80
-
81
- if command -v python3 &> /dev/null; then
82
- echo -e "\033[32mPython installed: $(python3 --version)\033[0m"
83
- else
84
- echo -e "\033[33mPython installation failed (optional)\033[0m"
85
- fi
86
- fi
87
- echo ""
88
-
89
- # ============ Check/Install uv ============
90
- echo -e "\033[36mChecking uv...\033[0m"
91
- if command -v uv &> /dev/null; then
92
- echo -e "\033[32muv installed: $(uv --version)\033[0m"
93
- else
94
- echo -e "\033[33muv not found, installing...\033[0m"
95
-
96
- if [[ "$OS" == "macOS" ]] || [[ "$OS" == "Linux" ]]; then
97
- curl -LsSf https://astral.sh/uv/install.sh | sh
98
- source $HOME/.local/bin/env 2>/dev/null || true
99
-
100
- if command -v uv &> /dev/null; then
101
- echo -e "\033[32muv installed: $(uv --version)\033[0m"
102
- else
103
- echo -e "\033[33muv installation failed (optional)\033[0m"
104
- fi
105
- fi
106
- fi
107
- echo ""
108
-
109
- # ============ Install Foliko ============
110
- echo -e "\033[36mInstalling Foliko...\033[0m"
111
- npm install -g foliko
112
-
113
- if command -v foliko &> /dev/null; then
114
- echo ""
115
- echo -e "\033[32mInstallation complete!\033[0m"
116
- echo "Run: foliko chat"
117
- else
118
- echo ""
119
- echo -e "\033[31mInstallation failed. Try manually: npm install -g foliko\033[0m"
120
- exit 1
121
- fi
1
+ #!/bin/bash
2
+ # Foliko Installer
3
+
4
+ set -e
5
+
6
+ echo -e "\033[36mFoliko Installer\033[0m"
7
+ echo -e "\033[36m=================\033[0m"
8
+ echo ""
9
+
10
+ # Detect OS
11
+ detect_os() {
12
+ if [[ "$OSTYPE" == "darwin"* ]]; then
13
+ echo "macOS"
14
+ elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
15
+ echo "Linux"
16
+ else
17
+ echo "unknown"
18
+ fi
19
+ }
20
+
21
+ OS=$(detect_os)
22
+
23
+ # ============ Check/Install Node.js ============
24
+ echo -e "\033[36mChecking Node.js...\033[0m"
25
+ if command -v node &> /dev/null; then
26
+ echo -e "\033[32mNode.js installed: $(node --version)\033[0m"
27
+ else
28
+ echo -e "\033[33mNode.js not found, installing...\033[0m"
29
+
30
+ if [[ "$OS" == "macOS" ]]; then
31
+ if command -v brew &> /dev/null; then
32
+ brew install node
33
+ else
34
+ echo -e "\033[31mHomebrew not found. Install it first:\033[0m"
35
+ echo "/bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
36
+ exit 1
37
+ fi
38
+ elif [[ "$OS" == "Linux" ]]; then
39
+ if command -v apt-get &> /dev/null; then
40
+ sudo apt-get update && sudo apt-get install -y nodejs npm
41
+ elif command -v yum &> /dev/null; then
42
+ sudo yum install -y nodejs npm
43
+ elif command -v pacman &> /dev/null; then
44
+ sudo pacman -S nodejs npm
45
+ else
46
+ echo -e "\033[31mNo package manager found. Install Node.js manually: https://nodejs.org/\033[0m"
47
+ exit 1
48
+ fi
49
+ fi
50
+
51
+ if command -v node &> /dev/null; then
52
+ echo -e "\033[32mNode.js installed: $(node --version)\033[0m"
53
+ else
54
+ echo -e "\033[31mNode.js installation failed\033[0m"
55
+ exit 1
56
+ fi
57
+ fi
58
+ echo ""
59
+
60
+ # ============ Check/Install Python ============
61
+ echo -e "\033[36mChecking Python...\033[0m"
62
+ if command -v python3 &> /dev/null; then
63
+ echo -e "\033[32mPython installed: $(python3 --version)\033[0m"
64
+ else
65
+ echo -e "\033[33mPython not found, installing...\033[0m"
66
+
67
+ if [[ "$OS" == "macOS" ]]; then
68
+ if command -v brew &> /dev/null; then
69
+ brew install python3
70
+ fi
71
+ elif [[ "$OS" == "Linux" ]]; then
72
+ if command -v apt-get &> /dev/null; then
73
+ sudo apt-get update && sudo apt-get install -y python3 python3-venv python3-pip
74
+ elif command -v yum &> /dev/null; then
75
+ sudo yum install -y python3
76
+ elif command -v pacman &> /dev/null; then
77
+ sudo pacman -S python python-pip
78
+ fi
79
+ fi
80
+
81
+ if command -v python3 &> /dev/null; then
82
+ echo -e "\033[32mPython installed: $(python3 --version)\033[0m"
83
+ else
84
+ echo -e "\033[33mPython installation failed (optional)\033[0m"
85
+ fi
86
+ fi
87
+ echo ""
88
+
89
+ # ============ Check/Install uv ============
90
+ echo -e "\033[36mChecking uv...\033[0m"
91
+ if command -v uv &> /dev/null; then
92
+ echo -e "\033[32muv installed: $(uv --version)\033[0m"
93
+ else
94
+ echo -e "\033[33muv not found, installing...\033[0m"
95
+
96
+ if [[ "$OS" == "macOS" ]] || [[ "$OS" == "Linux" ]]; then
97
+ curl -LsSf https://astral.sh/uv/install.sh | sh
98
+ source $HOME/.local/bin/env 2>/dev/null || true
99
+
100
+ if command -v uv &> /dev/null; then
101
+ echo -e "\033[32muv installed: $(uv --version)\033[0m"
102
+ else
103
+ echo -e "\033[33muv installation failed (optional)\033[0m"
104
+ fi
105
+ fi
106
+ fi
107
+ echo ""
108
+
109
+ # ============ Install Foliko ============
110
+ echo -e "\033[36mInstalling Foliko...\033[0m"
111
+ npm install -g foliko
112
+
113
+ if command -v foliko &> /dev/null; then
114
+ echo ""
115
+ echo -e "\033[32mInstallation complete!\033[0m"
116
+ echo "Run: foliko chat"
117
+ else
118
+ echo ""
119
+ echo -e "\033[31mInstallation failed. Try manually: npm install -g foliko\033[0m"
120
+ exit 1
121
+ fi
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foliko",
3
- "version": "2.0.11",
3
+ "version": "2.0.13",
4
4
  "description": "简约的插件化 Agent 框架",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -340,6 +340,7 @@ class SchedulerPlugin extends Plugin {
340
340
  }),
341
341
  });
342
342
 
343
+ log.info(` [start] Scheduler 插件启动,当前时间: ${new Date().toISOString()} timezone=${this.config.timezone}`);
343
344
  this._loadPersistedTasks();
344
345
  return this;
345
346
  }
@@ -432,7 +433,11 @@ class SchedulerPlugin extends Plugin {
432
433
  // once:startAt 限定未来触发
433
434
  task.scheduleHandle = new Cron(runAt, this._cronOptions(task), () => this._onFire(task));
434
435
  }
436
+ // 打印下次执行时间便于调试
437
+ const nextRun = task.scheduleHandle.nextRun();
438
+ log.info(` [_createTask] 创建任务成功: ${task.name} cron="${cron || ''}" 下次执行: ${nextRun ? nextRun.toISOString() : 'once-立即?'} timezone=${task.timezone}`);
435
439
  } catch (err) {
440
+ log.error(` [_createTask] 创建调度失败: ${err.message}`);
436
441
  return { success: false, error: `调度创建失败: ${err.message}` };
437
442
  }
438
443
 
@@ -465,30 +470,39 @@ class SchedulerPlugin extends Plugin {
465
470
  }
466
471
 
467
472
  _cronOptions(task) {
468
- return {
473
+ const opts = {
469
474
  timezone: this.config.timezone,
470
475
  protect: true, // 防重叠:上一次还没跑完,跳过本次
471
476
  catch: true, // catch-up:进程恢复后补触发错过的触发
472
477
  name: `scheduler:${task.id}`,
473
478
  unref: true, // 不阻止进程退出
474
479
  };
480
+ log.debug(` [_cronOptions] task=${task.name} cron=${task.cronExpression || 'once'} timezone=${opts.timezone}`);
481
+ return opts;
475
482
  }
476
483
 
477
484
  // ============================================================
478
485
  // 触发回调
479
486
  // ============================================================
480
487
  async _onFire(task) {
481
- if (!task.enabled) return;
488
+ log.info(` [_onFire] >>> 任务触发: ${task.name} (id=${task.id}) cron=${task.cronExpression || 'once'} timezone=${task.timezone}`);
489
+
490
+ if (!task.enabled) {
491
+ log.warn(` [_onFire] 任务 ${task.name} 已禁用,跳过`);
492
+ return;
493
+ }
482
494
  if (task.running) {
483
495
  // 理论上 protect:true 已经处理过;这里再保险一次
484
- log.warn(` 任务 ${task.name} 仍在执行中,跳过本次触发`);
496
+ log.warn(` [_onFire] 任务 ${task.name} 仍在执行中,跳过本次触发`);
485
497
  return;
486
498
  }
487
499
  task.running = true;
488
500
  task.lastRun = new Date();
489
501
  task.runCount++;
502
+ log.info(` [_onFire] 开始执行任务: ${task.name} (第${task.runCount}次)`);
490
503
  try {
491
504
  await this._executeTask(task);
505
+ log.info(` [_onFire] <<< 任务执行完成: ${task.name}`);
492
506
  } finally {
493
507
  task.running = false;
494
508
  }
@@ -890,12 +904,20 @@ class SchedulerPlugin extends Plugin {
890
904
  // ============================================================
891
905
  _loadPersistedTasks() {
892
906
  const savedTasks = this._taskStore.loadTasks();
893
- if (!savedTasks || savedTasks.length === 0) return;
907
+ log.info(` [_loadPersistedTasks] 开始加载任务,当前时间: ${new Date().toISOString()}`);
908
+ if (!savedTasks || savedTasks.length === 0) {
909
+ log.info(` [_loadPersistedTasks] 没有已保存的任务`);
910
+ return;
911
+ }
912
+ log.info(` [_loadPersistedTasks] 从磁盘加载了 ${savedTasks.length} 个任务`);
894
913
  const now = Date.now();
895
914
 
896
915
  for (const saved of savedTasks) {
897
916
  // 已完成的 once 任务不再恢复
898
- if (saved.type === 'once' && (saved.runCount || 0) > 0) continue;
917
+ if (saved.type === 'once' && (saved.runCount || 0) > 0) {
918
+ log.debug(` [_loadPersistedTasks] 跳过已完成的 once 任务: ${saved.name}`);
919
+ continue;
920
+ }
899
921
 
900
922
  const task = {
901
923
  ...saved,
@@ -910,19 +932,25 @@ class SchedulerPlugin extends Plugin {
910
932
  try {
911
933
  if (task.type === 'cron' && task.enabled && task.cronExpression) {
912
934
  task.scheduleHandle = new Cron(task.cronExpression, this._cronOptions(task), () => this._onFire(task));
935
+ const nextRun = task.scheduleHandle.nextRun();
936
+ log.info(` [_loadPersistedTasks] 恢复 cron 任务: ${task.name} cron="${task.cronExpression}" 下次执行: ${nextRun ? nextRun.toISOString() : 'N/A'}`);
913
937
  this._tasks.set(task.id, task);
914
938
  } else if (task.type === 'once' && task.enabled) {
915
- if (!task.runAt) continue;
939
+ if (!task.runAt) {
940
+ log.warn(` [_loadPersistedTasks] 跳过没有 runAt 的 once 任务: ${task.name}`);
941
+ continue;
942
+ }
916
943
  const fireAt = task.runAt.getTime();
917
944
  if (fireAt <= now) {
918
945
  // 已过期:超过 grace period 就丢弃
919
946
  if (now - fireAt > ONCE_EXPIRY_GRACE_MS) {
920
- log.warn(` 丢弃过期任务 ${task.name}(已过期 ${Math.round((now - fireAt) / 1000)}s,超出 24h 容忍期)`);
947
+ log.warn(` [_loadPersistedTasks] 丢弃过期任务 ${task.name}(已过期 ${Math.round((now - fireAt) / 1000)}s,超出 24h 容忍期)`);
921
948
  continue;
922
949
  }
923
950
  // B4/B5 修复:catchup 也用 croner 调度过去时间,croner 会立即触发;
924
951
  // stop() 能真正取消,update 走 stop()+new Cron() 不会双触发
925
952
  // protect:false 是因为"补触发"不应被 startup 期间的并发阻塞
953
+ log.info(` [_loadPersistedTasks] 恢复过期的 once 任务(立即触发): ${task.name} 原定执行: ${task.runAt.toISOString()}`);
926
954
  task.scheduleHandle = new Cron(task.runAt, {
927
955
  ...this._cronOptions(task),
928
956
  protect: false,
@@ -930,15 +958,18 @@ class SchedulerPlugin extends Plugin {
930
958
  this._tasks.set(task.id, task);
931
959
  } else {
932
960
  // 未来触发
961
+ log.info(` [_loadPersistedTasks] 恢复 future once 任务: ${task.name} 执行时间: ${task.runAt.toISOString()}`);
933
962
  task.scheduleHandle = new Cron(task.runAt, this._cronOptions(task), () => this._onFire(task));
934
963
  this._tasks.set(task.id, task);
935
964
  }
965
+ } else {
966
+ log.debug(` [_loadPersistedTasks] 跳过任务: ${task.name} type=${task.type} enabled=${task.enabled}`);
936
967
  }
937
968
  } catch (err) {
938
- log.error(` 恢复任务失败: ${task.name}`, err.message);
969
+ log.error(` [_loadPersistedTasks] 恢复任务失败: ${task.name}`, err.message);
939
970
  }
940
971
  }
941
- log.info(` 已恢复 ${this._tasks.size} 个定时任务`);
972
+ log.info(` [_loadPersistedTasks] 完成,共恢复 ${this._tasks.size} 个定时任务`);
942
973
  }
943
974
 
944
975
  // ============================================================