@epoch-agent/infra 0.2.0 → 0.3.2

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.
@@ -249,6 +249,10 @@ web:
249
249
  mkdir_parent_not_absolute: 要在哪儿建必须给一条绝对路径:{parent}
250
250
  mkdir_bad_name: 目录名只能是一段名字,不能带路径分隔符,也不能是 . 或 ..:{name}
251
251
  mkdir_failed: 建不出这个目录:{path}
252
+ pick_prompt: 选一个工作区目录
253
+ pick_unavailable: 这台机器上弹不出系统目录框:它只在服务端和浏览器同机时才开(回环绑定、不是 ssh 起的、平台是 macOS 或 Windows)—— 用逐层浏览那一屏挑
254
+ pick_busy: 已经有一个目录选择框开着了 —— 去把它答掉(它可能被这扇窗口盖住了)
255
+ pick_failed: 系统目录框弹不出来:{detail}
252
256
  plan_mode_unavailable: 这个进程没有 plan 模式(权限层没起来)
253
257
  plan_mode_bad_action: action 必须是 {actions} 之一
254
258
  permission_unavailable: 这个进程没有权限层,档位改不了(它此刻显示的是配置里那一档)
@@ -260,7 +264,7 @@ web:
260
264
  rewind_bad_overwrite: overwrite 必须是一组文件路径(用户逐个确认过的那几个);没有要覆盖的就整个别给这个字段
261
265
  rewind_no_checkpoint: 没有第 {turn} 轮的检查点
262
266
  settings_write_bad_request: 请求体要有 key(设置项的点分路径)、layer({layers} 之一)和 value(字符串 / 数字 / 布尔)
263
- settings_write_unknown_key: 这个键改不了。这条路只写 model maxTurns —— 其余每一项都只有内置默认和用户级两层,写进任何设置文件都不生效
267
+ settings_write_unknown_key: 这个键这样改不了:要么它压根不在可写名单里(比如降级链 —— 它是一条有序的链,不是一个标量),要么这个键只写得进用户级、而请求写的是项目本地。项目级那两层只认 permissions / model / maxTurns,别的键写进去会被启动诊断报成「未知配置项」
264
268
  settings_write_bad_value: 这个值不合这一项的值域(比如 maxTurns 要正整数),没有写进去
265
269
  settings_write_unwritable: '{path} 这份文件这一层认不出它的写法(或者它已经坏了),没有覆盖它 —— 请自己编辑那个文件'
266
270
  settings_write_io: 写 {path} 失败:可能是没有写权限,或者那个目录建不出来
@@ -268,6 +272,8 @@ web:
268
272
  mcp_unknown_server: 这个进程里没有名为「{name}」的 MCP server —— 连接是启动时按 mcp.json 建的,你手上这份清单可能已经旧了,刷新一下再看
269
273
  skill_unknown: 没有名为「{name}」的技能 —— 能力页那份列表可能已经旧了,刷新一下再看
270
274
  provider_unknown: 不支持名为「{name}」的 provider —— 可选的那几家是一份固定清单,你手上这份可能已经旧了,刷新一下再看
275
+ provider_key_not_applicable: '{name} 不用 API key —— 配一把进去也不会有人读它,这家现在就是通的'
276
+ provider_key_empty: 没收到 key —— 把它粘进那个框再保存。(想撤掉已经配好的那把,这一版还没有入口,去 ~/.epoch 或者钥匙串里删)
271
277
  mcp_add_lan_exposed: 这一档下加不了 MCP server —— 服务是用 --host 绑到回环之外的,而我们没法确认发出这一下的浏览器就在这台机器上。加一台等于往 mcp.json 里写一条「启动哪个可执行文件」,而那台当场就会被起起来,往后这台机器上每一次跑 epoch(含 CLI 和 TUI)也都会照着它起。出路两条:到跑着服务的那台机器上直接改那个文件;或者去掉 --host 重启一次。
272
278
  mcp_add_bad_transport: 传输类型只能是 stdio / sse / http
273
279
  mcp_add_bad_name: server 名「{name}」不能用 —— 它会原样变成工具名的一部分,所以只收字母数字开头、由字母数字和 _ - 组成的名字(最长 48)。手写 mcp.json 不受这条管,这条只管从界面加的
@@ -301,6 +307,17 @@ web:
301
307
  reference_store_unavailable: 这台机器上没有会话库(SQLite 没起来),引用不了历史会话
302
308
  file_candidates_no_workspace: 这个会话还没有绑工作区,列不了文件 —— 先在输入框底栏挑一个目录
303
309
  file_list_unavailable: 工作区文件清单列不出来(没有 .git 也不是可读目录),补全用不了 —— 路径手打照样能附上
310
+ file_view_no_workspace: 这个会话还没有绑工作区,看不了文件 —— 先在输入框底栏挑一个目录
311
+ file_view_missing_path: 没说要看哪个文件(缺 path)
312
+ file_view_denied: 这个文件不在工作区里,或者被权限规则拦住了 —— 模型读不到的文件,这儿也看不到
313
+ file_view_missing: 这个文件现在不在那儿了
314
+ file_view_not_a_file: 这是一个目录,不是文件
315
+ file_view_unreadable: 这个文件读不出来(权限位、正在被写、或者盘出了问题)
316
+ file_view_too_large: 这个文件太大,站内看不了(上限 {max} 字节)—— 用默认应用打开,或者下载下来看
317
+ file_view_not_text: 这不是文本文件,取不到正文 —— 图片 / PDF / 媒体走字节那条路
318
+ file_open_extension_not_allowed: 这种文件不交给系统应用打开 —— 代码和文本站内就能看,而压缩包「打开」等于解压
319
+ file_open_not_same_machine: 这个浏览器不在服务那台机器上,打开了窗口也弹在别人屏幕上
320
+ file_open_launch_failed: 系统应用没起来
304
321
  ui:
305
322
  conn:
306
323
  connecting: 连接中
@@ -325,32 +342,51 @@ web:
325
342
  rej_context: 上下文已用 {used},超过 {model} 的窗口({window})。先开一段新会话,或者换个窗口更大的模型
326
343
  cav_context_tight: 换过去了,但上下文已用 {used},接近 {model} 的窗口({window}),可能撑不过几轮
327
344
  cav_no_tools: 换过去了,但 {model} 不支持工具调用 —— 它只能聊天,读不了也写不了文件
328
- pick_provider: Provider
345
+ pick_provider: 提供商
329
346
  pick_provider_none: 挑一家…
347
+ pick_model: 模型名称
348
+ suggest_open: 看看探到了哪些模型
330
349
  provider_no_key: '{label}(没配 key)'
331
350
  probe_probing: 正在问 {provider} 有哪些模型…不用等,上面直接敲一个也行
332
351
  probe_no_key: '{provider} 还没配 key,问不了它的模型清单。设一个 {env},或者跑 epoch model 配一把'
333
352
  probe_no_key_bare: '{provider} 还没配 key,问不了它的模型清单。跑 epoch model 配一把'
353
+ probe_no_key_here: '{provider} 还没配 key,问不了它的模型清单 —— 上面那个 API Key 框填一把就行'
354
+ key_goto: 去设置页配
334
355
  probe_failed_cache: 没问通 {provider}(网络 / key 不对 / 那个地址没有 /models)。下面是上次探到的那一份,可能已经过期 —— 也可以直接敲
335
356
  probe_failed_static: 没问通 {provider}(网络 / key 不对 / 那个地址没有 /models)。下面是内置的那一份,可能已经过期 —— 也可以直接敲
336
357
  probe_empty: '{provider} 一个模型名都没给出来,内置清单里也是空的 —— 直接敲一个吧'
337
358
  probe_ok: 从 {provider} 问到 {count} 个
338
- suggest_note: 下面这些是探到的建议,不是全部 —— 新模型、自建的多半不在里面,照旧直接敲
359
+ suggest_note: 这些是探到的建议,不是全部 —— 新模型、自建的多半不在里面,照旧直接敲
339
360
  refresh: 重新探
340
361
  refresh_hint: 绕开缓存,重新问一次这家 provider
362
+ key_label: API Key
363
+ key_placeholder: 粘一把 key 进来
364
+ key_save: 保存 Key
365
+ key_saving: 存 Key…
366
+ key_show: 显示
367
+ key_hide: 隐藏
368
+ key_has: 已配置 {hint}({env})。存一把新的会盖掉它
369
+ key_none: 这把 key 优先进系统钥匙串;拿不到钥匙串才落 ~/.epoch/.env(0600)。写进去的是 {env}
370
+ key_saved_secure: 已存进 {backend}(加密)。模型清单已经用新 key 重新问过一遍了
371
+ key_saved_plain: ⚠️ 系统钥匙串用不了,这把 key 以明文存在了 {path}(权限 0600)。同机器上能读到这个文件的人就能拿到它
341
372
  newsession:
342
373
  open: 新建会话
343
374
  dirpick:
344
375
  back: 返回
345
376
  anchors: 常去的地方
377
+ anchors_detail: 主目录、服务进程的启动目录、以及来过的工作区
346
378
  up: 往上一层
379
+ back_last: 回到刚才那一层
347
380
  loading: 读取中…
348
381
  empty: 这一层没有子目录 —— 可以直接挑它,或者在下面敲一条路径
349
382
  omitted: 这一层还有 {count} 个没列出来(一层最多列 1000 个)—— 要那些的话在下面敲路径
350
383
  show_hidden: 显示隐藏目录(. 开头的)
351
384
  show_hidden_count: 显示隐藏目录(. 开头的,这一层有 {count} 个)
352
385
  unreadable: 没权限进这个目录:{path}
353
- into: 进入 {name}
386
+ into_of: 进入 {name}({path})
387
+ use: 就用 {name}
388
+ use_here: 就选这一层
389
+ use_here_of: 就选这一层:{path}
354
390
  known: 来过
355
391
  manual_label: 或者直接敲一条绝对路径
356
392
  manual_hint: 例如 /Users/you/work/repo
@@ -363,14 +399,10 @@ web:
363
399
  title: 今天想做点什么?
364
400
  sidebar:
365
401
  search: 搜索会话
366
- capability: 身份 · 技能 · 连接器
367
- plugins: 插件
368
402
  automation: 自动化
369
403
  automation_pending: 有 {count} 条定时任务欠着授权,到点了会再卡一次
370
404
  settings: 设置
371
- session: 会话
372
- usage_session: 本会话用量
373
- usage_run: 最近一轮用量
405
+ host_menu: 宿主菜单
374
406
  cost: 花费
375
407
  cost_of: 约 ${spent} / ${limit}
376
408
  cost_est: 估算
@@ -386,6 +418,7 @@ web:
386
418
  running: 进行中
387
419
  updated_at: 最近活动
388
420
  count: '{count} 条会话'
421
+ new_in_space: 在「{name}」里开一段新会话
389
422
  empty: 还没有会话
390
423
  no_match: 没有匹配的会话
391
424
  acts: 会话「{title}」的操作
@@ -457,6 +490,18 @@ web:
457
490
  clip_lines: 只显示了前 {shown} 行,这个文件一共 {total} 行。
458
491
  clip_chars: 在第 {line} 行上截断了 —— 这一行太长。这个文件一共 {total} 行。
459
492
  binary_note: 这类文件这儿看不了,用系统自带的程序打开。
493
+ file:
494
+ loading: 正在打开…
495
+ denied: 这个文件不在工作区里,或者被权限规则拦住了 —— 模型读不到的文件,这儿也看不到。
496
+ missing: 这个文件现在不在那儿了。
497
+ not_a_file: 这是一个目录,不是文件。
498
+ too_large: 这个文件太大,站内看不了。
499
+ unreadable: 这个文件读不出来。
500
+ no_answer: 服务端没有回答这条路径。
501
+ no_session: 还没有会话,看不了文件。
502
+ opaque: 这种文件浏览器画不出来。用你机器上的默认应用打开,或者下载下来看。
503
+ open_with_app: 用默认应用打开
504
+ download: 下载
460
505
  plan:
461
506
  empty: 这个会话还没有被批准的计划
462
507
  empty_hint: 模型交上来的计划要你在输入区那块板上批一次;批过的那一份才会留在这儿。
@@ -506,7 +551,7 @@ web:
506
551
  dismiss: 知道了
507
552
  session_gone: 这段对话在服务端上已经没有了 —— 多半是服务端重启过,重启会换一个新会话。这一段回不来了,不过新的那个可以接着用。
508
553
  session_gone_open: 去当前会话
509
- session_gone_stuck: 这段对话在服务端上已经没有了,而且现在连「还有哪个会话能用」都问不出来 —— 多半是服务端进程已经停了。回终端看一眼它还在不在。
554
+ session_gone_stuck: 这段对话在服务端上已经没有了。
510
555
  thread:
511
556
  thinking_label: 深度思考
512
557
  head_estimate: 预计 {tokens} token
@@ -539,6 +584,8 @@ web:
539
584
  art_no_file: 没能落盘 —— 这个产物打不开。
540
585
  art_download: 下载 {name}
541
586
  art_download_any: 下载这个产物
587
+ user_image_alt: 这条消息附的图片({mediaType})
588
+ user_image_alt_any: 这条消息附的图片
542
589
  expand: 展开剩余 {count} 行
543
590
  collapse: 收起
544
591
  todo_title: 交付清单
@@ -622,6 +669,7 @@ web:
622
669
  fact_detail: 详情
623
670
  fact_reason: 原因
624
671
  target_none: (无)
672
+ more_lines: ↓ 还有 {count} 行没显示
625
673
  allow_once: 允许一次
626
674
  allow_session: 本会话内始终允许
627
675
  allow_session_hint: 退出即失效
@@ -662,6 +710,7 @@ web:
662
710
  stalled: 《{title}》原地打转,已经停下
663
711
  aborted: 《{title}》被中止了
664
712
  filtered: 《{title}》被模型拒答了
713
+ compliance: 《{title}》触了内容合规限制
665
714
  budget: 《{title}》触了预算上限,提前收工
666
715
  failed: 《{title}》出错了
667
716
  go: 查看
@@ -686,6 +735,9 @@ web:
686
735
  placeholder_gone: 这段对话在服务端上已经没有了,发不出去
687
736
  hint_queue: 排队发送
688
737
  send: 发送
738
+ usage_session: 本会话
739
+ usage_run: 最近一轮
740
+ usage_detail: '{scope}用量:{up}↑ {down}↓'
689
741
  commands_label: 斜杠命令
690
742
  command_warnings: /{name} 展开时有几处要说明:
691
743
  builtin_notice: /{name}
@@ -705,7 +757,8 @@ web:
705
757
  workspace_pick_note: 清单是本机最近用过的那几个目录。要在一个没来过的目录里开会话,先在那儿跑一次 epoch。
706
758
  workspace_browse: 打开本地文件夹…
707
759
  workspace_browse_detail: 逐层挑一个目录,或者直接敲一条绝对路径(列的是跑 epoch 那台机器上的目录)
708
- permission: 权限 {level}
760
+ workspace_browse_native: 弹一个系统对话框来挑(跑 epoch 那台机器上的)
761
+ permission: 权限:{level}
709
762
  plan_mode: 计划模式
710
763
  plan_on_hint: 进计划模式:模型先只读地调研、交一份计划给你批,期间不动文件
711
764
  plan_off_hint: 退出计划模式,回到进入前那一档权限
@@ -757,6 +810,10 @@ web:
757
810
  lvl_bypass: 跳过全部检查
758
811
  lvl_bypass_detail: 什么都不问,整条导轨会变红
759
812
  blocked_managed: 这台机器装了企业托管设置,「跳过全部检查」那一档被它关掉了。详情见「设置 › 安全中心」
813
+ keep_env_pinned: 这一档只对当前这次有效:环境变量 EPOCH_PERMISSION 压着它,下次启动还是按那个来
814
+ keep_unwritable: 这一档只对当前这次有效:配置文件的写法这条路认不出来,没敢改它
815
+ keep_io: 这一档只对当前这次有效:配置文件没写成(盘是只读的,或者没有权限)
816
+ keep_no_config: 这一档只对当前这次有效:这个进程说不出用户配置文件在哪儿
760
817
  fatal:
761
818
  unauthorized: 没有访问凭据
762
819
  unauthorized_hint: 回到起 epoch web 的那个终端,用它打印的那条带 token 的地址重新打开。
@@ -768,6 +825,7 @@ web:
768
825
  pane_model: 模型与 Provider
769
826
  pane_memory: 记忆与上下文
770
827
  pane_spend: 用量与花费
828
+ history_only: 这段会话只剩历史,引擎还没装起来 —— 点开一段旧会话只回放对话,装引擎要等你发下一条消息。这一屏问的是那台引擎此刻的状态,所以现在没有东西可看:回到会话里发一条,它会自己接回来。
771
829
  pane_budget: 预算
772
830
  pane_tools: 工具
773
831
  pane_about: 关于
@@ -793,8 +851,6 @@ web:
793
851
  none_recorded: 这段对话跑过,但每一轮的账没有被记下来(这段会话早于记账那一次改动)。这些数字不会自己回来。
794
852
  g_total: 合计
795
853
  g_turns: 逐轮
796
- total: 这 {turns} 轮一共 {tokens} token,约 {cost}。
797
- total_tokens: 这 {turns} 轮一共 {tokens} token。
798
854
  total_unmeasured: 这段会话跑了 {turns} 轮,但一轮的用量都没报上来,所以连 token 总数也没有。
799
855
  partial: 上面这个金额只是其中 {priced} 轮的和 —— 另外 {unpriced} 轮报了用量,但那些轮用的模型查不到单价。下面那张表里费用那一格空着的就是它们。
800
856
  unknown: 金额说不上来,不是没花钱:这几轮用的模型在这台机器上查不到单价,花了多少只有 provider 那一边知道。
@@ -820,6 +876,7 @@ web:
820
876
  why: 为什么是这个值
821
877
  chain_win: 生效
822
878
  g_other: 其它
879
+ overridable_sum: 哪些键能被上层压过
823
880
  overridable: 只有这几个键能被项目级 / 项目本地 / 命令行 / 企业托管压过去:{keys}。其余每一项都只有内置默认和用户级两层 —— 写进 .epoch/settings.json 也不会生效,启动诊断里会报一条「未知配置项」。
824
881
  overridable_perm: 名单里的 permissions 是三张列表(allow / ask / deny),合并时取并集而不是高层覆盖,所以它的来源标注是逐条的 —— 在「安全中心 › 权限规则」那一节。
825
882
  managed_locked: 这一项由这台机器上的企业托管设置定,改用户级或项目级都不会生效。那份文件普通用户写不了,要改得找管理员。
@@ -828,12 +885,13 @@ web:
828
885
  save: 保存
829
886
  new_value: 新的值
830
887
  write_layer: 写进
888
+ write_file: 写进文件
831
889
  dirty: 未保存
832
890
  futile_shadowed: 写进{layer}也不会生效:{by}也写了这一项,它排在更上面,加载时会把你写的这个压回去。要让它生效,请改写{by}或更高的层。
833
891
  futile_untrusted: 这个工作区还没被信任,{layer}里的设置在加载时会被整份丢掉(只有 deny 规则例外),所以写进去等于没写。先在「安全中心 › 工作区与信任」里信任这个目录,或者改写用户级 —— 用户级不过信任闸门。
834
892
  wrote: 已写进{layer}:{value}
835
893
  wrote_stale: 这个进程启动时读过一次配置就不再重读,所以它现在用的仍然是 {value} —— 重启 epoch web 之后才会换成刚写的那个值。新开一个会话也不行,配置是整个进程一份。
836
- lede_model: 这个进程此刻在用的模型和 provider。要改:编辑 ~/.epoch/config.yaml,或者跑 epoch model
894
+ lede_model: 这个进程此刻在用的模型。改这里的行会写进 ~/.epoch/config.yaml。provider 和 API key 不在这一屏上 —— 那两样跑 epoch model 配。
837
895
  k_model: 主模型
838
896
  k_models_utility: 副模型
839
897
  h_models_utility: 压缩上下文、生成会话标题这类杂活用它。没配就一律走主模型。
@@ -841,7 +899,7 @@ web:
841
899
  k_fallback_providers: 降级链
842
900
  h_fallback_providers: 主 provider 连不上时按这个顺序往下试。
843
901
  lede_memory: 前两项决定一轮能装多少、能跑多少步;后两项决定装不下的时候怎么办。上下文窗口填大于模型真实上限的值只会换来一次 400。
844
- k_context_length: 上下文窗口
902
+ k_context_length: 上下文窗口(token)
845
903
  h_context_length: 只在模型元数据查不到时才用这个值兜底;查得到就以元数据为准,填了也不生效。下面那条压缩线算的是引擎真在用的那个窗口。
846
904
  k_max_turns: 单轮最多几步
847
905
  h_max_turns: 一轮里模型最多调用几次工具。到顶就停下来把话说完。
@@ -852,8 +910,7 @@ web:
852
910
  ctx_line: 这份配置下,提示词涨到 {tokens} token 时开始压缩 —— 上下文窗口 {window} 的 {percent}%。
853
911
  ctx_line_caveat: 这是那条线本身。刚压过不久、或者连着几次压缩都失败时,跨线了也会先不压。
854
912
  ctx_off: 自动压缩已关掉。长会话撞到上下文窗口上限时没有任何自动补救 —— 那一轮会直接失败,而且上下文不会自己变短。手动的 /compact 不受这个开关影响,仍然能用。
855
- ctx_no_switch: 这两行在界面上改不了,和上面两行一样:能被项目级配置覆盖的键只有那三个(下面那份名单),压缩不在里面 —— 否则一个仓库就能让你在它里面开的长会话悄悄撞满窗口。改它要自己写 ~/.epoch/config.yaml:
856
- ctx_restart: 改完要重启 epoch web 那个进程才生效 —— 这个进程装配时读过一次配置就不再重读。
913
+ ctx_not_overridable: 这两行只写得进用户级:能被项目级配置覆盖的键只有那三个(下面那份名单),压缩不在里面 —— 否则一个仓库就能让你在它里面开的长会话悄悄撞满窗口。
857
914
  budget_title: 此刻花在哪儿了
858
915
  budget_used: 已用 {used},占 {limit} 窗口的 {percent}%。
859
916
  budget_used_only: 已用 {used}。这个模型的上下文窗口查不到,所以说不出占了几成。
@@ -863,13 +920,21 @@ web:
863
920
  budget_compacting: 正在压缩…
864
921
  budget_compact_hint: 把早期消息重写成一份摘要,给接下来的对话腾出窗口。要发一次模型请求(花钱),但这段对话的记录一行都不会少 —— 变的只是下一轮送进模型的那一份。
865
922
  lede_budget: 金额只在配了上限之后才出现在界面上。没配上限时这几行都是「未设置」,那也是默认状态。
866
- k_budget_max_cost: 花费上限
923
+ k_budget_max_cost: 花费上限(美元)
924
+ h_budget_max_cost: 按会话累计,不是单次请求的上限 —— 断了用 --resume 回来接着算。到线的那一轮不会先花掉再报:闸门在发下一发请求之前就拦。
867
925
  k_budget_max_tokens: Token 上限
868
926
  h_budget_max_tokens: 两把尺子都配了的话,闸门报更紧的那一份。
869
927
  k_budget_warn_at: 用到几成时提醒
870
928
  h_budget_warn_at: 百分比。只在跨线那一次提醒,不每轮刷屏。
871
929
  k_budget_unknown_pricing: 模型没有定价数据时
872
930
  h_budget_unknown_pricing: block 是直接拦下,warn 是告警放行。没有定价数据时花费是「不知道」而不是 0,两者必须分开处理。
931
+ ex_budget_max_cost: 例如 5
932
+ ex_budget_max_tokens: 例如 1000000
933
+ ex_budget_warn_at: 例如 80
934
+ blocked_empty: 这一格不能空着。清空不等于把这个配置项删掉 —— 这条路上没有删键这回事;要让它回到默认值,去上面那个文件里把这一行删掉。
935
+ blocked_pick: 上面那排里挑一个。
936
+ blocked_number: 这一格要一个数,「{text}」读不出数来。别带单位、别带千分位的逗号。
937
+ blocked_boolean: 这一格只认 true 和 false 两个词 —— 它们是要写进 yaml 的那两个字面量。
873
938
  sec:
874
939
  lede: 这个 agent 现在能碰什么、谁在管着它。
875
940
  no_session: 还没有会话。安全状态里有三样东西按会话绑:工作区、它的信任判定、以及跟着信任走的项目级策略目录 —— 没有会话就没有「哪一个」可说。
@@ -993,7 +1058,7 @@ web:
993
1058
  audit_code_headless_unauthorized: 非交互,未预授权
994
1059
  audit_code_user_approved: 你批准了
995
1060
  audit_code_user_denied: 你拒绝了
996
- perm_where: 上面这一档在输入框那一行改,立刻生效;下面那一档是新会话的起点,改 ~/.epoch/config.yaml 后重启。
1061
+ perm_where: 两档都在输入框那一行改:换一次立刻生效,同时记成下面这个起点(写进 ~/.epoch/config.yaml),新会话和下次启动都从它开始。
997
1062
  perm_now: 此刻
998
1063
  perm_default: 默认
999
1064
  perm_now_changed: (本会话改过)
@@ -1065,7 +1130,7 @@ web:
1065
1130
  skill_unindexed: 未进索引
1066
1131
  skills_capped_note: 有 {count} 条被 `skills.maxIndexed` 截在索引外:它们不占每一轮的上下文,模型也列不出它们。那一格调大或者去掉就能恢复。
1067
1132
  skills_role_note: 有 {count} 条不在这段会话身份的技能白名单里,所以没进索引。⚠️ 那不是一把锁:正文照旧读得到 —— 收窄的是上下文预算,不是可达性。
1068
- no_toggle: 没有「关掉一个技能」这个开关:只要文件在目录里,它就会被扫到。不想要它,把那个目录挪走;只是想省上下文的话,`skills.maxIndexed` 能给索引封顶。
1133
+ no_toggle: 没有「关掉一个技能」这个开关:只要文件在目录里,它就会被扫到。不想要它,用行尾那个「删除」把它连目录一起删掉(拿不回来);只是想省上下文的话,`skills.maxIndexed` 能给索引封顶。
1069
1134
  import_entry: 导入技能
1070
1135
  import_title: 导入技能
1071
1136
  import_lede: 从这台跑着服务的机器上导入。接受一个含 SKILL.md 的文件夹、一棵「分类/名字」两层的技能树、一个打包好的 .zip,或者单独一份带 frontmatter 的 .md。
@@ -1096,13 +1161,42 @@ web:
1096
1161
  skill_view_no_count: 看一眼不会影响它的评分 —— 那本账只记模型真的用过它的次数。
1097
1162
  skill_truncated: 这份 SKILL.md 太大(一共 {bytes} 字节),下面只是开头那一截。要读全的话直接打开那个文件。
1098
1163
  skill_bytes: 一共 {bytes} 字节
1164
+ skill_remove: 删除
1165
+ skill_remove_ask: 删掉 {name}?连它整个目录一起,删了拿不回来。
1166
+ skill_remove_yes: 删除
1167
+ skill_cancel: 取消
1168
+ skill_removed: 已经删掉 {name}。刚刚被删掉的是这个目录:
1099
1169
  plugins: 插件
1100
- plug_lede: 一个插件是一包扩展物:斜杠命令、身份、技能、hook、deny 规则、MCP server。从这台机器上已加的市场里挑一个装下来 —— 这一页只能从那张单子里挑,指不了路径也传不了文件。
1170
+ plug_lede: 一个插件是一包扩展物:斜杠命令、身份、技能、hook、deny 规则、MCP server,包里还能带任意语言的脚本。装它有两条路:从已加的市场里挑一条,或者指一个本机上的插件目录(那一档只是建一条软链)。传文件传不了。
1101
1171
  plug_installed_head: 装着的({count})
1102
1172
  plug_installed_empty: 一个插件都没装。
1103
1173
  plug_market_head: 市场里有什么({count})
1104
- plug_market_empty: 已加的市场里一个插件都没有。加一个市场要在命令行上:epoch plugin marketplace add <地址>
1174
+ plug_market_empty: 已加的市场里一个插件都没有 —— 市场是加上了,只是那份目录里没东西。
1175
+ plug_market_none_added: 还没加过任何插件市场。按上面那个「添加」,或者指一个本机上的插件目录直接装。
1105
1176
  plug_no_desc: (这一条在市场目录里没写说明)
1177
+ plug_add: 添加
1178
+ plug_add_title: 添加插件
1179
+ plug_add_back: 回到插件列表
1180
+ plug_add_tab_local: 本地目录
1181
+ plug_add_tab_market: 市场
1182
+ plug_add_hint_local: 这是跑着这个服务的那台机器上的路径,不是你这台电脑上的。要绝对路径(/ 开头),指向一个插件目录 —— 里面得有 epoch-plugin.json。装它只是建一条软链:改源码、重启一次就生效。
1183
+ plug_add_path_placeholder: /home/you/dev/my-toolkit
1184
+ plug_add_path_label: 插件目录的绝对路径
1185
+ plug_add_look: 看看会装什么
1186
+ plug_add_browse: 浏览…
1187
+ plug_add_browse_off: 收起
1188
+ plug_add_pick_here: 选这一层
1189
+ plug_market_lede: 市场是一份插件目录(一份 JSON)。加它不装任何东西 —— 加完之后回列表那一屏挑要装哪一条,那条路上的安装前预览一点没变。
1190
+ plug_market_placeholder: /srv/market 或 github:acme/market
1191
+ plug_market_label: 市场地址
1192
+ plug_market_add: 添加市场
1193
+ plug_market_add_failed: 这个市场加不进来
1194
+ plug_market_none: 一个市场都没加。
1195
+ plug_market_entries: '{count} 条'
1196
+ plug_market_remove: 移除
1197
+ plug_market_remove_ask: 移除它?从它装的插件照旧留着,只是以后在这儿挑不到新的了。
1198
+ plug_market_remove_yes: 移除
1199
+ plug_market_remove_failed: 移除不了
1106
1200
  plug_restart: 这一程动过插件,那些改动还没生效
1107
1201
  plug_restart_why: 扩展物是在启动时加载的,所以刚装 / 更新 / 卸载的那些要下一程才算数 —— 这一程的命令表、hook、身份表一个字都没变。要它们生效:重启跑着这个界面的那个服务(终端里 Ctrl+C,再跑一次 epoch web)。如果这个界面是嵌在别的程序里的,那次重建只有那个程序做得到 —— 这一页上没有、也不会有一个「立即生效」的按钮。
1108
1202
  plug_state_active: 已生效
@@ -1297,6 +1391,9 @@ web:
1297
1391
  how_to_block: 要挡住一个工具,就在权限规则表里加一条 deny。规则写进配置文件才算数,这个界面从头到尾不改配置 —— 安全中心那一屏能告诉你现在有哪些规则、各是哪一层加的。
1298
1392
  goto_rules: 去看规则表
1299
1393
  mcp_note: MCP 服务器带来的工具也在这张表里,名字长这样:mcp__<服务器名>__<工具名>。「来源」那一列写着它是从哪台服务器来的。
1394
+ tip:
1395
+ what: 说明
1396
+ about: '{name} 的说明'
1300
1397
  about:
1301
1398
  loading: 正在读…
1302
1399
  lede: 出问题时把这一屏截下来贴进 issue,比描述现象快。
@@ -1419,15 +1516,26 @@ web:
1419
1516
  remove_confirm: 删掉「{name}」?系统调度器里那条注册会一起撤掉。运行录像留着。
1420
1517
  form_new: 新建定时任务
1421
1518
  form_edit: 编辑定时任务
1519
+ g_what: 做什么
1520
+ g_what_note: 到点了让它干的那件事
1521
+ g_where: 在哪儿跑
1522
+ g_where_note: 不填也能跑,各有一个确定的缺省
1523
+ g_when: 什么时候跑
1524
+ g_may: 能做什么
1525
+ g_may_note: 这一组决定它半夜替你按下哪些「确认」
1526
+ g_cost: 花多少
1527
+ g_cost_note: 三把尺子,任何一把到顶都停
1528
+ required: 必填
1422
1529
  f_name: 名称
1423
1530
  f_prompt: 提示词
1424
1531
  f_prompt_hint: 到点了让 agent 做什么。写清楚做完要留下什么 —— 没人在旁边追问。
1425
1532
  f_workdir: 工作空间(可选)
1426
- f_workdir_hint: 服务端的绝对路径
1427
- f_workdir_note: 不填就跑在 ~/.epoch/automation/<任务 id>/ 里。它**不会**继承任何一个终端的当前目录。
1533
+ f_workdir_note: 不填就跑在 ~/.epoch/automation/<任务 id>/ 里。任何一个终端的当前目录它都不会继承。
1428
1534
  f_workdir_default: ~/.epoch/automation/<任务 id>/
1535
+ f_workdir_none: 不指定工作空间
1429
1536
  f_model: 模型(可选)
1430
1537
  f_model_hint: 不填就用配置里那个
1538
+ f_model_provider_note: 挑了哪一家就记进这条任务,到点按它跑。⚠️ 到点时这台机器上这一家要是没配 key,它会退回默认模型接着跑,并在运行记录里记一条。
1431
1539
  f_kind: 执行频率
1432
1540
  k_daily: 每天
1433
1541
  k_weekly: 每周
@@ -1443,11 +1551,14 @@ web:
1443
1551
  f_days_note: 31 号在小月不触发 —— 两个平台的原生行为都是这样。
1444
1552
  f_start: 生效开始(可选)
1445
1553
  f_end: 生效结束(可选)
1554
+ f_window_note: 两头都算在内。哪一头不填就是那一头不限。到点了但不在区间里的那几次会记成「跳过(不在生效区间)」,不会补跑。
1555
+ f_window_once: 只跑一次的任务不能带生效区间 —— 它自己就是一个日期,所以这两格在这一档下填不了。
1446
1556
  f_permission: 权限档
1447
1557
  f_bypass_ack: 我明白:这个任务将在 {workDir} 里不经确认地做任何事,包括删文件和跑任意命令。
1448
1558
  f_turns: 最多轮次
1559
+ f_turns_hint: 一轮里模型最多调用几次工具,1 到 1000。到顶就停下来把话说完。
1449
1560
  f_timeout: 超时(分钟)
1450
- f_timeout_note: 唯一能拦住「一条命令挂住了」的那把尺子。
1561
+ f_timeout_note: 唯一能拦住「一条命令挂住了」的那把尺子。最多 24 小时。
1451
1562
  f_budget: 这一次最多花多少(美元)
1452
1563
  f_budget_why: 必填,而且我们不给默认值:这个任务没人看着,一个假默认会让「一觉醒来 40 美元」变成我们的错。
1453
1564
  save_and_run: 保存并先跑一次
@@ -1797,6 +1908,8 @@ skill:
1797
1908
  import_bad_name_dots: 技能名不能是 . 或 ..
1798
1909
  import_bad_name_char: '技能名「{name}」里有不能当目录名的字符(< > : " / \ | ? * 和控制字符)。其中冒号是插件 / 宿主技能的前缀分隔符,用户级技能占用它会冒充成插件技能'
1799
1910
  import_bad_name_trailing: 技能名「{name}」以点或空格结尾 —— Windows 上这样的目录建得出来却打不开
1911
+ remove_no_system: 技能系统这次没起来 —— 没有一份技能在这个进程里,也就没有能删的。看一眼启动诊断里 Skill 那几条
1912
+ remove_unknown: 没有叫「{name}」的技能 —— 手上这份清单可能已经旧了,刷新一下
1800
1913
  host_capabilities:
1801
1914
  loaded: '{namespace}:身份 {roles} 个、技能目录 {skillDirs} 个、MCP server {mcpServers} 台、工具 {tools} 个(前两样的名字加 {namespace}: 前缀,后两样加 {namespace}__ —— 它们要进工具名,而工具名里不能有冒号)'
1802
1915
  bad_role_name: 身份 "{name}" 的名字不合法(只允许小写字母、数字、连字符,且不能以连字符开头),这一条已跳过;其余照常注入
@@ -1931,6 +2044,7 @@ mcp_write:
1931
2044
  invalid: 配置无效
1932
2045
  mcp_config:
1933
2046
  invalid_json: 一个字节都没写 —— 这份内容不是合法的 JSON:{why}
2047
+ stale_disk: 一个字节都没写 —— 算这次改动的时候 ~/.epoch/mcp.json 被别人动过了;重新读一遍再改
1934
2048
  role_write:
1935
2049
  bad_name: 身份名「{name}」不能用 —— 只允许小写字母、数字和连字符,而且不能以连字符开头。这个名字同时是文件名和派活时用的那个词(delegate_task 的 role、--agent 的取值),所以收得严
1936
2050
  taken: 已经有一个叫「{name}」的身份了 —— 换个名字。这里不覆盖也不自动改名:覆盖要删掉那份文件里你自己写的正文,改名会让派活时用的那个词和你敲进去的对不上
@@ -1953,7 +2067,11 @@ plugin_control:
1953
2067
  market_remote_off: '宿主预置的市场 {source} 是远程地址(取目录要发一次 HTTP),而远程档默认关着,这一条已跳过;本地目录那些不受影响。要放开就在 buildRuntime 的 hostMarketplaces 上给 allowRemote: true'
1954
2068
  market_failed: 宿主预置的市场 {source} 没接上:{reason}。这一条已跳过,其余照常
1955
2069
  market_ready: 已预置市场 {name}({count} 个插件可选)
1956
- not_a_ref: '"{ref}" 不是一个市场引用(形状是 <市场>/<插件>,epoch plugin search 能看到有哪些)。这条路**只能从已加的市场清单里挑**,指不了任意路径 —— 要装清单外的东西请用命令行的 epoch plugin install'
2070
+ not_a_ref: '"{ref}" 不是一个市场引用(形状是 <市场>/<插件>,epoch plugin search 能看到有哪些)。这条路**只能从已加的市场清单里挑** —— 装本机上一个目录走「本地目录」那条,装清单外的远程东西请用命令行的 epoch plugin install'
2071
+ not_local_path: '"{path}" 不是一条本地绝对路径。这条路只收本机上一个插件目录(装它就是建一条软链),收不了 github: / npm: / 压缩包地址 —— 那些要么从市场装,要么用命令行的 epoch plugin install。相对路径也不收:它会按跑着这个服务的那个进程的工作目录展开,而那多半不是你以为的地方'
2072
+ market_source_empty: '市场地址是空的。填一条本地路径 / 目录,或者一个 github: / https:// 地址'
2073
+ market_add_remote_off: '{source} 是远程市场地址(取它的目录要发一次 HTTP),而远程档默认关着。本地路径那些不受影响;要放开远程就在 buildRuntime 的 hostMarketplaces 上给 allowRemote: true'
2074
+ market_missing: 没加过市场 {name}
1957
2075
  entry_remote_off: '{ref} 的来源是 {source},装它要 git clone / 下载解压,而远程档默认关着(本地目录那档只是建一条软链,风险不是同一个量级)。要放开就在 buildRuntime 的 hostMarketplaces 上给 allowRemote: true'
1958
2076
  update_remote_off: '{name} 装自 {source},更新它要重新 git clone / 下载,而远程档默认关着。要放开就在 buildRuntime 的 hostMarketplaces 上给 allowRemote: true'
1959
2077
  linked_no_update: '{name} 是本地软链({source}),源码目录改了重建一次就生效,没有可更新的东西'
@@ -2069,6 +2187,7 @@ provider:
2069
2187
  label_openai_compatible: OpenAI Compatible(通用适配)
2070
2188
  response_format_with_tools: 同一次请求不能既要 tools 又要 responseFormat:模型要么调工具、要么出一段 JSON,只能挑一样
2071
2189
  response_format_dropped: '{model} 没有接住这一轮的强制 JSON 约束(请求照常发出了),这一轮的输出可能不是 JSON'
2190
+ key_not_applicable: '{provider} 不用 API key,配了也不会被读到'
2072
2191
  utility:
2073
2192
  aborted: 这一次一次性补全在发出之前被中止了(未发送,未计费)
2074
2193
  terminal_setup:
@@ -3121,6 +3240,7 @@ untrusted:
3121
3240
  skipped: 工作区不受信任,项目{what}未加载(epoch trust 可信任当前目录)
3122
3241
  what_commands: 命令
3123
3242
  what_policy: 策略规则
3243
+ what_compliance: 合规词库
3124
3244
  what_skills: 技能
3125
3245
  what_roles: 角色
3126
3246
  hooks_tail: 工作区不受信任,项目 hook 未加载(epoch trust 可信任当前目录)—— hook 会执行命令,这里没有「只收紧的那部分照样生效」的例外
@@ -3166,6 +3286,7 @@ hook_load:
3166
3286
  bad_event: 不是合法的 hook 事件名,已忽略。可用:{types}
3167
3287
  not_array: 期望数组(每个元素一条 hook),已忽略整个事件
3168
3288
  entry_skipped: '{message};该 hook 已跳过'
3289
+ no_plugin_root: 用到了 ${EPOCH_PLUGIN_ROOT},但这一份不是插件带来的配置,我们给不出插件根 —— 那个占位符原样留着,路径多半指不到地方
3169
3290
  rejected: Hook 拒绝了操作
3170
3291
  rejected_this: Hook 拒绝了此操作
3171
3292
  timeout: Command hook 超时
@@ -3177,6 +3298,40 @@ policy_load:
3177
3298
  not_kv: 既不是 [[rule]] 也不是 key = "value",已忽略:{preview}
3178
3299
  before_first_rule: '{key} 出现在第一个 [[rule]] 之前,已忽略'
3179
3300
  rule_skipped: '{message};该规则已跳过'
3301
+ compliance_cmd:
3302
+ cmd_root: 内容合规闸门的自检
3303
+ cmd_check: 判一段文本会不会被拦,命中的是哪几个字
3304
+ cmd_status: 这台机器上这层现在什么状态(开关 / 条数 / 各类别档位)
3305
+ arg_text: 要判的文本
3306
+ opt_stdin: 从标准输入读(判一整个文件时用)
3307
+ need_text: 要判什么?给一段文本,或者加 --stdin 从标准输入读
3308
+ disabled: '内容合规没启用(compliance.enabled: false),这一段不会被判'
3309
+ clean: 干净:一条都没命中
3310
+ verdict: 判定:{action},命中 {count} 条
3311
+ hit: ' [{category}] {action} ← {excerpt}(规则 {rule})'
3312
+ blocked: 这一档是 block:输入侧这次请求根本不发出去(也不计费);开了输出侧的话,命中那一句一个字都不会出现在屏幕上
3313
+ released: 过滤后:{text}
3314
+ status_enabled: 启用:{enabled}
3315
+ status_rules: 规则:生效 {active} 条(内置 {builtin} + 用户词库 {user})
3316
+ status_dir: 用户词库目录:{dir}
3317
+ status_scope: 通道:输出 {output} / 输入 {input} / 跳过代码 {code}
3318
+ status_action: ' {category} → {action}'
3319
+ status_project_note: 注意:项目级词库(<项目根>/.epoch/compliance/)要过工作区信任闸门,本命令不读它 —— 真会话里会读
3320
+ compliance:
3321
+ category_sep: 、
3322
+ category:
3323
+ sexual: 色情低俗
3324
+ political: 涉政 / 国家安全
3325
+ hate: 民族种族歧视
3326
+ violence: 暴力恐怖
3327
+ illegal: 违法犯罪
3328
+ self_harm: 自残自杀
3329
+ privacy: 个人敏感信息
3330
+ compliance_load:
3331
+ dir_read_failed: 合规词库目录读取失败:{reason}
3332
+ file_read_failed: 读取失败,已跳过整个文件:{reason}
3333
+ unknown_file: 文件名不是类别名,已跳过整个文件。认得的类别:{categories}(正则写成 <类别>.regex.txt,豁免词写成 exempt.txt)
3334
+ bad_regex: 正则编译失败,该条已跳过:{reason}
3180
3335
  skill_load:
3181
3336
  degraded: '{message};已按无 frontmatter 加载'
3182
3337
  not_a_map: frontmatter 不是键值对(顶层要是一个 YAML 对象);已按无 frontmatter 加载
@@ -3279,7 +3434,12 @@ context_breakdown:
3279
3434
  agent_run:
3280
3435
  error: '错误: {message}'
3281
3436
  images_unsupported: 当前模型不支持图片输入,已取消本次请求(未发送,未计费)。请换用支持视觉的模型(如 gpt-4o / claude-sonnet-4-6 / gemini-2.5-flash),或去掉 {count} 张图片后重试。
3437
+ images_dropped: '{provider} 把这一轮的 {count} 张图片丢掉了(它自己报的:{feature}),模型实际上没看见图 —— 这一轮的回答别当真。请求已发出并计费。多半是这个 provider 的 SDK 版本还不支持图片,或这个模型其实不认图。'
3438
+ images_dropped_provider_unknown: 当前 provider
3282
3439
  content_filter: 模型因安全策略拒绝响应,请换一种方式提问。
3440
+ compliance_output: 这段回复触及内容合规限制({categories}),已停止输出。
3441
+ compliance_input: 你的消息触及内容合规限制({categories}),本次请求未发送,未计费。
3442
+ compliance_input_masked: 你的消息里有触及内容合规限制({categories})的词,已打码后再发给模型 —— 模型看到的不是你屏幕上这句的原文。
3283
3443
  stalled: 检测到死循环:{info}。任务已终止。
3284
3444
  stall_info: 连续 {count} 轮调用 {tool}({args}),检测到死循环
3285
3445
  max_turns: 已达到最大轮次 {max},任务未完成即终止。
@@ -3468,6 +3628,7 @@ secret:
3468
3628
  infra_misc:
3469
3629
  shell_not_on_path: 'shell: 配置的 {kind}({exe})不在 PATH 上,已回退到 cmd.exe'
3470
3630
  ripgrep_install_windows: winget install BurntSushi.ripgrep.MSVC(或 scoop install ripgrep)
3631
+ ripgrep_chmod_hint: chmod +x "{path}";这个目录归 root 时前面加 sudo
3471
3632
  schema_failed: '{path} 校验失败({count} 处):\n{detail}'
3472
3633
  schema_more: 还有 {count} 处问题未列出
3473
3634
  schema_unknown_key: 未知配置项,已忽略(不影响其他配置生效)
@@ -3513,6 +3674,9 @@ boot:
3513
3674
  managed_hooks_only: 企业托管设置开启了 allowManagedHooksOnly,用户级与项目级 hook 都不加载({path})
3514
3675
  policy_load_failed: 加载失败(跳过)
3515
3676
  perm_rules: 权限规则 {total} 条(allow {allow} / ask {ask} / deny {deny})
3677
+ compliance_ready: 生效 {active} 条(内置 {builtin} + 外部词库 {external})
3678
+ compliance_off: '未启用(compliance.enabled: false)'
3679
+ compliance_load_failed: 外部词库加载失败,只用内置种子表
3516
3680
  commands_all_failed: '{count} 个文件都没能加载,当前没有可用的自定义命令'
3517
3681
  command_allowed_tools: '{name} 的 allowed-tools 里 {tools} 不存在,已忽略'
3518
3682
  tools_cost: '{count} 个({split})≈ {tokens}k tokens/轮'
@@ -3522,6 +3686,7 @@ boot:
3522
3686
  shell_kind: '{kind}(terminal 工具的命令交给它执行)'
3523
3687
  plugin_register_failed: 注册失败 ({reason})
3524
3688
  ripgrep_missing: 未安装,file_search 不可用({hint})
3689
+ ripgrep_not_executable: 装下来了但没有执行位,file_search 暂时不可用({hint})
3525
3690
  ripgrep_system: 用系统安装的 rg
3526
3691
  ripgrep_builtin: 用内置的 rg{version}
3527
3692
  mcp_none: 未配置(~/.epoch/mcp.json 不存在或为空)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epoch-agent/infra",
3
- "version": "0.2.0",
3
+ "version": "0.3.2",
4
4
  "private": false,
5
5
  "description": "epoch-agent 基础设施:路径真源、SQLite 连接与迁移、日志、平台兼容、命令安全表",
6
6
  "repository": {
@@ -35,9 +35,9 @@
35
35
  "vitest": "^3.0.0"
36
36
  },
37
37
  "optionalDependencies": {
38
- "@epoch-agent/vendor-ripgrep-darwin-arm64": "14.2.0",
39
- "@epoch-agent/vendor-ripgrep-win32-x64": "14.2.0",
40
- "@epoch-agent/vendor-ripgrep-darwin-x64": "14.2.0"
38
+ "@epoch-agent/vendor-ripgrep-darwin-arm64": "14.2.1",
39
+ "@epoch-agent/vendor-ripgrep-darwin-x64": "14.2.1",
40
+ "@epoch-agent/vendor-ripgrep-win32-x64": "14.2.1"
41
41
  },
42
42
  "engines": {
43
43
  "node": ">=22.0.0"