@gavinc-cn/touchstone-dsh 0.2.0 → 0.4.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.
Files changed (116) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +23 -15
  3. package/README.zh.md +17 -12
  4. package/auth.py +0 -0
  5. package/backend/lib/access.js +44 -0
  6. package/backend/lib/agents.js +341 -0
  7. package/backend/lib/args.js +94 -0
  8. package/backend/lib/auth.js +195 -0
  9. package/backend/lib/board.js +6227 -0
  10. package/backend/lib/builtin-assets.js +1177 -0
  11. package/backend/lib/casescan.js +456 -0
  12. package/backend/lib/chat.js +2090 -0
  13. package/backend/lib/cookie.js +76 -0
  14. package/backend/lib/db.js +2260 -0
  15. package/backend/lib/dshdriver.js +1148 -0
  16. package/backend/lib/dshevents.js +851 -0
  17. package/backend/lib/export-cases.js +261 -0
  18. package/backend/lib/feishu.js +1747 -0
  19. package/backend/lib/feishu_cfg.js +262 -0
  20. package/backend/lib/feishu_conv.js +1484 -0
  21. package/backend/lib/feishu_device.js +428 -0
  22. package/backend/lib/feishu_inbound.js +2077 -0
  23. package/backend/lib/feishu_provision.js +886 -0
  24. package/backend/lib/feishu_rest.js +398 -0
  25. package/backend/lib/feishu_slash.js +568 -0
  26. package/backend/lib/feishu_ws.js +950 -0
  27. package/backend/lib/http.js +312 -0
  28. package/backend/lib/lib.js +973 -0
  29. package/backend/lib/loadcase.js +749 -0
  30. package/backend/lib/loadgen.js +1407 -0
  31. package/backend/lib/localbus.js +164 -0
  32. package/backend/lib/lock.js +426 -0
  33. package/backend/lib/proc.js +361 -0
  34. package/backend/lib/prompts.js +1021 -0
  35. package/backend/lib/pybase64.js +114 -0
  36. package/backend/lib/pyjson.js +214 -0
  37. package/backend/lib/query.js +125 -0
  38. package/backend/lib/rag.js +1310 -0
  39. package/backend/lib/runner.js +4546 -0
  40. package/backend/lib/seed_hint.js +40 -0
  41. package/backend/lib/servercaps.js +182 -0
  42. package/backend/lib/serverstate.js +227 -0
  43. package/backend/lib/sessparse.js +1176 -0
  44. package/backend/lib/sse.js +207 -0
  45. package/backend/lib/static.js +84 -0
  46. package/backend/lib/taskjson.js +302 -0
  47. package/backend/lib/waitq.js +2114 -0
  48. package/backend/lib/worktree.js +588 -0
  49. package/backend/lib/zstd-frames.js +218 -0
  50. package/backend/routes/admin.js +553 -0
  51. package/backend/routes/agents.js +149 -0
  52. package/backend/routes/assets.js +145 -0
  53. package/backend/routes/board.js +1228 -0
  54. package/backend/routes/feishu.js +269 -0
  55. package/backend/routes/feishu_app.js +249 -0
  56. package/backend/routes/feishu_hook.js +358 -0
  57. package/backend/routes/index.js +298 -0
  58. package/backend/routes/projects.js +1138 -0
  59. package/backend/routes/sessions.js +1003 -0
  60. package/backend/routes/tasks.js +1530 -0
  61. package/backend/schema/fixtures/ancient.sql +189 -0
  62. package/backend/schema/fixtures/pre_alter.sql +177 -0
  63. package/backend/schema/migrations.json +154 -0
  64. package/backend/schema/schema.json +1451 -0
  65. package/backend/schema/schema.sql +216 -0
  66. package/backend/server.js +505 -0
  67. package/board.py +96 -13
  68. package/builtin_assets.py +0 -0
  69. package/builtin_prompts/free_style/flow.md +0 -0
  70. package/builtin_prompts/free_style/load_test.md +0 -0
  71. package/builtin_prompts/free_style/templates/bug_report_template.md +0 -0
  72. package/builtin_prompts/free_style/templates/case_template.md +0 -0
  73. package/builtin_prompts/free_style/templates/index_template.md +0 -0
  74. package/builtin_prompts/free_style/templates/load_charts_template.md +0 -0
  75. package/builtin_prompts/free_style/templates/load_index_template.md +0 -0
  76. package/builtin_prompts/free_style/templates/load_plan_template.md +0 -0
  77. package/builtin_prompts/free_style/templates/load_scenario_template.md +0 -0
  78. package/builtin_prompts/free_style/templates/status_template.md +0 -0
  79. package/chat.py +33 -0
  80. package/db.py +294 -129
  81. package/dsh-plugin/cordis.patch.yml +0 -0
  82. package/dsh-plugin/install.sh +22 -8
  83. package/dsh-plugin/lib/client.bundle.js +111 -2
  84. package/dsh-plugin/lib/index.js +340 -29
  85. package/dsh-plugin/lib/pack-closure.mjs +291 -0
  86. package/dsh-plugin/scripts/build.mjs +0 -0
  87. package/dsh-plugin/scripts/prepack-check.mjs +30 -2
  88. package/dsh-plugin/scripts/select-bundle.mjs +0 -0
  89. package/dsh-plugin/src/client.js +111 -2
  90. package/dshevents.py +0 -0
  91. package/export_cases.py +0 -0
  92. package/extensions/dsh-autocommit/asset.json +0 -0
  93. package/extensions/dsh-autocommit/pkg/lib/index.mjs +0 -0
  94. package/extensions/dsh-autocommit/pkg/package.json +0 -0
  95. package/feishu.py +417 -3
  96. package/feishu_conv.py +0 -0
  97. package/lib.py +0 -0
  98. package/lifecycle.py +116 -13
  99. package/loadcase.py +0 -0
  100. package/loadgen.py +0 -0
  101. package/localbus.py +0 -0
  102. package/migrate_p7b.py +0 -0
  103. package/package.json +6 -1
  104. package/platcompat.py +0 -0
  105. package/prompts.py +0 -0
  106. package/rag.py +0 -0
  107. package/requirements.txt +0 -0
  108. package/server.py +155 -11
  109. package/touchstone.py +0 -0
  110. package/waitq.py +0 -0
  111. package/webui/dist-plugin/assets/index-3QsYQi7y.css +1 -0
  112. package/webui/dist-plugin/assets/index-B8AMtW7y.js +486 -0
  113. package/webui/dist-plugin/index.html +2 -2
  114. package/worktree.py +0 -0
  115. package/webui/dist-plugin/assets/index-JLwyZZxC.js +0 -484
  116. package/webui/dist-plugin/assets/index-tJ0TlvQ3.css +0 -1
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Cookie 头解析与 Set-Cookie 生成(`server.py` 会话面两处语义的对应物,M6.9 · R2)。
3
+ *
4
+ * ── 对应关系(逐行对照) ────────────────────────────────────────────────────────
5
+ * - `cookieToken(headers)` ← `server.py:5249-5254` `_cookie_token`
6
+ * for part in self.headers.get("Cookie", "").split(";"):
7
+ * name, _, value = part.strip().partition("=")
8
+ * if name == auth.COOKIE_NAME: return value
9
+ * - `sessionCookie(token)` ← `server.py:1511-1513`(登录)与 `server.py:1568-1570`(注册),
10
+ * 两处写的是同一串:`ts_session=<token>; HttpOnly; SameSite=Lax; Path=/; Max-Age=604800`
11
+ * - `clearSessionCookie()` ← `server.py:1525-1526`(登出):
12
+ * `ts_session=; HttpOnly; SameSite=Lax; Path=/; Max-Age=0`
13
+ *
14
+ * ── 三个易错点(照抄 Python,别想当然) ──────────────────────────────────────────
15
+ * 1. **`partition("=")` 按第一个 `=` 切**:`ts_session=a=b` 的值是 `a=b`;没有 `=` 时
16
+ * Python 的 partition 返回 `("ts_session", "", "")` ⇒ 值空串。
17
+ * 2. **返回值可能是空串**:`ts_session=` 命中了但值是 `""`。Python 的 `_cookie_token` 返回
18
+ * `""`(不是 None),调用方 `_current_user` 里 `if not token: return None` 把空串按 falsy
19
+ * 与「无 cookie」同路处理。本函数照抄这个形态:**命中返回字符串(可能是 `""`),
20
+ * 未命中返回 `null`**;空串与 null 的区别一律由调用方按 falsy 统一处理。
21
+ * 3. **头名大小写不敏感、cookie 名精确**:`self.headers.get` 是 `email.message.Message.get`
22
+ * (头名大小写不敏感,Node 的 `req.headers` 键统一小写),但 cookie **名**比较是
23
+ * `name == auth.COOKIE_NAME` 的**精确**比较 ⇒ `TS_SESSION=x` 不算命中。
24
+ * 另:`part.strip()` 剥的是整段(含名字两侧),故 ` ts_session = x ` 的 name 是
25
+ * `"ts_session "`,同样不命中。
26
+ *
27
+ * 零 npm 依赖:只用 node 内建(复用 lib.js 的 `pyStrip` 以取得 Python `str.strip()` 的
28
+ * Unicode 空白口径)。
29
+ */
30
+ import { COOKIE_NAME, SESSION_TTL } from './auth.js';
31
+ import { pyStrip } from './lib.js';
32
+
33
+ /**
34
+ * 从请求头里取会话 token。对齐 `server.py:_cookie_token`:
35
+ * 逐段 `strip` → 按第一个 `=` 切 → 名字精确等于 `ts_session` 就返回其值(首个命中者胜)。
36
+ *
37
+ * 入参就是 Node 的 `req.headers`(键小写 `cookie`),同时兜住 `Cookie`/`COOKIE` 等写法
38
+ * (对齐 Python `self.headers.get` 的头名大小写不敏感)。
39
+ * @param {object|null|undefined} headers 请求头对象(缺失即视为没有 Cookie 头)
40
+ * @returns {string|null} 命中返回其值(**可能是空串**,falsy);未命中返回 null
41
+ */
42
+ export function cookieToken(headers) {
43
+ if (!headers || typeof headers !== 'object') return null;
44
+ let raw = null;
45
+ for (const key of Object.keys(headers)) {
46
+ if (key.toLowerCase() === 'cookie') { raw = headers[key]; break; }
47
+ }
48
+ if (typeof raw !== 'string') return null;
49
+ for (const part of raw.split(';')) {
50
+ const text = pyStrip(part);
51
+ const eq = text.indexOf('=');
52
+ const name = eq === -1 ? text : text.slice(0, eq);
53
+ const value = eq === -1 ? '' : text.slice(eq + 1);
54
+ if (name === COOKIE_NAME) return value;
55
+ }
56
+ return null;
57
+ }
58
+
59
+ /**
60
+ * 登录/注册响应的 Set-Cookie 值。对齐 `server.py:1511-1513`(属性顺序、空格逐字节照抄):
61
+ * `ts_session=<token>; HttpOnly; SameSite=Lax; Path=/; Max-Age=604800`
62
+ * @param {string} token `auth.newToken()` 的产物
63
+ * @returns {string}
64
+ */
65
+ export function sessionCookie(token) {
66
+ return `${COOKIE_NAME}=${token}; HttpOnly; SameSite=Lax; Path=/; Max-Age=${SESSION_TTL}`;
67
+ }
68
+
69
+ /**
70
+ * 登出响应的 Set-Cookie 值(清 cookie)。对齐 `server.py:1525-1526`:
71
+ * `ts_session=; HttpOnly; SameSite=Lax; Path=/; Max-Age=0`
72
+ * @returns {string}
73
+ */
74
+ export function clearSessionCookie() {
75
+ return `${COOKIE_NAME}=; HttpOnly; SameSite=Lax; Path=/; Max-Age=0`;
76
+ }