freddie 0.0.41

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 (307) hide show
  1. package/AGENTS.md +180 -0
  2. package/CHANGELOG.md +32 -0
  3. package/README.md +130 -0
  4. package/bin/freddie.js +116 -0
  5. package/package.json +59 -0
  6. package/skills/creative/README.md +3 -0
  7. package/skills/creative/architecture-diagram/SKILL.md +52 -0
  8. package/skills/creative/ascii-video/SKILL.md +60 -0
  9. package/skills/creative/concept-diagrams/SKILL.md +65 -0
  10. package/skills/data/README.md +3 -0
  11. package/skills/data/etl-pipelines/SKILL.md +60 -0
  12. package/skills/data/sql-explainer/SKILL.md +60 -0
  13. package/skills/ops/README.md +3 -0
  14. package/skills/ops/incident-response/SKILL.md +74 -0
  15. package/skills/ops/log-triage/SKILL.md +79 -0
  16. package/skills/planning/README.md +3 -0
  17. package/skills/planning/okr-drafter/SKILL.md +60 -0
  18. package/skills/planning/weekly-review/SKILL.md +64 -0
  19. package/skills/software-development/README.md +3 -0
  20. package/skills/software-development/code-review/SKILL.md +70 -0
  21. package/skills/software-development/rfc-writer/SKILL.md +68 -0
  22. package/skills/software-development/systematic-debugging/SKILL.md +80 -0
  23. package/src/acp/auth.js +21 -0
  24. package/src/acp/entry.js +2 -0
  25. package/src/acp/events.js +10 -0
  26. package/src/acp/main.js +8 -0
  27. package/src/acp/permissions.js +29 -0
  28. package/src/acp/server.js +84 -0
  29. package/src/acp/session.js +26 -0
  30. package/src/acp/tools.js +17 -0
  31. package/src/agent/account_usage.js +19 -0
  32. package/src/agent/acptoapi-bridge.js +80 -0
  33. package/src/agent/anthropic_adapter.js +10 -0
  34. package/src/agent/auxiliary_client.js +20 -0
  35. package/src/agent/bedrock_adapter.js +11 -0
  36. package/src/agent/codex_responses_adapter.js +10 -0
  37. package/src/agent/compress/compressor.js +55 -0
  38. package/src/agent/compress/fallback.js +14 -0
  39. package/src/agent/compress/index.js +6 -0
  40. package/src/agent/compress/policy.js +47 -0
  41. package/src/agent/compress/prompt.js +46 -0
  42. package/src/agent/compress/prune.js +16 -0
  43. package/src/agent/compress/tokens.js +31 -0
  44. package/src/agent/context_references.js +40 -0
  45. package/src/agent/copilot_acp_client.js +6 -0
  46. package/src/agent/credential_pool.js +30 -0
  47. package/src/agent/credential_sources.js +18 -0
  48. package/src/agent/curator.js +5 -0
  49. package/src/agent/display.js +23 -0
  50. package/src/agent/error_classifier.js +15 -0
  51. package/src/agent/file_safety.js +9 -0
  52. package/src/agent/gemini_cloudcode_adapter.js +9 -0
  53. package/src/agent/gemini_native_adapter.js +11 -0
  54. package/src/agent/gemini_schema.js +19 -0
  55. package/src/agent/google_code_assist.js +8 -0
  56. package/src/agent/google_oauth.js +21 -0
  57. package/src/agent/image_gen_provider.js +8 -0
  58. package/src/agent/image_gen_registry.js +6 -0
  59. package/src/agent/image_routing.js +13 -0
  60. package/src/agent/insights.js +9 -0
  61. package/src/agent/llm_resolver.js +21 -0
  62. package/src/agent/lmstudio_reasoning.js +13 -0
  63. package/src/agent/machine.js +102 -0
  64. package/src/agent/manual_compression_feedback.js +5 -0
  65. package/src/agent/memory_manager.js +14 -0
  66. package/src/agent/memory_provider.js +1 -0
  67. package/src/agent/model_metadata.js +28 -0
  68. package/src/agent/models_dev.js +13 -0
  69. package/src/agent/moonshot_schema.js +11 -0
  70. package/src/agent/oauth_endpoints.js +79 -0
  71. package/src/agent/onboarding.js +16 -0
  72. package/src/agent/pi-bridge.js +37 -0
  73. package/src/agent/prompt_builder.js +12 -0
  74. package/src/agent/prompt_caching.js +24 -0
  75. package/src/agent/rate_limit_tracker.js +12 -0
  76. package/src/agent/redact.js +25 -0
  77. package/src/agent/retry_utils.js +17 -0
  78. package/src/agent/shell_hooks.js +16 -0
  79. package/src/agent/skill_commands.js +16 -0
  80. package/src/agent/skill_preprocessing.js +12 -0
  81. package/src/agent/skill_utils.js +14 -0
  82. package/src/agent/subdirectory_hints.js +17 -0
  83. package/src/agent/title_generator.js +13 -0
  84. package/src/agent/trajectory.js +9 -0
  85. package/src/agent/usage_pricing.js +16 -0
  86. package/src/auth.js +84 -0
  87. package/src/batch.js +32 -0
  88. package/src/cli/auth_commands.js +17 -0
  89. package/src/cli/azure_detect.js +9 -0
  90. package/src/cli/backup.js +17 -0
  91. package/src/cli/banner.js +13 -0
  92. package/src/cli/browser_connect.js +11 -0
  93. package/src/cli/callbacks.js +5 -0
  94. package/src/cli/claw.js +8 -0
  95. package/src/cli/cli_output.js +19 -0
  96. package/src/cli/clipboard.js +24 -0
  97. package/src/cli/codex_models.js +8 -0
  98. package/src/cli/colors.js +13 -0
  99. package/src/cli/completer.js +98 -0
  100. package/src/cli/completion.js +21 -0
  101. package/src/cli/copilot_auth.js +9 -0
  102. package/src/cli/curator_cli.js +5 -0
  103. package/src/cli/curses.js +15 -0
  104. package/src/cli/debug.js +6 -0
  105. package/src/cli/default_soul.js +20 -0
  106. package/src/cli/dingtalk_auth.js +12 -0
  107. package/src/cli/doctor.js +15 -0
  108. package/src/cli/dump.js +11 -0
  109. package/src/cli/env_loader.js +25 -0
  110. package/src/cli/fallback_cmd.js +9 -0
  111. package/src/cli/gateway_cli.js +17 -0
  112. package/src/cli/hooks.js +9 -0
  113. package/src/cli/interactive.js +61 -0
  114. package/src/cli/logs.js +32 -0
  115. package/src/cli/main.js +7 -0
  116. package/src/cli/mcp_config.js +9 -0
  117. package/src/cli/memory_setup.js +12 -0
  118. package/src/cli/model_catalog.js +23 -0
  119. package/src/cli/model_normalize.js +12 -0
  120. package/src/cli/model_switch.js +11 -0
  121. package/src/cli/models.js +13 -0
  122. package/src/cli/nous_subscription.js +12 -0
  123. package/src/cli/oneshot.js +6 -0
  124. package/src/cli/pairing.js +21 -0
  125. package/src/cli/platforms.js +14 -0
  126. package/src/cli/plugins.js +4 -0
  127. package/src/cli/plugins_cmd.js +21 -0
  128. package/src/cli/profiles_cli.js +6 -0
  129. package/src/cli/providers.js +18 -0
  130. package/src/cli/pty_bridge.js +16 -0
  131. package/src/cli/relaunch.js +7 -0
  132. package/src/cli/runtime_provider.js +9 -0
  133. package/src/cli/setup.js +131 -0
  134. package/src/cli/skills_config.js +6 -0
  135. package/src/cli/skills_hub.js +8 -0
  136. package/src/cli/slack_cli.js +17 -0
  137. package/src/cli/status.js +10 -0
  138. package/src/cli/timeouts.js +5 -0
  139. package/src/cli/tips.js +14 -0
  140. package/src/cli/tools_config.js +15 -0
  141. package/src/cli/uninstall.js +8 -0
  142. package/src/cli/vercel_auth.js +13 -0
  143. package/src/cli/voice.js +6 -0
  144. package/src/cli/web_server.js +13 -0
  145. package/src/cli/webhook.js +12 -0
  146. package/src/commands/profile.js +72 -0
  147. package/src/commands/registry.js +94 -0
  148. package/src/config.js +125 -0
  149. package/src/context/engine.js +42 -0
  150. package/src/cron/cron-parse.js +27 -0
  151. package/src/cron/scheduler.js +63 -0
  152. package/src/db.js +178 -0
  153. package/src/gateway/base.js +13 -0
  154. package/src/gateway/builtin_hooks/boot.js +5 -0
  155. package/src/gateway/builtin_hooks/broadcast.js +3 -0
  156. package/src/gateway/builtin_hooks/deny.js +6 -0
  157. package/src/gateway/builtin_hooks/index.js +17 -0
  158. package/src/gateway/builtin_hooks/presence.js +4 -0
  159. package/src/gateway/builtin_hooks/routing.js +7 -0
  160. package/src/gateway/helpers.js +27 -0
  161. package/src/gateway/platforms/api_server.js +21 -0
  162. package/src/gateway/platforms/bluebubbles.js +32 -0
  163. package/src/gateway/platforms/dingtalk.js +32 -0
  164. package/src/gateway/platforms/discord.js +24 -0
  165. package/src/gateway/platforms/email.js +51 -0
  166. package/src/gateway/platforms/feishu.js +32 -0
  167. package/src/gateway/platforms/feishu_comment.js +12 -0
  168. package/src/gateway/platforms/feishu_comment_rules.js +11 -0
  169. package/src/gateway/platforms/homeassistant.js +32 -0
  170. package/src/gateway/platforms/matrix.js +40 -0
  171. package/src/gateway/platforms/mattermost.js +29 -0
  172. package/src/gateway/platforms/qqbot.js +32 -0
  173. package/src/gateway/platforms/signal.js +33 -0
  174. package/src/gateway/platforms/slack.js +34 -0
  175. package/src/gateway/platforms/sms.js +34 -0
  176. package/src/gateway/platforms/telegram.js +38 -0
  177. package/src/gateway/platforms/telegram_network.js +17 -0
  178. package/src/gateway/platforms/webhook.js +19 -0
  179. package/src/gateway/platforms/wecom.js +32 -0
  180. package/src/gateway/platforms/wecom_callback.js +15 -0
  181. package/src/gateway/platforms/wecom_crypto.js +16 -0
  182. package/src/gateway/platforms/weixin.js +32 -0
  183. package/src/gateway/platforms/whatsapp.js +40 -0
  184. package/src/gateway/platforms/yuanbao.js +9 -0
  185. package/src/gateway/platforms/yuanbao_media.js +5 -0
  186. package/src/gateway/platforms/yuanbao_proto.js +9 -0
  187. package/src/gateway/platforms/yuanbao_sticker.js +6 -0
  188. package/src/gateway/run.js +42 -0
  189. package/src/gateway/service.js +143 -0
  190. package/src/home.js +44 -0
  191. package/src/index.js +47 -0
  192. package/src/mcp/server.js +49 -0
  193. package/src/observability/debug.js +31 -0
  194. package/src/observability/log.js +38 -0
  195. package/src/plugins/achievements/index.js +9 -0
  196. package/src/plugins/cockpit/index.js +8 -0
  197. package/src/plugins/context_engine/index.js +13 -0
  198. package/src/plugins/disk_cleanup/index.js +22 -0
  199. package/src/plugins/google_meet/index.js +19 -0
  200. package/src/plugins/image_gen/index.js +5 -0
  201. package/src/plugins/manager.js +66 -0
  202. package/src/plugins/memory/_index.js +8 -0
  203. package/src/plugins/memory/byterover.js +25 -0
  204. package/src/plugins/memory/hindsight.js +25 -0
  205. package/src/plugins/memory/holographic.js +31 -0
  206. package/src/plugins/memory/honcho.js +25 -0
  207. package/src/plugins/memory/mem0.js +25 -0
  208. package/src/plugins/memory/openviking.js +25 -0
  209. package/src/plugins/memory/provider.js +35 -0
  210. package/src/plugins/memory/retaindb.js +25 -0
  211. package/src/plugins/memory/supermemory.js +25 -0
  212. package/src/plugins/observability/index.js +18 -0
  213. package/src/plugins/platforms/index.js +20 -0
  214. package/src/plugins/spotify/index.js +22 -0
  215. package/src/rl/atropos.js +22 -0
  216. package/src/rl/cli.js +18 -0
  217. package/src/sessions.js +84 -0
  218. package/src/skills/index.js +49 -0
  219. package/src/skin/engine.js +81 -0
  220. package/src/swe/runner.js +26 -0
  221. package/src/time.js +25 -0
  222. package/src/tools/ansi_strip.js +8 -0
  223. package/src/tools/approval.js +15 -0
  224. package/src/tools/bash.js +35 -0
  225. package/src/tools/binary_extensions.js +22 -0
  226. package/src/tools/browser.js +48 -0
  227. package/src/tools/budget_config.js +13 -0
  228. package/src/tools/checkpoint.js +29 -0
  229. package/src/tools/clarify.js +15 -0
  230. package/src/tools/code_execution.js +27 -0
  231. package/src/tools/credential_files.js +16 -0
  232. package/src/tools/cronjob.js +16 -0
  233. package/src/tools/debug_helpers.js +9 -0
  234. package/src/tools/delegate.js +28 -0
  235. package/src/tools/discord_tool.js +13 -0
  236. package/src/tools/edit.js +31 -0
  237. package/src/tools/env_passthrough.js +15 -0
  238. package/src/tools/environments/base.js +26 -0
  239. package/src/tools/environments/daytona.js +48 -0
  240. package/src/tools/environments/docker.js +14 -0
  241. package/src/tools/environments/file_sync.js +60 -0
  242. package/src/tools/environments/index.js +36 -0
  243. package/src/tools/environments/local.js +31 -0
  244. package/src/tools/environments/modal.js +33 -0
  245. package/src/tools/environments/singularity.js +38 -0
  246. package/src/tools/environments/ssh.js +14 -0
  247. package/src/tools/environments/vercel_sandbox.js +47 -0
  248. package/src/tools/feishu_doc.js +15 -0
  249. package/src/tools/feishu_drive.js +14 -0
  250. package/src/tools/file_operations.js +17 -0
  251. package/src/tools/file_state.js +16 -0
  252. package/src/tools/file_tools.js +23 -0
  253. package/src/tools/fuzzy_match.js +8 -0
  254. package/src/tools/grep.js +51 -0
  255. package/src/tools/homeassistant_tool.js +15 -0
  256. package/src/tools/image_gen.js +33 -0
  257. package/src/tools/interrupt.js +18 -0
  258. package/src/tools/managed_tool_gateway.js +11 -0
  259. package/src/tools/mcp_oauth.js +21 -0
  260. package/src/tools/mcp_oauth_manager.js +20 -0
  261. package/src/tools/mcp_tool.js +36 -0
  262. package/src/tools/memory.js +66 -0
  263. package/src/tools/mixture_of_agents.js +14 -0
  264. package/src/tools/neutts_synth.js +13 -0
  265. package/src/tools/openrouter_client.js +13 -0
  266. package/src/tools/osv_check.js +11 -0
  267. package/src/tools/patch_parser.js +42 -0
  268. package/src/tools/path_security.js +16 -0
  269. package/src/tools/process_registry.js +17 -0
  270. package/src/tools/read.js +26 -0
  271. package/src/tools/registry.js +54 -0
  272. package/src/tools/rl_training.js +13 -0
  273. package/src/tools/schema_sanitizer.js +18 -0
  274. package/src/tools/send_message.js +32 -0
  275. package/src/tools/session_search.js +23 -0
  276. package/src/tools/skill_manager.js +17 -0
  277. package/src/tools/skill_usage.js +20 -0
  278. package/src/tools/skills_guard.js +17 -0
  279. package/src/tools/skills_hub.js +31 -0
  280. package/src/tools/skills_index.js +14 -0
  281. package/src/tools/skills_sync.js +19 -0
  282. package/src/tools/skills_tool.js +11 -0
  283. package/src/tools/slash_confirm.js +16 -0
  284. package/src/tools/terminal.js +29 -0
  285. package/src/tools/tirith_security.js +25 -0
  286. package/src/tools/todo.js +54 -0
  287. package/src/tools/tool_backend_helpers.js +26 -0
  288. package/src/tools/tool_output_limits.js +15 -0
  289. package/src/tools/tool_result_storage.js +20 -0
  290. package/src/tools/transcription.js +19 -0
  291. package/src/tools/tts.js +19 -0
  292. package/src/tools/url_safety.js +15 -0
  293. package/src/tools/vision.js +18 -0
  294. package/src/tools/voice_mode.js +10 -0
  295. package/src/tools/web_search.js +37 -0
  296. package/src/tools/web_tools.js +18 -0
  297. package/src/tools/website_policy.js +14 -0
  298. package/src/tools/write.js +25 -0
  299. package/src/tools/xai_http.js +13 -0
  300. package/src/tools/yuanbao_tools.js +13 -0
  301. package/src/toolset_distributions.js +18 -0
  302. package/src/toolsets.js +26 -0
  303. package/src/tui/index.js +26 -0
  304. package/src/utils.js +54 -0
  305. package/src/web/app.js +547 -0
  306. package/src/web/index.html +167 -0
  307. package/src/web/server.js +109 -0
@@ -0,0 +1,167 @@
1
+ <!doctype html>
2
+ <html lang="en" class="ds-247420" data-theme="dark">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Foph Dashboard</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
8
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600&family=Archivo+Black&family=JetBrains+Mono:wght@400;500&display=swap">
9
+ <script type="importmap">
10
+ { "imports": { "anentrypoint-design": "/vendor/anentrypoint-design/247420.js" } }
11
+ </script>
12
+ <style>
13
+ html, body {
14
+ margin: 0; padding: 0; min-height: 100vh;
15
+ }
16
+
17
+ html[data-theme="light"] body { background: var(--paper, #F5F0E4); color: var(--ink, #1F1B16); }
18
+ html[data-theme="dark"] body { background: var(--panel-0, #1A1B1E); color: var(--panel-text, #E8EAED); }
19
+
20
+ html[data-theme="light"] .ds-247420 {
21
+ --paper: #F5F0E4;
22
+ --ink: #1F1B16;
23
+ --panel-0: #F5F0E4;
24
+ --panel-1: #FBF6EB;
25
+ --panel-2: #F0E9DA;
26
+ --panel-3: #E3DAC7;
27
+ --panel-hover: #EBE1CD;
28
+ --panel-select: #D8ECCB;
29
+ --panel-text: #1F1B16;
30
+ --panel-text-2: #6B6B6B;
31
+ --panel-text-3: #8A8A8A;
32
+ --panel-accent: #3A66FF;
33
+ --panel-accent-2: #3A66FF;
34
+ --panel-accent-fg: #FFFFFF;
35
+ --green: #3F8A4A;
36
+ --purple: #6B3A78;
37
+ --mascot: #F07AA8;
38
+ --sun: #FFD86B;
39
+ --flame: #FF8454;
40
+ --sky: #6FA9FF;
41
+ --live: #2BB07F;
42
+ --warn: #FF6B4A;
43
+ --link: #3A66FF;
44
+ }
45
+
46
+ html[data-theme="dark"] .ds-247420 {
47
+ --paper: #2D2E30;
48
+ --ink: #E8EAED;
49
+ --panel-0: #1A1B1E;
50
+ --panel-1: #24252A;
51
+ --panel-2: #2D2E30;
52
+ --panel-3: #36383E;
53
+ --panel-hover: #3D3F45;
54
+ --panel-select: #1F3A2F;
55
+ --panel-text: #E8EAED;
56
+ --panel-text-2: #A0A0A0;
57
+ --panel-text-3: #7D7D7D;
58
+ --panel-accent: #8AB4F8;
59
+ --panel-accent-2: #8AB4F8;
60
+ --panel-accent-fg: #1A1B1E;
61
+ --green: #5CB85C;
62
+ --purple: #BA68C8;
63
+ --mascot: #F48FB1;
64
+ --sun: #FFD68A;
65
+ --flame: #FF9B6B;
66
+ --sky: #90CAF9;
67
+ --live: #4CAF50;
68
+ --warn: #FF7043;
69
+ --link: #90CAF9;
70
+ }
71
+
72
+ .ds-247420, .ds-247420 * {
73
+ font-family: Nunito, -apple-system, system-ui, sans-serif;
74
+ }
75
+ .ds-247420 h1, .ds-247420 h2, .ds-247420 h3, .ds-247420 h4, .ds-247420 h5, .ds-247420 h6 {
76
+ font-family: 'Archivo Black', sans-serif;
77
+ }
78
+ .ds-247420 code, .ds-247420 pre, .ds-247420 .code, .ds-247420 .meta, .ds-247420 .cli,
79
+ .ds-247420 [class*="mono"], .ds-247420 kbd {
80
+ font-family: 'JetBrains Mono', ui-monospace, monospace;
81
+ }
82
+
83
+ .ds-247420 .panel { border-radius: 20px; }
84
+ .ds-247420 .app-side a.active {
85
+ background: var(--panel-select);
86
+ color: var(--panel-text);
87
+ font-weight: 600;
88
+ }
89
+
90
+ .ds-247420 .app-status {
91
+ background: var(--panel-0);
92
+ color: var(--panel-text-2);
93
+ padding: 6px 16px;
94
+ border-top: none;
95
+ height: auto;
96
+ }
97
+
98
+ .ds-247420 input, .ds-247420 textarea, .ds-247420 select {
99
+ background: var(--panel-1);
100
+ color: var(--panel-text);
101
+ border: none;
102
+ border-radius: 10px;
103
+ padding: 8px 12px;
104
+ font-size: 14px;
105
+ outline: none;
106
+ font-family: inherit;
107
+ }
108
+ .ds-247420 input:focus, .ds-247420 textarea:focus {
109
+ background: var(--panel-2);
110
+ box-shadow: inset 0 0 0 2px var(--panel-accent-2);
111
+ }
112
+
113
+ .ds-247420 button {
114
+ font-family: inherit;
115
+ cursor: pointer;
116
+ border-radius: 10px;
117
+ font-weight: 600;
118
+ border: none;
119
+ padding: 8px 16px;
120
+ }
121
+ .ds-247420 button.primary {
122
+ background: var(--panel-accent-2);
123
+ color: var(--panel-accent-fg);
124
+ }
125
+ .ds-247420 button.danger {
126
+ background: var(--warn);
127
+ color: white;
128
+ }
129
+ .ds-247420 button.ghost {
130
+ background: transparent;
131
+ color: var(--panel-text);
132
+ border: 1px solid var(--panel-2);
133
+ }
134
+ .ds-247420 button:hover {
135
+ background: var(--panel-hover);
136
+ }
137
+
138
+ .ds-247420 table { width: 100%; border-collapse: collapse; }
139
+ .ds-247420 th, .ds-247420 td { text-align: left; padding: 8px 14px; border-bottom: 1px solid var(--panel-2); font-size: 13px; }
140
+ .ds-247420 th { color: var(--panel-text-2); font-weight: 600; background: var(--panel-1); }
141
+ .ds-247420 tr.clickable { cursor: pointer; }
142
+ .ds-247420 tr.clickable:hover td { background: var(--panel-hover); }
143
+
144
+ .ds-247420 .kpi { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1px; background: var(--panel-2); padding: 1px; border-radius: 20px; overflow: hidden; }
145
+ .ds-247420 .kpi-card { background: var(--panel-1); padding: 14px 18px; }
146
+ .ds-247420 .kpi-card .num { font-size: 1.75rem; color: var(--panel-text); font-weight: 400; font-family: 'JetBrains Mono', monospace; }
147
+ .ds-247420 .kpi-card .lbl { font-size: 0.75rem; color: var(--panel-text-2); font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; margin-top: 2px; }
148
+
149
+ .ds-247420 .row-form { display: flex; gap: 8px; flex-wrap: wrap; align-items: stretch; margin-bottom: 12px; }
150
+ .ds-247420 .row-form input { flex: 1; min-width: 140px; }
151
+
152
+ .ds-247420 .chat .chat-thread { max-height: calc(100vh - 320px); overflow-y: auto; }
153
+
154
+ .ds-247420 .chip { border-radius: 6px; padding: 4px 10px; font-size: 12px; font-weight: 600; display: inline-block; }
155
+ .ds-247420 .chip.ok { background: var(--green); color: white; }
156
+ .ds-247420 .chip.miss { background: var(--warn); color: white; }
157
+
158
+ .ds-247420 .empty { color: var(--panel-text-3); padding: 12px 0; }
159
+ .ds-247420 a { color: var(--link); text-decoration: none; }
160
+ .ds-247420 a:hover { text-decoration: underline; }
161
+ </style>
162
+ </head>
163
+ <body>
164
+ <div id="app"></div>
165
+ <script type="module" src="./app.js"></script>
166
+ </body>
167
+ </html>
@@ -0,0 +1,109 @@
1
+ import express from 'express'
2
+ import path from 'node:path'
3
+ import fs from 'node:fs'
4
+ import { fileURLToPath } from 'node:url'
5
+ import { listSessions, search, getMessages } from '../sessions.js'
6
+ import { registry, discoverBuiltinTools } from '../tools/registry.js'
7
+ import { listDebug, snapshot, snapshotAll, attachDebugRoutes } from '../observability/debug.js'
8
+ import { loadConfig, saveConfigValue } from '../config.js'
9
+ import { listJobs, createJob, deleteJob } from '../cron/scheduler.js'
10
+ import { listSkills } from '../skills/index.js'
11
+ import { listAllProfiles } from '../commands/profile.js'
12
+ import { COMMAND_REGISTRY } from '../commands/registry.js'
13
+ import { getFophHome } from '../home.js'
14
+ import { runTurn } from '../agent/machine.js'
15
+ import { runBatch } from '../batch.js'
16
+
17
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
18
+
19
+ const ENV_KEYS = [
20
+ 'ANTHROPIC_API_KEY','OPENAI_API_KEY','GROQ_API_KEY','OPENROUTER_API_KEY',
21
+ 'TELEGRAM_BOT_TOKEN','DISCORD_BOT_TOKEN','SLACK_BOT_TOKEN','SLACK_SIGNING_SECRET',
22
+ 'WHATSAPP_API_TOKEN','SIGNAL_CLI_URL','MATRIX_HOMESERVER','MATTERMOST_URL',
23
+ 'HONCHO_API_KEY','MEM0_API_KEY','SUPERMEMORY_API_KEY','BYTEROVER_API_KEY',
24
+ 'HINDSIGHT_API_KEY','OPENVIKING_API_KEY','RETAINDB_API_KEY','SERPAPI_KEY',
25
+ 'REPLICATE_API_TOKEN','SMTP_HOST','TWILIO_SID','HASS_TOKEN',
26
+ ]
27
+
28
+ function readLogs(subsystem, max = 200) {
29
+ const file = path.join(getFophHome(), 'logs', `${subsystem}.log`)
30
+ if (!fs.existsSync(file)) return []
31
+ const lines = fs.readFileSync(file, 'utf8').trim().split('\n').filter(Boolean).slice(-max)
32
+ return lines.map(l => { try { return JSON.parse(l) } catch { return { raw: l } } })
33
+ }
34
+
35
+ export async function createDashboard({ port = 0 } = {}) {
36
+ await discoverBuiltinTools()
37
+ const app = express()
38
+ app.use(express.json())
39
+ app.use(express.static(__dirname))
40
+ app.use('/vendor/anentrypoint-design', express.static(path.join(__dirname, '..', '..', 'node_modules', 'anentrypoint-design', 'dist')))
41
+ app.get('/api/sessions', (_, res) => res.json(listSessions()))
42
+ app.get('/api/sessions/:id/messages', (req, res) => res.json(getMessages(req.params.id)))
43
+ app.get('/api/search', (req, res) => res.json(search(String(req.query.q || ''))))
44
+ app.get('/api/tools', (_, res) => res.json(registry.list().map(t => ({ name: t.name, toolset: t.toolset, schema: t.schema }))))
45
+ app.get('/api/debug', (_, res) => res.json(listDebug()))
46
+ app.get('/api/debug-all', (_, res) => res.json(snapshotAll()))
47
+ app.get('/api/config', (_, res) => res.json(loadConfig()))
48
+ app.get('/api/cron', (_, res) => res.json(listJobs()))
49
+ app.get('/api/skills', (_, res) => {
50
+ const home = listSkills()
51
+ const bundled = listSkills([path.resolve('skills')])
52
+ res.json({ home, bundled })
53
+ })
54
+ app.get('/api/profiles', (_, res) => res.json(listAllProfiles()))
55
+ app.get('/api/commands', (_, res) => res.json(COMMAND_REGISTRY))
56
+ app.get('/api/env', (_, res) => res.json(ENV_KEYS.map(k => ({ key: k, set: !!process.env[k] }))))
57
+ app.get('/api/logs/:subsystem', (req, res) => res.json(readLogs(req.params.subsystem, Number(req.query.max) || 200)))
58
+ app.get('/api/logs', (_, res) => {
59
+ const dir = path.join(getFophHome(), 'logs')
60
+ if (!fs.existsSync(dir)) return res.json([])
61
+ res.json(fs.readdirSync(dir).filter(f => f.endsWith('.log')).map(f => f.replace(/\.log$/, '')))
62
+ })
63
+ app.get('/api/health', (_, res) => res.json({ ok: true, ts: Date.now(), foph_home: getFophHome() }))
64
+ app.get('/api/tools/detail', (_, res) => res.json(registry.list().map(t => ({ name: t.name, toolset: t.toolset, description: t.schema?.description || '' }))))
65
+ app.get('/api/gateway', (_, res) => {
66
+ const platforms = ['webhook', 'api_server', 'telegram', 'discord', 'slack', 'whatsapp', 'signal', 'matrix',
67
+ 'mattermost', 'email', 'sms', 'mqtt', 'feishu', 'line', 'viber', 'teams', 'wechat', 'rss']
68
+ res.json({ platforms: platforms.map(p => ({ name: p, enabled: false, note: 'start with freddie gateway --port <port>' })) })
69
+ })
70
+ app.post('/api/batch', async (req, res) => {
71
+ const { prompts = [], concurrency = 4, model = '' } = req.body || {}
72
+ if (!prompts.length) return res.status(400).json({ error: 'prompts required' })
73
+ try { res.json(await runBatch({ prompts, concurrency, model })) } catch (e) { res.status(500).json({ error: String(e.message || e) }) }
74
+ })
75
+
76
+ app.post('/api/cron', (req, res) => {
77
+ const { cron, prompt, model = null } = req.body || {}
78
+ if (!cron || !prompt) return res.status(400).json({ error: 'cron and prompt required' })
79
+ try { res.json({ id: createJob({ cron, prompt, model }) }) } catch (e) { res.status(400).json({ error: String(e.message || e) }) }
80
+ })
81
+ app.delete('/api/cron/:id', (req, res) => { deleteJob(Number(req.params.id)); res.json({ ok: true }) })
82
+
83
+ app.post('/api/config', (req, res) => {
84
+ const { key, value } = req.body || {}
85
+ if (!key) return res.status(400).json({ error: 'key required' })
86
+ try { res.json(saveConfigValue(key, value)) } catch (e) { res.status(400).json({ error: String(e.message || e) }) }
87
+ })
88
+
89
+ app.post('/api/chat', async (req, res) => {
90
+ const { prompt, sessionId = null } = req.body || {}
91
+ if (!prompt) return res.status(400).json({ error: 'prompt required' })
92
+ res.setHeader('Content-Type', 'text/event-stream')
93
+ res.setHeader('Cache-Control', 'no-cache')
94
+ res.setHeader('Connection', 'keep-alive')
95
+ const send = (event, data) => res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`)
96
+ send('start', { ts: Date.now(), sessionId })
97
+ try {
98
+ const out = await runTurn({ prompt, timeoutMs: 30000 })
99
+ for (const m of out.messages) send('message', m)
100
+ send('done', { result: out.result || '', iterations: out.iterations })
101
+ } catch (e) { send('error', { error: String(e.message || e) }) }
102
+ res.end()
103
+ })
104
+
105
+ attachDebugRoutes(app)
106
+ const server = await new Promise(r => { const s = app.listen(port, () => r(s)) })
107
+ const actualPort = server.address().port
108
+ return { server, port: actualPort, url: `http://127.0.0.1:${actualPort}/`, stop: () => new Promise(r => server.close(() => r())) }
109
+ }