@tsa-group/claude-usage 0.4.4 → 0.4.5

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.
Files changed (2) hide show
  1. package/dist/install.js +35 -11
  2. package/package.json +1 -1
package/dist/install.js CHANGED
@@ -130,19 +130,43 @@ function winUninstall() {
130
130
  rmSync(VBS_PATH());
131
131
  return 0;
132
132
  }
133
+ /** schtasks 的 LastTaskResult。0 以外的值多半代表背景任務其實沒跑成功。 */
134
+ const TASK_RESULT = {
135
+ 0: "上次執行成功",
136
+ 267011: "尚未執行過",
137
+ 267009: "正在執行中",
138
+ 267014: "上次被中止",
139
+ };
133
140
  function winStatus() {
134
- // winInstall:不設 encoding。Windows 主控台是本地碼頁(繁中 CP950),用 utf8
135
- // 解碼會把整段表格變成亂碼,而使用者要看的只是「這個工作在不在、下次何時跑」。
136
- const r = spawnSync("schtasks", ["/Query", "/TN", WIN_TASK]);
137
- if (r.status !== 0) {
138
- console.log("bg-task: NOT installed (schtasks)");
139
- return r.status ?? 1;
141
+ // 不要印 schtasks 的原始輸出:它走**主控台代碼頁**(繁中是 CP950),而 Node 只會
142
+ // 用 utf8/latin1 解,中文必定變亂碼(實測「下午 03:45 就緒」印成 `¤U¤È 03:45 ´N°ü`)。
143
+ // 先前的版本用正則挑日期迴避,但仍會連帶吃到後面的本地化文字。
144
+ // 改走 PowerShell ScheduledTasks cmdlet,**自己指定 ASCII 安全的輸出格式** ——
145
+ // 順便拿到 LastTaskResult,那正是「背景任務上次到底有沒有跑成功」的直接答案,
146
+ // 而那是 schtasks 表格裡最該看、卻最容易被亂碼蓋掉的一欄。
147
+ const cmd = `$ErrorActionPreference='SilentlyContinue';` +
148
+ `$t=Get-ScheduledTask -TaskName '${WIN_TASK}';` +
149
+ `if(-not $t){'MISSING'}else{` +
150
+ `$i=Get-ScheduledTaskInfo -TaskName '${WIN_TASK}';` +
151
+ `$last=if($i.LastRunTime){$i.LastRunTime.ToString('yyyy-MM-dd HH:mm')}else{'-'};` +
152
+ `$next=if($i.NextRunTime){$i.NextRunTime.ToString('yyyy-MM-dd HH:mm')}else{'-'};` +
153
+ `"$($t.State)|$($i.LastTaskResult)|$last|$next"}`;
154
+ const r = spawnSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", cmd], { encoding: "utf8", timeout: 15_000, windowsHide: true });
155
+ const line = (r.stdout ?? "").trim();
156
+ if (r.status !== 0 || !line || line === "MISSING") {
157
+ console.log(`bg-task: NOT installed —— 跑 claude-usage install 重新註冊`);
158
+ return 1;
159
+ }
160
+ const [state, resultRaw, last, next] = line.split("|");
161
+ const result = Number(resultRaw);
162
+ const meaning = TASK_RESULT[result] ?? `結束碼 ${resultRaw}`;
163
+ console.log(`bg-task: 已註冊 "${WIN_TASK}" 狀態=${state} 上次=${last} 下次=${next}`);
164
+ console.log(` ${meaning}`);
165
+ // 只有「成功」與「還沒跑過」算正常;其餘代表背景任務其實沒在做事。
166
+ if (result !== 0 && result !== 267011 && result !== 267009) {
167
+ console.log(` ! 背景任務上次沒有正常結束 —— 細節: schtasks /Query /TN ${WIN_TASK} /V /FO LIST`);
168
+ return 1;
140
169
  }
141
- // 只挑出下次執行時間那一段數字/日期,避開會亂碼的本地化欄位標題
142
- const raw = (r.stdout ?? Buffer.alloc(0)).toString("latin1");
143
- const when = raw.match(/\d{4}[/-]\d{1,2}[/-]\d{1,2}[^\r\n]*/)?.[0]?.trim();
144
- console.log(`bg-task: 已註冊 "${WIN_TASK}"${when ? `,下次執行 ${when}` : ""}`);
145
- console.log(` 完整資訊: schtasks /Query /TN ${WIN_TASK} /V /FO LIST`);
146
170
  return 0;
147
171
  }
148
172
  const sessionStartGroups = (s) => s.hooks?.SessionStart ?? [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsa-group/claude-usage",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "description": "Per-user Claude usage collector — measures Claude Code token detail and account-level rate-limit utilization locally, reports to your own ingest server.",
5
5
  "type": "module",
6
6
  "bin": {