feique 1.1.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 (227) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +220 -0
  3. package/README.md +265 -0
  4. package/dist/backend/claude.d.ts +36 -0
  5. package/dist/backend/claude.js +358 -0
  6. package/dist/backend/claude.js.map +1 -0
  7. package/dist/backend/codex.d.ts +31 -0
  8. package/dist/backend/codex.js +100 -0
  9. package/dist/backend/codex.js.map +1 -0
  10. package/dist/backend/factory.d.ts +9 -0
  11. package/dist/backend/factory.js +56 -0
  12. package/dist/backend/factory.js.map +1 -0
  13. package/dist/backend/types.d.ts +54 -0
  14. package/dist/backend/types.js +2 -0
  15. package/dist/backend/types.js.map +1 -0
  16. package/dist/bridge/commands.d.ts +135 -0
  17. package/dist/bridge/commands.js +860 -0
  18. package/dist/bridge/commands.js.map +1 -0
  19. package/dist/bridge/service.d.ts +160 -0
  20. package/dist/bridge/service.js +3785 -0
  21. package/dist/bridge/service.js.map +1 -0
  22. package/dist/bridge/task-queue.d.ts +14 -0
  23. package/dist/bridge/task-queue.js +81 -0
  24. package/dist/bridge/task-queue.js.map +1 -0
  25. package/dist/bridge/types.d.ts +39 -0
  26. package/dist/bridge/types.js +2 -0
  27. package/dist/bridge/types.js.map +1 -0
  28. package/dist/cli.d.ts +2 -0
  29. package/dist/cli.js +1199 -0
  30. package/dist/cli.js.map +1 -0
  31. package/dist/codex/capabilities.d.ts +20 -0
  32. package/dist/codex/capabilities.js +41 -0
  33. package/dist/codex/capabilities.js.map +1 -0
  34. package/dist/codex/runner.d.ts +47 -0
  35. package/dist/codex/runner.js +294 -0
  36. package/dist/codex/runner.js.map +1 -0
  37. package/dist/codex/session-index.d.ts +22 -0
  38. package/dist/codex/session-index.js +205 -0
  39. package/dist/codex/session-index.js.map +1 -0
  40. package/dist/collaboration/awareness.d.ts +36 -0
  41. package/dist/collaboration/awareness.js +107 -0
  42. package/dist/collaboration/awareness.js.map +1 -0
  43. package/dist/collaboration/digest.d.ts +65 -0
  44. package/dist/collaboration/digest.js +178 -0
  45. package/dist/collaboration/digest.js.map +1 -0
  46. package/dist/collaboration/handoff.d.ts +66 -0
  47. package/dist/collaboration/handoff.js +94 -0
  48. package/dist/collaboration/handoff.js.map +1 -0
  49. package/dist/collaboration/insights.d.ts +24 -0
  50. package/dist/collaboration/insights.js +243 -0
  51. package/dist/collaboration/insights.js.map +1 -0
  52. package/dist/collaboration/knowledge.d.ts +26 -0
  53. package/dist/collaboration/knowledge.js +105 -0
  54. package/dist/collaboration/knowledge.js.map +1 -0
  55. package/dist/collaboration/timeline.d.ts +31 -0
  56. package/dist/collaboration/timeline.js +150 -0
  57. package/dist/collaboration/timeline.js.map +1 -0
  58. package/dist/collaboration/trust.d.ts +49 -0
  59. package/dist/collaboration/trust.js +176 -0
  60. package/dist/collaboration/trust.js.map +1 -0
  61. package/dist/config/codex-skill.d.ts +7 -0
  62. package/dist/config/codex-skill.js +44 -0
  63. package/dist/config/codex-skill.js.map +1 -0
  64. package/dist/config/doctor.d.ts +12 -0
  65. package/dist/config/doctor.js +314 -0
  66. package/dist/config/doctor.js.map +1 -0
  67. package/dist/config/init.d.ts +3 -0
  68. package/dist/config/init.js +123 -0
  69. package/dist/config/init.js.map +1 -0
  70. package/dist/config/load.d.ts +33 -0
  71. package/dist/config/load.js +252 -0
  72. package/dist/config/load.js.map +1 -0
  73. package/dist/config/mutate.d.ts +21 -0
  74. package/dist/config/mutate.js +86 -0
  75. package/dist/config/mutate.js.map +1 -0
  76. package/dist/config/paths.d.ts +3 -0
  77. package/dist/config/paths.js +33 -0
  78. package/dist/config/paths.js.map +1 -0
  79. package/dist/config/schema.d.ts +308 -0
  80. package/dist/config/schema.js +250 -0
  81. package/dist/config/schema.js.map +1 -0
  82. package/dist/control-plane/project-session.d.ts +67 -0
  83. package/dist/control-plane/project-session.js +234 -0
  84. package/dist/control-plane/project-session.js.map +1 -0
  85. package/dist/feishu/base.d.ts +19 -0
  86. package/dist/feishu/base.js +93 -0
  87. package/dist/feishu/base.js.map +1 -0
  88. package/dist/feishu/cards.d.ts +22 -0
  89. package/dist/feishu/cards.js +144 -0
  90. package/dist/feishu/cards.js.map +1 -0
  91. package/dist/feishu/client.d.ts +61 -0
  92. package/dist/feishu/client.js +315 -0
  93. package/dist/feishu/client.js.map +1 -0
  94. package/dist/feishu/diagnostics.d.ts +42 -0
  95. package/dist/feishu/diagnostics.js +194 -0
  96. package/dist/feishu/diagnostics.js.map +1 -0
  97. package/dist/feishu/doc.d.ts +13 -0
  98. package/dist/feishu/doc.js +59 -0
  99. package/dist/feishu/doc.js.map +1 -0
  100. package/dist/feishu/extractors.d.ts +7 -0
  101. package/dist/feishu/extractors.js +215 -0
  102. package/dist/feishu/extractors.js.map +1 -0
  103. package/dist/feishu/long-connection.d.ts +12 -0
  104. package/dist/feishu/long-connection.js +41 -0
  105. package/dist/feishu/long-connection.js.map +1 -0
  106. package/dist/feishu/message-resource.d.ts +14 -0
  107. package/dist/feishu/message-resource.js +309 -0
  108. package/dist/feishu/message-resource.js.map +1 -0
  109. package/dist/feishu/replay.d.ts +37 -0
  110. package/dist/feishu/replay.js +114 -0
  111. package/dist/feishu/replay.js.map +1 -0
  112. package/dist/feishu/task.d.ts +18 -0
  113. package/dist/feishu/task.js +86 -0
  114. package/dist/feishu/task.js.map +1 -0
  115. package/dist/feishu/text.d.ts +23 -0
  116. package/dist/feishu/text.js +155 -0
  117. package/dist/feishu/text.js.map +1 -0
  118. package/dist/feishu/webhook.d.ts +23 -0
  119. package/dist/feishu/webhook.js +130 -0
  120. package/dist/feishu/webhook.js.map +1 -0
  121. package/dist/feishu/wiki.d.ts +52 -0
  122. package/dist/feishu/wiki.js +300 -0
  123. package/dist/feishu/wiki.js.map +1 -0
  124. package/dist/index.d.ts +9 -0
  125. package/dist/index.js +9 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/knowledge/search.d.ts +11 -0
  128. package/dist/knowledge/search.js +83 -0
  129. package/dist/knowledge/search.js.map +1 -0
  130. package/dist/logging.d.ts +3 -0
  131. package/dist/logging.js +40 -0
  132. package/dist/logging.js.map +1 -0
  133. package/dist/mcp/server.d.ts +34 -0
  134. package/dist/mcp/server.js +1196 -0
  135. package/dist/mcp/server.js.map +1 -0
  136. package/dist/memory/embedding-factory.d.ts +6 -0
  137. package/dist/memory/embedding-factory.js +20 -0
  138. package/dist/memory/embedding-factory.js.map +1 -0
  139. package/dist/memory/embeddings.d.ts +40 -0
  140. package/dist/memory/embeddings.js +150 -0
  141. package/dist/memory/embeddings.js.map +1 -0
  142. package/dist/memory/ollama-embeddings.d.ts +63 -0
  143. package/dist/memory/ollama-embeddings.js +215 -0
  144. package/dist/memory/ollama-embeddings.js.map +1 -0
  145. package/dist/memory/retrieve.d.ts +17 -0
  146. package/dist/memory/retrieve.js +29 -0
  147. package/dist/memory/retrieve.js.map +1 -0
  148. package/dist/memory/summarize.d.ts +13 -0
  149. package/dist/memory/summarize.js +58 -0
  150. package/dist/memory/summarize.js.map +1 -0
  151. package/dist/observability/cost.d.ts +12 -0
  152. package/dist/observability/cost.js +22 -0
  153. package/dist/observability/cost.js.map +1 -0
  154. package/dist/observability/dashboard-html.d.ts +5 -0
  155. package/dist/observability/dashboard-html.js +304 -0
  156. package/dist/observability/dashboard-html.js.map +1 -0
  157. package/dist/observability/metrics.d.ts +36 -0
  158. package/dist/observability/metrics.js +230 -0
  159. package/dist/observability/metrics.js.map +1 -0
  160. package/dist/observability/readiness.d.ts +31 -0
  161. package/dist/observability/readiness.js +57 -0
  162. package/dist/observability/readiness.js.map +1 -0
  163. package/dist/observability/server.d.ts +84 -0
  164. package/dist/observability/server.js +181 -0
  165. package/dist/observability/server.js.map +1 -0
  166. package/dist/projects/paths.d.ts +9 -0
  167. package/dist/projects/paths.js +30 -0
  168. package/dist/projects/paths.js.map +1 -0
  169. package/dist/runtime/instance-lock.d.ts +12 -0
  170. package/dist/runtime/instance-lock.js +99 -0
  171. package/dist/runtime/instance-lock.js.map +1 -0
  172. package/dist/runtime/process.d.ts +2 -0
  173. package/dist/runtime/process.js +43 -0
  174. package/dist/runtime/process.js.map +1 -0
  175. package/dist/runtime/shutdown.d.ts +11 -0
  176. package/dist/runtime/shutdown.js +38 -0
  177. package/dist/runtime/shutdown.js.map +1 -0
  178. package/dist/security/access.d.ts +13 -0
  179. package/dist/security/access.js +160 -0
  180. package/dist/security/access.js.map +1 -0
  181. package/dist/service/install.d.ts +19 -0
  182. package/dist/service/install.js +35 -0
  183. package/dist/service/install.js.map +1 -0
  184. package/dist/service/templates.d.ts +22 -0
  185. package/dist/service/templates.js +118 -0
  186. package/dist/service/templates.js.map +1 -0
  187. package/dist/state/audit-log.d.ts +33 -0
  188. package/dist/state/audit-log.js +116 -0
  189. package/dist/state/audit-log.js.map +1 -0
  190. package/dist/state/config-history-store.d.ts +27 -0
  191. package/dist/state/config-history-store.js +65 -0
  192. package/dist/state/config-history-store.js.map +1 -0
  193. package/dist/state/handoff-store.d.ts +20 -0
  194. package/dist/state/handoff-store.js +97 -0
  195. package/dist/state/handoff-store.js.map +1 -0
  196. package/dist/state/idempotency-store.d.ts +19 -0
  197. package/dist/state/idempotency-store.js +84 -0
  198. package/dist/state/idempotency-store.js.map +1 -0
  199. package/dist/state/memory-store.d.ts +137 -0
  200. package/dist/state/memory-store.js +713 -0
  201. package/dist/state/memory-store.js.map +1 -0
  202. package/dist/state/pending-command-store.d.ts +30 -0
  203. package/dist/state/pending-command-store.js +108 -0
  204. package/dist/state/pending-command-store.js.map +1 -0
  205. package/dist/state/run-state-store.d.ts +58 -0
  206. package/dist/state/run-state-store.js +269 -0
  207. package/dist/state/run-state-store.js.map +1 -0
  208. package/dist/state/session-store.d.ts +56 -0
  209. package/dist/state/session-store.js +275 -0
  210. package/dist/state/session-store.js.map +1 -0
  211. package/dist/state/trust-store.d.ts +15 -0
  212. package/dist/state/trust-store.js +53 -0
  213. package/dist/state/trust-store.js.map +1 -0
  214. package/dist/utils/fs.d.ts +4 -0
  215. package/dist/utils/fs.js +26 -0
  216. package/dist/utils/fs.js.map +1 -0
  217. package/dist/utils/json.d.ts +1 -0
  218. package/dist/utils/json.js +9 -0
  219. package/dist/utils/json.js.map +1 -0
  220. package/dist/utils/path.d.ts +3 -0
  221. package/dist/utils/path.js +22 -0
  222. package/dist/utils/path.js.map +1 -0
  223. package/dist/utils/serial-executor.d.ts +5 -0
  224. package/dist/utils/serial-executor.js +12 -0
  225. package/dist/utils/serial-executor.js.map +1 -0
  226. package/package.json +71 -0
  227. package/skills/feique-session/SKILL.md +27 -0
@@ -0,0 +1,29 @@
1
+ export async function retrieveMemoryContext(store, input) {
2
+ const threadSummary = input.threadId
3
+ ? await store.getThreadSummary(input.conversationKey, input.projectAlias, input.threadId)
4
+ : null;
5
+ const recent = await store.listRecentProjectMemories(input.projectAlias, input.searchLimit);
6
+ const pinned = recent.filter((record) => record.pinned);
7
+ const searched = input.query.trim()
8
+ ? await store.searchProjectMemories(input.projectAlias, input.query, input.searchLimit)
9
+ : [];
10
+ const relevant = searched.length > 0 ? searched : recent;
11
+ const pinnedIds = new Set(pinned.map((item) => item.id));
12
+ const groupRecent = input.includeGroupMemories && input.groupChatId
13
+ ? await store.listRecentGroupMemories(input.projectAlias, input.groupChatId, input.searchLimit)
14
+ : [];
15
+ const groupPinned = groupRecent.filter((record) => record.pinned);
16
+ const groupSearched = input.includeGroupMemories && input.groupChatId && input.query.trim()
17
+ ? await store.searchGroupMemories(input.projectAlias, input.groupChatId, input.query, input.searchLimit)
18
+ : [];
19
+ const groupRelevant = groupSearched.length > 0 ? groupSearched : groupRecent;
20
+ const groupPinnedIds = new Set(groupPinned.map((item) => item.id));
21
+ return {
22
+ threadSummary: threadSummary ?? undefined,
23
+ pinnedMemories: pinned.slice(0, input.searchLimit),
24
+ relevantMemories: relevant.filter((item) => !pinnedIds.has(item.id)).slice(0, input.searchLimit),
25
+ pinnedGroupMemories: groupPinned.slice(0, input.searchLimit),
26
+ relevantGroupMemories: groupRelevant.filter((item) => !groupPinnedIds.has(item.id)).slice(0, input.searchLimit),
27
+ };
28
+ }
29
+ //# sourceMappingURL=retrieve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrieve.js","sourceRoot":"","sources":["../../src/memory/retrieve.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,KAAkB,EAClB,KAQC;IAED,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ;QAClC,CAAC,CAAC,MAAM,KAAK,CAAC,gBAAgB,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC;QACzF,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,yBAAyB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAC5F,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE;QACjC,CAAC,CAAC,MAAM,KAAK,CAAC,qBAAqB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC;QACvF,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;IACzD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAEzD,MAAM,WAAW,GAAG,KAAK,CAAC,oBAAoB,IAAI,KAAK,CAAC,WAAW;QACjE,CAAC,CAAC,MAAM,KAAK,CAAC,uBAAuB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC;QAC/F,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClE,MAAM,aAAa,GAAG,KAAK,CAAC,oBAAoB,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE;QACzF,CAAC,CAAC,MAAM,KAAK,CAAC,mBAAmB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC;QACxG,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC;IAC7E,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAEnE,OAAO;QACL,aAAa,EAAE,aAAa,IAAI,SAAS;QACzC,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;QAClD,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;QAChG,mBAAmB,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;QAC5D,qBAAqB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;KAChH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface ThreadSummaryInput {
2
+ previousSummary?: string;
3
+ prompt: string;
4
+ responseExcerpt: string;
5
+ maxChars: number;
6
+ }
7
+ export interface ThreadSummaryDraft {
8
+ summary: string;
9
+ filesTouched: string[];
10
+ openTasks: string[];
11
+ decisions: string[];
12
+ }
13
+ export declare function summarizeThreadTurn(input: ThreadSummaryInput): ThreadSummaryDraft;
@@ -0,0 +1,58 @@
1
+ const FILE_PATH_PATTERN = /(?:^|[\s(])((?:[A-Za-z0-9._-]+\/)+[A-Za-z0-9._-]+\.[A-Za-z0-9_-]+)(?=$|[\s):,])/g;
2
+ export function summarizeThreadTurn(input) {
3
+ const files = uniqueStrings([
4
+ ...extractFilePaths(input.prompt),
5
+ ...extractFilePaths(input.responseExcerpt),
6
+ ]).slice(0, 8);
7
+ const decisions = extractNumberedItems(afterMarker(input.responseExcerpt, ['决定', '变更', '已完成', '已实现'])).slice(0, 4);
8
+ const openTasks = extractNumberedItems(afterMarker(input.responseExcerpt, ['建议下一步', '下一步', 'todo', '后续'])).slice(0, 4);
9
+ const sections = [
10
+ `最近目标: ${compactLine(input.prompt, 220)}`,
11
+ `最近结果: ${compactLine(input.responseExcerpt, 420)}`,
12
+ ...(files.length > 0 ? [`涉及文件: ${files.join(', ')}`] : []),
13
+ ...(decisions.length > 0 ? [`关键结论: ${decisions.join(';')}`] : []),
14
+ ...(openTasks.length > 0 ? [`待办: ${openTasks.join(';')}`] : []),
15
+ ];
16
+ const previous = input.previousSummary ? compactLine(input.previousSummary, 360) : undefined;
17
+ const summary = truncateToBudget([previous ? `上次摘要: ${previous}` : undefined, ...sections].filter(Boolean).join('\n'), input.maxChars);
18
+ return {
19
+ summary,
20
+ filesTouched: files,
21
+ openTasks,
22
+ decisions,
23
+ };
24
+ }
25
+ function extractFilePaths(input) {
26
+ const matches = Array.from(input.matchAll(FILE_PATH_PATTERN)).map((match) => match[1] ?? '');
27
+ return matches.filter(Boolean);
28
+ }
29
+ function afterMarker(input, markers) {
30
+ const normalized = input.replace(/\r/g, '');
31
+ for (const marker of markers) {
32
+ const index = normalized.indexOf(marker);
33
+ if (index >= 0) {
34
+ return normalized.slice(index);
35
+ }
36
+ }
37
+ return normalized;
38
+ }
39
+ function extractNumberedItems(input) {
40
+ const matches = input.match(/(?:^|\n)\d+\.\s+(.+)/g) ?? [];
41
+ return matches
42
+ .map((line) => line.replace(/(?:^|\n)\d+\.\s+/, '').trim())
43
+ .filter(Boolean)
44
+ .map((line) => compactLine(line, 140));
45
+ }
46
+ function compactLine(input, maxChars) {
47
+ return truncateToBudget(input.replace(/\s+/g, ' ').trim(), maxChars);
48
+ }
49
+ function truncateToBudget(input, maxChars) {
50
+ if (input.length <= maxChars) {
51
+ return input;
52
+ }
53
+ return `${input.slice(0, Math.max(0, maxChars - 1)).trim()}…`;
54
+ }
55
+ function uniqueStrings(values) {
56
+ return Array.from(new Set(values));
57
+ }
58
+ //# sourceMappingURL=summarize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarize.js","sourceRoot":"","sources":["../../src/memory/summarize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Token cost estimation for backend runs.
3
+ *
4
+ * Default rates are approximate per-1M-token prices (USD).
5
+ * These can be refined later via config; the point is to have
6
+ * a reasonable default for dashboard / digest reporting.
7
+ */
8
+ /**
9
+ * Estimate the USD cost for a single run based on token counts.
10
+ * Returns `undefined` when there is no token data to work with.
11
+ */
12
+ export declare function estimateCost(inputTokens?: number, outputTokens?: number, backend?: string): number | undefined;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Token cost estimation for backend runs.
3
+ *
4
+ * Default rates are approximate per-1M-token prices (USD).
5
+ * These can be refined later via config; the point is to have
6
+ * a reasonable default for dashboard / digest reporting.
7
+ */
8
+ const RATES = {
9
+ codex: { input: 2.0, output: 8.0 },
10
+ claude: { input: 3.0, output: 15.0 },
11
+ };
12
+ /**
13
+ * Estimate the USD cost for a single run based on token counts.
14
+ * Returns `undefined` when there is no token data to work with.
15
+ */
16
+ export function estimateCost(inputTokens, outputTokens, backend) {
17
+ if (!inputTokens && !outputTokens)
18
+ return undefined;
19
+ const rate = RATES[backend ?? 'codex'] ?? RATES.codex;
20
+ return ((inputTokens ?? 0) * rate.input + (outputTokens ?? 0) * rate.output) / 1_000_000;
21
+ }
22
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/observability/cost.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,KAAK,GAAsD;IAC/D,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IAClC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;CACrC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,WAAoB,EACpB,YAAqB,EACrB,OAAgB;IAEhB,IAAI,CAAC,WAAW,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAC;IACpD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,KAAM,CAAC;IACvD,OAAO,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;AAC3F,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Self-contained HTML dashboard for Feique bridge.
3
+ * No external dependencies — all CSS and JS are inline.
4
+ */
5
+ export declare function renderDashboardHtml(): string;
@@ -0,0 +1,304 @@
1
+ /**
2
+ * Self-contained HTML dashboard for Feique bridge.
3
+ * No external dependencies — all CSS and JS are inline.
4
+ */
5
+ export function renderDashboardHtml() {
6
+ return `<!DOCTYPE html>
7
+ <html lang="zh-CN">
8
+ <head>
9
+ <meta charset="utf-8">
10
+ <meta name="viewport" content="width=device-width, initial-scale=1">
11
+ <title>飞鹊 仪表板</title>
12
+ <style>
13
+ * { margin: 0; padding: 0; box-sizing: border-box; }
14
+ body {
15
+ background: #0a0e17;
16
+ color: #c9d1d9;
17
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
18
+ font-size: 14px;
19
+ line-height: 1.5;
20
+ padding: 20px;
21
+ }
22
+ h1 { font-size: 20px; color: #e6edf3; margin-bottom: 16px; }
23
+ h2 { font-size: 15px; color: #8b949e; margin-bottom: 10px; text-transform: uppercase; letter-spacing: 0.5px; }
24
+ .grid {
25
+ display: grid;
26
+ grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
27
+ gap: 16px;
28
+ margin-bottom: 20px;
29
+ }
30
+ .card {
31
+ background: #161b22;
32
+ border: 1px solid #30363d;
33
+ border-radius: 8px;
34
+ padding: 16px;
35
+ }
36
+ .card h2 { margin-bottom: 12px; }
37
+ .stat-row {
38
+ display: flex;
39
+ justify-content: space-between;
40
+ padding: 4px 0;
41
+ border-bottom: 1px solid #21262d;
42
+ }
43
+ .stat-row:last-child { border-bottom: none; }
44
+ .stat-label { color: #8b949e; }
45
+ .stat-value { font-family: "SF Mono", "Fira Code", monospace; color: #e6edf3; }
46
+ .badge {
47
+ display: inline-block;
48
+ padding: 2px 8px;
49
+ border-radius: 12px;
50
+ font-size: 12px;
51
+ font-family: "SF Mono", "Fira Code", monospace;
52
+ }
53
+ .badge-green { background: #0d1117; border: 1px solid #238636; color: #3fb950; }
54
+ .badge-yellow { background: #0d1117; border: 1px solid #9e6a03; color: #d29922; }
55
+ .badge-red { background: #0d1117; border: 1px solid #da3633; color: #f85149; }
56
+ .badge-blue { background: #0d1117; border: 1px solid #1f6feb; color: #58a6ff; }
57
+ .badge-gray { background: #0d1117; border: 1px solid #484f58; color: #8b949e; }
58
+ table {
59
+ width: 100%;
60
+ border-collapse: collapse;
61
+ font-family: "SF Mono", "Fira Code", monospace;
62
+ font-size: 13px;
63
+ }
64
+ th {
65
+ text-align: left;
66
+ padding: 6px 8px;
67
+ border-bottom: 1px solid #30363d;
68
+ color: #8b949e;
69
+ font-weight: 500;
70
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
71
+ }
72
+ td {
73
+ padding: 6px 8px;
74
+ border-bottom: 1px solid #21262d;
75
+ white-space: nowrap;
76
+ overflow: hidden;
77
+ text-overflow: ellipsis;
78
+ max-width: 200px;
79
+ }
80
+ .header {
81
+ display: flex;
82
+ justify-content: space-between;
83
+ align-items: center;
84
+ margin-bottom: 20px;
85
+ }
86
+ .header-right {
87
+ font-size: 12px;
88
+ color: #484f58;
89
+ font-family: "SF Mono", "Fira Code", monospace;
90
+ }
91
+ .refresh-dot {
92
+ display: inline-block;
93
+ width: 6px;
94
+ height: 6px;
95
+ border-radius: 50%;
96
+ background: #238636;
97
+ margin-right: 6px;
98
+ animation: pulse 2s infinite;
99
+ }
100
+ @keyframes pulse {
101
+ 0%, 100% { opacity: 1; }
102
+ 50% { opacity: 0.3; }
103
+ }
104
+ .empty { color: #484f58; font-style: italic; padding: 8px 0; }
105
+ .section-full { grid-column: 1 / -1; }
106
+ </style>
107
+ </head>
108
+ <body>
109
+ <div class="header">
110
+ <h1>飞鹊 仪表板</h1>
111
+ <div class="header-right"><span class="refresh-dot"></span><span id="ts">--</span></div>
112
+ </div>
113
+
114
+ <div class="grid">
115
+ <div class="card" id="service-card">
116
+ <h2>服务状态</h2>
117
+ <div id="service-body"><div class="empty">加载中...</div></div>
118
+ </div>
119
+ <div class="card" id="team-card">
120
+ <h2>团队活跃</h2>
121
+ <div id="team-body"><div class="empty">加载中...</div></div>
122
+ </div>
123
+ <div class="card" id="cost-card">
124
+ <h2>24h 运行统计</h2>
125
+ <div id="cost-body"><div class="empty">加载中...</div></div>
126
+ </div>
127
+ <div class="card" id="handoff-card">
128
+ <h2>交接 / 评审</h2>
129
+ <div id="handoff-body"><div class="empty">加载中...</div></div>
130
+ </div>
131
+ </div>
132
+
133
+ <div class="grid">
134
+ <div class="card section-full" id="projects-card">
135
+ <h2>项目概览</h2>
136
+ <div id="projects-body"><div class="empty">加载中...</div></div>
137
+ </div>
138
+ </div>
139
+
140
+ <div class="grid">
141
+ <div class="card section-full" id="runs-card">
142
+ <h2>最近运行</h2>
143
+ <div id="runs-body"><div class="empty">加载中...</div></div>
144
+ </div>
145
+ </div>
146
+
147
+ <script>
148
+ function statusBadge(status) {
149
+ const map = {
150
+ running: 'badge-blue',
151
+ queued: 'badge-yellow',
152
+ success: 'badge-green',
153
+ failure: 'badge-red',
154
+ cancelled: 'badge-gray',
155
+ stale: 'badge-gray',
156
+ orphaned: 'badge-yellow',
157
+ };
158
+ return '<span class="badge ' + (map[status] || 'badge-gray') + '">' + esc(status) + '</span>';
159
+ }
160
+
161
+ function trustBadge(level) {
162
+ const map = {
163
+ autonomous: 'badge-green',
164
+ execute: 'badge-blue',
165
+ suggest: 'badge-yellow',
166
+ observe: 'badge-gray',
167
+ };
168
+ return '<span class="badge ' + (map[level] || 'badge-gray') + '">' + esc(level) + '</span>';
169
+ }
170
+
171
+ function stageBadge(stage) {
172
+ const map = {
173
+ ready: 'badge-green',
174
+ starting: 'badge-yellow',
175
+ degraded: 'badge-red',
176
+ stopping: 'badge-yellow',
177
+ stopped: 'badge-gray',
178
+ };
179
+ return '<span class="badge ' + (map[stage] || 'badge-gray') + '">' + esc(stage) + '</span>';
180
+ }
181
+
182
+ function esc(s) {
183
+ if (s == null) return '';
184
+ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
185
+ }
186
+
187
+ function shortTime(iso) {
188
+ if (!iso) return '--';
189
+ try {
190
+ var d = new Date(iso);
191
+ return d.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
192
+ } catch { return iso; }
193
+ }
194
+
195
+ function pct(n) {
196
+ if (n == null || isNaN(n)) return '--';
197
+ return (n * 100).toFixed(0) + '%';
198
+ }
199
+
200
+ function statRow(label, value) {
201
+ return '<div class="stat-row"><span class="stat-label">' + esc(label) + '</span><span class="stat-value">' + value + '</span></div>';
202
+ }
203
+
204
+ function render(data) {
205
+ document.getElementById('ts').textContent = shortTime(data.timestamp);
206
+
207
+ // Service
208
+ var s = data.service || {};
209
+ document.getElementById('service-body').innerHTML =
210
+ statRow('服务', esc(s.name || '--')) +
211
+ statRow('阶段', stageBadge(s.stage || 'unknown')) +
212
+ statRow('就绪', s.ready ? '<span class="badge badge-green">是</span>' : '<span class="badge badge-red">否</span>') +
213
+ statRow('启动警告', esc(s.startupWarnings ?? 0)) +
214
+ statRow('启动错误', esc(s.startupErrors ?? 0));
215
+
216
+ // Team
217
+ var t = data.team || {};
218
+ var teamHtml = statRow('活跃成员', esc(t.active_members ?? 0));
219
+ if (t.active_runs && t.active_runs.length > 0) {
220
+ teamHtml += '<div style="margin-top:8px;font-size:12px;color:#8b949e;">运行中:</div>';
221
+ t.active_runs.forEach(function(r) {
222
+ teamHtml += '<div style="padding:4px 0;border-bottom:1px solid #21262d;font-family:monospace;font-size:12px;">' +
223
+ statusBadge(r.status) + ' ' + esc(r.project_alias) +
224
+ ' <span style="color:#484f58;">' + esc((r.prompt_excerpt || '').substring(0, 40)) + '</span></div>';
225
+ });
226
+ }
227
+ if (t.queued_runs && t.queued_runs.length > 0) {
228
+ teamHtml += '<div style="margin-top:8px;font-size:12px;color:#8b949e;">排队中: ' + t.queued_runs.length + '</div>';
229
+ }
230
+ document.getElementById('team-body').innerHTML = teamHtml || '<div class="empty">无活跃运行</div>';
231
+
232
+ // Cost / 24h stats
233
+ var c = data.cost || {};
234
+ var costHtml = statRow('24h 总运行', esc(c.total_runs_24h ?? 0));
235
+ if (c.by_project) {
236
+ Object.keys(c.by_project).forEach(function(proj) {
237
+ var p = c.by_project[proj];
238
+ costHtml += statRow(proj, esc(p.runs) + ' 次 / 成功 ' + esc(p.success));
239
+ });
240
+ }
241
+ document.getElementById('cost-body').innerHTML = costHtml;
242
+
243
+ // Handoffs & Reviews
244
+ var h = data.handoffs || {};
245
+ var rv = data.reviews || {};
246
+ document.getElementById('handoff-body').innerHTML =
247
+ statRow('待处理交接', esc(h.pending ?? 0)) +
248
+ statRow('24h 已完成交接', esc(h.completed_24h ?? 0)) +
249
+ statRow('待评审', esc(rv.pending ?? 0)) +
250
+ statRow('24h 已完成评审', esc(rv.completed_24h ?? 0));
251
+
252
+ // Projects
253
+ var projects = data.projects || [];
254
+ if (projects.length === 0) {
255
+ document.getElementById('projects-body').innerHTML = '<div class="empty">暂无项目数据</div>';
256
+ } else {
257
+ var html = '<table><tr><th>项目</th><th>总运行</th><th>成功率</th><th>活跃</th><th>信任等级</th></tr>';
258
+ projects.forEach(function(p) {
259
+ html += '<tr><td>' + esc(p.alias) + '</td><td>' + esc(p.total_runs) +
260
+ '</td><td>' + pct(p.success_rate) + '</td><td>' + esc(p.active_runs) +
261
+ '</td><td>' + trustBadge(p.trust_level) + '</td></tr>';
262
+ });
263
+ html += '</table>';
264
+ document.getElementById('projects-body').innerHTML = html;
265
+ }
266
+
267
+ // Recent runs
268
+ var allRuns = (t.active_runs || []).concat(t.queued_runs || []);
269
+ // Also include recent completed runs if available from projects data
270
+ if (data._recent_runs && data._recent_runs.length > 0) {
271
+ allRuns = data._recent_runs;
272
+ }
273
+ if (allRuns.length === 0) {
274
+ document.getElementById('runs-body').innerHTML = '<div class="empty">暂无运行记录</div>';
275
+ } else {
276
+ var rhtml = '<table><tr><th>运行 ID</th><th>项目</th><th>操作者</th><th>状态</th><th>开始时间</th><th>提示摘要</th></tr>';
277
+ allRuns.slice(0, 20).forEach(function(r) {
278
+ rhtml += '<tr><td title="' + esc(r.run_id) + '">' + esc((r.run_id || '').substring(0, 8)) +
279
+ '</td><td>' + esc(r.project_alias) +
280
+ '</td><td>' + esc(r.actor_id || '--') +
281
+ '</td><td>' + statusBadge(r.status) +
282
+ '</td><td>' + shortTime(r.started_at) +
283
+ '</td><td title="' + esc(r.prompt_excerpt) + '">' + esc((r.prompt_excerpt || '').substring(0, 50)) +
284
+ '</td></tr>';
285
+ });
286
+ rhtml += '</table>';
287
+ document.getElementById('runs-body').innerHTML = rhtml;
288
+ }
289
+ }
290
+
291
+ function fetchData() {
292
+ fetch('/api/dashboard')
293
+ .then(function(r) { return r.json(); })
294
+ .then(render)
295
+ .catch(function(e) { console.error('Dashboard fetch error:', e); });
296
+ }
297
+
298
+ fetchData();
299
+ setInterval(fetchData, 10000);
300
+ </script>
301
+ </body>
302
+ </html>`;
303
+ }
304
+ //# sourceMappingURL=dashboard-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-html.js","sourceRoot":"","sources":["../../src/observability/dashboard-html.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,mBAAmB;IACjC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAwSD,CAAC;AACT,CAAC"}
@@ -0,0 +1,36 @@
1
+ export interface MetricsSink {
2
+ incrementCounter(name: string, labels?: Record<string, string>, value?: number): void;
3
+ observe(name: string, value: number, labels?: Record<string, string>): void;
4
+ }
5
+ export interface ReadinessMetricSnapshot {
6
+ ok: boolean;
7
+ ready: boolean;
8
+ startupWarnings: number;
9
+ startupErrors: number;
10
+ }
11
+ export type CollaborationEventType = 'handoff' | 'pickup' | 'review' | 'approve' | 'reject' | 'learn' | 'recall' | 'digest';
12
+ export declare class MetricsRegistry implements MetricsSink {
13
+ private readonly counters;
14
+ private readonly summaries;
15
+ private readonly gauges;
16
+ private readonly histograms;
17
+ private readonly startedAtSeconds;
18
+ incrementCounter(name: string, labels?: Record<string, string>, value?: number): void;
19
+ setGauge(name: string, value: number, labels?: Record<string, string>): void;
20
+ incrementGauge(name: string, labels?: Record<string, string>, value?: number): void;
21
+ observe(name: string, value: number, labels?: Record<string, string>): void;
22
+ observeHistogram(name: string, value: number, buckets: number[], labels?: Record<string, string>): void;
23
+ recordIncomingMessage(chatType: string, command: string): void;
24
+ recordDuplicateEvent(kind: 'message' | 'card'): void;
25
+ recordCardAction(action: string): void;
26
+ recordCodexTurnStarted(projectAlias: string, runId?: string): void;
27
+ recordCodexTurn(status: 'success' | 'failure' | 'cancelled', projectAlias: string, durationSeconds: number, runId?: string): void;
28
+ recordOutboundMessage(msgType: 'text' | 'interactive' | 'post', status: 'success' | 'failure'): void;
29
+ recordQueueDepth(project: string, depth: number): void;
30
+ recordCost(project: string, backend: string, costUsd: number): void;
31
+ recordTokens(project: string, backend: string, inputTokens: number, outputTokens: number): void;
32
+ recordCollaborationEvent(type: CollaborationEventType): void;
33
+ recordTrustLevel(project: string, level: string): void;
34
+ recordReadiness(snapshot: ReadinessMetricSnapshot): void;
35
+ renderPrometheus(): string;
36
+ }