@zq-silk/yui 2.17.0 → 2.19.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.
- package/dist/cli/commandCatalog.js +2 -1
- package/dist/commands/controllerCommands.js +14 -4
- package/dist/commands/durableJobCommands.js +50 -3
- package/dist/commands/globalRoleCommands.js +18 -12
- package/dist/commands/inboxCommands.js +1 -0
- package/dist/commands/operatorCommands.js +10 -2
- package/dist/controlPlaneCli.js +21 -4
- package/dist/controller/clientRuntime.js +34 -13
- package/dist/controller/controller.js +45 -22
- package/dist/controller/diagnosticJournal.js +214 -0
- package/dist/controller/fileSchedulerStoreAdapter.js +143 -101
- package/dist/controller/globalInputDelivery.js +6 -2
- package/dist/controller/globalRuntimeAttention.js +11 -3
- package/dist/controller/jobControl.js +1 -1
- package/dist/controller/jobDefinitionControl.js +24 -13
- package/dist/controller/jobSupervisor.js +4 -0
- package/dist/controller/messageHealth.js +354 -0
- package/dist/controller/runtime.js +75 -5
- package/dist/controller/taskHostTerminalRecovery.js +11 -0
- package/dist/controller/workerSchedulerStore.js +24 -0
- package/dist/core/boundedRpc.js +4 -0
- package/dist/core/controllerServer.js +1 -1
- package/dist/core/controllerTelemetry.js +92 -19
- package/dist/job/globalShell.js +51 -0
- package/dist/job/jobBusinessResult.js +4 -3
- package/dist/job/jobDefinition.js +6 -1
- package/dist/job/jobRunner.js +9 -0
- package/dist/job/scheduleService.js +2 -0
- package/dist/message/globalInboxRecovery.js +30 -19
- package/dist/message/globalProviderRetry.js +7 -1
- package/dist/runtime/builtinAgentErrorMappers.js +4 -0
- package/dist/runtime/globalSessionHealth.js +39 -0
- package/dist/scheduler/roleRunStall.js +10 -10
- package/dist/storage/contextRecords.js +16 -0
- package/dist/storage/persistenceWorker.js +41 -19
- package/dist/storage/sqliteSchema.js +35 -11
- package/dist/storage/sqliteStore.js +102 -8
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +25 -11
- package/dist/storage/taskReadRevisionSchema.js +39 -0
- package/dist/web/assets/client/app/catalog.js +0 -29
- package/dist/web/assets/client/app/jobs.js +115 -0
- package/dist/web/assets/client/app/main.js +17 -6
- package/dist/web/assets/client/app/manage.js +1 -0
- package/dist/web/assets/client/app/settings.js +1 -5
- package/dist/web/assets/client/i18n/en.js +203 -18
- package/dist/web/assets/client/i18n/zh-CN.js +202 -17
- package/dist/web/assets/client/index.js +2 -0
- package/dist/web/assets/client/layout/manageShell.js +61 -15
- package/dist/web/assets/client/layout/router.js +2 -1
- package/dist/web/assets/client/lib/prefs.js +1 -1
- package/dist/web/assets/client/views/jobs.js +1042 -160
- package/dist/web/assets/client/views/sidebar.js +3 -0
- package/dist/web/assets/shared/manageNav.js +3 -1
- package/dist/web/assets/shell/appRail.js +2 -1
- package/dist/web/assets/shell/manage.js +7 -2
- package/dist/web/assets/shell/models.js +4 -3
- package/dist/web/assets/shell/settingsContent.js +0 -3
- package/dist/web/assets/shell/sidebar.js +0 -1
- package/dist/web/assets/styles/views/jobs.js +301 -12
- package/dist/web/assets/styles/views/sidebar.js +1 -2
- package/dist/web/webServer.js +28 -1
- package/docs/global-shell-jobs.md +78 -0
- package/docs/job-runs.md +6 -3
- package/docs/managed-turn-and-session-runtime.md +170 -0
- package/docs/managed-turn-and-session-runtime.zh-CN.md +116 -0
- package/docs/release-workflow.md +63 -0
- package/docs/release-workflow.zh-CN.md +44 -0
- package/docs/storage-baseline.md +14 -1
- package/docs/storage-baseline.zh-CN.md +6 -1
- package/docs/testing/verification-levels.md +2 -2
- package/docs/testing/verification-levels.zh-CN.md +2 -2
- package/package.json +1 -1
|
@@ -48,7 +48,6 @@ export const ZH_CN = {
|
|
|
48
48
|
"permissions.empty": "没有匹配的模板。",
|
|
49
49
|
"permissions.retry": "重新读取",
|
|
50
50
|
"tabs.jobs": "Job",
|
|
51
|
-
"settings.section.jobs": "Job 与时间计划",
|
|
52
51
|
"jobs.builtinSync": "内置 Project 同步 · 仅安全快进",
|
|
53
52
|
"jobs.automatic": "自动同步偏好",
|
|
54
53
|
"jobs.syncEvery": "同步间隔(毫秒,最少 60000)",
|
|
@@ -60,14 +59,52 @@ export const ZH_CN = {
|
|
|
60
59
|
"jobs.executor": "执行方式",
|
|
61
60
|
"jobs.executionTask": "打开执行 Task",
|
|
62
61
|
"jobs.sourceJob": "创建来源 Job / Run",
|
|
63
|
-
"jobs
|
|
64
|
-
"jobs.
|
|
65
|
-
"jobs.
|
|
66
|
-
"jobs.
|
|
67
|
-
"jobs.
|
|
68
|
-
"jobs.
|
|
69
|
-
"jobs.
|
|
70
|
-
"jobs.
|
|
62
|
+
"nav.jobs": "Job",
|
|
63
|
+
"jobs.scopeLabel": "归属",
|
|
64
|
+
"jobs.scopeHelp": "全局,或某个拥有 Job 的 Task。计数、搜索与列表只描述这一范围。",
|
|
65
|
+
"jobs.scopesError": "归属列表不可用:",
|
|
66
|
+
"jobs.search": "搜索 Job",
|
|
67
|
+
"jobs.count": "{total} 个 Job",
|
|
68
|
+
"jobs.countFiltered": "{shown} / {total} 个 Job",
|
|
69
|
+
"jobs.noMatch": "此范围内没有匹配搜索的 Job。",
|
|
70
|
+
"jobs.noSchedule": "无计划",
|
|
71
|
+
"jobs.noRunsShort": "无 Run",
|
|
72
|
+
"jobs.nextShort": "下次",
|
|
73
|
+
"jobs.plan": "计划",
|
|
74
|
+
"jobs.definition": "定义",
|
|
75
|
+
"jobs.execution": "执行",
|
|
76
|
+
"jobs.runVsPlan": "Run 状态只描述一次执行,不会开启或关闭计划。",
|
|
77
|
+
"jobs.type": "类型",
|
|
78
|
+
"jobs.type.projectSync": "Project 同步",
|
|
79
|
+
"jobs.kind.shell": "Shell 命令",
|
|
80
|
+
"jobs.form.scripts": "脚本文件",
|
|
81
|
+
"jobs.form.scriptPath": "相对路径",
|
|
82
|
+
"jobs.form.scriptContent": "脚本内容",
|
|
83
|
+
"jobs.form.addScript": "添加脚本",
|
|
84
|
+
"jobs.form.stepOptions": "超时与环境变量",
|
|
85
|
+
"jobs.form.shellHome": "命令与脚本由此 Job 管理,每次运行使用独立目录中的版本快照。可用 sh scripts/run.sh 调用脚本。命令以本机用户权限执行,不是安全沙箱;保存不会立即执行。",
|
|
86
|
+
"jobs.kind.task": "Task 委派",
|
|
87
|
+
"jobs.kind.agent": "Agent 运行",
|
|
88
|
+
"jobs.kind.builtin": "内置动作",
|
|
89
|
+
"jobs.kind.process": "进程",
|
|
90
|
+
"jobs.ownerGlobal": "全局",
|
|
91
|
+
"jobs.ownerTask": "Task",
|
|
92
|
+
"jobs.openInJobs": "在 Job 中打开",
|
|
93
|
+
"jobs.moved": "Job 已从设置移到独立入口,此链接现在在这里打开。",
|
|
94
|
+
"catalog.sourceJob": "Job",
|
|
95
|
+
"catalog.sourceRemoved": "已移除任务分类筛选:列表显示全部任务,Job 有独立入口。",
|
|
96
|
+
"schedule.enabled": "开启",
|
|
97
|
+
"schedule.disabled": "关闭",
|
|
98
|
+
"schedule.completed": "已完成",
|
|
99
|
+
"schedule.needs-attention": "需要处理",
|
|
100
|
+
"schedule.retired": "已停用",
|
|
101
|
+
"admission.admitted": "已接纳",
|
|
102
|
+
"admission.overlap": "跳过(重叠)",
|
|
103
|
+
"admission.blocked": "被阻止",
|
|
104
|
+
"trigger.manual": "手动",
|
|
105
|
+
"trigger.schedule": "计划",
|
|
106
|
+
"trigger.retry": "重试",
|
|
107
|
+
"jobs.recentSuccess": "最近成功",
|
|
71
108
|
"jobs.diagnostics": "执行诊断",
|
|
72
109
|
"jobs.artifacts": "已登记固定产物",
|
|
73
110
|
"jobs.registeredOnly": "仅可读取已登记的准确归属、Run、commit、路径及摘要。引用图片也须独立登记。",
|
|
@@ -86,7 +123,9 @@ export const ZH_CN = {
|
|
|
86
123
|
"jobs.project": "目标 Project",
|
|
87
124
|
"jobs.name": "名称",
|
|
88
125
|
"jobs.action": "受控操作",
|
|
89
|
-
"jobs.newJob": "
|
|
126
|
+
"jobs.newJob": "新建 Job",
|
|
127
|
+
"jobs.newJobIn": "新 Job 将归属于",
|
|
128
|
+
"jobs.ownerShort": "归属",
|
|
90
129
|
"jobs.editJob": "编辑 Job",
|
|
91
130
|
"jobs.runNow": "立即运行",
|
|
92
131
|
"jobs.newSchedule": "创建时间计划",
|
|
@@ -94,10 +133,11 @@ export const ZH_CN = {
|
|
|
94
133
|
"jobs.cancelRun": "取消本次 Run",
|
|
95
134
|
"jobs.disable": "停用后续计划",
|
|
96
135
|
"jobs.enable": "启用时间计划",
|
|
97
|
-
"jobs.refresh": "
|
|
136
|
+
"jobs.refresh": "刷新",
|
|
98
137
|
"jobs.save": "保存",
|
|
99
138
|
"jobs.close": "关闭编辑",
|
|
100
139
|
"jobs.discard": "放弃当前未保存的草稿?",
|
|
140
|
+
"jobs.leaveBusy": "仍有提交在进行中;收到回执前保留当前视图。",
|
|
101
141
|
"jobs.loading": "正在读取权威状态…",
|
|
102
142
|
"jobs.submitting": "提交中…",
|
|
103
143
|
"jobs.saved": "已保存;不代表已执行或执行成功。",
|
|
@@ -108,16 +148,84 @@ export const ZH_CN = {
|
|
|
108
148
|
"jobs.unknown": "提交结果未知,不会重发。请先检查当前事实和原操作,再决定后续动作。",
|
|
109
149
|
"jobs.empty": "此范围暂无 Job。创建定义不会立即执行。",
|
|
110
150
|
"jobs.configuration": "执行配置",
|
|
111
|
-
"jobs.taskConfig": "
|
|
112
|
-
"jobs.
|
|
151
|
+
"jobs.taskConfig": "保存仅更新配置,不会立即执行。请勿填写密码或密钥;运行时仍需满足对应权限与工作区要求。",
|
|
152
|
+
"jobs.saveAsNew": "另存为新 Job",
|
|
153
|
+
"jobs.kindCopyHelp": "你选择了不同的执行方式。保存将创建新的 Job;原 Job、执行历史和时间计划保持不变,不会复制或启动计划。",
|
|
154
|
+
"jobs.rebind": "保存 Project 刷新 Job 会绑定当前目录中的目标,但不会立即执行刷新。",
|
|
113
155
|
"jobs.rule": "时间规则",
|
|
114
156
|
"jobs.instant": "执行时间/周期锚点(带 UTC 偏移的 ISO 时间)",
|
|
115
157
|
"jobs.every": "周期间隔(毫秒,至少 1000)",
|
|
116
158
|
"jobs.cron": "Cron 表达式(五字段)",
|
|
117
159
|
"jobs.timezone": "时区",
|
|
118
|
-
"jobs.scheduleHelp": "
|
|
160
|
+
"jobs.scheduleHelp": "新计划保存后启用;编辑已有计划不会改变启停状态。",
|
|
161
|
+
"jobs.form.customCron": "自定义 Cron",
|
|
162
|
+
"jobs.form.cron": "重复执行",
|
|
163
|
+
"jobs.form.interval": "固定间隔",
|
|
164
|
+
"jobs.form.once": "仅执行一次",
|
|
165
|
+
"jobs.form.daily": "每天",
|
|
166
|
+
"jobs.form.weekly": "每周",
|
|
167
|
+
"jobs.form.monthly": "每月",
|
|
168
|
+
"jobs.form.advanced": "高级详情",
|
|
169
|
+
"jobs.form.frequency": "重复频率",
|
|
170
|
+
"jobs.form.time": "执行时间",
|
|
171
|
+
"jobs.form.time24": "执行时间 · 24 小时制",
|
|
172
|
+
"jobs.form.quickTime": "常用时间",
|
|
173
|
+
"jobs.form.cronRequired": "输入 Cron 表达式,或返回选择执行频率。",
|
|
174
|
+
"jobs.form.cronSymbols": "* 表示任意值,, 分隔多个值,- 表示范围,/ 表示步长。例如 0 9 * * 1-5:每周一至周五 09:00。保存时由服务端校验。",
|
|
175
|
+
"jobs.form.cron.minute": "分钟",
|
|
176
|
+
"jobs.form.cron.hour": "小时",
|
|
177
|
+
"jobs.form.cron.date": "日期",
|
|
178
|
+
"jobs.form.cron.month": "月份",
|
|
179
|
+
"jobs.form.cron.weekday": "星期",
|
|
180
|
+
"jobs.form.cron.minuteRange": "0–59",
|
|
181
|
+
"jobs.form.cron.hourRange": "0–23",
|
|
182
|
+
"jobs.form.cron.dateRange": "1–31",
|
|
183
|
+
"jobs.form.cron.monthRange": "1–12",
|
|
184
|
+
"jobs.form.cron.weekdayRange": "0–7,0/7 为周日",
|
|
185
|
+
"jobs.form.day": "每月几号",
|
|
186
|
+
"jobs.form.weekdays": "执行星期",
|
|
187
|
+
"jobs.form.monthHelp": "选择 29–31 日时,没有该日期的月份不会执行。",
|
|
188
|
+
"jobs.form.complexHelp": "自定义五字段 Cron。保存时由服务端校验;复杂规则保持原样,不自动转换。",
|
|
189
|
+
"jobs.form.replaceComplex": "此表达式不能无损转换为常见频率。改用可视化表单将替换当前规则,是否继续?",
|
|
190
|
+
"jobs.form.zonePreserved": "时间按此计划保存的时区执行,编辑不会改变时区。",
|
|
191
|
+
"jobs.form.forJob": "执行 Job",
|
|
192
|
+
"jobs.form.internalId": "内部标识",
|
|
193
|
+
"jobs.form.idHelp": "用于链接和关联记录,系统自动生成,通常无需修改。",
|
|
194
|
+
"jobs.form.paused": "已暂停后续执行,已有执行历史不受影响。",
|
|
195
|
+
"jobs.form.cronTime": "请选择有效的执行时间。",
|
|
196
|
+
"jobs.form.cronDays": "请至少选择一天。",
|
|
197
|
+
"jobs.form.cronDay": "日期应为 1–31 的整数。",
|
|
198
|
+
"jobs.form.monthRule": "每月 {day} 日 {time}",
|
|
199
|
+
"jobs.form.command": "命令",
|
|
200
|
+
"jobs.form.remove": "移除",
|
|
201
|
+
"jobs.form.addStep": "添加步骤",
|
|
202
|
+
"jobs.form.addEnv": "添加环境变量",
|
|
203
|
+
"jobs.form.envName": "变量名",
|
|
204
|
+
"jobs.form.envValue": "变量值",
|
|
205
|
+
"jobs.form.timeout": "超时(毫秒,可选)",
|
|
206
|
+
"jobs.form.target": "执行目标",
|
|
207
|
+
"jobs.form.goal": "完成目标",
|
|
208
|
+
"jobs.form.delivery": "完成交付",
|
|
209
|
+
"jobs.form.task-created": "创建任务",
|
|
210
|
+
"jobs.form.work-item": "已有工作项",
|
|
211
|
+
"jobs.form.new": "新建任务",
|
|
212
|
+
"jobs.form.operator": "全局 Operator",
|
|
213
|
+
"jobs.form.task": "任务角色",
|
|
214
|
+
"jobs.form.job": "独立 Agent",
|
|
215
|
+
"jobs.form.serial": "串行",
|
|
216
|
+
"jobs.form.isolated": "隔离执行",
|
|
217
|
+
"jobs.form.concurrency": "执行策略",
|
|
218
|
+
"jobs.form.addBinding": "添加 Project",
|
|
219
|
+
"jobs.form.directory": "目录",
|
|
220
|
+
"jobs.form.baseRef": "基准分支",
|
|
221
|
+
"jobs.form.unchanged": "未展示字段会原样保留。",
|
|
222
|
+
"jobs.form.duplicateEnv": "环境变量名不能为空或重复。",
|
|
223
|
+
"jobs.form.positiveInteger": "请输入正整数。",
|
|
224
|
+
"jobs.form.needStep": "请至少添加一个执行步骤。",
|
|
225
|
+
"jobs.form.argvHelp": "此步骤直接执行以下参数,不通过 Shell;命令字段仅作说明。",
|
|
226
|
+
"jobs.form.addArgument": "添加参数",
|
|
119
227
|
"jobs.state": "状态",
|
|
120
|
-
"jobs.recentRun": "
|
|
228
|
+
"jobs.recentRun": "最近 Run",
|
|
121
229
|
"jobs.refreshAttempt": "Project 最近尝试",
|
|
122
230
|
"jobs.refreshSuccess": "Project 最近成功刷新",
|
|
123
231
|
"jobs.onceCompleted": "一次性计划已准入;completed 不代表其 Run 已成功。",
|
|
@@ -128,7 +236,7 @@ export const ZH_CN = {
|
|
|
128
236
|
"jobs.lastAttempt": "最近准入尝试",
|
|
129
237
|
"jobs.lastSuccess": "最近成功的计划 Run",
|
|
130
238
|
"jobs.refreshFacts": "Project 刷新:最近尝试/最近成功",
|
|
131
|
-
"jobs.history": "执行历史
|
|
239
|
+
"jobs.history": "执行历史",
|
|
132
240
|
"jobs.noRuns": "尚无执行记录。",
|
|
133
241
|
"jobs.inspectRun": "查看此次尝试的 Run",
|
|
134
242
|
"jobs.trigger": "触发来源",
|
|
@@ -138,6 +246,83 @@ export const ZH_CN = {
|
|
|
138
246
|
"jobs.logs": "步骤日志",
|
|
139
247
|
"jobs.truncated": "末尾 64 KiB",
|
|
140
248
|
"jobs.noLogs": "暂无已写入检查点的步骤日志;这不代表成功。",
|
|
249
|
+
"jobs.copy": "复制",
|
|
250
|
+
"jobs.copied": "已复制",
|
|
251
|
+
"jobs.copyManual": "请手动复制:",
|
|
252
|
+
"jobs.copyJson": "复制 JSON",
|
|
253
|
+
"jobs.copyCommand": "复制命令",
|
|
254
|
+
"jobs.jsonInvalid": "配置不是有效的 JSON:",
|
|
255
|
+
"jobs.preview": "保存后显示为",
|
|
256
|
+
"jobs.basics": "基本信息",
|
|
257
|
+
"jobs.runDetail": "Run 详情",
|
|
258
|
+
"jobs.closeRun": "关闭 Run 详情",
|
|
259
|
+
"jobs.started": "开始时间",
|
|
260
|
+
"jobs.updated": "更新时间",
|
|
261
|
+
"jobs.duration": "耗时",
|
|
262
|
+
"jobs.exit": "退出",
|
|
263
|
+
"jobs.failedStep": "失败步骤",
|
|
264
|
+
"jobs.retryOf": "重试自",
|
|
265
|
+
"jobs.steps": "步骤",
|
|
266
|
+
"jobs.overview": "执行概况",
|
|
267
|
+
"jobs.successRate": "成功率",
|
|
268
|
+
"jobs.avgDuration": "平均耗时",
|
|
269
|
+
"jobs.sparkLabel": "最近 {count} 次 Run,{ok} 次成功",
|
|
270
|
+
"jobs.runCount": "共 {count} 次",
|
|
271
|
+
"jobs.showMore": "再显示 {count} 条",
|
|
272
|
+
"jobs.filterRuns": "按状态筛选 Run",
|
|
273
|
+
"jobs.filter.all": "全部",
|
|
274
|
+
"jobs.filter.active": "进行中",
|
|
275
|
+
"jobs.col.status": "状态",
|
|
276
|
+
"jobs.col.run": "Run",
|
|
277
|
+
"jobs.col.started": "开始",
|
|
278
|
+
"jobs.lastAttemptShort": "最近尝试",
|
|
279
|
+
"jobs.lastSuccessShort": "最近成功",
|
|
280
|
+
"jobs.ruleDaily": "每天 {time}",
|
|
281
|
+
"jobs.ruleWeekly": "每周 {days} {time}",
|
|
282
|
+
"jobs.ruleEvery": "每 {period}",
|
|
283
|
+
"jobs.ruleOnce": "一次 · {at}",
|
|
284
|
+
"jobs.ruleAnchor": "起点",
|
|
285
|
+
"jobs.cfg.input": "输入参数",
|
|
286
|
+
"jobs.cfg.workspace": "工作区",
|
|
287
|
+
"jobs.cfg.head": "HEAD",
|
|
288
|
+
"jobs.cfg.owner": "执行归属",
|
|
289
|
+
"jobs.cfg.ownerTask": "本 Task",
|
|
290
|
+
"jobs.cfg.env": "环境变量",
|
|
291
|
+
"jobs.cfg.noEnv": "无",
|
|
292
|
+
"jobs.cfg.goal": "目标",
|
|
293
|
+
"jobs.cfg.target": "执行目标",
|
|
294
|
+
"jobs.cfg.concurrency": "并发",
|
|
295
|
+
"jobs.cfg.agentInput": "Agent 指令",
|
|
296
|
+
"jobs.cfg.other": "其他字段",
|
|
297
|
+
"jobs.cfg.raw": "准确配置",
|
|
298
|
+
"jobs.cfg.noParams": "无参数",
|
|
299
|
+
"jobs.cfg.emptyList": "空列表",
|
|
300
|
+
"jobs.cfg.emptyText": "空",
|
|
301
|
+
"jobs.cfg.fields": "{count} 个字段",
|
|
302
|
+
"jobs.cfg.value": "值",
|
|
303
|
+
"jobs.cfg.timeout": "超时",
|
|
304
|
+
"jobs.cfg.cwd": "目录",
|
|
305
|
+
"jobs.cfg.unnamed": "未命名",
|
|
306
|
+
"jobs.cfg.description": "描述",
|
|
307
|
+
"jobs.cfg.bindings": "Project 绑定",
|
|
308
|
+
"jobs.cfg.task": "Task",
|
|
309
|
+
"jobs.cfg.workItem": "WorkItem",
|
|
310
|
+
"jobs.cfg.role": "角色",
|
|
311
|
+
"jobs.cfg.agent": "Agent",
|
|
312
|
+
"jobs.cfg.ownerRun": "所属 Run",
|
|
313
|
+
"jobs.cfg.attempt": "集成尝试",
|
|
314
|
+
"jobs.action.system.noop": "空操作检查",
|
|
315
|
+
"jobs.action.project.refresh": "Project 刷新",
|
|
316
|
+
"jobs.goal.delivery": "在新 Task 中交付",
|
|
317
|
+
"jobs.goal.task-created": "创建 Task",
|
|
318
|
+
"jobs.goal.work-item": "执行 WorkItem",
|
|
319
|
+
"jobs.target.new": "新 Task",
|
|
320
|
+
"jobs.target.work-item": "已有 WorkItem",
|
|
321
|
+
"jobs.target.operator": "Operator",
|
|
322
|
+
"jobs.target.task": "Task 角色",
|
|
323
|
+
"jobs.target.job": "Job 自有 Agent",
|
|
324
|
+
"jobs.concurrency.serial": "串行",
|
|
325
|
+
"jobs.concurrency.isolated": "隔离",
|
|
141
326
|
"models.subscriptionAuth": "官方订阅",
|
|
142
327
|
"models.account": "账号",
|
|
143
328
|
"models.providerReadOnlyHelp": "由来源服务管理,请在对应服务中修改配置。",
|
|
@@ -146,7 +331,7 @@ export const ZH_CN = {
|
|
|
146
331
|
"models.window.weekly": "每周",
|
|
147
332
|
"models.window.monthly": "每月",
|
|
148
333
|
"manage.nav": "主导航",
|
|
149
|
-
"manage.workbench": "
|
|
334
|
+
"manage.workbench": "任务",
|
|
150
335
|
"manage.sections": "分区",
|
|
151
336
|
"manage.collapseSections": "收起分区列表",
|
|
152
337
|
"manage.showSections": "展开分区列表",
|
|
@@ -68,6 +68,7 @@ import { JOBS_SCRIPT } from "./views/jobs.js";
|
|
|
68
68
|
import { PERMISSIONS_SCRIPT } from "./views/permissions.js";
|
|
69
69
|
import { MODELS_VIEW_SCRIPT } from "./views/models.js";
|
|
70
70
|
import { MODELS_SCRIPT } from "./app/models.js";
|
|
71
|
+
import { JOBS_APP_SCRIPT } from "./app/jobs.js";
|
|
71
72
|
import { MANAGE_SHELL_SCRIPT } from "./layout/manageShell.js";
|
|
72
73
|
import { MANAGE_SCRIPT } from "./app/manage.js";
|
|
73
74
|
import { LOGIN_SCRIPT } from "./app/login.js";
|
|
@@ -75,6 +76,7 @@ export { APP_SCRIPT } from "./app/main.js";
|
|
|
75
76
|
export const CLIENT_MODULES = Object.freeze({
|
|
76
77
|
"views/skills": SKILLS_SCRIPT,
|
|
77
78
|
"views/jobs": JOBS_SCRIPT,
|
|
79
|
+
"app/jobs": JOBS_APP_SCRIPT,
|
|
78
80
|
"views/permissions": PERMISSIONS_SCRIPT,
|
|
79
81
|
"views/models": MODELS_VIEW_SCRIPT,
|
|
80
82
|
"lib/dom": DOM_SCRIPT,
|
|
@@ -16,22 +16,30 @@ export function manageArea(page, section) {
|
|
|
16
16
|
export function pageSections(page) {
|
|
17
17
|
return Object.values(SECTIONS).flat().filter(item => item.page === page).map(item => item.section);
|
|
18
18
|
}
|
|
19
|
+
const TASK_ID = /^task-\d+$/;
|
|
19
20
|
export function readManageRoute(url) {
|
|
20
21
|
const parts = url.pathname.split("/").filter(Boolean);
|
|
22
|
+
// Jobs has its own entry. The retired Settings section keeps its links
|
|
23
|
+
// working: it opens the same Job (canonicalized without a Back step).
|
|
24
|
+
const legacyJobs = parts[0] === "settings" && (parts[1] || url.searchParams.get("section")) === "jobs";
|
|
25
|
+
if (parts[0] === "jobs" || legacyJobs) {
|
|
26
|
+
const task = url.searchParams.get("task");
|
|
27
|
+
return { page: "jobs", section: "jobs", task: task && TASK_ID.test(task) ? task : null,
|
|
28
|
+
job: url.searchParams.get("job"), jobRun: url.searchParams.get("jobRun"),
|
|
29
|
+
artifact: url.searchParams.get("artifact"), ...(legacyJobs ? { moved: true } : {}) };
|
|
30
|
+
}
|
|
21
31
|
const area = parts[0] === "settings" ? "settings" : "models";
|
|
22
32
|
const requested = parts[1] || url.searchParams.get("section");
|
|
23
33
|
const section = (SECTIONS[area].find(item => item.section === requested) ||
|
|
24
34
|
(area === "models" && requested === "connection" ? SECTIONS.settings.at(-1) : SECTIONS[area][0])).section;
|
|
25
35
|
return { page: section === "connection" ? "models" : area, section,
|
|
26
|
-
...(section === "jobs" ? { job: url.searchParams.get("job"), jobRun: url.searchParams.get("jobRun"),
|
|
27
|
-
artifact: url.searchParams.get("artifact") } : {}),
|
|
28
36
|
source: url.searchParams.get("source") === "command-code" ? "command-code" : "factory" };
|
|
29
37
|
}
|
|
30
38
|
export function manageHref(next) {
|
|
31
|
-
if (next.
|
|
39
|
+
if (next.page === "jobs") {
|
|
32
40
|
const query = new URLSearchParams();
|
|
33
|
-
for (const key of ["job", "jobRun", "artifact"]) if (next[key]) query.set(key, next[key]);
|
|
34
|
-
return "/
|
|
41
|
+
for (const key of ["task", "job", "jobRun", "artifact"]) if (next[key]) query.set(key, next[key]);
|
|
42
|
+
return "/jobs" + (query.size ? "?" + query : "");
|
|
35
43
|
}
|
|
36
44
|
return "/" + manageArea(next.page, next.section) + "/" + next.section +
|
|
37
45
|
(next.section === "quota" && next.source === "command-code" ? "?source=command-code" : "");
|
|
@@ -53,11 +61,15 @@ function render() {
|
|
|
53
61
|
if (link.dataset.area === area) link.setAttribute("aria-current", "page"); else link.removeAttribute("aria-current");
|
|
54
62
|
});
|
|
55
63
|
// The list head and the top bar name where the reader is.
|
|
56
|
-
const areaTitle = i18n.t(area + ".title");
|
|
57
|
-
const
|
|
64
|
+
const areaTitle = i18n.t(area === "jobs" ? "nav.jobs" : area + ".title");
|
|
65
|
+
const page = pages.get(route.page);
|
|
66
|
+
const sectionTitle = page && page.crumb ? page.crumb()
|
|
67
|
+
: i18n.t((route.page === "models" ? "models" : "settings") + ".section." + route.section);
|
|
58
68
|
document.querySelector("#manage-area-title").textContent = areaTitle;
|
|
59
69
|
document.querySelector("#manage-crumb-area").textContent = areaTitle;
|
|
60
70
|
document.querySelector("#manage-crumb-section").textContent = sectionTitle;
|
|
71
|
+
// Area-only controls in the shared list head (the Jobs sync and refresh).
|
|
72
|
+
rail.querySelectorAll("[data-area-only]").forEach(node => { node.hidden = node.dataset.areaOnly !== area; });
|
|
61
73
|
rail.querySelectorAll("[data-area-group]").forEach(group => {
|
|
62
74
|
if (group.dataset.areaGroup === area) group.dataset.active = "true"; else delete group.dataset.active;
|
|
63
75
|
});
|
|
@@ -65,27 +77,60 @@ function render() {
|
|
|
65
77
|
document.title = sectionTitle + " · " + areaTitle + " · Yui";
|
|
66
78
|
}
|
|
67
79
|
function apply(next) {
|
|
80
|
+
// The page being left is told first, so it can set aside what must not
|
|
81
|
+
// outlive its visibility (a modal editor) without discarding it.
|
|
82
|
+
const previous = route && route.page !== next.page ? pages.get(route.page) : null;
|
|
83
|
+
if (previous && previous.hide) previous.hide();
|
|
68
84
|
route = next;
|
|
69
85
|
rememberPlace(manageArea(next.page, next.section), manageHref(next));
|
|
70
86
|
rememberPlace("manage", manageHref(next));
|
|
71
|
-
document.querySelector("#
|
|
72
|
-
document.querySelector("#settings-root").hidden = next.page !== "settings";
|
|
87
|
+
for (const name of ["models", "settings", "jobs"]) document.querySelector("#" + name + "-root").hidden = next.page !== name;
|
|
73
88
|
pages.get(next.page).show(next);
|
|
74
89
|
render();
|
|
75
90
|
}
|
|
76
91
|
// A section the reader switched to rises in (never on the first paint).
|
|
77
92
|
function revealSection() {
|
|
78
93
|
if (typeof enter !== "function") return;
|
|
79
|
-
enter(document.querySelector("#models-root:not([hidden]), #settings-root:not([hidden])"), "rise");
|
|
94
|
+
enter(document.querySelector("#models-root:not([hidden]), #settings-root:not([hidden]), #jobs-root:not([hidden])"), "rise");
|
|
95
|
+
}
|
|
96
|
+
// Every route change (link, control, Back/Forward) first asks the page it
|
|
97
|
+
// leaves and the page it enters; either may keep the current view.
|
|
98
|
+
function mayNavigate(next) {
|
|
99
|
+
for (const name of new Set([route.page, next.page])) {
|
|
100
|
+
const page = pages.get(name);
|
|
101
|
+
if (page && page.canNavigate && !page.canNavigate(next)) return false;
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
80
104
|
}
|
|
105
|
+
// Returns false when a page kept the current view (nothing changed).
|
|
81
106
|
export function navigateManage(next) {
|
|
82
107
|
const normalized = readManageRoute(new URL(manageHref(next), location.origin));
|
|
83
|
-
if (manageHref(normalized) === location.pathname + location.search) return;
|
|
108
|
+
if (manageHref(normalized) === location.pathname + location.search) return true;
|
|
109
|
+
if (!mayNavigate(normalized)) return false;
|
|
84
110
|
history.replaceState({ ...history.state, scroll: scroller().scrollTop }, "");
|
|
85
111
|
history.pushState({ scroll: 0 }, "", manageHref(normalized));
|
|
86
112
|
apply(normalized);
|
|
87
113
|
scroller().scrollTop = 0;
|
|
88
114
|
revealSection();
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
// A page settled on a more exact address for the current view (for example
|
|
118
|
+
// the Job it opened): record it in place, without a history step.
|
|
119
|
+
export function replaceManageRoute(next) {
|
|
120
|
+
route = next;
|
|
121
|
+
rememberPlace(manageArea(next.page, next.section), manageHref(next));
|
|
122
|
+
rememberPlace("manage", manageHref(next));
|
|
123
|
+
history.replaceState(history.state, "", manageHref(next));
|
|
124
|
+
render();
|
|
125
|
+
}
|
|
126
|
+
// A page already shows a selection the reader chose in place (for example a
|
|
127
|
+
// Run opened under its row): record it as a history step without applying it
|
|
128
|
+
// again, keeping the reading position for Back.
|
|
129
|
+
export function pushManageRoute(next) {
|
|
130
|
+
if (manageHref(next) === location.pathname + location.search) return;
|
|
131
|
+
history.replaceState({ ...history.state, scroll: scroller().scrollTop }, "");
|
|
132
|
+
history.pushState({ scroll: scroller().scrollTop }, "", manageHref(next));
|
|
133
|
+
replaceManageRoute(next);
|
|
89
134
|
}
|
|
90
135
|
export function createManageShell(options) {
|
|
91
136
|
return {
|
|
@@ -108,14 +153,15 @@ export function startManagement() {
|
|
|
108
153
|
if (!link || link.target || link.hasAttribute("download") || event.defaultPrevented ||
|
|
109
154
|
event.button > 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
|
|
110
155
|
const url = new URL(link.href);
|
|
111
|
-
|
|
112
|
-
if (url.searchParams.has("job")) return;
|
|
113
|
-
if (url.origin !== location.origin || !/^\/(models|settings)(\/|$)/.test(url.pathname)) return;
|
|
156
|
+
if (url.origin !== location.origin || !/^\/(models|settings|jobs)(\/|$)/.test(url.pathname)) return;
|
|
114
157
|
event.preventDefault();
|
|
115
158
|
navigateManage(readManageRoute(url));
|
|
116
159
|
});
|
|
117
160
|
window.addEventListener("popstate", () => {
|
|
118
|
-
|
|
161
|
+
const next = readManageRoute(new URL(location.href));
|
|
162
|
+
// A kept view restores its own address as the newest entry.
|
|
163
|
+
if (!mayNavigate(next)) { history.pushState({ scroll: scroller().scrollTop }, "", manageHref(route)); return; }
|
|
164
|
+
apply(next);
|
|
119
165
|
scroller().scrollTop = history.state?.scroll || 0;
|
|
120
166
|
revealSection();
|
|
121
167
|
});
|
|
@@ -23,7 +23,8 @@ export function syncUrl(state, replace) {
|
|
|
23
23
|
if (state.query) params.set("q", state.query); else params.delete("q");
|
|
24
24
|
if (state.attentionFilter) params.set("attention", state.attentionFilter); else params.delete("attention");
|
|
25
25
|
if (state.catalogAll) params.set("all", "true"); else params.delete("all");
|
|
26
|
-
|
|
26
|
+
// Tasks have no category filter: every real Task, Job-created ones marked.
|
|
27
|
+
params.delete("source");
|
|
27
28
|
applyUrl(params, replace);
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -18,7 +18,7 @@ export function clearPreference(key) {
|
|
|
18
18
|
// switching back restores the filters, Task or section the user left. Only
|
|
19
19
|
// same-origin paths of the expected area are accepted; anything else falls back.
|
|
20
20
|
const PLACES = { workbench: /^\/(?:\?|$)/, models: /^\/models(?:[/?]|$)/, settings: /^\/settings(?:[/?]|$)/,
|
|
21
|
-
manage: /^\/(?:models|settings)(?:[/?]|$)/ };
|
|
21
|
+
jobs: /^\/jobs(?:[/?]|$)/, manage: /^\/(?:jobs|models|settings)(?:[/?]|$)/ };
|
|
22
22
|
|
|
23
23
|
export function rememberPlace(area, href) {
|
|
24
24
|
if (!PLACES[area] || !PLACES[area].test(href)) return;
|