The task now runs scheduling\run-sync.ps1 instead of an inline cmd.exe loop: every provider is attempted, a run that dies without the app's own report pushes a high-priority FAILED with the exception class only, and each run's output is appended to cache\logs\scheduled-sync.log because Task Scheduler keeps none. Verified under PowerShell 7.6 on Linux with a stand-in cmd.exe; not yet run under Windows PowerShell 5.1 or Task Scheduler. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019rwKTmug58sEsJ72AuWsEi
95 lines
3.7 KiB
PowerShell
95 lines
3.7 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Register a Windows scheduled task that runs `ai-chat-exporter sync` daily.
|
|
|
|
.DESCRIPTION
|
|
The Windows counterpart to install-systemd-timer.sh. Creates a per-user task
|
|
(no admin rights needed) that runs the exporter from this repository, with
|
|
the working directory set to the repo so .env, cache\ and exports\ resolve
|
|
exactly as they do for an interactive run.
|
|
|
|
-Provider is repeatable. The CLI takes one provider per run, so each becomes
|
|
its own action, executed in order. List only the providers that work
|
|
unattended on this machine: a web provider whose session token has expired
|
|
fails the task every day, which trains you to ignore the failures you
|
|
actually want to notice.
|
|
|
|
.EXAMPLE
|
|
.\scheduling\Register-AiChatSyncTask.ps1 -Provider chatgpt,claude
|
|
|
|
.EXAMPLE
|
|
.\scheduling\Register-AiChatSyncTask.ps1 -Provider all -Time 21:30
|
|
|
|
.EXAMPLE
|
|
.\scheduling\Register-AiChatSyncTask.ps1 -Unregister
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[string[]]$Provider = @('all'),
|
|
[string]$Time = '09:00',
|
|
[string]$TaskName = 'AiChatExporterSync',
|
|
[switch]$Unregister
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$repo = Split-Path -Parent $PSScriptRoot
|
|
$launcher = Join-Path $repo 'ai-chat-exporter.cmd'
|
|
$wrapper = Join-Path $PSScriptRoot 'run-sync.ps1'
|
|
|
|
if ($Unregister) {
|
|
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction SilentlyContinue
|
|
Write-Host "Removed scheduled task '$TaskName'."
|
|
return
|
|
}
|
|
|
|
foreach ($f in $launcher, $wrapper) {
|
|
if (-not (Test-Path $f)) { throw "Not found: $f" }
|
|
}
|
|
|
|
# One action running run-sync.ps1, rather than one action per provider: Task
|
|
# Scheduler runs multiple actions in order but reports only the last one's
|
|
# result, so a failure in an earlier provider would be invisible. The script
|
|
# keeps going after a failure, exits non-zero if any provider failed, and pushes
|
|
# a FAILED notification for any run that died without sending its own.
|
|
#
|
|
# Providers go as separate arguments: under -File, "chatgpt,claude" would arrive
|
|
# as one string. -WindowStyle Hidden because the output now goes to
|
|
# cache\logs\scheduled-sync.log, so the console window would only ever be blank.
|
|
$taskArgs = "-NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden " +
|
|
"-File `"$wrapper`" $($Provider -join ' ')"
|
|
$actions = New-ScheduledTaskAction -Execute 'powershell.exe' `
|
|
-Argument $taskArgs `
|
|
-WorkingDirectory $repo
|
|
|
|
$trigger = New-ScheduledTaskTrigger -Daily -At $Time
|
|
|
|
# StartWhenAvailable is the counterpart of systemd's Persistent=true: a machine
|
|
# that was asleep at the scheduled time runs the archive when it wakes, rather
|
|
# than skipping the day entirely.
|
|
$settings = New-ScheduledTaskSettingsSet `
|
|
-StartWhenAvailable `
|
|
-DontStopIfGoingOnBatteries `
|
|
-AllowStartIfOnBatteries `
|
|
-ExecutionTimeLimit (New-TimeSpan -Hours 2)
|
|
|
|
Register-ScheduledTask -TaskName $TaskName `
|
|
-Action $actions `
|
|
-Trigger $trigger `
|
|
-Settings $settings `
|
|
-Description 'Export AI chat history and sync it to Joplin' `
|
|
-Force | Out-Null
|
|
|
|
Write-Host "Registered '$TaskName' - daily at $Time for: $($Provider -join ', ')"
|
|
Write-Host ''
|
|
Write-Host 'Command the task will run:'
|
|
Write-Host " powershell.exe $taskArgs"
|
|
Write-Host " (working directory: $repo)"
|
|
Write-Host ''
|
|
Write-Host 'Next steps:'
|
|
Write-Host " * Run it once now: Start-ScheduledTask -TaskName $TaskName"
|
|
Write-Host " * Check the result: Get-ScheduledTaskInfo -TaskName $TaskName"
|
|
Write-Host " * Read the run output: Get-Content '$repo\cache\logs\scheduled-sync.log' -Tail 50"
|
|
Write-Host ' * The terms-of-service notice must have been acknowledged'
|
|
Write-Host ' interactively once on this machine, or the task exits 1.'
|