cortico 0.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 (311) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +47 -0
  3. package/package.json +43 -0
  4. package/src/boot.ts +46 -0
  5. package/src/bot.ts +1342 -0
  6. package/src/config-file.ts +41 -0
  7. package/src/core/README.md +92 -0
  8. package/src/core/billing.ts +26 -0
  9. package/src/core/blobs.ts +106 -0
  10. package/src/core/bus.ts +311 -0
  11. package/src/core/config-schema.ts +201 -0
  12. package/src/core/config.ts +262 -0
  13. package/src/core/core.ts +699 -0
  14. package/src/core/cost.ts +244 -0
  15. package/src/core/event-store.ts +304 -0
  16. package/src/core/fork.ts +113 -0
  17. package/src/core/generation.ts +118 -0
  18. package/src/core/instance-lock.ts +215 -0
  19. package/src/core/ipc-logger.ts +105 -0
  20. package/src/core/language.ts +62 -0
  21. package/src/core/log-context.ts +38 -0
  22. package/src/core/loop.ts +1858 -0
  23. package/src/core/markers.ts +48 -0
  24. package/src/core/prefix.ts +121 -0
  25. package/src/core/run.ts +95 -0
  26. package/src/core/secrets.ts +18 -0
  27. package/src/core/session.ts +56 -0
  28. package/src/core/sessions.ts +261 -0
  29. package/src/core/state.ts +104 -0
  30. package/src/core/template.ts +72 -0
  31. package/src/core/timers.ts +129 -0
  32. package/src/core/tool-log.ts +135 -0
  33. package/src/core/transcript.ts +92 -0
  34. package/src/core/truncate.ts +121 -0
  35. package/src/core/types.ts +1140 -0
  36. package/src/core/usage-log.ts +79 -0
  37. package/src/core/util.ts +386 -0
  38. package/src/deploy-listing.ts +160 -0
  39. package/src/deploy.ts +162 -0
  40. package/src/extensions/README.md +72 -0
  41. package/src/extensions/dry-mount.ts +390 -0
  42. package/src/extensions/manifest.ts +153 -0
  43. package/src/extensions/runtime.ts +42 -0
  44. package/src/extensions.ts +519 -0
  45. package/src/launcher.ts +285 -0
  46. package/src/paths.ts +155 -0
  47. package/src/protocol/open-responses/LICENSE +201 -0
  48. package/src/protocol/open-responses/README.md +14 -0
  49. package/src/protocol/open-responses/context-helpers.ts +27 -0
  50. package/src/protocol/open-responses/context-log.ts +59 -0
  51. package/src/protocol/open-responses/context.ts +89 -0
  52. package/src/protocol/open-responses/generated.ts +115 -0
  53. package/src/protocol/open-responses/index.ts +33 -0
  54. package/src/protocol/open-responses/openapi.json +4230 -0
  55. package/src/protocol/open-responses/stream.ts +146 -0
  56. package/src/protocol/open-responses/tokens.ts +31 -0
  57. package/src/providers/README.md +86 -0
  58. package/src/providers/base.ts +111 -0
  59. package/src/providers/configuration.ts +97 -0
  60. package/src/providers/console/config.ts +21 -0
  61. package/src/providers/console/settings.ts +443 -0
  62. package/src/providers/console/strings.ts +74 -0
  63. package/src/providers/console/types.ts +11 -0
  64. package/src/providers/llamacpp/archive.ts +148 -0
  65. package/src/providers/llamacpp/catalog.ts +247 -0
  66. package/src/providers/llamacpp/config.ts +36 -0
  67. package/src/providers/llamacpp/console/client.ts +6 -0
  68. package/src/providers/llamacpp/console/models-panel.ts +120 -0
  69. package/src/providers/llamacpp/console/runtime-panel.ts +173 -0
  70. package/src/providers/llamacpp/console/server.ts +153 -0
  71. package/src/providers/llamacpp/index.ts +95 -0
  72. package/src/providers/llamacpp/native.ts +51 -0
  73. package/src/providers/llamacpp/options.ts +117 -0
  74. package/src/providers/llamacpp/runtime-store.ts +139 -0
  75. package/src/providers/llamacpp/runtime.ts +214 -0
  76. package/src/providers/llamacpp/server.ts +286 -0
  77. package/src/providers/llamacpp/strings.ts +230 -0
  78. package/src/providers/openai-responses-compat/config.ts +20 -0
  79. package/src/providers/openai-responses-compat/index.ts +89 -0
  80. package/src/providers/openai-responses-compat/native.ts +127 -0
  81. package/src/providers/openai-responses-compat/strings.ts +19 -0
  82. package/src/providers/pricebook.ts +75 -0
  83. package/src/providers/registry.ts +137 -0
  84. package/src/providers/strings.ts +71 -0
  85. package/src/providers/transport/chat.ts +156 -0
  86. package/src/providers/transport/errors.ts +48 -0
  87. package/src/providers/transport/history.ts +68 -0
  88. package/src/providers/transport/native-input.ts +83 -0
  89. package/src/providers/transport/native-types.ts +13 -0
  90. package/src/providers/transport/response-assembly.ts +191 -0
  91. package/src/providers/transport/response-http.ts +196 -0
  92. package/src/providers/transport/response-meters.ts +27 -0
  93. package/src/providers/transport/responses-input.ts +56 -0
  94. package/src/web/README.md +84 -0
  95. package/src/web/client/console-pages/builtins/llm-settings/panel.ts +625 -0
  96. package/src/web/client/console-pages/builtins/llm-settings/pricing-panel.ts +168 -0
  97. package/src/web/client/console-pages/builtins/llm-settings/strings.ts +213 -0
  98. package/src/web/client/console-pages/builtins.ts +10 -0
  99. package/src/web/client/console-pages/context.ts +135 -0
  100. package/src/web/client/console-pages/host.ts +633 -0
  101. package/src/web/client/console-pages/loader.ts +132 -0
  102. package/src/web/client/console-pages/strings.ts +90 -0
  103. package/src/web/client/console-pages/tools/strings.ts +49 -0
  104. package/src/web/client/console-pages/tools/view.ts +215 -0
  105. package/src/web/client/core/api.ts +200 -0
  106. package/src/web/client/core/language.ts +56 -0
  107. package/src/web/client/core/lifecycle.ts +132 -0
  108. package/src/web/client/core/router.ts +199 -0
  109. package/src/web/client/core/stream.ts +157 -0
  110. package/src/web/client/core/websocket.ts +82 -0
  111. package/src/web/client/features/appearance/index.ts +333 -0
  112. package/src/web/client/features/appearance/strings.ts +87 -0
  113. package/src/web/client/features/config/index.ts +11 -0
  114. package/src/web/client/features/config/strings.ts +41 -0
  115. package/src/web/client/features/config/view.ts +428 -0
  116. package/src/web/client/features/core/events.ts +197 -0
  117. package/src/web/client/features/core/index.ts +254 -0
  118. package/src/web/client/features/core/run.ts +56 -0
  119. package/src/web/client/features/core/runlog.ts +214 -0
  120. package/src/web/client/features/core/sessions.ts +53 -0
  121. package/src/web/client/features/core/strings.ts +157 -0
  122. package/src/web/client/features/extensions/index.ts +422 -0
  123. package/src/web/client/features/extensions/strings.ts +164 -0
  124. package/src/web/client/features/feature.ts +93 -0
  125. package/src/web/client/features/live/context.ts +280 -0
  126. package/src/web/client/features/live/fork.ts +156 -0
  127. package/src/web/client/features/live/index.ts +392 -0
  128. package/src/web/client/features/live/onboarding.ts +113 -0
  129. package/src/web/client/features/live/protocol.ts +122 -0
  130. package/src/web/client/features/live/sessions.ts +71 -0
  131. package/src/web/client/features/live/status.ts +68 -0
  132. package/src/web/client/features/live/strings.ts +252 -0
  133. package/src/web/client/features/live/timeline.ts +590 -0
  134. package/src/web/client/features/prompts/editor.ts +292 -0
  135. package/src/web/client/features/prompts/index.ts +346 -0
  136. package/src/web/client/features/prompts/strings.ts +136 -0
  137. package/src/web/client/features/prompts/view.ts +256 -0
  138. package/src/web/client/features/providers/index.ts +100 -0
  139. package/src/web/client/features/providers/strings.ts +23 -0
  140. package/src/web/client/features/settings/general.ts +28 -0
  141. package/src/web/client/features/settings/index.ts +82 -0
  142. package/src/web/client/features/settings/strings.ts +33 -0
  143. package/src/web/client/features/storage/index.ts +1 -0
  144. package/src/web/client/features/storage/strings.ts +45 -0
  145. package/src/web/client/features/storage/view.ts +154 -0
  146. package/src/web/client/features/usage/chart.ts +486 -0
  147. package/src/web/client/features/usage/index.ts +407 -0
  148. package/src/web/client/features/usage/labels.ts +46 -0
  149. package/src/web/client/features/usage/range.ts +36 -0
  150. package/src/web/client/features/usage/state.ts +37 -0
  151. package/src/web/client/features/usage/strings.ts +191 -0
  152. package/src/web/client/features/usage/tooltip.ts +86 -0
  153. package/src/web/client/features/usage/types.ts +96 -0
  154. package/src/web/client/features/worlds/index.ts +424 -0
  155. package/src/web/client/features/worlds/strings.ts +121 -0
  156. package/src/web/client/main.ts +273 -0
  157. package/src/web/client/shell/avatar.ts +233 -0
  158. package/src/web/client/shell/index.ts +549 -0
  159. package/src/web/client/shell/strings.ts +89 -0
  160. package/src/web/client/theme/handoff.ts +43 -0
  161. package/src/web/client/theme/palette.ts +109 -0
  162. package/src/web/client/theme/registry.ts +130 -0
  163. package/src/web/client/theme/storage.ts +72 -0
  164. package/src/web/client/theme/strings.ts +123 -0
  165. package/src/web/client/theme/studio.ts +366 -0
  166. package/src/web/client/ui/actions.ts +109 -0
  167. package/src/web/client/ui/data.ts +185 -0
  168. package/src/web/client/ui/dom.ts +23 -0
  169. package/src/web/client/ui/fields.ts +191 -0
  170. package/src/web/client/ui/format.ts +75 -0
  171. package/src/web/client/ui/icons.ts +183 -0
  172. package/src/web/client/ui/images.ts +91 -0
  173. package/src/web/client/ui/index.ts +89 -0
  174. package/src/web/client/ui/lamp.ts +125 -0
  175. package/src/web/client/ui/log.ts +98 -0
  176. package/src/web/client/ui/overlay.ts +184 -0
  177. package/src/web/client/ui/page.ts +8 -0
  178. package/src/web/client/ui/prompt-input.tsx +311 -0
  179. package/src/web/client/ui/sheet.ts +131 -0
  180. package/src/web/client/ui/strings.ts +71 -0
  181. package/src/web/console-pages.ts +367 -0
  182. package/src/web/files.ts +107 -0
  183. package/src/web/path-picker.ts +296 -0
  184. package/src/web/public/index.html +17 -0
  185. package/src/web/public/styles.css +1715 -0
  186. package/src/web/server.ts +1883 -0
  187. package/src/web/shared/client-panel.ts +603 -0
  188. package/src/web/shared/console-protocol.ts +560 -0
  189. package/src/web/shared/css.d.ts +1 -0
  190. package/src/web/shared/path-picker.ts +23 -0
  191. package/src/web/shared/theme.ts +256 -0
  192. package/src/web/theme-store.ts +37 -0
  193. package/src/world.ts +449 -0
  194. package/src/worlds/bilibili/ENV_PROMPT.md +5 -0
  195. package/src/worlds/bilibili/README.md +176 -0
  196. package/src/worlds/bilibili/audience-admission.ts +995 -0
  197. package/src/worlds/bilibili/client.ts +528 -0
  198. package/src/worlds/bilibili/coalescing-buffer.ts +125 -0
  199. package/src/worlds/bilibili/config.ts +185 -0
  200. package/src/worlds/bilibili/console/client.ts +202 -0
  201. package/src/worlds/bilibili/definition.ts +35 -0
  202. package/src/worlds/bilibili/gift-frame.ts +131 -0
  203. package/src/worlds/bilibili/normalize.ts +452 -0
  204. package/src/worlds/bilibili/overlay/announcement.ts +76 -0
  205. package/src/worlds/bilibili/overlay/assets.ts +82 -0
  206. package/src/worlds/bilibili/overlay/model.ts +494 -0
  207. package/src/worlds/bilibili/overlay/project.ts +202 -0
  208. package/src/worlds/bilibili/overlay/server.ts +286 -0
  209. package/src/worlds/bilibili/overlay/types.ts +217 -0
  210. package/src/worlds/bilibili/overlay/web/app.js +690 -0
  211. package/src/worlds/bilibili/overlay/web/editor.css +297 -0
  212. package/src/worlds/bilibili/overlay/web/editor.html +102 -0
  213. package/src/worlds/bilibili/overlay/web/editor.js +2116 -0
  214. package/src/worlds/bilibili/overlay/web/overlay.html +13 -0
  215. package/src/worlds/bilibili/overlay/web/styles.css +258 -0
  216. package/src/worlds/bilibili/protobuf.ts +123 -0
  217. package/src/worlds/bilibili/wire.ts +94 -0
  218. package/src/worlds/bilibili/world.ts +1389 -0
  219. package/src/worlds/console-fixture/ENV_PROMPT.md +1 -0
  220. package/src/worlds/console-fixture/console/client.ts +72 -0
  221. package/src/worlds/console-fixture/world.ts +73 -0
  222. package/src/worlds/index.ts +15 -0
  223. package/src/worlds/minecraft/ENV_PROMPT.md +32 -0
  224. package/src/worlds/minecraft/ENV_PROMPT_CAMERA.md +2 -0
  225. package/src/worlds/minecraft/LICENSE-mineflayer-pathfinder.txt +21 -0
  226. package/src/worlds/minecraft/README.md +917 -0
  227. package/src/worlds/minecraft/blueprint-plan.ts +915 -0
  228. package/src/worlds/minecraft/blueprint-registry.ts +566 -0
  229. package/src/worlds/minecraft/blueprint-repair.ts +236 -0
  230. package/src/worlds/minecraft/blueprint-resource.ts +272 -0
  231. package/src/worlds/minecraft/blueprint.ts +492 -0
  232. package/src/worlds/minecraft/body-lease.ts +340 -0
  233. package/src/worlds/minecraft/bridge.ts +749 -0
  234. package/src/worlds/minecraft/check.ts +651 -0
  235. package/src/worlds/minecraft/chests.ts +292 -0
  236. package/src/worlds/minecraft/client-launch.ts +272 -0
  237. package/src/worlds/minecraft/client-options.ts +85 -0
  238. package/src/worlds/minecraft/client-skins.ts +164 -0
  239. package/src/worlds/minecraft/client-window.ps1 +91 -0
  240. package/src/worlds/minecraft/client.ts +423 -0
  241. package/src/worlds/minecraft/combat-context.ts +109 -0
  242. package/src/worlds/minecraft/combat.ts +1552 -0
  243. package/src/worlds/minecraft/config.ts +499 -0
  244. package/src/worlds/minecraft/console/access.ts +218 -0
  245. package/src/worlds/minecraft/console/client.ts +244 -0
  246. package/src/worlds/minecraft/console/log.ts +110 -0
  247. package/src/worlds/minecraft/console/mount.ts +420 -0
  248. package/src/worlds/minecraft/console/skin.ts +257 -0
  249. package/src/worlds/minecraft/console/style.css +154 -0
  250. package/src/worlds/minecraft/console/world.ts +449 -0
  251. package/src/worlds/minecraft/deaths.ts +135 -0
  252. package/src/worlds/minecraft/definition.ts +18 -0
  253. package/src/worlds/minecraft/engine-child.ts +274 -0
  254. package/src/worlds/minecraft/engine-ipc.ts +98 -0
  255. package/src/worlds/minecraft/entity-facts.ts +132 -0
  256. package/src/worlds/minecraft/escape.ts +407 -0
  257. package/src/worlds/minecraft/executor.ts +14494 -0
  258. package/src/worlds/minecraft/explored.ts +156 -0
  259. package/src/worlds/minecraft/geometry.ts +205 -0
  260. package/src/worlds/minecraft/goal-plan.ts +647 -0
  261. package/src/worlds/minecraft/item-break.ts +126 -0
  262. package/src/worlds/minecraft/item-facts.ts +146 -0
  263. package/src/worlds/minecraft/item-pick.ts +67 -0
  264. package/src/worlds/minecraft/level-dat.ts +176 -0
  265. package/src/worlds/minecraft/log.ts +132 -0
  266. package/src/worlds/minecraft/mineflayer-fixes.ts +1180 -0
  267. package/src/worlds/minecraft/names.ts +377 -0
  268. package/src/worlds/minecraft/pathfinder-lib.d.ts +13 -0
  269. package/src/worlds/minecraft/pathfinder-perf.ts +796 -0
  270. package/src/worlds/minecraft/piglin.ts +49 -0
  271. package/src/worlds/minecraft/policy.ts +547 -0
  272. package/src/worlds/minecraft/precheck.ts +655 -0
  273. package/src/worlds/minecraft/proxy.ts +445 -0
  274. package/src/worlds/minecraft/ranged.ts +635 -0
  275. package/src/worlds/minecraft/readouts.ts +102 -0
  276. package/src/worlds/minecraft/round.ts +26 -0
  277. package/src/worlds/minecraft/search-observation.ts +92 -0
  278. package/src/worlds/minecraft/server-config.ts +467 -0
  279. package/src/worlds/minecraft/server.ts +658 -0
  280. package/src/worlds/minecraft/show.ts +84 -0
  281. package/src/worlds/minecraft/skills.ts +1763 -0
  282. package/src/worlds/minecraft/terrain.ts +1735 -0
  283. package/src/worlds/minecraft/window.ts +96 -0
  284. package/src/worlds/minecraft/works.ts +179 -0
  285. package/src/worlds/minecraft/world.ts +6438 -0
  286. package/src/worlds/qq/ENV_PROMPT.md +5 -0
  287. package/src/worlds/qq/config.ts +108 -0
  288. package/src/worlds/qq/console/client.ts +126 -0
  289. package/src/worlds/qq/console/events.ts +155 -0
  290. package/src/worlds/qq/console/gate.ts +232 -0
  291. package/src/worlds/qq/console/roster.ts +203 -0
  292. package/src/worlds/qq/console/style.css +65 -0
  293. package/src/worlds/qq/conversation.ts +28 -0
  294. package/src/worlds/qq/definition.ts +62 -0
  295. package/src/worlds/qq/driver.ts +375 -0
  296. package/src/worlds/qq/history-tools.ts +209 -0
  297. package/src/worlds/qq/normalize.ts +323 -0
  298. package/src/worlds/qq/qface-map.ts +282 -0
  299. package/src/worlds/qq/vision-prompt.ts +27 -0
  300. package/src/worlds/qq/vision.ts +642 -0
  301. package/src/worlds/qq/vlm.ts +142 -0
  302. package/src/worlds/qq/world.ts +1503 -0
  303. package/src/worlds/terminal/ENV_PROMPT.md +11 -0
  304. package/src/worlds/terminal/config.ts +9 -0
  305. package/src/worlds/terminal/definition.ts +14 -0
  306. package/src/worlds/terminal/world.ts +700 -0
  307. package/src/worlds/websearch/ENV_PROMPT.md +1 -0
  308. package/src/worlds/websearch/brave-client.ts +261 -0
  309. package/src/worlds/websearch/config.ts +75 -0
  310. package/src/worlds/websearch/definition.ts +20 -0
  311. package/src/worlds/websearch/world.ts +171 -0
@@ -0,0 +1,254 @@
1
+ /**
2
+ * core 的运行态、会话统计、事件流、日志、数据与配置页,不持有或显示人格前缀。
3
+ * 工具表不在这里:那是 Persona 页的框架页签。
4
+ * 子页状态由路由表达;未挂载的能力不显示页签。仅当前子页运行轮询,状态保存在挂载闭包,由调试帧或一次性 GET 填充。
5
+ */
6
+
7
+ import type { Disposable } from '../../../shared/client-panel.ts';
8
+ import type { FeatureContext, FrameworkFeature } from '../feature.ts';
9
+ import { pageIntro } from '../../ui/page.ts';
10
+ import { get } from '../../core/api.ts';
11
+ import { browserSocketEnv, openFrameworkSocket, type SocketEnv } from '../../core/websocket.ts';
12
+ import {
13
+ arr,
14
+ str,
15
+ type SessionStat,
16
+ type StatusSnapshot,
17
+ } from '../live/protocol.ts';
18
+ import { createEventsView } from './events.ts';
19
+ import { createRunlogView } from './runlog.ts';
20
+ import { createRunView } from './run.ts';
21
+ import { createSessionTable } from './sessions.ts';
22
+ import { S } from './strings.ts';
23
+ import { createConfigView } from '../config/view.ts';
24
+ import { createStorageView } from '../storage/view.ts';
25
+
26
+ const CORE_ROUTE = 'core';
27
+ const DEBUG_WS_PATH = '/ws/debug';
28
+
29
+ /** 一个子页签。`need` 是它依赖的 capability(null = 永远有)。 */
30
+ interface SubDef {
31
+ id: string;
32
+ label: string;
33
+ need: string | null;
34
+ }
35
+
36
+ const CORE_SUBS: readonly SubDef[] = [
37
+ { id: 'run', label: S.subRun, need: null },
38
+ { id: 'sessions', label: S.subSessions, need: 'sessions' },
39
+ { id: 'events', label: S.subEvents, need: null },
40
+ { id: 'runlog', label: S.subRunlog, need: null },
41
+ { id: 'data', label: S.subData, need: 'storage' },
42
+ { id: 'config', label: S.subConfig, need: 'config' },
43
+ ];
44
+
45
+ export interface CoreFeatureOptions {
46
+ env?: SocketEnv;
47
+ }
48
+
49
+ export function createCoreFeature(opts: CoreFeatureOptions = {}): FrameworkFeature {
50
+ return {
51
+ route: CORE_ROUTE,
52
+ label: S.navLabel,
53
+ icon: 'activity',
54
+ navGroup: S.navGroup,
55
+ // 事件流与运行日志不依赖任何可选表面,所以这一页永远有意义。
56
+ mount(ctx) {
57
+ return mountHarness(ctx, opts.env ?? browserSocketEnv(window));
58
+ },
59
+ };
60
+ }
61
+
62
+ export const coreFeature: FrameworkFeature = createCoreFeature();
63
+
64
+ function mountHarness(ctx: FeatureContext, env: SocketEnv): Disposable | void {
65
+ const { ui } = ctx;
66
+
67
+ const state = {
68
+ status: null as StatusSnapshot | null,
69
+ sessions: [] as SessionStat[],
70
+ };
71
+
72
+ const subs = CORE_SUBS.filter((s) => s.need === null || ctx.capabilities[s.need] === true);
73
+ const wanted = str(ctx.route.segments[1]);
74
+ let current = subs.some((s) => s.id === wanted) ? wanted : (subs[0]?.id ?? 'run');
75
+
76
+ // ── 页头 ─────────────────────────────────────────────────────────
77
+ const view = ui.h('div', 'coreview');
78
+ const head = pageIntro(ui, S.pageTitle);
79
+ head.className = 'featureintro pagehead';
80
+ const tabs = ui.segmented(
81
+ subs.map((s) => ({ value: s.id, label: s.label })),
82
+ { value: current, onSelect: (v) => show(v, true) },
83
+ );
84
+ const tabBar = ui.h('div', 'subtabs');
85
+ tabBar.appendChild(tabs.el);
86
+ const net = ui.msgline('');
87
+ tabBar.appendChild(net);
88
+ const scroll = ui.h('div', 'scroll');
89
+ const measure = ui.h('div', 'measure');
90
+ scroll.appendChild(measure);
91
+ view.append(head, tabBar, scroll);
92
+ ctx.root.appendChild(view);
93
+
94
+ const setNet = (online: boolean): void => {
95
+ net.className = online ? 'msgline' : 'msgline bad';
96
+ net.textContent = online ? '' : S.netOffline;
97
+ };
98
+
99
+ // ── 六个子页 ─────────────────────────────────────────────────────
100
+ const run = createRunView({ ui });
101
+ const sessions = createSessionTable(ui);
102
+ const events = createEventsView({
103
+ ui,
104
+ lifecycle: ctx.lifecycle,
105
+ signal: ctx.signal,
106
+ onNet: setNet,
107
+ onError: (err) => ctx.onError(err),
108
+ });
109
+ const runlog = createRunlogView({
110
+ ui,
111
+ signal: ctx.signal,
112
+ onNet: setNet,
113
+ onError: (err) => ctx.onError(err),
114
+ });
115
+ // Core 自己的存储项与配置组:按 owner 取,World / Persona / Memory 的各在自己页上。
116
+ const data = createStorageView({ ui, signal: ctx.signal, filter: (p) => p.owner === 'core', clearAll: true });
117
+ const dataSheet = ui.sheet({ title: S.dataTitle, en: 'core storage', desc: S.dataDesc });
118
+ dataSheet.body.appendChild(data.el);
119
+ const config = createConfigView({
120
+ ui,
121
+ lifecycle: ctx.lifecycle,
122
+ signal: ctx.signal,
123
+ filter: (group) => group.owner === 'core',
124
+ showOwner: false,
125
+ emptyText: S.configEmpty,
126
+ });
127
+ const configSheet = ui.sheet({ title: S.configTitle, en: 'core config', desc: S.configDesc });
128
+ configSheet.body.appendChild(config.el);
129
+
130
+ const panes: Record<string, HTMLElement> = {
131
+ run: run.el,
132
+ sessions: sessions.el,
133
+ events: events.el,
134
+ runlog: runlog.el,
135
+ data: dataSheet.el,
136
+ config: configSheet.el,
137
+ };
138
+
139
+ /** 每次进入某个子页要做的事。进来才拉数据——没打开的页不该占网络。 */
140
+ const enter: Record<string, () => void> = {
141
+ run: () => {
142
+ run.render(state.status);
143
+ if (!hasDebug) void refreshStatus();
144
+ },
145
+ sessions: () => {
146
+ sessions.render(state.sessions);
147
+ if (!hasDebug) void refreshSessions();
148
+ },
149
+ events: () => {
150
+ void events.init();
151
+ events.setPolling(!hasDebug);
152
+ },
153
+ runlog: () => {
154
+ void runlog.refresh();
155
+ },
156
+ data: () => {
157
+ void data.load();
158
+ },
159
+ config: () => {
160
+ void config.load();
161
+ },
162
+ };
163
+
164
+ function show(sub: string, navigate: boolean): void {
165
+ const next = subs.some((s) => s.id === sub) ? sub : (subs[0]?.id ?? 'run');
166
+ if (next !== current) {
167
+ // 离开事件流就停它的轮询:一个看不见的表不该继续问服务端要数据。
168
+ if (current === 'events') events.setPolling(false);
169
+ current = next;
170
+ }
171
+ tabs.setValue(current);
172
+ while (measure.children.length) measure.children[0].remove();
173
+ const pane = panes[current];
174
+ if (pane) measure.appendChild(pane);
175
+ enter[current]?.();
176
+ if (navigate) ctx.router.navigate([CORE_ROUTE, current]);
177
+ }
178
+
179
+ // 地址栏被别处改了(后退键、别的页跳过来)时跟上,不重建整页。
180
+ ctx.lifecycle.own(
181
+ ctx.router.onChange((route) => {
182
+ if (route.segments[0] !== CORE_ROUTE) return;
183
+ const sub = str(route.segments[1]) || (subs[0]?.id ?? 'run');
184
+ if (sub !== current) show(sub, false);
185
+ }),
186
+ );
187
+
188
+ // ── 数据 ─────────────────────────────────────────────────────────
189
+ async function refreshStatus(): Promise<void> {
190
+ try {
191
+ const st = await get<StatusSnapshot>('/api/status', { signal: ctx.signal });
192
+ state.status = st;
193
+ setNet(true);
194
+ if (current === 'run') run.render(st);
195
+ } catch (err) {
196
+ if ((err as { name?: string } | null)?.name === 'AbortError') return;
197
+ setNet(false);
198
+ ctx.onError(err);
199
+ }
200
+ }
201
+
202
+ async function refreshSessions(): Promise<void> {
203
+ try {
204
+ const d = await get<{ sessions?: SessionStat[] }>('/api/sessions', { signal: ctx.signal });
205
+ state.sessions = d?.sessions ?? [];
206
+ if (current === 'sessions') sessions.render(state.sessions);
207
+ } catch (err) {
208
+ if ((err as { name?: string } | null)?.name === 'AbortError') return;
209
+ ctx.onError(err);
210
+ }
211
+ }
212
+
213
+ const hasDebug = ctx.capabilities.debug === true;
214
+ if (hasDebug) {
215
+ openFrameworkSocket({
216
+ path: DEBUG_WS_PATH,
217
+ lifecycle: ctx.lifecycle,
218
+ env,
219
+ onNet: setNet,
220
+ onError: (err) => ctx.onError(err),
221
+ onFrame: (f) => {
222
+ switch (f.t) {
223
+ case 'hello':
224
+ state.sessions = arr<SessionStat>(f.sessions);
225
+ state.status = (f.status as StatusSnapshot | null) ?? null;
226
+ if (current === 'run') run.render(state.status);
227
+ if (current === 'sessions') sessions.render(state.sessions);
228
+ break;
229
+ case 'status':
230
+ state.status = (f.status as StatusSnapshot | null) ?? null;
231
+ if (current === 'run') run.render(state.status);
232
+ break;
233
+ case 'sessions':
234
+ state.sessions = arr<SessionStat>(f.sessions);
235
+ if (current === 'sessions') sessions.render(state.sessions);
236
+ break;
237
+ // 有推送就不必轮询:到了才追一次。
238
+ case 'event':
239
+ if (current === 'events') void events.poll();
240
+ break;
241
+ case 'runlog':
242
+ if (current === 'runlog') void runlog.refresh();
243
+ break;
244
+ default:
245
+ break;
246
+ }
247
+ },
248
+ });
249
+ } else {
250
+ void refreshStatus();
251
+ }
252
+
253
+ show(current, false);
254
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * 运行态概览。只读——暂停/继续那颗按钮在顶栏,这里不重复一份。
3
+ */
4
+
5
+ import type { ConsoleUi } from '../../../shared/client-panel.ts';
6
+ import { loopOf, type StatusSnapshot } from '../live/protocol.ts';
7
+ import { S } from './strings.ts';
8
+
9
+ export interface RunViewDeps {
10
+ ui: ConsoleUi;
11
+ }
12
+
13
+ export interface RunView {
14
+ el: HTMLElement;
15
+ render(st: StatusSnapshot | null): void;
16
+ }
17
+
18
+ export function createRunView(deps: RunViewDeps): RunView {
19
+ const { ui } = deps;
20
+ const sheet = ui.sheet({
21
+ title: S.runTitle,
22
+ en: 'context · cache · batches',
23
+ });
24
+ const grid = ui.statgrid();
25
+ sheet.body.appendChild(grid);
26
+
27
+ return {
28
+ el: sheet.el,
29
+ render(st) {
30
+ while (grid.children.length) grid.children[0].remove();
31
+ if (!st) {
32
+ grid.appendChild(ui.placeholder(S.noStatus));
33
+ return;
34
+ }
35
+ const loop = loopOf(st);
36
+ const u = loop.lastUsage ?? {};
37
+ const cache =
38
+ u.promptTokens ? ui.fmt.percent((u.cacheHitTokens || 0) / u.promptTokens) : '—';
39
+ const cards = [
40
+ { k: S.statContext, v: ui.fmt.count(loop.estTokens), unit: 'tok', accent: true },
41
+ { k: S.statMessages, v: loop.messageCount ?? '—', unit: S.unitMsgs },
42
+ { k: S.statCache, v: cache },
43
+ { k: S.statRounds, v: loop.roundsLastBatch ?? '—' },
44
+ { k: S.statBatches, v: loop.batchesHandled ?? '—' },
45
+ { k: S.statEvents, v: st.eventCount ?? '—', unit: S.unitEvents },
46
+ { k: S.statOnline, v: st.terminalOnline ?? '—', unit: S.unitPeople },
47
+ {
48
+ k: S.statRun,
49
+ v: loop.paused ? S.runPaused : loop.scheduleBlocked ? S.runBlocked : S.runRunning,
50
+ accent: !!(loop.paused || loop.scheduleBlocked),
51
+ },
52
+ ];
53
+ for (const c of cards) grid.appendChild(ui.stat(c));
54
+ },
55
+ };
56
+ }
@@ -0,0 +1,214 @@
1
+ /**
2
+ * 运行日志不进入 agent 上下文。/api/log?run&level&area&grep&round&limit 按条件从
3
+ * log.jsonl 尾部查满 limit 条;run 默认当前运行,清单取自 /api/runs。
4
+ * 文本输入去抖 300 ms,Enter 立即查询。
5
+ */
6
+
7
+ import type { ConsoleUi } from '../../../shared/client-panel.ts';
8
+ import { get } from '../../core/api.ts';
9
+ import { S } from './strings.ts';
10
+
11
+ export interface RunlogEntry {
12
+ ts: string;
13
+ level: string;
14
+ area: string;
15
+ event?: string;
16
+ msg: string;
17
+ /** 折叠汇总行代表的重复条数 */
18
+ repeat?: number;
19
+ data?: unknown;
20
+ err?: { name: string; message: string };
21
+ }
22
+
23
+ interface RunRow {
24
+ run: string;
25
+ startedAt?: string;
26
+ }
27
+
28
+ interface RunsReply {
29
+ current: string | null;
30
+ runs: RunRow[];
31
+ }
32
+
33
+ const TAIL = 200;
34
+ /** `data` 摘要最多印多少字。 */
35
+ const DATA_MAX = 300;
36
+ const DEBOUNCE_MS = 300;
37
+
38
+ function truncate(s: string, n: number): string {
39
+ return s && s.length > n ? `${s.slice(0, n)}…` : s;
40
+ }
41
+
42
+ export interface RunlogViewDeps {
43
+ ui: ConsoleUi;
44
+ signal: AbortSignal;
45
+ onNet(online: boolean): void;
46
+ onError(err: unknown): void;
47
+ }
48
+
49
+ export interface RunlogView {
50
+ el: HTMLElement;
51
+ refresh(): Promise<void>;
52
+ }
53
+
54
+ export function createRunlogView(deps: RunlogViewDeps): RunlogView {
55
+ const { ui } = deps;
56
+ const q = { run: '', level: 'debug', area: '', grep: '', round: '' };
57
+ let runsLoaded = false;
58
+ let debounce: ReturnType<typeof setTimeout> | null = null;
59
+
60
+ const cancel = (): void => {
61
+ if (debounce !== null) clearTimeout(debounce);
62
+ debounce = null;
63
+ };
64
+ const later = (): void => {
65
+ cancel();
66
+ debounce = setTimeout(() => {
67
+ debounce = null;
68
+ void view.refresh();
69
+ }, DEBOUNCE_MS);
70
+ };
71
+ const now = (): void => {
72
+ cancel();
73
+ void view.refresh();
74
+ };
75
+ deps.signal.addEventListener('abort', cancel, { once: true });
76
+
77
+ const bar = ui.rowbar();
78
+ const runSel = ui.select({
79
+ cls: 'mono',
80
+ options: [{ value: '', label: S.currentRun }],
81
+ onChange: (v) => {
82
+ q.run = v;
83
+ now();
84
+ },
85
+ });
86
+ const levelSel = ui.select({
87
+ options: [
88
+ { value: 'debug', label: S.allLevels },
89
+ { value: 'info', label: 'info+' },
90
+ { value: 'warn', label: 'warn+' },
91
+ { value: 'error', label: 'error' },
92
+ ],
93
+ value: q.level,
94
+ onChange: (v) => {
95
+ q.level = v;
96
+ now();
97
+ },
98
+ });
99
+ const areaIn = ui.input({
100
+ type: 'search',
101
+ cls: 'mono',
102
+ placeholder: S.areaPlaceholder,
103
+ onInput: (v) => {
104
+ q.area = v.trim();
105
+ later();
106
+ },
107
+ onCommit: now,
108
+ });
109
+ const grepIn = ui.input({
110
+ type: 'search',
111
+ placeholder: S.grepPlaceholder,
112
+ onInput: (v) => {
113
+ q.grep = v.trim();
114
+ later();
115
+ },
116
+ onCommit: now,
117
+ });
118
+ const roundIn = ui.input({
119
+ type: 'number',
120
+ cls: 'mono',
121
+ placeholder: S.roundPlaceholder,
122
+ onInput: (v) => {
123
+ q.round = v.trim();
124
+ later();
125
+ },
126
+ onCommit: now,
127
+ });
128
+ const refreshBtn = ui.button(S.refresh, {
129
+ size: 'sm',
130
+ onClick: () => {
131
+ runsLoaded = false;
132
+ now();
133
+ },
134
+ });
135
+ bar.append(
136
+ ui.h('span', 'pagedesc grow', S.runlogDesc),
137
+ runSel,
138
+ levelSel,
139
+ areaIn,
140
+ grepIn,
141
+ ui.field(S.roundField, roundIn),
142
+ refreshBtn,
143
+ );
144
+
145
+ const table = ui.table({
146
+ head: [S.logHeadTime, S.logHeadLevel, S.logHeadArea, S.logHeadMsg],
147
+ maxHeight: 'calc(100vh - 300px)',
148
+ });
149
+ const el = ui.h('div');
150
+ el.append(bar, table.el);
151
+
152
+ const query = (): string => {
153
+ const p = new URLSearchParams({ limit: String(TAIL), level: q.level });
154
+ if (q.run) p.set('run', q.run);
155
+ if (q.area) p.set('area', q.area);
156
+ if (q.grep) p.set('grep', q.grep);
157
+ if (q.round) p.set('round', q.round);
158
+ return `/api/log?${p.toString()}`;
159
+ };
160
+
161
+ /** 重画 run 下拉;已选的 run 还在就保留,否则回到当前 run。 */
162
+ const loadRuns = async (): Promise<void> => {
163
+ const d = await get<RunsReply>('/api/runs', { signal: deps.signal });
164
+ const runs = [...(d?.runs ?? [])].reverse();
165
+ const options = runs.map((r) => {
166
+ const op = ui.h('option', null, r.startedAt ? `${r.run} · ${r.startedAt}` : r.run);
167
+ op.value = r.run;
168
+ return op;
169
+ });
170
+ runSel.replaceChildren(...options);
171
+ const keep = runs.some((r) => r.run === q.run) ? q.run : (d?.current ?? '');
172
+ q.run = runs.some((r) => r.run === keep) ? keep : '';
173
+ runSel.value = q.run;
174
+ runsLoaded = true;
175
+ };
176
+
177
+ /** 正文格:msg,折叠计数,`data` 摘要,err.message 走警示色。 */
178
+ const bodyCell = (en: RunlogEntry): HTMLElement => {
179
+ const box = ui.h('span');
180
+ box.appendChild(ui.h('span', null, en.msg));
181
+ if (en.repeat) box.appendChild(ui.h('span', 'data-extra', ` ×${en.repeat + 1}`));
182
+ if (en.data !== undefined) {
183
+ box.appendChild(ui.h('span', 'data-extra', ` ${truncate(JSON.stringify(en.data), DATA_MAX)}`));
184
+ }
185
+ if (en.err) box.appendChild(ui.h('span', 'lv-error', ` ${en.err.message}`));
186
+ return box;
187
+ };
188
+
189
+ const view: RunlogView = {
190
+ el,
191
+ async refresh() {
192
+ try {
193
+ if (!runsLoaded) await loadRuns();
194
+ const entries = await get<RunlogEntry[]>(query(), { signal: deps.signal });
195
+ const rows = Array.isArray(entries) ? entries : [];
196
+ table.clear(rows.length ? undefined : S.noLog);
197
+ for (const en of rows) {
198
+ table.addRow([
199
+ { text: ui.fmt.clock(en.ts), cls: 'mono' },
200
+ { text: en.level, cls: `lv lv-${en.level}` },
201
+ { text: en.event ? `${en.area}/${en.event}` : en.area, cls: 'mono' },
202
+ { el: bodyCell(en), cls: 'txt' },
203
+ ]);
204
+ }
205
+ deps.onNet(true);
206
+ } catch (err) {
207
+ if ((err as { name?: string } | null)?.name === 'AbortError') return;
208
+ deps.onNet(false);
209
+ deps.onError(err);
210
+ }
211
+ },
212
+ };
213
+ return view;
214
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * 主 session 与 fork 本次运行的 token、缓存统计。数据来自 /ws/debug 的 sessions 帧或 /api/sessions;表格经 ui.table.addRow 写入文本,不将 session label 解析为 HTML。
3
+ */
4
+
5
+ import type { ConsoleUi } from '../../../shared/client-panel.ts';
6
+ import type { SessionStat } from '../live/protocol.ts';
7
+ import { S } from './strings.ts';
8
+
9
+ export interface SessionTable {
10
+ el: HTMLElement;
11
+ render(list: readonly SessionStat[]): void;
12
+ }
13
+
14
+ export function createSessionTable(ui: ConsoleUi): SessionTable {
15
+ const sheet = ui.sheet({
16
+ title: S.sessionsTitle,
17
+ en: 'usage / cache',
18
+ desc: S.sessionsDesc,
19
+ });
20
+ const table = ui.table({
21
+ head: [
22
+ 'session',
23
+ S.sesHeadStatus,
24
+ S.sesHeadCalls,
25
+ S.sesHeadInput,
26
+ S.sesHeadCache,
27
+ S.sesHeadOutput,
28
+ S.sesHeadMsgs,
29
+ ],
30
+ });
31
+ sheet.body.appendChild(table.el);
32
+
33
+ return {
34
+ el: sheet.el,
35
+ render(list) {
36
+ table.clear(list.length ? undefined : S.noSessions);
37
+ for (const s of list) {
38
+ const name = ui.h('span');
39
+ name.appendChild(ui.h('b', null, s.label));
40
+ name.appendChild(ui.h('span', 'data-extra', ` ${s.id}`));
41
+ table.addRow([
42
+ name,
43
+ { text: s.endedAt == null ? S.running : S.ended, cls: 'mono' },
44
+ { text: s.calls, cls: 'mono' },
45
+ { text: ui.fmt.count(s.promptTokens), cls: 'mono' },
46
+ { text: ui.fmt.percent(s.cacheHitRate), cls: 'mono' },
47
+ { text: ui.fmt.count(s.completionTokens), cls: 'mono' },
48
+ { text: s.messageCount, cls: 'mono' },
49
+ ]);
50
+ }
51
+ },
52
+ };
53
+ }