summrise-agent 1.2.493 → 1.2.495

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "summrise-agent",
3
- "version": "1.2.493",
3
+ "version": "1.2.495",
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
@@ -952,8 +952,8 @@ if (gotTheLock) {
952
952
  // whatever the agent turned out to be. show:false keeps it off screen until the
953
953
  // first document has painted (ready-to-show, below); backgroundColor paints that
954
954
  // first frame in the shell's own ink instead of Chromium's white, which is the one
955
- // of the two documents that had NOT already fixed this (WAIT_HTML hardcodes
956
- // background:#111, and the SPA's chrome is dark).
955
+ // of the two documents that had NOT already fixed this (the wait page
956
+ // hardcoded background:#111, and the SPA's chrome is dark).
957
957
  show: false,
958
958
  backgroundColor: "#111",
959
959
  // Taskbar + title-bar icon: without this Windows shows the stock
@@ -1039,38 +1039,130 @@ if (gotTheLock) {
1039
1039
  // and the watchdog could not fire (the device stayed stuck in silence,
1040
1040
  // the exact failure the watchdog exists to prevent).
1041
1041
  const agentReady = async () => agentResponds(800);
1042
- // stage-n: the wait page now carries a "Start Agent" action — the
1043
- // header comment promised it but it never existed. The button calls the
1044
- // shell's own /api/shell/start-agent (schtasks /run SummriseAgent — the
1045
- // only sanctioned spawn path), then keeps polling until the agent is
1046
- // up. This turns a dead-end white screen into a recoverable state when
1047
- // the SummriseAgent task is down (crash, stopped task, update mid-swap).
1048
- const WAIT_HTML = `<!doctype html><meta charset="utf-8"><title>Summrise</title>
1049
- <style>body{font-family:system-ui,sans-serif;background:#111;color:#eee;display:flex;align-items:center;justify-content:center;height:100vh;margin:0}div{text-align:center}p{color:#999}button{margin-top:18px;padding:10px 22px;font-size:15px;border-radius:8px;border:1px solid #444;background:#222;color:#eee;cursor:pointer}button:hover{background:#333}button:disabled{opacity:.5;cursor:default}</style>
1042
+ // stage-n: the wait page carries a "Start Agent" action — the header
1043
+ // comment promised it but it never existed. The button calls the shell's
1044
+ // own /api/shell/start-agent (schtasks /run SummriseAgent — the only
1045
+ // sanctioned spawn path). This turns a dead-end white screen into a
1046
+ // recoverable state when the SummriseAgent task is down (crash, stopped
1047
+ // task, update mid-swap).
1048
+ //
1049
+ // REWRITTEN (round 276). Three defects, all of them measured on the
1050
+ // device's own window at 1200x761, and all three are the same defect
1051
+ // wearing different clothes: THE PAGE ASSERTED THINGS IT HAD NOT CHECKED.
1052
+ //
1053
+ // 1. The heading said "Summrise Agent is not running". Nothing on this
1054
+ // path checked that. `loadDesktop` reaches this page when a request
1055
+ // to one address does not ANSWER — the agent may be running and
1056
+ // wedged, on another port, mid-restart, or still booting. The file's
1057
+ // own comment above `agentReady` says a wedged-but-listening agent
1058
+ // "holds the port yet never answers", which is the case the heading
1059
+ // got wrong. It now names the observation (a request went out and
1060
+ // nothing came back) and the address it went to.
1061
+ // 2. The subtext said "waiting for …" and then never showed the wait.
1062
+ // No attempt count, no clock — so a four-second boot and a six-hour
1063
+ // corpse rendered identically. It now carries both, and both TICK
1064
+ // (below), so the operator can tell patience from action.
1065
+ // 3. The button threw its answer away. `/api/shell/start-agent` returns
1066
+ // `{ok, error}` — `startAgentTask()` is `runSchtasks([...])` — and
1067
+ // the page did `await fetch(...)` and printed "started" regardless,
1068
+ // so a REFUSED start read exactly like an accepted one. It reads the
1069
+ // body now and says which happened.
1070
+ //
1071
+ // AND THE PAGE OWNS ITS OWN CLOCK, which is why `loadWaitPage` below will
1072
+ // not re-load a page that is already showing: a reload every 2-30 s wiped
1073
+ // the button's answer before it could be read, and re-rendered the
1074
+ // evidence from zero. The page polls the shell's own /api/shell/agent-status
1075
+ // (the shell is alive by construction — it is what draws this page) and
1076
+ // navigates itself to the SPA the moment the agent answers.
1077
+ //
1078
+ // THE COLOURS ARE THE DARK THEME'S TOKEN VALUES, LITERALLY, AND THAT IS
1079
+ // DELIBERATE: this page is drawn while the agent is mute, so it cannot
1080
+ // load the SPA's token sheet — but a fallback using its own greys is a
1081
+ // different product's screen. Values copied from
1082
+ // panel-react/src/styles/tokens.css `body[data-theme="dark"]`:
1083
+ // --bg #131418, --chrome-ink #ecedef, --chrome-ink-dim #a2a3ac,
1084
+ // --accent-solid #b03a0a, --accent-solid-hover #a63308, --accent-fg #fff,
1085
+ // --chrome-danger-ink #ff8787.
1086
+ //
1087
+ // NO BACKTICKS AND NO `${` BELOW except the two interpolations that are
1088
+ // meant: this is a template literal, and the incident class the pre-commit
1089
+ // hook was built for is a stray backtick inside one.
1090
+ const waitPageHtml = (checks) => `<!doctype html><meta charset="utf-8"><title>Summrise</title>
1091
+ <style>
1092
+ body{font-family:system-ui,sans-serif;background:#131418;color:#ecedef;display:flex;align-items:center;justify-content:center;height:100vh;margin:0}
1093
+ div{text-align:center;max-width:640px;padding:0 24px}
1094
+ h2{margin:0;font-size:24px;font-weight:600}
1095
+ p{margin:10px 0 0;font-size:15px;color:#a2a3ac}
1096
+ #action{margin-top:12px;font-size:14px}
1097
+ #action.failed{color:#ff8787}
1098
+ button{margin-top:18px;padding:10px 22px;font-size:15px;border-radius:8px;border:0;background:#b03a0a;color:#fff;cursor:pointer}
1099
+ button:hover:not(:disabled){background:#a63308}
1100
+ button:disabled{opacity:.5;cursor:default}
1101
+ </style>
1050
1102
  <div>
1051
- <h2>Summrise Agent is not running</h2>
1052
- <p id="status">waiting for ${(0, url_policy_1.agentBase)().replace("http://", "")}…</p>
1103
+ <h2>The Summrise Agent isn&#39;t answering</h2>
1104
+ <p id="status">no reply from ${(0, url_policy_1.agentBase)().replace("http://", "")}</p>
1105
+ <p id="action" hidden></p>
1053
1106
  <button id="start">Start Agent</button>
1054
1107
  </div>
1055
1108
  <script>
1056
- const btn = document.getElementById("start");
1057
- const st = document.getElementById("status");
1058
- let busy = false;
1059
- btn.addEventListener("click", async () => {
1109
+ var BASE = ${JSON.stringify((0, url_policy_1.agentBase)().replace("http://", ""))};
1110
+ var CTRL = "http://127.0.0.1:9444";
1111
+ var btn = document.getElementById("start");
1112
+ var st = document.getElementById("status");
1113
+ var act = document.getElementById("action");
1114
+ var checks = ${checks};
1115
+ var lastCheckAt = Date.now();
1116
+ function say(el, text, failed) {
1117
+ el.hidden = false;
1118
+ el.textContent = text;
1119
+ el.className = failed ? "failed" : "";
1120
+ }
1121
+ function age(ms) { return ms < 1500 ? "just now" : Math.round(ms / 1000) + "s ago"; }
1122
+ function paint() {
1123
+ st.textContent = "no reply from " + BASE + " \\u00b7 last check " + age(Date.now() - lastCheckAt)
1124
+ + " \\u00b7 " + checks + (checks === 1 ? " check" : " checks");
1125
+ }
1126
+ paint();
1127
+ setInterval(paint, 1000);
1128
+ function poll() {
1129
+ fetch(CTRL + "/api/shell/agent-status").then(function (r) { return r.json(); }).then(function (j) {
1130
+ checks += 1; lastCheckAt = Date.now(); paint();
1131
+ if (j && j.running) { location.replace("http://" + BASE + "/desktop/"); return; }
1132
+ setTimeout(poll, 2000);
1133
+ }).catch(function () {
1134
+ checks += 1; lastCheckAt = Date.now(); paint();
1135
+ setTimeout(poll, 2000);
1136
+ });
1137
+ }
1138
+ setTimeout(poll, 2000);
1139
+ var busy = false;
1140
+ btn.addEventListener("click", async function () {
1060
1141
  if (busy) return;
1061
1142
  busy = true; btn.disabled = true;
1062
- st.textContent = "starting SummriseAgent task…";
1143
+ say(act, "asking the SummriseAgent task to start\\u2026", false);
1063
1144
  try {
1064
- await fetch("http://127.0.0.1:9444/api/shell/start-agent", { method: "POST" });
1065
- st.textContent = "started — waiting for the agent to come up…";
1145
+ var r = await fetch(CTRL + "/api/shell/start-agent", { method: "POST" });
1146
+ var j = null;
1147
+ try { j = await r.json(); } catch (e) { j = null; }
1148
+ if (j && j.ok) {
1149
+ say(act, "the SummriseAgent task was started \\u2014 waiting for it to answer", false);
1150
+ } else {
1151
+ say(act, "the start request FAILED: " + ((j && j.error) || ("HTTP " + r.status)), true);
1152
+ }
1066
1153
  } catch (e) {
1067
- st.textContent = "start request failed (" + e + ") — the task may already be starting";
1154
+ say(act, "the start request did not reach the shell: " + e, true);
1068
1155
  }
1069
- setTimeout(() => { busy = false; btn.disabled = false; }, 3000);
1156
+ setTimeout(function () { busy = false; btn.disabled = false; }, 3000);
1070
1157
  });
1071
1158
  </script>`;
1072
- const loadWaitPage = () => {
1073
- win?.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(WAIT_HTML)}`).catch(() => { });
1159
+ const loadWaitPage = (checks) => {
1160
+ // DO NOT RE-LOAD A PAGE THAT IS ALREADY SHOWING (see the note above): the
1161
+ // reload wiped the button's answer and reset the evidence line, which is
1162
+ // what made the only control on this screen unfalsifiable.
1163
+ if (win?.webContents.getURL().startsWith("data:text/html"))
1164
+ return;
1165
+ win?.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(waitPageHtml(checks))}`).catch(() => { });
1074
1166
  };
1075
1167
  let retryMs = 2000;
1076
1168
  const nextRetry = () => { retryMs = Math.min(retryMs * 2, 30000); return retryMs; };
@@ -1105,8 +1197,11 @@ if (gotTheLock) {
1105
1197
  win?.loadURL(`${(0, url_policy_1.agentBase)()}/desktop/`).catch(() => { });
1106
1198
  }
1107
1199
  else {
1108
- loadWaitPage();
1200
+ // THE MISS IS COUNTED BEFORE THE PAGE IS HANDED THE NUMBER, because this
1201
+ // failed probe IS one: the count the operator reads is the number of
1202
+ // times the shell has asked and got nothing, including this one.
1109
1203
  agentMissCount += 1;
1204
+ loadWaitPage(agentMissCount);
1110
1205
  if (agentMissCount >= AUTO_START_AFTER_MISSES && Date.now() - lastAutoStartAt > AUTO_START_MIN_GAP_MS) {
1111
1206
  lastAutoStartAt = Date.now();
1112
1207
  agentMissCount = 0;