summrise-agent 1.2.491 → 1.2.492

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/bin/summrise.js CHANGED
@@ -310,8 +310,42 @@ exports.psq = psq;
310
310
  * silently reverts to the backing executable (stock `electron.exe`, since the shell runs
311
311
  * unpackaged) with nothing on the device to read that says why.
312
312
  * PowerShell/Windows AppUserModelIDs cannot contain spaces, and this one does not.
313
+ *
314
+ * WHY IT IS NOT `online.saisi.summrise.agent`, WHICH IS WHAT IT WAS CALLED BEFORE —
315
+ * MEASURED on desktop-14rjcr8 (release 1.2.490), ONE VARIABLE AT A TIME:
316
+ *
317
+ * | window's AppUserModelID | shortcut carries it | taskbar draws |
318
+ * | window's AppUserModelID | shortcuts carrying it | taskbar draws |
319
+ * | online.saisi.summrise.agent | both desktops + Start Menu | Electron logo |
320
+ * | online.saisi.summrise.desktop | both desktops + Start Menu | THE SUNRISE |
321
+ * | online.saisi.summrise.desktop | both desktops, Start Menu GONE | Electron logo |
322
+ *
323
+ * That third row is the one that decides where the identity has to live, and it was taken
324
+ * WITHOUT restarting anything: the same running shell, the same AppUserModelID already set,
325
+ * and the icon fell back to the Electron logo the moment the Start Menu shortcut was
326
+ * deleted. So the shortcut this lookup resolves is the **Start Menu** one — a desktop
327
+ * shortcut is not enough, and writing the identity onto `Summrise.lnk` in
328
+ * `%PUBLIC%\Desktop` alone changes nothing. Microsoft's appids.md does say to apply the ID
329
+ * to "all of the shortcuts" when an application has several launch locations, and it lists
330
+ * the Start menu FIRST; the measurement is what says which of them the taskbar actually
331
+ * reads.
332
+ *
333
+ * The other variables were held: the same `IPropertyStore` call read back on every
334
+ * shortcut, the same `icon.ico` (downloaded and RENDERED — it is the orange sunrise), the
335
+ * same shell restarted under the `SummriseDesktop` task, and in each restarted run the
336
+ * running process appended `AUMID-SET-OK` to a log from inside `setAppUserModelId`, so "the
337
+ * ID was set" is measured rather than assumed.
338
+ *
339
+ * WHY THE OLD ID WAS DEAD. Releases up to 1.2.489 set `online.saisi.summrise.agent` on the
340
+ * process while no shortcut anywhere carried it, so the shell resolved that ID against the
341
+ * backing executable — stock `electron.exe` — and kept the result. `shell:AppsFolder` still
342
+ * lists it as `name=[Electron] path=[online.saisi.summrise.agent]`, an app entry named after
343
+ * `electron.exe`. An ID already resolved to the wrong image is not repaired by writing the
344
+ * shortcut afterwards; the association has to be under a name the machine has never seen.
345
+ * Keep this string STABLE from here: changing it again costs the pin and the jump list, so
346
+ * this is a one-time migration, not a knob.
313
347
  */
314
- exports.DESKTOP_AUMID = "online.saisi.summrise.agent";
348
+ exports.DESKTOP_AUMID = "online.saisi.summrise.desktop";
315
349
  /** The two `IPropertyStore` values `Summrise.lnk` must carry, as DATA.
316
350
  *
317
351
  * Deliberately separated from the PowerShell that performs the write, and exported, so the
@@ -442,31 +476,60 @@ public static class SummriseLnk {
442
476
  // exported: unit-tested in test/cli.test.mjs.
443
477
  function deskShortcutRepairPs(scriptsQ, deskDirQ, sink) {
444
478
  const { id, icon } = lnkIdentity(`${deskDirQ}\\icon.ico`);
479
+ // BOTH shortcuts get the identity, and the START MENU one is the load-bearing half:
480
+ // deleting it from a running shell reverted the taskbar to the Electron logo with the ID
481
+ // still set on the process and both desktop shortcuts still carrying it (see DESKTOP_AUMID).
482
+ // The desktop link is kept because it is what a person double-clicks and because
483
+ // appids.md says to apply the ID to "all of the shortcuts" a user can launch from.
484
+ const lnk = (p, tag) => [
485
+ ` try { $dWs${tag} = New-Object -ComObject WScript.Shell; $dSc${tag} = $dWs${tag}.CreateShortcut(${p}); $dSc${tag}.TargetPath = Join-Path $env:SystemRoot 'System32\\WindowsPowerShell\\v1.0\\powershell.exe'; $dSc${tag}.Arguments = '-NoProfile -ExecutionPolicy Bypass -File "' + $dPs1 + '"'; $dSc${tag}.WorkingDirectory = '${deskDirQ}'; $dSc${tag}.IconLocation = $dIco + ',0'; $dSc${tag}.Save(); 'desk: ' + ${p} + ' repointed to electron shell' | ${sink} } catch { ('desk: ' + ${p} + ' repair failed: ' + $_.Exception.Message) | ${sink} }`,
486
+ ` if ($dSet) { try { [SummriseLnk]::Write(${p}, $dId, $dRes); ('desk: ' + ${p} + ' taskbar identity [' + [SummriseLnk]::Read(${p}) + ']') | ${sink} } catch { ('desk: ' + ${p} + ' identity write failed: ' + $_.Exception.Message) | ${sink} } }`,
487
+ ];
445
488
  return [
446
489
  `$dLnk = Join-Path $env:PUBLIC 'Desktop\\Summrise.lnk'`,
490
+ // ALL-USERS Start Menu: the shortcut the shell's app resolver actually reads, and it is
491
+ // CREATED here when absent — a machine that never had one is exactly the machine whose
492
+ // taskbar shows the Electron logo, and no amount of desktop-side repair reaches it.
493
+ // `setup` already requires elevation (HKLM writes, Program Files), so ProgramData is
494
+ // writable on every path that calls this.
495
+ `$dSm = Join-Path $env:ProgramData 'Microsoft\\Windows\\Start Menu\\Programs\\Summrise.lnk'`,
447
496
  `$dIco = '${deskDirQ}\\icon.ico'`,
448
497
  `$dPs1 = '${scriptsQ}\\start-desktop.ps1'`,
449
498
  `$dId = '${id}'`,
450
499
  `$dRes = '${icon}'`,
451
500
  `$dSet = $false`,
452
- `$dNeed = $false`,
453
- `if (Test-Path $dLnk) {`,
454
- // Compiled only when there IS a link to write, so a headless install does not pay for
455
- // it. The `-as [type]` guard keeps a second call in one process from turning a
456
- // "type already exists" throw into a silent skip of the write below.
501
+ `$dShell = (Test-Path $dIco) -and (Test-Path $dPs1)`,
502
+ // Compiled when there is a SHELL to point at, not when a desktop link happens to exist:
503
+ // the Start Menu shortcut is created from nothing, so gating this on `$dLnk` would skip
504
+ // the identity on precisely the installs that need it. The `-as [type]` guard keeps a
505
+ // second call in one process from turning a "type already exists" throw into a silent
506
+ // skip of every write below.
507
+ `if ($dShell) {`,
457
508
  ` $dCs = @'\n${LNK_PROPS_CS}\n'@`,
458
509
  ` try { if (-not ('SummriseLnk' -as [type])) { Add-Type -TypeDefinition $dCs }; $dSet = [bool]('SummriseLnk' -as [type]) } catch { ('desk: lnk identity helper unavailable: ' + $_.Exception.Message) | ${sink} }`,
510
+ `}`,
511
+ `$dNeed = $false`,
512
+ `if (Test-Path $dLnk) {`,
459
513
  ` try { $dEx = (New-Object -ComObject WScript.Shell).CreateShortcut($dLnk); if (($dEx.TargetPath -like '*summrise-desktop.exe') -or ($dEx.TargetPath -like '*summrise-tray.exe') -or (-not (Test-Path $dEx.TargetPath))) { $dNeed = $true } } catch { $dNeed = $true }`,
460
514
  // ...and a link that is otherwise healthy still needs repairing when its identity is
461
515
  // missing or names a different ID/icon. `Read` returns "id|icon", so ONE comparison
462
516
  // covers both properties — and it is the same call the verification below prints.
463
517
  ` if ($dSet) { try { if (([SummriseLnk]::Read($dLnk)) -ne ($dId + '|' + $dRes)) { $dNeed = $true } } catch { $dNeed = $true } }`,
464
518
  `}`,
465
- `if ($dNeed -and (Test-Path $dIco) -and (Test-Path $dPs1)) {`,
466
- ` try { $dWs = New-Object -ComObject WScript.Shell; $dSc = $dWs.CreateShortcut($dLnk); $dSc.TargetPath = Join-Path $env:SystemRoot 'System32\\WindowsPowerShell\\v1.0\\powershell.exe'; $dSc.Arguments = '-NoProfile -ExecutionPolicy Bypass -File "' + $dPs1 + '"'; $dSc.WorkingDirectory = '${deskDirQ}'; $dSc.IconLocation = $dIco + ',0'; $dSc.Save(); 'desk: Summrise.lnk repointed to electron shell' | ${sink} } catch { ('desk: Summrise.lnk repair failed: ' + $_.Exception.Message) | ${sink} }`,
467
- // The verification is the READ-BACK, not the absence of an exception: SetValue+Commit
468
- // returning cleanly is a claim about a call, and this records what the file now carries.
469
- ` if ($dSet) { try { [SummriseLnk]::Write($dLnk, $dId, $dRes); ('desk: Summrise.lnk taskbar identity [' + [SummriseLnk]::Read($dLnk) + ']') | ${sink} } catch { ('desk: Summrise.lnk identity write failed: ' + $_.Exception.Message) | ${sink} } }`,
519
+ // The Start Menu link is created when ABSENT and rewritten when its identity is wrong —
520
+ // it is never deleted, and a link that already matches is left alone so a second `setup`
521
+ // does not churn the file.
522
+ `$dSmNeed = $false`,
523
+ `if ($dShell) {`,
524
+ ` if (-not (Test-Path $dSm)) { $dSmNeed = $true }`,
525
+ ` elseif (-not $dSet) { $dSmNeed = $true }`,
526
+ ` else { try { if (([SummriseLnk]::Read($dSm)) -ne ($dId + '|' + $dRes)) { $dSmNeed = $true } } catch { $dSmNeed = $true } }`,
527
+ `}`,
528
+ `if ($dNeed -and $dShell) {`,
529
+ ...lnk("$dLnk", "1"),
530
+ `}`,
531
+ `if ($dSmNeed -and $dShell) {`,
532
+ ...lnk("$dSm", "2"),
470
533
  `}`,
471
534
  `foreach ($dRx in @('summrise-desktop.exe','summrise-tray.exe')) { $dRp = '${deskDirQ}\\' + $dRx; if (Test-Path $dRp) { try { Remove-Item -Force -ErrorAction Stop $dRp; ('desk: removed retired ' + $dRx) | ${sink} } catch { ('desk: retired ' + $dRx + ' locked, kept') | ${sink} } } }`,
472
535
  ];
@@ -505,7 +568,30 @@ function desktopTaskPs(installQ) {
505
568
  `$dt1 = New-ScheduledTaskTrigger -AtLogOn`,
506
569
  `$dw1 = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(3) -RepetitionInterval (New-TimeSpan -Minutes 5)`,
507
570
  `$pr = New-ScheduledTaskPrincipal -UserId ('{0}\\{1}' -f $env:USERDOMAIN, $env:USERNAME) -LogonType Interactive -RunLevel Highest`,
508
- `$st = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 10) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -MultipleInstances IgnoreNew`,
571
+ // NO EXECUTION TIME LIMIT -- the same value, in the same spelling, the agent's own task has
572
+ // carried since round 118 for the same reason: `- ExecutionTimeLimit 0 never kill the
573
+ // running task`. It was `-Minutes 10` here, and that WAS the defect.
574
+ //
575
+ // WHY A LIMIT KILLS A SHELL MEANT TO LIVE INDEFINITELY: this task's action is
576
+ // desktop-pulse.vbs -> ensure-desktop.ps1 -> start-desktop.ps1, and that last line is
577
+ // `& electron.exe .` -- the PowerShell CALL OPERATOR, which WAITS. The PowerShell the task
578
+ // launched therefore stays alive for as long as the shell does, as the shell's PARENT, and
579
+ // Task Scheduler enforces ExecutionTimeLimit on that process tree. Ten minutes after every
580
+ // start the scheduler killed the running shell; five minutes later the guarded pulse
581
+ // correctly brought a fresh one back; ten minutes after that it died again. The operator
582
+ // reported that as "反复重启", four times.
583
+ //
584
+ // NOTHING RELIED ON THE KILL, which is why removing it is the fix rather than a trade. This
585
+ // repository's recovery for a shell that is GONE is the guarded 5-minute pulse, and
586
+ // summrise-desktop-electron/src/main.ts says so from the other side, naming a logon-only task
587
+ // as one that "cannot recover a wedged shell". A shell that is RUNNING but wedged was never
588
+ // this limit's business either: the pulse's guard is a process-EXISTENCE check
589
+ // (`if (Get-Process electron) { exit }`), so it cannot see a wedged shell whether the limit is
590
+ // ten minutes or absent. `summrise update` is what heals a wedged shell, and its log says so.
591
+ //
592
+ // Measured on desktop-14rjcr8: under PT10M the four electron PIDs were replaced about every
593
+ // ten minutes; under PT0S the same four PIDs were still there 11 minutes later.
594
+ `$st = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Seconds 0) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -MultipleInstances IgnoreNew`,
509
595
  `Register-ScheduledTask SummriseDesktop -Action $da -Trigger @($dt1,$dw1) -Principal $pr -Settings $st -Force | Out-Null`,
510
596
  `Start-ScheduledTask -TaskName SummriseDesktop`,
511
597
  ];
@@ -3021,7 +3107,15 @@ const commands = {
3021
3107
  ` $da = New-ScheduledTaskAction -Execute 'wscript.exe' -Argument ('"' + $vb1 + '"') -WorkingDirectory '${q}'`,
3022
3108
  ` $dt1 = New-ScheduledTaskTrigger -AtLogOn`,
3023
3109
  ` $dw1 = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(3) -RepetitionInterval (New-TimeSpan -Minutes 5)`,
3024
- ` Set-ScheduledTask -TaskName 'SummriseDesktop' -Action $da -Trigger @($dt1, $dw1) | Out-Null`,
3110
+ // AND THE SETTINGS, WHICH IS THE HALF THAT REACHES A MACHINE ALREADY INSTALLED.
3111
+ // This call used to pass only -Action and -Trigger, and `Set-ScheduledTask` PRESERVES the
3112
+ // components it is not given — so an execution limit already on the task survived every
3113
+ // update. That is the wrong shape for a heal: `summrise update` is the only mechanism that
3114
+ // reaches the fleet, and a device carrying the old 10-minute limit would have kept it
3115
+ // forever while its log said "hardened". The value is the same one `setup` writes, so the
3116
+ // two cannot diverge — and installer_integrity.rs holds both ends to it.
3117
+ ` $dst = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Seconds 0) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -MultipleInstances IgnoreNew`,
3118
+ ` Set-ScheduledTask -TaskName 'SummriseDesktop' -Action $da -Trigger @($dt1, $dw1) -Settings $dst | Out-Null`,
3025
3119
  ` "[$(Get-Date -Format o)] desk: SummriseDesktop hardened (guarded 5-min pulse)" | ${log}`,
3026
3120
  `}`,
3027
3121
  `if ((Test-Path $deskDir) -and (Test-Path $deskStart)) {`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "summrise-agent",
3
- "version": "1.2.491",
3
+ "version": "1.2.492",
4
4
  "description": "Summrise Agent — Windows device MCP server (terminal/SSH/serial) + panel. Self-hosted npm distribution.",
5
5
  "//build": "唯一构建路径:在本目录执行 npm run build。它是自包含的:经 npm exec 按需拉取 typescript@5,无需预装任何 node_modules(干净检出可跑;旧脚本引用 ../summrise-desktop-electron/node_modules/.bin/tsc,干净检出必 ENOENT)。必须用 npm exec --package … -- tsc 的形式:npx 会吃掉传给 tsc 的 -p/--outDir 等参数(round-435:npx 写法从未真正跑通过)。先编 electron TS(--noCheck 纯 emit,与 release.yml 一致)同步两处 src/*.js,再编 src/summrise.ts 到 bin/summrise.js 并校验 round-298 标记(弱 oracle,只证某次构建发生,新鲜性由 publish-release.sh 的 tsc 重编 + cmp 门保证)。",
6
6
  "bin": {
Binary file
@@ -909,10 +909,17 @@ if (gotTheLock) {
909
909
  // there) as System.AppUserModel.ID — the same string — plus RelaunchIconResource pointing
910
910
  // at the sunrise .ico. KEEP THE TWO IN STEP; the literal below is a copy because this file
911
911
  // is emitted to plain JS in two packages and cannot import the CLI's module.
912
+ // THE VALUE IS NOT THE ONE THIS FILE USED BEFORE ("…summrise.agent"), and that is the
913
+ // measured half of the fix rather than a rename. On desktop-14rjcr8, with that string set
914
+ // on the window AND read back off the shortcut, the taskbar still drew the Electron logo:
915
+ // releases up to 1.2.489 had already resolved that AUMID — set with no shortcut anywhere —
916
+ // against the backing executable and kept the answer, and `shell:AppsFolder` still lists it
917
+ // as an app named "Electron". The same machine drew the SUNRISE under a string it had never
918
+ // seen, with every other variable held. DESKTOP_AUMID carries the two-row table.
912
919
  // (The same shortcut association is also the documented precondition for the hide-to-tray
913
920
  // toast below: Electron requires a Start Menu shortcut carrying the ID and a
914
921
  // ToastActivatorCLSID, and this one carries neither — unchanged by this call.)
915
- const AUMID = "online.saisi.summrise.agent";
922
+ const AUMID = "online.saisi.summrise.desktop";
916
923
  try {
917
924
  if (process.platform === "win32")
918
925
  electron_1.app.setAppUserModelId(AUMID);