weflow-cli 1.14.0 → 1.14.1
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/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/scripts/daily_mail.py +6 -1
- package/scripts/daily_task.ps1 +34 -9
- package/scripts/semantic_search.py +9 -1
package/CHANGELOG.md
CHANGED
|
@@ -17,6 +17,22 @@ purpose** - a hand-written "latest is X" is exactly the claim that goes stale he
|
|
|
17
17
|
|
|
18
18
|
All notable user-facing changes are recorded here. This project follows [Semantic Versioning](https://semver.org/).
|
|
19
19
|
|
|
20
|
+
## 1.14.1
|
|
21
|
+
|
|
22
|
+
- **The daily run now keeps the retrieval indexes fresh.** On 2026-10-22 the semantic index was
|
|
23
|
+
still at 10-15 and the phrase index at 10-17, so `search` could not find anything newer than a
|
|
24
|
+
week ago - nothing had ever refreshed them. After the day's report is written, the wrapper runs
|
|
25
|
+
`semantic_search.py update` (embeds only what is missing: 4,061 new records on that first run)
|
|
26
|
+
and `semantic_search.py phrase-build` (local FTS, no API cost). Each has its own log and neither
|
|
27
|
+
can fail the day.
|
|
28
|
+
- **The noon pass mails too, and says it is half a day.** It used to generate silently, which read
|
|
29
|
+
as "it never ran" - the only evidence was a log file. The noon email is titled
|
|
30
|
+
「…(截至中午)」 and states that the complete version arrives the next morning, so the two daily
|
|
31
|
+
emails cannot be mistaken for duplicates.
|
|
32
|
+
- **`phrase-build` no longer fails when `VACUUM` cannot run.** `VACUUM` needs a temp file, and in a
|
|
33
|
+
restricted environment it reports `unable to open database file` *after* the index has been
|
|
34
|
+
written successfully - that turned a good rebuild into exit code 1.
|
|
35
|
+
|
|
20
36
|
## 1.14.0
|
|
21
37
|
|
|
22
38
|
- **A daily report you can receive by mail, cut down to the topics you actually read.**
|
package/package.json
CHANGED
package/scripts/daily_mail.py
CHANGED
|
@@ -423,6 +423,7 @@ def main():
|
|
|
423
423
|
ap.add_argument('--date', required=True, help='YYYY-MM-DD')
|
|
424
424
|
ap.add_argument('--to', default='', help='收件人;缺省用配置 dailyMailTo,再缺省发给自己')
|
|
425
425
|
ap.add_argument('--topics', default=','.join(DEFAULT_TOPICS), help='逗号分隔的主题')
|
|
426
|
+
ap.add_argument('--label', default='', help='标题后缀,如「截至中午」——区分半日速览与次日完整版')
|
|
426
427
|
ap.add_argument('--no-digest', action='store_true', help='不生成每主题的 AI 综述(省钱、更快)')
|
|
427
428
|
ap.add_argument('--dry-run', action='store_true', help='只渲染,不发送')
|
|
428
429
|
args = ap.parse_args()
|
|
@@ -449,7 +450,11 @@ def main():
|
|
|
449
450
|
print(f'正文含 GitHub 链接: {with_repo} 篇')
|
|
450
451
|
|
|
451
452
|
text_body, html_body, total = render(args.date, groups, digests, bodies, clusters)
|
|
452
|
-
|
|
453
|
+
label = (args.label or '').strip()
|
|
454
|
+
suffix = f'({label})' if label else ''
|
|
455
|
+
subject = f'公众号日报 {args.date}{suffix}:{" / ".join(t for t in topics if groups.get(t))} {total} 篇'
|
|
456
|
+
if label:
|
|
457
|
+
text_body = f'【{label}】以下是到此刻为止收到的 {total} 篇。完整版会在次日凌晨按整天重发。\n\n' + text_body
|
|
453
458
|
|
|
454
459
|
user, auth = smtp_settings()
|
|
455
460
|
to = args.to or str(cfg.get('dailyMailTo') or '') or user
|
package/scripts/daily_task.ps1
CHANGED
|
@@ -128,18 +128,43 @@ if ($proc.ExitCode -eq 0 -and $rest.Count -eq 0) {
|
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
#
|
|
132
|
-
#
|
|
133
|
-
#
|
|
134
|
-
#
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
131
|
+
# Retrieval indexes lag behind unless something refreshes them: on 2026-10-22 the
|
|
132
|
+
# semantic index was still at 10-15 (7 days stale) and the phrase index at 10-17, so
|
|
133
|
+
# `search` simply could not find anything newer. Both run here, after the day is on
|
|
134
|
+
# disk, in their own logs -- a failure is recorded and never fails the day.
|
|
135
|
+
$searchScript = Join-Path $PSScriptRoot 'semantic_search.py'
|
|
136
|
+
if ($mode -eq 'day' -and (Test-Path $searchScript)) {
|
|
137
|
+
$idxOut = Join-Path $logDir ('index-{0}.log' -f $stamp)
|
|
138
|
+
$idxErr = Join-Path $logDir ('index-{0}.err.log' -f $stamp)
|
|
139
|
+
# `update` only embeds what is not in the index yet (4,061 new records on the first
|
|
140
|
+
# run after a week). `phrase-build` is local FTS, no API, so it rebuilds in full.
|
|
141
|
+
$idxProc = Start-Process -FilePath $python `
|
|
142
|
+
-ArgumentList @($searchScript, 'update', '--article-days', '30') `
|
|
143
|
+
-NoNewWindow -Wait -PassThru -RedirectStandardOutput $idxOut -RedirectStandardError $idxErr
|
|
144
|
+
$phraseProc = Start-Process -FilePath $python `
|
|
145
|
+
-ArgumentList @($searchScript, 'phrase-build') `
|
|
146
|
+
-NoNewWindow -Wait -PassThru `
|
|
147
|
+
-RedirectStandardOutput (Join-Path $logDir ('phrase-{0}.log' -f $stamp)) `
|
|
148
|
+
-RedirectStandardError (Join-Path $logDir ('phrase-{0}.err.log' -f $stamp))
|
|
149
|
+
if ($idxProc.ExitCode -ne 0 -or $phraseProc.ExitCode -ne 0) {
|
|
150
|
+
Add-Content -Path (Join-Path $logDir 'daily-task.log') -Value `
|
|
151
|
+
('===== {0} index update failed (update={1}, phrase={2}), see {3} =====' -f `
|
|
152
|
+
(Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $idxProc.ExitCode, $phraseProc.ExitCode, $idxErr) -Encoding UTF8
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
# **Both passes mail now.** The noon pass used to be silent, which read as "it never
|
|
157
|
+
# ran" - the only way to tell it had done anything was to open the log. The two emails
|
|
158
|
+
# are clearly different: the noon one is labelled 截至中午 and says the complete version
|
|
159
|
+
# follows next morning. Mail is still its own step with its own log pair, so a mail
|
|
160
|
+
# failure never fails the day nor blocks the noon marker.
|
|
138
161
|
$mailScript = Join-Path $PSScriptRoot 'daily_mail.py'
|
|
139
162
|
$mailOut = Join-Path $logDir ('daily-mail-{0}{1}.log' -f $stamp, $suffix)
|
|
140
163
|
$mailErr = Join-Path $logDir ('daily-mail-{0}{1}.err.log' -f $stamp, $suffix)
|
|
141
|
-
if (
|
|
142
|
-
$
|
|
164
|
+
if (Test-Path $mailScript) {
|
|
165
|
+
$mailArgs = @($mailScript, '--date', $targetDay)
|
|
166
|
+
if ($mode -eq 'noon') { $mailArgs += @('--label', '截至中午') }
|
|
167
|
+
$mailProc = Start-Process -FilePath $python -ArgumentList $mailArgs `
|
|
143
168
|
-NoNewWindow -Wait -PassThru -RedirectStandardOutput $mailOut -RedirectStandardError $mailErr
|
|
144
169
|
if ($mailProc.ExitCode -ne 0) {
|
|
145
170
|
Add-Content -Path (Join-Path $logDir 'daily-task.log') -Value `
|
|
@@ -1235,7 +1235,15 @@ def build_phrase_index(line: str = 'all', db_path=None, meta_path=None):
|
|
|
1235
1235
|
conn.executemany('INSERT INTO hits(body, rid, line, label, date, title)'
|
|
1236
1236
|
' VALUES (?, ?, ?, ?, ?, ?)', rows)
|
|
1237
1237
|
conn.commit()
|
|
1238
|
-
|
|
1238
|
+
# `VACUUM` 要写临时文件;在受限环境(沙箱 / %TEMP% 不可写)它会报
|
|
1239
|
+
# `unable to open database file`,而**数据其实已经写进去了** —— 那一步只是把库压实。
|
|
1240
|
+
# 所以它失败不能被当成"索引没建好":2026-10-22 实测 155MB 的库内容完整,
|
|
1241
|
+
# 却因为这一行让整个 phrase-build 的退出码变成非 0。
|
|
1242
|
+
try:
|
|
1243
|
+
conn.execute('VACUUM')
|
|
1244
|
+
except Exception as exc:
|
|
1245
|
+
print(f'[WARN] 短语索引已写入,但 VACUUM 失败({type(exc).__name__}: {exc})'
|
|
1246
|
+
'——只是没压实,查询不受影响', file=sys.stderr)
|
|
1239
1247
|
finally:
|
|
1240
1248
|
conn.close()
|
|
1241
1249
|
return {'records': len(rows), 'byLine': by_line, 'textMissing': text_missing,
|