@gavinc-cn/touchstone-dsh 0.1.1 → 0.3.0
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/README.md +39 -11
- package/README.zh.md +25 -10
- package/backend/lib/access.js +44 -0
- package/backend/lib/agents.js +341 -0
- package/backend/lib/args.js +94 -0
- package/backend/lib/auth.js +195 -0
- package/backend/lib/board.js +6154 -0
- package/backend/lib/builtin-assets.js +1177 -0
- package/backend/lib/casescan.js +456 -0
- package/backend/lib/chat.js +2053 -0
- package/backend/lib/cookie.js +76 -0
- package/backend/lib/db.js +2260 -0
- package/backend/lib/dshdriver.js +1148 -0
- package/backend/lib/dshevents.js +851 -0
- package/backend/lib/export-cases.js +261 -0
- package/backend/lib/feishu.js +1738 -0
- package/backend/lib/feishu_cfg.js +228 -0
- package/backend/lib/feishu_conv.js +1484 -0
- package/backend/lib/feishu_device.js +428 -0
- package/backend/lib/feishu_inbound.js +1674 -0
- package/backend/lib/feishu_provision.js +855 -0
- package/backend/lib/feishu_rest.js +398 -0
- package/backend/lib/feishu_slash.js +568 -0
- package/backend/lib/feishu_ws.js +950 -0
- package/backend/lib/http.js +312 -0
- package/backend/lib/lib.js +973 -0
- package/backend/lib/loadcase.js +749 -0
- package/backend/lib/loadgen.js +1407 -0
- package/backend/lib/localbus.js +164 -0
- package/backend/lib/lock.js +405 -0
- package/backend/lib/proc.js +278 -0
- package/backend/lib/prompts.js +1021 -0
- package/backend/lib/pybase64.js +114 -0
- package/backend/lib/pyjson.js +214 -0
- package/backend/lib/query.js +125 -0
- package/backend/lib/rag.js +1310 -0
- package/backend/lib/runner.js +4520 -0
- package/backend/lib/servercaps.js +182 -0
- package/backend/lib/serverstate.js +237 -0
- package/backend/lib/sessparse.js +1176 -0
- package/backend/lib/sse.js +207 -0
- package/backend/lib/static.js +84 -0
- package/backend/lib/taskjson.js +302 -0
- package/backend/lib/waitq.js +2114 -0
- package/backend/lib/worktree.js +588 -0
- package/backend/lib/zstd-frames.js +218 -0
- package/backend/routes/admin.js +553 -0
- package/backend/routes/agents.js +149 -0
- package/backend/routes/assets.js +145 -0
- package/backend/routes/board.js +1220 -0
- package/backend/routes/feishu.js +269 -0
- package/backend/routes/feishu_app.js +215 -0
- package/backend/routes/feishu_hook.js +358 -0
- package/backend/routes/index.js +297 -0
- package/backend/routes/projects.js +1059 -0
- package/backend/routes/sessions.js +946 -0
- package/backend/routes/tasks.js +1530 -0
- package/backend/schema/fixtures/ancient.sql +189 -0
- package/backend/schema/fixtures/pre_alter.sql +177 -0
- package/backend/schema/migrations.json +154 -0
- package/backend/schema/schema.json +1451 -0
- package/backend/schema/schema.sql +216 -0
- package/backend/server.js +498 -0
- package/board.py +805 -72
- package/chat.py +590 -17
- package/db.py +356 -140
- package/dsh-plugin/cordis.patch.yml +7 -3
- package/dsh-plugin/install.sh +28 -11
- package/dsh-plugin/lib/agent-driver.js +710 -89
- package/dsh-plugin/lib/client.bundle.js +94 -9
- package/dsh-plugin/lib/index.js +529 -39
- package/dsh-plugin/lib/pack-closure.mjs +291 -0
- package/dsh-plugin/scripts/prepack-check.mjs +30 -2
- package/dsh-plugin/src/client.js +94 -9
- package/dshdriver.py +74 -5
- package/dshevents.py +65 -3
- package/feishu.py +1197 -34
- package/feishu_conv.py +920 -0
- package/lifecycle.py +116 -13
- package/package.json +6 -1
- package/requirements.txt +2 -1
- package/server.py +218 -26
- package/sessparse.py +150 -44
- package/touchstone.py +6 -3
- package/waitq.py +23 -0
- package/webui/dist-plugin/assets/index-ChP3sg6y.css +1 -0
- package/webui/dist-plugin/assets/index-UrMyeAXF.js +484 -0
- package/webui/dist-plugin/index.html +2 -2
- package/webui/dist-plugin/assets/index-B0WoP1Qy.css +0 -1
- package/webui/dist-plugin/assets/index-DtwKoi1T.js +0 -473
package/dshevents.py
CHANGED
|
@@ -61,6 +61,11 @@ class EventHub:
|
|
|
61
61
|
# 与 `_sessions` 同样遵守「断连=未知」不变量——None 时调用方一律不动作。
|
|
62
62
|
self._archived = None
|
|
63
63
|
self._connected = False
|
|
64
|
+
# 快照对齐是否**可信**(2026-10-08 批次,B):只有「(重)连时拿到过权威快照」
|
|
65
|
+
# 才置 True——空快照且插件未声明完整时保留旧表但置 False(见 `_align`)。
|
|
66
|
+
# 读口 `aligned()` = connected ∧ _aligned:调用方据此决定「能否按缺席推断
|
|
67
|
+
# 会话已结束」(`board._iw_once`)与「能否按实况搬列」(`board.recover`)。
|
|
68
|
+
self._aligned = False
|
|
64
69
|
self._last_seq = 0
|
|
65
70
|
self._frames = 0
|
|
66
71
|
self._reconnects = 0
|
|
@@ -101,6 +106,22 @@ class EventHub:
|
|
|
101
106
|
with self._cond:
|
|
102
107
|
return self._connected
|
|
103
108
|
|
|
109
|
+
def aligned(self):
|
|
110
|
+
"""注册表是否**可信**(= 链路在线 ∧ 曾用插件权威快照对齐过)。
|
|
111
|
+
|
|
112
|
+
为什么需要它(2026-10-08 批次 B,bug_report/20261008_1935):
|
|
113
|
+
插件重新 apply(热重载)时驱动实例重建、`/live` 会短暂返回空表——旧实现
|
|
114
|
+
`self._sessions = fresh` 直接清空注册表,调用方随即把「未知」当成
|
|
115
|
+
「会话已结束/空闲」:`board.recover()` 把**正在运行的卡**搬去待审核,
|
|
116
|
+
且调和器此后再也读不到该会话 ⇒ 不自愈。现在空快照保留旧表并置
|
|
117
|
+
`_aligned=False`,本读口给出「是否可信」的单点判据:
|
|
118
|
+
- False ⇒ 一律不据实况写列(未知 ≠ 空闲,同「断连=未知」不变量);
|
|
119
|
+
- True ⇒ 会话不在注册表即可判「已结束」(`board._iw_once` 的补口)。
|
|
120
|
+
插件半(A 批次)在 `/live` 里声明 `complete` 后,真·零会话的宿主也能可信。
|
|
121
|
+
"""
|
|
122
|
+
with self._cond:
|
|
123
|
+
return bool(self._connected and self._aligned)
|
|
124
|
+
|
|
104
125
|
def get(self, sid):
|
|
105
126
|
"""单会话实时态;未连接或未知会话返回 None(=未知,不是空闲)。
|
|
106
127
|
|
|
@@ -146,6 +167,7 @@ class EventHub:
|
|
|
146
167
|
"""诊断信息(/api 健康与测试断言用)。"""
|
|
147
168
|
with self._cond:
|
|
148
169
|
return {"connected": self._connected, "sessions": len(self._sessions),
|
|
170
|
+
"aligned": bool(self._connected and self._aligned),
|
|
149
171
|
"last_seq": self._last_seq, "frames": self._frames,
|
|
150
172
|
"reconnects": self._reconnects, "changed": self._changed,
|
|
151
173
|
"archived": None if self._archived is None else len(self._archived),
|
|
@@ -226,8 +248,20 @@ class EventHub:
|
|
|
226
248
|
新的状态轮询」。归档集取不到时保持「未知」(None),调用方一律不动作。
|
|
227
249
|
"""
|
|
228
250
|
try:
|
|
229
|
-
|
|
230
|
-
|
|
251
|
+
# 用 live_snapshot()(原始 dict)而不是 live()(行表 list)——2026-10-08 修正:
|
|
252
|
+
# 旧写法 `dshdriver.live() or {}` 把行表当 dict 取 `.get("sessions")`,
|
|
253
|
+
# `/live` 非空时必抛 AttributeError 被下面 except 吞掉 ⇒ 中枢**永久未对齐**
|
|
254
|
+
# (aligned() 恒 False,C/D 两处补口在真机等于失效)。契约见
|
|
255
|
+
# tests/test_session_visibility.py::test_live_readers_contract。
|
|
256
|
+
resp = dshdriver.live_snapshot() or {}
|
|
257
|
+
rows = resp.get("sessions") or []
|
|
258
|
+
# 插件完整声明(A 批次后新增,旧插件缺省 None=未声明):只有它才让
|
|
259
|
+
# 「空表」具备「宿主里确实没有会话」的语义,否则空表一律按未知处理。
|
|
260
|
+
complete = resp.get("complete") is True
|
|
261
|
+
except Exception as exc: # noqa: BLE001 — 对齐失败不阻断重连
|
|
262
|
+
self._set_aligned(False) # 取不到快照=不能确认任何事
|
|
263
|
+
print(f"[dshevents] /live 对齐失败({exc}):保留 {len(self._sessions)} 条"
|
|
264
|
+
f"既有会话、标记未对齐", flush=True)
|
|
231
265
|
return
|
|
232
266
|
try:
|
|
233
267
|
archived = {str(s) for s in (dshdriver.archived() or []) if s}
|
|
@@ -265,11 +299,34 @@ class EventHub:
|
|
|
265
299
|
"inbox": old.get("inbox") or [],
|
|
266
300
|
"updated_at": now,
|
|
267
301
|
}
|
|
268
|
-
|
|
302
|
+
# —— 快照可信判定(2026-10-08 批次 B)——
|
|
303
|
+
# 非空快照 = 权威整表;空快照只有插件声明完整(complete)才算权威空。
|
|
304
|
+
# 其余情况(热重载后驱动实例重建、不重枚举已有会话 ⇒ 空表)=**未知**:
|
|
305
|
+
# 旧表原样保留(宁可多等不可误放行),只把可信标志置 False——
|
|
306
|
+
# 调用方一律不据此推断忙/闲,也绝不据「缺席」判会话已结束。
|
|
307
|
+
trusted = bool(fresh) or complete
|
|
308
|
+
if trusted:
|
|
309
|
+
self._sessions = fresh
|
|
310
|
+
kept = len(self._sessions)
|
|
311
|
+
self._aligned = trusted
|
|
269
312
|
if archived is not None:
|
|
270
313
|
self._archived = archived
|
|
271
314
|
self._changed += 1
|
|
272
315
|
self._cond.notify_all()
|
|
316
|
+
if not trusted and kept:
|
|
317
|
+
# 留痕(插件形态落 <库目录>/plugin-backend.log):这是可诊断的降级态,
|
|
318
|
+
# 不是静默——旧表保留期间看板列不做忙/闲写入,直到下一次权威快照。
|
|
319
|
+
print(f"[dshevents] /live 空快照且插件未声明完整:保留 {kept} 条既有会话、"
|
|
320
|
+
f"标记未对齐(热重载后驱动实例重建的已知形态,见 "
|
|
321
|
+
f"bug_report/20261008_1935)", flush=True)
|
|
322
|
+
|
|
323
|
+
def _set_aligned(self, value):
|
|
324
|
+
"""置「快照可信」标志(变更才唤醒订阅者;调用方持锁外语义同 `_set_connected`)。"""
|
|
325
|
+
with self._cond:
|
|
326
|
+
if self._aligned != bool(value):
|
|
327
|
+
self._aligned = bool(value)
|
|
328
|
+
self._changed += 1
|
|
329
|
+
self._cond.notify_all()
|
|
273
330
|
|
|
274
331
|
def _set_connected(self, value):
|
|
275
332
|
with self._cond:
|
|
@@ -401,6 +458,11 @@ def connected():
|
|
|
401
458
|
return HUB.connected()
|
|
402
459
|
|
|
403
460
|
|
|
461
|
+
def aligned():
|
|
462
|
+
"""注册表可信读口(在线 ∧ 曾用权威快照对齐);未对齐 ⇒ 调用方不写列、不推断。"""
|
|
463
|
+
return HUB.aligned()
|
|
464
|
+
|
|
465
|
+
|
|
404
466
|
def get(sid):
|
|
405
467
|
return HUB.get(sid)
|
|
406
468
|
|