@very_aq/codex-cli-web 0.0.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.
Files changed (204) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +228 -0
  3. package/README.zh-CN.md +228 -0
  4. package/package.json +38 -0
  5. package/server/dist/admin/userAdminRoutes.d.ts +7 -0
  6. package/server/dist/admin/userAdminRoutes.js +91 -0
  7. package/server/dist/admin/userAdminRoutes.js.map +1 -0
  8. package/server/dist/app.d.ts +22 -0
  9. package/server/dist/app.js +993 -0
  10. package/server/dist/app.js.map +1 -0
  11. package/server/dist/auth/adminInit.d.ts +41 -0
  12. package/server/dist/auth/adminInit.js +126 -0
  13. package/server/dist/auth/adminInit.js.map +1 -0
  14. package/server/dist/auth/bootstrapAdmin.d.ts +6 -0
  15. package/server/dist/auth/bootstrapAdmin.js +11 -0
  16. package/server/dist/auth/bootstrapAdmin.js.map +1 -0
  17. package/server/dist/auth/httpAuth.d.ts +16 -0
  18. package/server/dist/auth/httpAuth.js +31 -0
  19. package/server/dist/auth/httpAuth.js.map +1 -0
  20. package/server/dist/auth/password.d.ts +2 -0
  21. package/server/dist/auth/password.js +68 -0
  22. package/server/dist/auth/password.js.map +1 -0
  23. package/server/dist/auth/requireAdmin.d.ts +2 -0
  24. package/server/dist/auth/requireAdmin.js +14 -0
  25. package/server/dist/auth/requireAdmin.js.map +1 -0
  26. package/server/dist/auth/roles.d.ts +3 -0
  27. package/server/dist/auth/roles.js +13 -0
  28. package/server/dist/auth/roles.js.map +1 -0
  29. package/server/dist/auth/session.d.ts +24 -0
  30. package/server/dist/auth/session.js +127 -0
  31. package/server/dist/auth/session.js.map +1 -0
  32. package/server/dist/auth/sqlite/authDb.d.ts +18 -0
  33. package/server/dist/auth/sqlite/authDb.js +26 -0
  34. package/server/dist/auth/sqlite/authDb.js.map +1 -0
  35. package/server/dist/auth/sqlite/legacyImport.d.ts +22 -0
  36. package/server/dist/auth/sqlite/legacyImport.js +208 -0
  37. package/server/dist/auth/sqlite/legacyImport.js.map +1 -0
  38. package/server/dist/auth/sqlite/schema.d.ts +11 -0
  39. package/server/dist/auth/sqlite/schema.js +47 -0
  40. package/server/dist/auth/sqlite/schema.js.map +1 -0
  41. package/server/dist/auth/sqlite/sqliteUserStore.d.ts +12 -0
  42. package/server/dist/auth/sqlite/sqliteUserStore.js +194 -0
  43. package/server/dist/auth/sqlite/sqliteUserStore.js.map +1 -0
  44. package/server/dist/auth/userStore.d.ts +19 -0
  45. package/server/dist/auth/userStore.js +26 -0
  46. package/server/dist/auth/userStore.js.map +1 -0
  47. package/server/dist/auth/userTypes.d.ts +13 -0
  48. package/server/dist/auth/userTypes.js +3 -0
  49. package/server/dist/auth/userTypes.js.map +1 -0
  50. package/server/dist/chat/attachmentPathRedaction.d.ts +5 -0
  51. package/server/dist/chat/attachmentPathRedaction.js +67 -0
  52. package/server/dist/chat/attachmentPathRedaction.js.map +1 -0
  53. package/server/dist/chat/chatItemEnricher.d.ts +5 -0
  54. package/server/dist/chat/chatItemEnricher.js +40 -0
  55. package/server/dist/chat/chatItemEnricher.js.map +1 -0
  56. package/server/dist/chat/codexEventProjector.d.ts +33 -0
  57. package/server/dist/chat/codexEventProjector.js +482 -0
  58. package/server/dist/chat/codexEventProjector.js.map +1 -0
  59. package/server/dist/chat/contextUsageProjector.d.ts +10 -0
  60. package/server/dist/chat/contextUsageProjector.js +472 -0
  61. package/server/dist/chat/contextUsageProjector.js.map +1 -0
  62. package/server/dist/chat/fileChangeExtractor.d.ts +5 -0
  63. package/server/dist/chat/fileChangeExtractor.js +121 -0
  64. package/server/dist/chat/fileChangeExtractor.js.map +1 -0
  65. package/server/dist/chat/markdown/markdownAst.d.ts +5 -0
  66. package/server/dist/chat/markdown/markdownAst.js +154 -0
  67. package/server/dist/chat/markdown/markdownAst.js.map +1 -0
  68. package/server/dist/chat/systemToolCallSummary.d.ts +10 -0
  69. package/server/dist/chat/systemToolCallSummary.js +112 -0
  70. package/server/dist/chat/systemToolCallSummary.js.map +1 -0
  71. package/server/dist/chat/terminal/terminalPlainText.d.ts +14 -0
  72. package/server/dist/chat/terminal/terminalPlainText.js +139 -0
  73. package/server/dist/chat/terminal/terminalPlainText.js.map +1 -0
  74. package/server/dist/chat/textMetrics.d.ts +9 -0
  75. package/server/dist/chat/textMetrics.js +24 -0
  76. package/server/dist/chat/textMetrics.js.map +1 -0
  77. package/server/dist/chat/threadTurnsProjector.d.ts +12 -0
  78. package/server/dist/chat/threadTurnsProjector.js +292 -0
  79. package/server/dist/chat/threadTurnsProjector.js.map +1 -0
  80. package/server/dist/chat/todoPlanProjector.d.ts +8 -0
  81. package/server/dist/chat/todoPlanProjector.js +94 -0
  82. package/server/dist/chat/todoPlanProjector.js.map +1 -0
  83. package/server/dist/chat/todoPlanTypes.d.ts +21 -0
  84. package/server/dist/chat/todoPlanTypes.js +3 -0
  85. package/server/dist/chat/todoPlanTypes.js.map +1 -0
  86. package/server/dist/chat/types.d.ts +138 -0
  87. package/server/dist/chat/types.js +3 -0
  88. package/server/dist/chat/types.js.map +1 -0
  89. package/server/dist/cli/configArg.d.ts +21 -0
  90. package/server/dist/cli/configArg.js +70 -0
  91. package/server/dist/cli/configArg.js.map +1 -0
  92. package/server/dist/codex/appServerProcess.d.ts +24 -0
  93. package/server/dist/codex/appServerProcess.js +56 -0
  94. package/server/dist/codex/appServerProcess.js.map +1 -0
  95. package/server/dist/codex/cliArgs.d.ts +17 -0
  96. package/server/dist/codex/cliArgs.js +34 -0
  97. package/server/dist/codex/cliArgs.js.map +1 -0
  98. package/server/dist/codex/codexAppServer.d.ts +103 -0
  99. package/server/dist/codex/codexAppServer.js +206 -0
  100. package/server/dist/codex/codexAppServer.js.map +1 -0
  101. package/server/dist/codex/jsonl.d.ts +4 -0
  102. package/server/dist/codex/jsonl.js +23 -0
  103. package/server/dist/codex/jsonl.js.map +1 -0
  104. package/server/dist/codex/jsonrpc.d.ts +43 -0
  105. package/server/dist/codex/jsonrpc.js +96 -0
  106. package/server/dist/codex/jsonrpc.js.map +1 -0
  107. package/server/dist/config/serverConfig.d.ts +150 -0
  108. package/server/dist/config/serverConfig.js +64 -0
  109. package/server/dist/config/serverConfig.js.map +1 -0
  110. package/server/dist/env.d.ts +101 -0
  111. package/server/dist/env.js +523 -0
  112. package/server/dist/env.js.map +1 -0
  113. package/server/dist/history/http/historyRoutes.d.ts +18 -0
  114. package/server/dist/history/http/historyRoutes.js +67 -0
  115. package/server/dist/history/http/historyRoutes.js.map +1 -0
  116. package/server/dist/history/index.d.ts +24 -0
  117. package/server/dist/history/index.js +30 -0
  118. package/server/dist/history/index.js.map +1 -0
  119. package/server/dist/history/ingest/historyIngestService.d.ts +15 -0
  120. package/server/dist/history/ingest/historyIngestService.js +42 -0
  121. package/server/dist/history/ingest/historyIngestService.js.map +1 -0
  122. package/server/dist/history/projector/extractIds.d.ts +36 -0
  123. package/server/dist/history/projector/extractIds.js +111 -0
  124. package/server/dist/history/projector/extractIds.js.map +1 -0
  125. package/server/dist/history/projector/projectCodexEvent.d.ts +27 -0
  126. package/server/dist/history/projector/projectCodexEvent.js +845 -0
  127. package/server/dist/history/projector/projectCodexEvent.js.map +1 -0
  128. package/server/dist/history/query/historyQueryService.d.ts +34 -0
  129. package/server/dist/history/query/historyQueryService.js +170 -0
  130. package/server/dist/history/query/historyQueryService.js.map +1 -0
  131. package/server/dist/history/sqlite/schema.d.ts +11 -0
  132. package/server/dist/history/sqlite/schema.js +34 -0
  133. package/server/dist/history/sqlite/schema.js.map +1 -0
  134. package/server/dist/history/sqlite/sqliteHistoryStore.d.ts +69 -0
  135. package/server/dist/history/sqlite/sqliteHistoryStore.js +206 -0
  136. package/server/dist/history/sqlite/sqliteHistoryStore.js.map +1 -0
  137. package/server/dist/history/types.d.ts +29 -0
  138. package/server/dist/history/types.js +3 -0
  139. package/server/dist/history/types.js.map +1 -0
  140. package/server/dist/index.d.ts +1 -0
  141. package/server/dist/index.js +166 -0
  142. package/server/dist/index.js.map +1 -0
  143. package/server/dist/security/executionPolicy.d.ts +33 -0
  144. package/server/dist/security/executionPolicy.js +72 -0
  145. package/server/dist/security/executionPolicy.js.map +1 -0
  146. package/server/dist/security/origin.d.ts +11 -0
  147. package/server/dist/security/origin.js +40 -0
  148. package/server/dist/security/origin.js.map +1 -0
  149. package/server/dist/settings/sqliteUserSettingsStore.d.ts +12 -0
  150. package/server/dist/settings/sqliteUserSettingsStore.js +62 -0
  151. package/server/dist/settings/sqliteUserSettingsStore.js.map +1 -0
  152. package/server/dist/settings/userSettingsRoutes.d.ts +8 -0
  153. package/server/dist/settings/userSettingsRoutes.js +55 -0
  154. package/server/dist/settings/userSettingsRoutes.js.map +1 -0
  155. package/server/dist/settings/userSettingsStore.d.ts +19 -0
  156. package/server/dist/settings/userSettingsStore.js +26 -0
  157. package/server/dist/settings/userSettingsStore.js.map +1 -0
  158. package/server/dist/settings/userSettingsTypes.d.ts +70 -0
  159. package/server/dist/settings/userSettingsTypes.js +196 -0
  160. package/server/dist/settings/userSettingsTypes.js.map +1 -0
  161. package/server/dist/status/codexTaskTracker.d.ts +21 -0
  162. package/server/dist/status/codexTaskTracker.js +123 -0
  163. package/server/dist/status/codexTaskTracker.js.map +1 -0
  164. package/server/dist/status/threadContextUsage.d.ts +19 -0
  165. package/server/dist/status/threadContextUsage.js +229 -0
  166. package/server/dist/status/threadContextUsage.js.map +1 -0
  167. package/server/dist/threadList/threadListServerCache.d.ts +10 -0
  168. package/server/dist/threadList/threadListServerCache.js +42 -0
  169. package/server/dist/threadList/threadListServerCache.js.map +1 -0
  170. package/server/dist/tools/cwdSuggest.d.ts +11 -0
  171. package/server/dist/tools/cwdSuggest.js +128 -0
  172. package/server/dist/tools/cwdSuggest.js.map +1 -0
  173. package/server/dist/workspace/accessControl.d.ts +16 -0
  174. package/server/dist/workspace/accessControl.js +82 -0
  175. package/server/dist/workspace/accessControl.js.map +1 -0
  176. package/server/dist/workspace/sqliteUserWorkspaceStore.d.ts +12 -0
  177. package/server/dist/workspace/sqliteUserWorkspaceStore.js +82 -0
  178. package/server/dist/workspace/sqliteUserWorkspaceStore.js.map +1 -0
  179. package/server/dist/workspace/threadAccess.d.ts +19 -0
  180. package/server/dist/workspace/threadAccess.js +22 -0
  181. package/server/dist/workspace/threadAccess.js.map +1 -0
  182. package/server/dist/workspace/threadListVisibility.d.ts +25 -0
  183. package/server/dist/workspace/threadListVisibility.js +104 -0
  184. package/server/dist/workspace/threadListVisibility.js.map +1 -0
  185. package/server/dist/workspace/userWorkspaceRoutes.d.ts +7 -0
  186. package/server/dist/workspace/userWorkspaceRoutes.js +124 -0
  187. package/server/dist/workspace/userWorkspaceRoutes.js.map +1 -0
  188. package/server/dist/workspace/userWorkspaceStore.d.ts +12 -0
  189. package/server/dist/workspace/userWorkspaceStore.js +23 -0
  190. package/server/dist/workspace/userWorkspaceStore.js.map +1 -0
  191. package/server/dist/ws/socketIoBridge.d.ts +32 -0
  192. package/server/dist/ws/socketIoBridge.js +194 -0
  193. package/server/dist/ws/socketIoBridge.js.map +1 -0
  194. package/server/dist/ws/types.d.ts +113 -0
  195. package/server/dist/ws/types.js +3 -0
  196. package/server/dist/ws/types.js.map +1 -0
  197. package/server/dist/ws/wsHub.d.ts +119 -0
  198. package/server/dist/ws/wsHub.js +1259 -0
  199. package/server/dist/ws/wsHub.js.map +1 -0
  200. package/web/dist/assets/index-CY6cnwQz.js +174 -0
  201. package/web/dist/assets/index-DI7kJHr2.css +32 -0
  202. package/web/dist/favicon-mask.svg +9 -0
  203. package/web/dist/favicon.svg +26 -0
  204. package/web/dist/index.html +75 -0
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractFileChangesFromAny = extractFileChangesFromAny;
4
+ /**
5
+ * 判断字符串是否为对象被隐式转字符串后的占位值。
6
+ */
7
+ function isObjectStringPlaceholder(value) {
8
+ return value.trim().toLowerCase() === "[object object]";
9
+ }
10
+ /**
11
+ * 从候选值中提取可用字符串;无效时返回空串。
12
+ */
13
+ function normalizeStringCandidate(raw) {
14
+ if (typeof raw !== "string")
15
+ return "";
16
+ const value = raw.trim();
17
+ if (!value || isObjectStringPlaceholder(value))
18
+ return "";
19
+ return value;
20
+ }
21
+ /**
22
+ * 归一化文件路径,避免对象路径被渲染成 `[object Object]`。
23
+ */
24
+ function normalizeFileChangePath(change) {
25
+ // 常见路径来源字段,按优先级尝试。
26
+ const rawPath = change.path ??
27
+ change.file ??
28
+ change.filename ??
29
+ change.target?.path ??
30
+ change.target?.file ??
31
+ change.source?.path ??
32
+ change.source?.file;
33
+ const directPath = normalizeStringCandidate(rawPath);
34
+ if (directPath)
35
+ return directPath;
36
+ if (rawPath && typeof rawPath === "object") {
37
+ // 某些协议会把路径包在对象里,继续提取常见字段。
38
+ const nestedPathObject = rawPath;
39
+ const nestedPath = normalizeStringCandidate(nestedPathObject.path) ||
40
+ normalizeStringCandidate(nestedPathObject.file) ||
41
+ normalizeStringCandidate(nestedPathObject.filename) ||
42
+ normalizeStringCandidate(nestedPathObject.value) ||
43
+ normalizeStringCandidate(nestedPathObject.text);
44
+ if (nestedPath)
45
+ return nestedPath;
46
+ }
47
+ return "";
48
+ }
49
+ /**
50
+ * 归一化文件变更类型,支持对象结构并提供稳定回退值。
51
+ */
52
+ function normalizeFileChangeKind(change) {
53
+ // 常见 kind/type 来源字段,优先使用顶层。
54
+ const rawKind = change.kind ?? change.type ?? change.action ?? change.operation ?? change.op ?? change.status;
55
+ const directKind = normalizeStringCandidate(rawKind);
56
+ if (directKind)
57
+ return directKind;
58
+ if (rawKind && typeof rawKind === "object") {
59
+ // kind 本身可能是对象,如 { type: "edit" }。
60
+ const nestedKindObject = rawKind;
61
+ const nestedKind = normalizeStringCandidate(nestedKindObject.kind) ||
62
+ normalizeStringCandidate(nestedKindObject.type) ||
63
+ normalizeStringCandidate(nestedKindObject.action) ||
64
+ normalizeStringCandidate(nestedKindObject.operation) ||
65
+ normalizeStringCandidate(nestedKindObject.op) ||
66
+ normalizeStringCandidate(nestedKindObject.status) ||
67
+ normalizeStringCandidate(nestedKindObject.value) ||
68
+ normalizeStringCandidate(nestedKindObject.name) ||
69
+ normalizeStringCandidate(nestedKindObject.label) ||
70
+ normalizeStringCandidate(nestedKindObject.text);
71
+ if (nestedKind)
72
+ return nestedKind;
73
+ // 兜底:处理 { added: true } 这类布尔键语义。
74
+ const truthyKey = Object.entries(nestedKindObject).find((entry) => entry[1] === true)?.[0];
75
+ const normalizedTruthyKey = normalizeStringCandidate(truthyKey);
76
+ if (normalizedTruthyKey)
77
+ return normalizedTruthyKey;
78
+ }
79
+ return "change";
80
+ }
81
+ /**
82
+ * 将未知结构的 fileChange 数组归一化为 `FileChange[]`。
83
+ */
84
+ function normalizeFileChanges(raw) {
85
+ const arr = Array.isArray(raw) ? raw : [];
86
+ const out = [];
87
+ for (const change of arr) {
88
+ // 每条变更先归一化路径,路径缺失则忽略该条目。
89
+ const path = normalizeFileChangePath(change ?? {});
90
+ if (!path)
91
+ continue;
92
+ // 归一化 kind,避免对象直接 String 化成 `[object Object]`。
93
+ const kind = normalizeFileChangeKind(change ?? {});
94
+ const diff = typeof change?.diff === "string"
95
+ ? String(change.diff)
96
+ : typeof change?.patch === "string"
97
+ ? String(change.patch)
98
+ : typeof change?.unifiedDiff === "string"
99
+ ? String(change.unifiedDiff)
100
+ : "";
101
+ out.push({ path, kind, diff });
102
+ }
103
+ return out;
104
+ }
105
+ /**
106
+ * 从未知对象中提取 file changes。
107
+ */
108
+ function extractFileChangesFromAny(raw) {
109
+ const record = raw;
110
+ if (!record)
111
+ return [];
112
+ return normalizeFileChanges(record?.changes ??
113
+ record?.diff?.changes ??
114
+ record?.patch?.changes ??
115
+ record?.fileChanges ??
116
+ record?.file_changes ??
117
+ record?.files ??
118
+ record?.edits ??
119
+ []);
120
+ }
121
+ //# sourceMappingURL=fileChangeExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileChangeExtractor.js","sourceRoot":"","sources":["../../src/chat/fileChangeExtractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { UiMarkdownAst } from "../types";
2
+ /**
3
+ * 解析 Markdown 文本为 UiMarkdownAst;无内容时返回 null。
4
+ */
5
+ export declare function buildMarkdownAst(markdown: string): UiMarkdownAst | null;
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildMarkdownAst = buildMarkdownAst;
7
+ const micromark_util_sanitize_uri_1 = require("micromark-util-sanitize-uri");
8
+ const unified_1 = require("unified");
9
+ const remark_breaks_1 = __importDefault(require("remark-breaks"));
10
+ const remark_gfm_1 = __importDefault(require("remark-gfm"));
11
+ const remark_parse_1 = __importDefault(require("remark-parse"));
12
+ const remark_rehype_1 = __importDefault(require("remark-rehype"));
13
+ /**
14
+ * 判断未知节点是否为 HAST element。
15
+ */
16
+ function isHastElement(node) {
17
+ if (!node || typeof node !== "object")
18
+ return false;
19
+ return node.type === "element" && typeof node.tagName === "string";
20
+ }
21
+ /**
22
+ * 判断未知节点是否为 HAST root。
23
+ */
24
+ function isHastRoot(node) {
25
+ if (!node || typeof node !== "object")
26
+ return false;
27
+ return node.type === "root";
28
+ }
29
+ /**
30
+ * 判断未知节点是否为 HAST text。
31
+ */
32
+ function isHastText(node) {
33
+ if (!node || typeof node !== "object")
34
+ return false;
35
+ return node.type === "text" && typeof node.value === "string";
36
+ }
37
+ /**
38
+ * 归一化 className 字段为 string[],便于追加自定义样式类。
39
+ */
40
+ function normalizeClassName(value) {
41
+ if (Array.isArray(value))
42
+ return value.map((v) => String(v ?? "").trim()).filter(Boolean);
43
+ if (typeof value === "string")
44
+ return value.split(/\s+/u).map((v) => v.trim()).filter(Boolean);
45
+ return [];
46
+ }
47
+ /**
48
+ * 为 properties.className 追加一个 class(去重)。
49
+ */
50
+ function appendClassName(properties, className) {
51
+ const normalizedClassName = className.trim();
52
+ if (!normalizedClassName)
53
+ return;
54
+ const existing = normalizeClassName(properties.className);
55
+ if (existing.includes(normalizedClassName)) {
56
+ properties.className = existing;
57
+ return;
58
+ }
59
+ properties.className = [...existing, normalizedClassName];
60
+ }
61
+ /**
62
+ * 安全读取可序列化的字符串属性。
63
+ */
64
+ function readStringProperty(value) {
65
+ if (typeof value === "string")
66
+ return value;
67
+ if (typeof value === "number" && Number.isFinite(value))
68
+ return String(value);
69
+ return "";
70
+ }
71
+ /**
72
+ * 归一化链接地址,避免 `javascript:` 等危险协议。
73
+ */
74
+ function normalizeSafeUrl(rawUrl) {
75
+ const raw = readStringProperty(rawUrl).trim();
76
+ if (!raw)
77
+ return "";
78
+ return (0, micromark_util_sanitize_uri_1.sanitizeUri)(raw);
79
+ }
80
+ /**
81
+ * 将 HAST 节点转换为可 JSON 序列化、前端可直接渲染的 UiMarkdownAst。
82
+ *
83
+ * 说明:
84
+ * - 后端解析 Markdown,前端仅渲染;
85
+ * - 不透传 position/data 等调试字段,降低 payload;
86
+ * - 注入与现有 CSS 对齐的 className(mdPre/mdCodeInline);
87
+ * - 对 url 做 sanitize,避免 XSS。
88
+ */
89
+ function toUiMarkdownAst(node, parentTagName) {
90
+ if (isHastRoot(node)) {
91
+ const children = Array.isArray(node.children) ? node.children : [];
92
+ const nextChildren = children
93
+ .map((child) => toUiMarkdownAst(child, null))
94
+ .filter((child) => Boolean(child));
95
+ return { type: "root", children: nextChildren };
96
+ }
97
+ if (isHastText(node))
98
+ return { type: "text", value: node.value };
99
+ if (!isHastElement(node))
100
+ return null;
101
+ const tagName = node.tagName;
102
+ if (!tagName)
103
+ return null;
104
+ const rawProperties = node.properties && typeof node.properties === "object" ? node.properties : {};
105
+ const properties = { ...rawProperties };
106
+ if (tagName === "a") {
107
+ properties.href = normalizeSafeUrl(properties.href);
108
+ properties.target = "_blank";
109
+ properties.rel = "noreferrer";
110
+ }
111
+ if (tagName === "img") {
112
+ properties.src = normalizeSafeUrl(properties.src);
113
+ properties.loading = "lazy";
114
+ properties.alt = readStringProperty(properties.alt);
115
+ }
116
+ if (tagName === "pre") {
117
+ appendClassName(properties, "mdPre");
118
+ }
119
+ if (tagName === "code" && parentTagName !== "pre") {
120
+ appendClassName(properties, "mdCodeInline");
121
+ }
122
+ const children = Array.isArray(node.children) ? node.children : [];
123
+ const nextChildren = children
124
+ .map((child) => toUiMarkdownAst(child, tagName))
125
+ .filter((child) => Boolean(child));
126
+ const outNode = {
127
+ type: "element",
128
+ tagName,
129
+ properties: Object.keys(properties).length ? properties : undefined,
130
+ children: nextChildren,
131
+ };
132
+ return outNode;
133
+ }
134
+ /**
135
+ * 解析 Markdown 文本为 UiMarkdownAst;无内容时返回 null。
136
+ */
137
+ function buildMarkdownAst(markdown) {
138
+ const normalizedMarkdown = String(markdown ?? "");
139
+ if (!normalizedMarkdown.trim())
140
+ return null;
141
+ const processor = (0, unified_1.unified)()
142
+ .use(remark_parse_1.default)
143
+ .use(remark_gfm_1.default)
144
+ .use(remark_breaks_1.default)
145
+ // 默认不允许危险 HTML,保持与前端 `skipHtml` 一致。
146
+ .use(remark_rehype_1.default, { allowDangerousHtml: false });
147
+ const mdast = processor.parse(normalizedMarkdown);
148
+ const hast = processor.runSync(mdast);
149
+ if (!hast)
150
+ return null;
151
+ const root = isHastRoot(hast) ? hast : { type: "root", children: [hast] };
152
+ return toUiMarkdownAst(root, null);
153
+ }
154
+ //# sourceMappingURL=markdownAst.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdownAst.js","sourceRoot":"","sources":["../../../src/chat/markdown/markdownAst.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { SystemToolCallSummary } from "./types";
2
+ /**
3
+ * 尝试把 system 文本解析为 CLI 风格的工具调用摘要。
4
+ * 若结构不明显,返回 `null` 并由上层回退到普通文本渲染。
5
+ */
6
+ export declare function parseSystemToolCallSummary(text: string): SystemToolCallSummary | null;
7
+ /**
8
+ * 生成折叠态单行预览文本,避免结构化内容退化成冗长纯文本。
9
+ */
10
+ export declare function buildSystemToolCallSummaryPreview(summary: SystemToolCallSummary): string;
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseSystemToolCallSummary = parseSystemToolCallSummary;
4
+ exports.buildSystemToolCallSummaryPreview = buildSystemToolCallSummaryPreview;
5
+ /**
6
+ * 阶段标题前缀:支持 `• xxx` / `- xxx` / `1. xxx`。
7
+ */
8
+ const STAGE_PREFIX_REGEXP = /^(?:[•●▪◦*-]|\d+\.)\s+/u;
9
+ /**
10
+ * 子步骤前缀:支持 `↳ xxx`、`-> xxx`、`└ xxx` 等。
11
+ */
12
+ const STEP_PREFIX_REGEXP = /^(?:↳|->|=>|›|└|├|-)\s+/u;
13
+ /**
14
+ * 状态行常见前缀(用于降低误判)。
15
+ */
16
+ const STATUS_LINE_PREFIX_REGEXP = /^(?:planning|inspecting|exploring|search(?:ing)?|running|thinking|analyzing|executing)\b/i;
17
+ /**
18
+ * 子步骤常见动作前缀:覆盖无箭头但语义明确的工具调用行。
19
+ */
20
+ const STEP_ACTION_PREFIX_REGEXP = /^(?:read|search|searched|inspect|inspected|explore|explored|write|wrote|edit|edited|run|ran|execute|executed|open|click|find|grep|rg|cat)\b/i;
21
+ /**
22
+ * 归一化单行文本:统一 tab,并去掉尾部空白。
23
+ */
24
+ function normalizeLine(rawLine) {
25
+ return rawLine.replace(/\t/g, " ").replace(/\s+$/u, "");
26
+ }
27
+ /**
28
+ * 去掉阶段前缀并返回正文;无法匹配时返回空串。
29
+ */
30
+ function extractStageTitle(line) {
31
+ if (!STAGE_PREFIX_REGEXP.test(line))
32
+ return "";
33
+ return line.replace(STAGE_PREFIX_REGEXP, "").trim();
34
+ }
35
+ /**
36
+ * 去掉子步骤前缀并返回正文;无法匹配时返回空串。
37
+ */
38
+ function extractStepText(line) {
39
+ if (!STEP_PREFIX_REGEXP.test(line))
40
+ return "";
41
+ return line.replace(STEP_PREFIX_REGEXP, "").trim();
42
+ }
43
+ /**
44
+ * 尝试把 system 文本解析为 CLI 风格的工具调用摘要。
45
+ * 若结构不明显,返回 `null` 并由上层回退到普通文本渲染。
46
+ */
47
+ function parseSystemToolCallSummary(text) {
48
+ const normalizedText = String(text ?? "").replace(/\r\n/g, "\n").trim();
49
+ if (!normalizedText)
50
+ return null;
51
+ const sourceLines = normalizedText.split("\n");
52
+ const parsedStages = [];
53
+ const parsedStatusLines = [];
54
+ // currentStage:当前正在填充的阶段;只有遇到阶段标题后才会有值。
55
+ let currentStage = null;
56
+ // totalStepCount:统计子步骤总数,用于“是否值得结构化展示”的判定。
57
+ let totalStepCount = 0;
58
+ for (const rawLine of sourceLines) {
59
+ const normalizedLine = normalizeLine(rawLine);
60
+ const trimmedLine = normalizedLine.trim();
61
+ if (!trimmedLine)
62
+ continue;
63
+ // hasLeadingIndent:用于区分“顶层阶段”与“阶段内子步骤”。
64
+ const hasLeadingIndent = /^\s+/u.test(normalizedLine);
65
+ const stageTitle = !hasLeadingIndent ? extractStageTitle(trimmedLine) : "";
66
+ if (stageTitle) {
67
+ const stage = { title: stageTitle, steps: [] };
68
+ parsedStages.push(stage);
69
+ currentStage = stage;
70
+ continue;
71
+ }
72
+ const stepText = extractStepText(trimmedLine);
73
+ if (stepText && currentStage) {
74
+ currentStage.steps.push(stepText);
75
+ totalStepCount += 1;
76
+ continue;
77
+ }
78
+ if (hasLeadingIndent && currentStage) {
79
+ currentStage.steps.push(trimmedLine);
80
+ totalStepCount += 1;
81
+ continue;
82
+ }
83
+ if (currentStage && STEP_ACTION_PREFIX_REGEXP.test(trimmedLine)) {
84
+ currentStage.steps.push(trimmedLine);
85
+ totalStepCount += 1;
86
+ continue;
87
+ }
88
+ parsedStatusLines.push(trimmedLine);
89
+ currentStage = null;
90
+ }
91
+ if (!parsedStages.length)
92
+ return null;
93
+ // 仅有“普通列表”时不启用结构化展示,避免误伤 system 的普通 Markdown。
94
+ const hasLikelyStatusLine = parsedStatusLines.some((statusLine) => STATUS_LINE_PREFIX_REGEXP.test(statusLine));
95
+ if (totalStepCount <= 0 && !hasLikelyStatusLine)
96
+ return null;
97
+ return { stages: parsedStages, statusLines: parsedStatusLines };
98
+ }
99
+ /**
100
+ * 生成折叠态单行预览文本,避免结构化内容退化成冗长纯文本。
101
+ */
102
+ function buildSystemToolCallSummaryPreview(summary) {
103
+ const firstStageTitle = summary.stages[0]?.title?.trim() || "工具调用";
104
+ const totalStepCount = summary.stages.reduce((count, stage) => count + stage.steps.length, 0);
105
+ const stageCount = summary.stages.length;
106
+ const countPreview = totalStepCount > 0 ? `${totalStepCount} 条操作` : `${stageCount} 个阶段`;
107
+ const statusPreview = summary.statusLines[0]?.trim();
108
+ if (!statusPreview)
109
+ return `${firstStageTitle} · ${countPreview}`;
110
+ return `${firstStageTitle} · ${countPreview} · ${statusPreview}`;
111
+ }
112
+ //# sourceMappingURL=systemToolCallSummary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemToolCallSummary.js","sourceRoot":"","sources":["../../src/chat/systemToolCallSummary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { countLines, getTextMetrics } from "../textMetrics";
2
+ export { countLines, getTextMetrics };
3
+ /**
4
+ * 以增量方式模拟终端输出,处理常见光标移动与擦除序列。
5
+ *
6
+ * 说明:
7
+ * - 该逻辑与 Web 侧旧实现保持一致(用于保持展示/复制行为不变);
8
+ * - 仅覆盖常见的 `\r`、`\b` 与部分 CSI 序列,不追求完整 VT100 支持。
9
+ */
10
+ export declare function appendTerminalDelta(existing: string, delta: string): string;
11
+ /**
12
+ * 规范化终端文本,支持包含 ANSI 增量符号的场景。
13
+ */
14
+ export declare function normalizeTerminalText(text: string): string;
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTextMetrics = exports.countLines = void 0;
4
+ exports.appendTerminalDelta = appendTerminalDelta;
5
+ exports.normalizeTerminalText = normalizeTerminalText;
6
+ const textMetrics_1 = require("../textMetrics");
7
+ Object.defineProperty(exports, "countLines", { enumerable: true, get: function () { return textMetrics_1.countLines; } });
8
+ Object.defineProperty(exports, "getTextMetrics", { enumerable: true, get: function () { return textMetrics_1.getTextMetrics; } });
9
+ /**
10
+ * 去除 OSC 序列(常见于终端设置标题、超链接等),避免 UI 复制/预览出现控制字符。
11
+ */
12
+ function stripOscSequences(text) {
13
+ return text.replace(/\x1b\][^\x07]*(?:\x07|\x1b\\)/g, "");
14
+ }
15
+ /**
16
+ * 以增量方式模拟终端输出,处理常见光标移动与擦除序列。
17
+ *
18
+ * 说明:
19
+ * - 该逻辑与 Web 侧旧实现保持一致(用于保持展示/复制行为不变);
20
+ * - 仅覆盖常见的 `\r`、`\b` 与部分 CSI 序列,不追求完整 VT100 支持。
21
+ */
22
+ function appendTerminalDelta(existing, delta) {
23
+ const input = stripOscSequences(delta).replace(/\r\n/g, "\n");
24
+ const lastNewlineIndex = existing.lastIndexOf("\n");
25
+ let prefix = lastNewlineIndex >= 0 ? existing.slice(0, lastNewlineIndex + 1) : "";
26
+ let line = lastNewlineIndex >= 0 ? existing.slice(lastNewlineIndex + 1) : existing;
27
+ let lineBuffer = Array.from(line);
28
+ let column = lineBuffer.length;
29
+ const ensureColumn = (nextColumn) => {
30
+ if (nextColumn <= lineBuffer.length)
31
+ return;
32
+ for (let index = lineBuffer.length; index < nextColumn; index += 1)
33
+ lineBuffer.push(" ");
34
+ };
35
+ const eraseInLine = (mode) => {
36
+ if (mode === 0) {
37
+ lineBuffer = lineBuffer.slice(0, column);
38
+ return;
39
+ }
40
+ if (mode === 1) {
41
+ ensureColumn(column);
42
+ for (let index = 0; index < column; index += 1)
43
+ lineBuffer[index] = " ";
44
+ return;
45
+ }
46
+ if (mode === 2) {
47
+ const keepColumn = column;
48
+ lineBuffer = [];
49
+ ensureColumn(keepColumn);
50
+ }
51
+ };
52
+ const writeChar = (character) => {
53
+ ensureColumn(column);
54
+ if (column === lineBuffer.length)
55
+ lineBuffer.push(character);
56
+ else
57
+ lineBuffer[column] = character;
58
+ column += 1;
59
+ };
60
+ const isFinalByte = (character) => {
61
+ const codePoint = character.charCodeAt(0);
62
+ return codePoint >= 0x40 && codePoint <= 0x7e;
63
+ };
64
+ for (let index = 0; index < input.length; index += 1) {
65
+ const character = input[index];
66
+ if (character === "\n") {
67
+ prefix += lineBuffer.join("") + "\n";
68
+ lineBuffer = [];
69
+ column = 0;
70
+ continue;
71
+ }
72
+ if (character === "\r") {
73
+ column = 0;
74
+ continue;
75
+ }
76
+ if (character === "\b") {
77
+ column = Math.max(0, column - 1);
78
+ continue;
79
+ }
80
+ if (character === "\t") {
81
+ writeChar(" ");
82
+ writeChar(" ");
83
+ continue;
84
+ }
85
+ if (character === "\x1b") {
86
+ if (input[index + 1] === "[") {
87
+ let cursor = index + 2;
88
+ let paramText = "";
89
+ while (cursor < input.length && !isFinalByte(input[cursor])) {
90
+ paramText += input[cursor];
91
+ cursor += 1;
92
+ }
93
+ const finalByte = cursor < input.length ? input[cursor] : "";
94
+ index = cursor;
95
+ if (paramText.includes("?"))
96
+ continue;
97
+ const firstParam = (() => {
98
+ const header = paramText.split(";")[0] ?? "";
99
+ const value = header ? Number(header) : 0;
100
+ return Number.isFinite(value) ? value : 0;
101
+ })();
102
+ if (finalByte === "m")
103
+ continue;
104
+ if (finalByte === "K") {
105
+ eraseInLine(firstParam);
106
+ continue;
107
+ }
108
+ if (finalByte === "D") {
109
+ column = Math.max(0, column - (firstParam || 1));
110
+ continue;
111
+ }
112
+ if (finalByte === "C") {
113
+ column += firstParam || 1;
114
+ ensureColumn(column);
115
+ continue;
116
+ }
117
+ if (finalByte === "G") {
118
+ column = Math.max(0, (firstParam || 1) - 1);
119
+ ensureColumn(column);
120
+ continue;
121
+ }
122
+ continue;
123
+ }
124
+ continue;
125
+ }
126
+ writeChar(character);
127
+ }
128
+ line = lineBuffer.join("");
129
+ return prefix + line;
130
+ }
131
+ /**
132
+ * 规范化终端文本,支持包含 ANSI 增量符号的场景。
133
+ */
134
+ function normalizeTerminalText(text) {
135
+ if (!text)
136
+ return "";
137
+ return appendTerminalDelta("", text);
138
+ }
139
+ //# sourceMappingURL=terminalPlainText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminalPlainText.js","sourceRoot":"","sources":["../../../src/chat/terminal/terminalPlainText.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { TextMetrics } from "./types";
2
+ /**
3
+ * 统计纯文本行数,避免高频 split 带来的额外分配。
4
+ */
5
+ export declare function countLines(text: string): number;
6
+ /**
7
+ * 返回文本的字符数与行数,用于折叠阈值判定。
8
+ */
9
+ export declare function getTextMetrics(text: string): TextMetrics;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.countLines = countLines;
4
+ exports.getTextMetrics = getTextMetrics;
5
+ /**
6
+ * 统计纯文本行数,避免高频 split 带来的额外分配。
7
+ */
8
+ function countLines(text) {
9
+ if (!text)
10
+ return 0;
11
+ let lines = 1;
12
+ for (let index = 0; index < text.length; index += 1) {
13
+ if (text.charCodeAt(index) === 10)
14
+ lines += 1;
15
+ }
16
+ return lines;
17
+ }
18
+ /**
19
+ * 返回文本的字符数与行数,用于折叠阈值判定。
20
+ */
21
+ function getTextMetrics(text) {
22
+ return { chars: text.length, lines: countLines(text) };
23
+ }
24
+ //# sourceMappingURL=textMetrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textMetrics.js","sourceRoot":"","sources":["../../src/chat/textMetrics.ts"],"names":[],"mappings":";;AAKA,gCAOC;AAKD,wCAEC;AAjBD;;GAEG;AACH,SAAgB,UAAU,CAAC,IAAY;IACrC,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAC;IACpB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,EAAE;YAAE,KAAK,IAAI,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc,CAAC,IAAY;IACzC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;AACzD,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ChatItem } from "./types";
2
+ /**
3
+ * 将 thread payload 中的 turns 转换为 ChatItem[](用于 thread_opened 快照)。
4
+ */
5
+ export declare function projectThreadToChatItems(thread: unknown): ChatItem[];
6
+ /**
7
+ * 将 thread turns slice 转换为 ChatItem[](用于翻页加载旧消息)。
8
+ */
9
+ export declare function projectTurnsToChatItems(turns: unknown[], opts: {
10
+ createdAtMs: number;
11
+ turnsStart: number;
12
+ }): ChatItem[];