dsh-run2skill 0.1.1-alpha → 0.3.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/lib/client.js CHANGED
@@ -4219,35 +4219,48 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4219
4219
  }
4220
4220
  //#endregion
4221
4221
  //#region \0run2skill-css:run2skill-settings-page.module.css.mjs
4222
- const css = ".run2skill_page_OghXMq{max-width:960px;color:var(--dsw-alias-content-primary,inherit);gap:20px;padding:8px 0 32px;display:grid}.run2skill_intro_OghXMq,.run2skill_muted_OghXMq{color:var(--dsw-alias-content-secondary,currentColor);margin:0;font-size:13px;line-height:1.5}.run2skill_section_OghXMq{border:1px solid var(--dsw-alias-border-subtle,color-mix(in srgb, currentColor 16%, transparent));background:var(--dsw-alias-surface-primary,transparent);border-radius:16px;overflow:hidden}.run2skill_sectionBody_OghXMq{gap:14px;padding:0 18px 18px 48px;display:grid}.run2skill_toolbar_OghXMq,.run2skill_actions_OghXMq,.run2skill_modeGroup_OghXMq{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.run2skill_attentionList_OghXMq,.run2skill_proposalList_OghXMq{gap:8px;margin:0;padding:0;list-style:none;display:grid}.run2skill_proposalLayout_OghXMq{grid-template-columns:minmax(220px,.8fr) minmax(0,1.6fr);gap:16px;display:grid}.run2skill_proposalListButton_OghXMq{text-align:start;white-space:normal;justify-content:flex-start;width:100%}.run2skill_detail_OghXMq{border:1px solid var(--dsw-alias-border-subtle,color-mix(in srgb, currentColor 16%, transparent));background:var(--dsw-alias-surface-secondary,transparent);border-radius:12px;min-width:0;max-height:640px;padding:14px;overflow:auto}.run2skill_detail_OghXMq pre{white-space:pre-wrap;unicode-bidi:isolate;overflow:auto}.run2skill_status_OghXMq{min-height:20px;margin:0;font-size:13px}.run2skill_danger_OghXMq{color:var(--dsw-alias-content-negative,var(--dsw-alias-content-primary,currentColor))}.run2skill_backdrop_OghXMq,.run2skill_rejectOverlay_OghXMq{background:var(--dsw-alias-overlay,color-mix(in srgb, currentColor 35%, transparent));position:fixed;inset:0}.run2skill_backdrop_OghXMq{z-index:999}.run2skill_rejectOverlay_OghXMq{z-index:1001;place-items:center;padding:16px;display:grid}.run2skill_legacyDialog_OghXMq{z-index:1000;border:1px solid var(--dsw-alias-border-subtle,currentColor);background:var(--dsw-alias-surface-primary,inherit);color:var(--dsw-alias-content-primary,inherit);box-shadow:var(--dsw-alias-shadow-modal,0 16px 48px color-mix(in srgb, currentColor 35%, transparent));border-radius:16px;grid-template-columns:minmax(16rem,24rem) minmax(0,1fr);gap:16px;padding:16px;display:grid;position:fixed;inset:5vh 5vw;overflow:hidden}.run2skill_blocked_OghXMq{pointer-events:none;display:contents}.run2skill_queue_OghXMq,.run2skill_legacyDetail_OghXMq{min-width:0;overflow:auto}.run2skill_legacyHeader_OghXMq{justify-content:space-between;align-items:center;gap:8px;display:flex}.run2skill_legacyList_OghXMq{margin:0;padding:0;list-style:none}.run2skill_rejectCard_OghXMq{background:var(--dsw-alias-surface-primary,inherit);border-radius:16px;max-width:32rem;padding:16px}.run2skill_textBlock_OghXMq{white-space:pre-wrap;overflow-wrap:anywhere;unicode-bidi:isolate;overflow:auto}.run2skill_previewFacts_OghXMq{grid-template-columns:max-content 1fr;gap:6px 12px;display:grid}.run2skill_previewFacts_OghXMq dt,.run2skill_previewFacts_OghXMq dd{margin:0}@media (width<=720px){.run2skill_proposalLayout_OghXMq{grid-template-columns:1fr}.run2skill_sectionBody_OghXMq{padding-left:18px}}";
4222
+ const css = ".run2skill_page_R4wX7a{width:min(100%,1040px);color:var(--dsw-alias-label-primary);gap:24px;padding:16px 0 48px;display:grid}.run2skill_intro_R4wX7a,.run2skill_muted_R4wX7a{color:var(--dsw-alias-label-secondary);margin:0;font-size:13px;line-height:1.5}.run2skill_section_R4wX7a{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);box-shadow:0 1px 2px var(--dsw-alias-border-l1);border-radius:16px;overflow:hidden}.run2skill_sectionHeader_R4wX7a{box-sizing:border-box;height:auto;min-height:56px;padding:14px 20px}.run2skill_sectionTitle_R4wX7a{font-size:15px}.run2skill_sectionBody_R4wX7a{gap:18px;padding:12px 24px 24px 56px;display:grid;container-type:inline-size}.run2skill_attentionGroup_R4wX7a{gap:16px;min-width:0;display:grid}.run2skill_empty_R4wX7a{min-height:56px;color:var(--dsw-alias-label-secondary);place-items:center;margin:0;font-size:13px;display:grid}.run2skill_toolbar_R4wX7a,.run2skill_actions_R4wX7a,.run2skill_modeGroup_R4wX7a{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.run2skill_attentionList_R4wX7a,.run2skill_proposalList_R4wX7a,.run2skill_activityList_R4wX7a{gap:8px;margin:0;padding:0;list-style:none;display:grid}.run2skill_activityItem_R4wX7a{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:12px;justify-content:space-between;align-items:center;gap:12px;padding:12px 14px;display:flex}.run2skill_activitySummary_R4wX7a{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.run2skill_proposalToolbar_R4wX7a{grid-template-columns:minmax(12rem,1fr) auto;align-items:center;gap:8px;display:grid}.run2skill_proposalToolbar_R4wX7a>:first-child{width:100%}.run2skill_proposalToolbarCompact_R4wX7a{justify-content:flex-end;display:flex}.run2skill_proposalToolbarCompact_R4wX7a>:first-child{width:auto}.run2skill_proposalLayout_R4wX7a{grid-template-columns:1fr;gap:12px;display:grid}.run2skill_proposalListButton_R4wX7a{text-align:start;white-space:normal;overflow-wrap:anywhere;border-radius:10px;flex-direction:column;justify-content:flex-start;align-items:flex-start;gap:2px;width:100%;height:auto;min-height:48px;padding:8px 12px}.run2skill_proposalListButton_R4wX7a[aria-current=true]{border-color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary);box-shadow:inset 3px 0 var(--dsw-alias-brand-primary)}.run2skill_proposalName_R4wX7a{max-width:100%;font-size:14px;font-weight:600;line-height:20px}.run2skill_proposalMeta_R4wX7a{max-width:100%;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}.run2skill_detail_R4wX7a{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:12px;min-width:0;max-height:640px;padding:18px;overflow:auto}.run2skill_detail_R4wX7a>:first-child{margin-top:0}.run2skill_detailFacts_R4wX7a{grid-template-columns:minmax(6rem,max-content) minmax(0,1fr);gap:8px 16px;margin:0 0 20px;display:grid}.run2skill_detailFacts_R4wX7a dt{color:var(--dsw-alias-label-secondary);font-size:13px}.run2skill_detailFacts_R4wX7a dd{overflow-wrap:anywhere;min-width:0;margin:0}.run2skill_detail_R4wX7a pre{white-space:pre-wrap;unicode-bidi:isolate;overflow:auto}.run2skill_technicalDetails_R4wX7a{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;margin:16px 0;padding:10px 12px}.run2skill_technicalDetails_R4wX7a summary{cursor:pointer;color:var(--dsw-alias-label-secondary);font-size:13px}.run2skill_technicalDetails_R4wX7a[open] summary{margin-bottom:12px}.run2skill_status_R4wX7a{min-height:20px;margin:0;font-size:13px}.run2skill_danger_R4wX7a{color:var(--dsw-alias-state-error-primary)}.run2skill_backdrop_R4wX7a,.run2skill_rejectOverlay_R4wX7a{background:var(--dsw-alias-bg-mask-1);position:fixed;inset:0}.run2skill_backdrop_R4wX7a{z-index:999}.run2skill_rejectOverlay_R4wX7a{z-index:1001;place-items:center;padding:16px;display:grid}.run2skill_legacyDialog_R4wX7a{z-index:1000;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);box-shadow:0 16px 48px var(--dsw-alias-bg-mask-1);border-radius:16px;grid-template-columns:minmax(16rem,24rem) minmax(0,1fr);gap:16px;padding:16px;display:grid;position:fixed;inset:5vh 5vw;overflow:hidden}.run2skill_blocked_R4wX7a{pointer-events:none;display:contents}.run2skill_queue_R4wX7a,.run2skill_legacyDetail_R4wX7a{min-width:0;overflow:auto}.run2skill_legacyHeader_R4wX7a{justify-content:space-between;align-items:center;gap:8px;display:flex}.run2skill_legacyList_R4wX7a{margin:0;padding:0;list-style:none}.run2skill_rejectCard_R4wX7a{background:var(--dsw-alias-bg-layer-1);border-radius:16px;max-width:32rem;padding:16px}.run2skill_textBlock_R4wX7a{white-space:pre-wrap;overflow-wrap:anywhere;unicode-bidi:isolate;overflow:auto}.run2skill_previewFacts_R4wX7a{grid-template-columns:max-content 1fr;gap:6px 12px;display:grid}.run2skill_previewFacts_R4wX7a dt,.run2skill_previewFacts_R4wX7a dd{margin:0}@container (width>=760px){.run2skill_proposalLayout_R4wX7a{grid-template-columns:minmax(240px,.8fr) minmax(0,1.6fr);gap:20px}}@container (width<=420px){.run2skill_proposalToolbar_R4wX7a,.run2skill_detailFacts_R4wX7a{grid-template-columns:1fr}.run2skill_proposalToolbar_R4wX7a>:last-child{justify-self:start}.run2skill_detailFacts_R4wX7a dt:not(:first-child){margin-top:8px}}@media (width<=720px){.run2skill_sectionBody_R4wX7a{padding:8px 18px 20px}.run2skill_activityItem_R4wX7a{flex-direction:column;align-items:flex-start}}";
4223
4223
  if (typeof document !== "undefined") upsertRun2skillStyle(css);
4224
4224
  var _run2skill_css_run2skill_settings_page_module_css_default = {
4225
- "proposalLayout": "run2skill_proposalLayout_OghXMq",
4226
- "section": "run2skill_section_OghXMq",
4227
- "danger": "run2skill_danger_OghXMq",
4228
- "legacyDetail": "run2skill_legacyDetail_OghXMq",
4229
- "attentionList": "run2skill_attentionList_OghXMq",
4230
- "legacyList": "run2skill_legacyList_OghXMq",
4231
- "page": "run2skill_page_OghXMq",
4232
- "modeGroup": "run2skill_modeGroup_OghXMq",
4233
- "rejectCard": "run2skill_rejectCard_OghXMq",
4234
- "previewFacts": "run2skill_previewFacts_OghXMq",
4235
- "proposalList": "run2skill_proposalList_OghXMq",
4236
- "legacyHeader": "run2skill_legacyHeader_OghXMq",
4237
- "textBlock": "run2skill_textBlock_OghXMq",
4238
- "rejectOverlay": "run2skill_rejectOverlay_OghXMq",
4239
- "queue": "run2skill_queue_OghXMq",
4240
- "backdrop": "run2skill_backdrop_OghXMq",
4241
- "status": "run2skill_status_OghXMq",
4242
- "intro": "run2skill_intro_OghXMq",
4243
- "detail": "run2skill_detail_OghXMq",
4244
- "legacyDialog": "run2skill_legacyDialog_OghXMq",
4245
- "muted": "run2skill_muted_OghXMq",
4246
- "sectionBody": "run2skill_sectionBody_OghXMq",
4247
- "blocked": "run2skill_blocked_OghXMq",
4248
- "toolbar": "run2skill_toolbar_OghXMq",
4249
- "actions": "run2skill_actions_OghXMq",
4250
- "proposalListButton": "run2skill_proposalListButton_OghXMq"
4225
+ "textBlock": "run2skill_textBlock_R4wX7a",
4226
+ "previewFacts": "run2skill_previewFacts_R4wX7a",
4227
+ "attentionList": "run2skill_attentionList_R4wX7a",
4228
+ "rejectCard": "run2skill_rejectCard_R4wX7a",
4229
+ "status": "run2skill_status_R4wX7a",
4230
+ "empty": "run2skill_empty_R4wX7a",
4231
+ "proposalListButton": "run2skill_proposalListButton_R4wX7a",
4232
+ "danger": "run2skill_danger_R4wX7a",
4233
+ "page": "run2skill_page_R4wX7a",
4234
+ "attentionGroup": "run2skill_attentionGroup_R4wX7a",
4235
+ "sectionTitle": "run2skill_sectionTitle_R4wX7a",
4236
+ "backdrop": "run2skill_backdrop_R4wX7a",
4237
+ "blocked": "run2skill_blocked_R4wX7a",
4238
+ "actions": "run2skill_actions_R4wX7a",
4239
+ "legacyDialog": "run2skill_legacyDialog_R4wX7a",
4240
+ "modeGroup": "run2skill_modeGroup_R4wX7a",
4241
+ "activityItem": "run2skill_activityItem_R4wX7a",
4242
+ "proposalToolbarCompact": "run2skill_proposalToolbarCompact_R4wX7a",
4243
+ "detail": "run2skill_detail_R4wX7a",
4244
+ "intro": "run2skill_intro_R4wX7a",
4245
+ "technicalDetails": "run2skill_technicalDetails_R4wX7a",
4246
+ "muted": "run2skill_muted_R4wX7a",
4247
+ "activitySummary": "run2skill_activitySummary_R4wX7a",
4248
+ "proposalList": "run2skill_proposalList_R4wX7a",
4249
+ "detailFacts": "run2skill_detailFacts_R4wX7a",
4250
+ "legacyHeader": "run2skill_legacyHeader_R4wX7a",
4251
+ "sectionBody": "run2skill_sectionBody_R4wX7a",
4252
+ "sectionHeader": "run2skill_sectionHeader_R4wX7a",
4253
+ "proposalLayout": "run2skill_proposalLayout_R4wX7a",
4254
+ "activityList": "run2skill_activityList_R4wX7a",
4255
+ "rejectOverlay": "run2skill_rejectOverlay_R4wX7a",
4256
+ "toolbar": "run2skill_toolbar_R4wX7a",
4257
+ "section": "run2skill_section_R4wX7a",
4258
+ "proposalToolbar": "run2skill_proposalToolbar_R4wX7a",
4259
+ "queue": "run2skill_queue_R4wX7a",
4260
+ "legacyDetail": "run2skill_legacyDetail_R4wX7a",
4261
+ "proposalName": "run2skill_proposalName_R4wX7a",
4262
+ "proposalMeta": "run2skill_proposalMeta_R4wX7a",
4263
+ "legacyList": "run2skill_legacyList_R4wX7a"
4251
4264
  };
4252
4265
  //#endregion
4253
4266
  //#region src/client/purge-settings.ts
@@ -4258,10 +4271,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4258
4271
  const digest = string().regex(/^[a-f0-9]{64}$/);
4259
4272
  const isoDateTime = string().datetime({ offset: true });
4260
4273
  const count = number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
4261
- const scopeBinding = discriminatedUnion("scope", [object({
4274
+ const projectBinding = object({
4262
4275
  scope: literal("PROJECT"),
4263
4276
  workspaceId: string().min(1).max(256)
4264
- }).strict(), object({ scope: literal("USER") }).strict()]);
4277
+ }).strict();
4278
+ const scopeBinding = discriminatedUnion("scope", [
4279
+ object({ scope: literal("ALL") }).strict(),
4280
+ projectBinding,
4281
+ object({ scope: literal("USER") }).strict()
4282
+ ]);
4265
4283
  const previewSchema = object({
4266
4284
  apiVersion: literal(1),
4267
4285
  previewId,
@@ -4271,6 +4289,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4271
4289
  hideBefore: isoDateTime,
4272
4290
  workItemCount: count,
4273
4291
  lineageCount: count,
4292
+ derivedRecordCount: count,
4274
4293
  blockedOrUnprovenCount: count,
4275
4294
  willDelete: array(object({
4276
4295
  kind: _enum(["WORK_ITEMS", "LINEAGES"]),
@@ -4369,21 +4388,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4369
4388
  throw new PurgeResponseError({ code: "PURGE_STORAGE_UNAVAILABLE" });
4370
4389
  }
4371
4390
  function completionAnnouncement(scope, receipt) {
4372
- return `${scope === void 0 ? "run2skill 数据" : `${scope} run2skill 数据`}清理完成:${String(receipt.deletedWorkItems)} 条待处理数据,${String(receipt.deletedLineages)} 条发布沿袭记录。`;
4391
+ return `${scope === "ALL" ? "Run2Skill 缓存" : scope === void 0 ? "Run2Skill 数据" : `${scope} Run2Skill 数据`}清理完成:${String(receipt.deletedWorkItems)} 条待处理数据,${String(receipt.deletedLineages)} 条 Skill 关联记录。`;
4373
4392
  }
4374
4393
  function polledCompletionAnnouncement(scope) {
4375
- return `${scope === void 0 ? "" : `${scope} `}run2skill 数据清理完成。`;
4394
+ return scope === "ALL" ? "Run2Skill 缓存清理完成。" : `${scope === void 0 ? "" : `${scope} `}Run2Skill 数据清理完成。`;
4376
4395
  }
4377
4396
  function errorAnnouncement(error, durableBoundary = false) {
4378
4397
  if (error.code === "PURGE_PREVIEW_STALE") return "清理预览已失效,请重新预览后确认。";
4379
- if (error.code === "PURGE_BUSY") return `当前有 ${String(error.busyPublicationCount ?? 0)} 条正在发布;请等待发布完成后重新预览。`;
4398
+ if (error.code === "PURGE_BUSY") return `当前有 ${String(error.busyPublicationCount ?? 0)} 份技能草稿正在保存;请等待保存完成后重新预览。`;
4380
4399
  if (error.code === "PURGE_ALREADY_RUNNING") return "已有一项数据清理正在运行,请等待完成。";
4381
4400
  if (error.code === "PURGE_SCOPE_UNAVAILABLE") return "当前作用域无法可靠确认,未执行清理。";
4382
4401
  if (error.code === "PURGE_INCOMPATIBLE") return "当前数据版本不兼容,未执行清理。";
4383
- if (error.code === "PURGE_FENCE_LIMIT") return "PROJECT 清理保护记录已达上限,未执行清理。";
4402
+ if (error.code === "PURGE_FENCE_LIMIT") return "缓存清理保护记录已达上限,未执行清理。";
4384
4403
  return durableBoundary ? "数据清理未完成;已建立的清理边界继续隐藏,可重试。" : "数据清理暂不可用;未确认已建立清理边界,请稍后重试。";
4385
4404
  }
4386
4405
  const initialState$1 = {
4406
+ hostDataEpoch: 0,
4387
4407
  statusPhase: "LOADING",
4388
4408
  previewPending: false,
4389
4409
  mutationPending: false,
@@ -4523,6 +4543,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4523
4543
  await this.#execute(async (signal) => {
4524
4544
  this.#publish({
4525
4545
  ...this.#state,
4546
+ hostDataEpoch: this.#state.hostDataEpoch + 1,
4526
4547
  mutationPending: true,
4527
4548
  error: void 0,
4528
4549
  announcement: ""
@@ -4558,6 +4579,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4558
4579
  await this.#execute(async (signal) => {
4559
4580
  this.#publish({
4560
4581
  ...this.#state,
4582
+ hostDataEpoch: this.#state.hostDataEpoch + 1,
4561
4583
  mutationPending: true,
4562
4584
  error: void 0,
4563
4585
  announcement: "正在重试数据清理。"
@@ -4591,6 +4613,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4591
4613
  if (receipt.state === "COMPLETED") {
4592
4614
  this.#publish({
4593
4615
  ...this.#state,
4616
+ hostDataEpoch: this.#state.hostDataEpoch + 1,
4594
4617
  statusPhase: "READY",
4595
4618
  status: {
4596
4619
  apiVersion: 1,
@@ -4610,7 +4633,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4610
4633
  mutationPending: false,
4611
4634
  preview: void 0,
4612
4635
  inProgressReceipt: receipt,
4613
- announcement: `run2skill 数据清理进行中:${receipt.phase ?? "HIDING"}。`
4636
+ announcement: `Run2Skill 数据清理进行中:${receipt.phase ?? "HIDING"}。`
4614
4637
  });
4615
4638
  }
4616
4639
  async #readStatusAfterFailure(error, durableBoundary = false) {
@@ -4635,8 +4658,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4635
4658
  const status = parseValue$1(statusSchema, await this.call("purge/status", { apiVersion: 1 }, abort.signal));
4636
4659
  if (this.#disposed || abort.signal.aborted) return;
4637
4660
  const completed = status.state === "IDLE" && (this.#state.status?.state === "IN_PROGRESS" || this.#state.inProgressReceipt?.state === "IN_PROGRESS");
4661
+ const started = status.state === "IN_PROGRESS" && this.#state.status?.state !== "IN_PROGRESS" && this.#state.inProgressReceipt?.state !== "IN_PROGRESS" && !this.#state.mutationPending;
4638
4662
  this.#publish({
4639
4663
  ...this.#state,
4664
+ hostDataEpoch: started || completed ? this.#state.hostDataEpoch + 1 : this.#state.hostDataEpoch,
4640
4665
  statusPhase: "READY",
4641
4666
  status,
4642
4667
  inProgressReceipt: status.state === "IDLE" ? void 0 : this.#state.inProgressReceipt,
@@ -4699,13 +4724,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4699
4724
  };
4700
4725
  const phaseCopy = {
4701
4726
  HIDING: "正在隐藏命中数据",
4702
- DELETING_LINEAGES: "正在删除发布沿袭记录",
4727
+ DELETING_LINEAGES: "正在删除 Skill 关联记录",
4703
4728
  DELETING_WORK_ITEMS: "正在删除待处理数据",
4704
4729
  VERIFYING: "正在验证清理结果"
4705
4730
  };
4706
4731
  function PreviewSummary({ preview }) {
4707
- const keep = Object.fromEntries(preview.willKeep.map((item) => [item.reason, item.count]));
4708
- return (0, react.createElement)("dl", null, (0, react.createElement)("dt", null, "将删除"), (0, react.createElement)("dd", null, `${String(preview.workItemCount)} 条待处理数据;${String(preview.lineageCount)} 条发布沿袭记录`), (0, react.createElement)("dt", null, "将保留"), (0, react.createElement)("dd", null, `${String(keep.KEEP_NEW ?? 0)} 条边界后新数据;${String(keep.KEEP_SCOPE ?? 0)} 条其他作用域数据`), (0, react.createElement)("dt", null, "无法证明"), (0, react.createElement)("dd", null, `${String(preview.blockedOrUnprovenCount)} 条无法证明作用域的数据将保留`), (0, react.createElement)("dt", null, "正在发布"), (0, react.createElement)("dd", null, `${String(preview.busyPublicationCount)} 条;存在时确认会安全拒绝`));
4732
+ return (0, react.createElement)("dl", null, (0, react.createElement)("dt", null, "将删除"), (0, react.createElement)("dd", null, `${String(preview.workItemCount)} 条待处理数据;${String(preview.lineageCount)} 条 Skill 关联记录;${String(preview.derivedRecordCount)} 条其他中间缓存`), (0, react.createElement)("dt", null, "将保留"), (0, react.createElement)("dd", null, "已发布 Skill、DSH 原始会话记录和非 Run2Skill 设置"), (0, react.createElement)("dt", null, "正在保存的技能草稿"), (0, react.createElement)("dd", null, `${String(preview.busyPublicationCount)} 份;存在时不会开始清理`));
4709
4733
  }
4710
4734
  function PurgeConfirmationDialog(props) {
4711
4735
  const dialogRef = (0, react.useRef)(null);
@@ -4742,8 +4766,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4742
4766
  if (preview === void 0 || scope === void 0) return null;
4743
4767
  return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
4744
4768
  open: true,
4745
- title: `确认清理 ${scope} run2skill 数据?`,
4746
- description: "此操作只清理本次预览边界内的 run2skill 数据,不会卸载插件。",
4769
+ title: scope === "ALL" ? "确认清理所有缓存?" : `确认清理 ${scope} Run2Skill 数据?`,
4770
+ description: "此操作只清理 Run2Skill 自己产生的中间缓存数据,不会卸载插件。",
4747
4771
  closeLabel: "关闭清理确认框",
4748
4772
  onClose: () => {
4749
4773
  props.controller.cancelPreview();
@@ -4774,7 +4798,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4774
4798
  event.preventDefault();
4775
4799
  }, dialogRef.current, typeof document === "undefined" ? void 0 : document.activeElement);
4776
4800
  }
4777
- }, (0, react.createElement)("ul", null, (0, react.createElement)("li", null, "删除 run2skill 的过滤 Evidence、Experience、pending、Proposal、Revision metadata、usage 和相关审计事实。"), (0, react.createElement)("li", null, "保留 DSH Session Log。"), (0, react.createElement)("li", null, "保留所有已发布的原生 Skill。"), (0, react.createElement)("li", null, "删除 Lineage 后,保留的 Skill 将作为普通现有 Skill 使用。")), (0, react.createElement)(PreviewSummary, { preview })));
4801
+ }, (0, react.createElement)("ul", null, (0, react.createElement)("li", null, "删除 Run2Skill 产生的中间缓存、待处理技能草稿、失败与非敏感诊断记录。"), (0, react.createElement)("li", null, "保留 DSH 的原始会话记录。"), (0, react.createElement)("li", null, "保留所有已发布的原生 Skill。"), (0, react.createElement)("li", null, "删除 Skill 关联记录后,保留的 Skill 仍可作为普通 Skill 使用。")), (0, react.createElement)(PreviewSummary, { preview })));
4778
4802
  }
4779
4803
  function PurgeSettingsSection(props) {
4780
4804
  const surfaceActive = props.active ?? true;
@@ -4787,31 +4811,29 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4787
4811
  else props.controller.pause();
4788
4812
  }, [surfaceActive, props.controller]);
4789
4813
  const state = (0, react.useSyncExternalStore)(props.controller.subscribe, props.controller.snapshot, props.controller.snapshot);
4814
+ const lastCompletion = (0, react.useRef)("");
4815
+ (0, react.useEffect)(() => {
4816
+ if (!state.announcement.includes("清理完成") || state.announcement === lastCompletion.current) return;
4817
+ lastCompletion.current = state.announcement;
4818
+ props.onCompleted?.();
4819
+ }, [props.onCompleted, state.announcement]);
4790
4820
  const restoreRef = (0, react.useMemo)(() => ({ current: null }), []);
4791
4821
  const active = state.status?.state === "IN_PROGRESS" ? state.status : void 0;
4792
4822
  const activeReceipt = state.inProgressReceipt?.state === "IN_PROGRESS" ? state.inProgressReceipt : void 0;
4793
4823
  const activePhase = active?.phase ?? activeReceipt?.phase ?? (activeReceipt === void 0 ? void 0 : "HIDING");
4794
4824
  const disabled = state.previewPending || state.mutationPending || active !== void 0 || activeReceipt !== void 0;
4795
- return (0, react.createElement)("section", { "aria-labelledby": "run2skill-purge-heading" }, (0, react.createElement)("h3", { id: "run2skill-purge-heading" }, "清理 run2skill 数据"), (0, react.createElement)("p", null, "清理只影响 run2skill 派生数据;不会删除 DSH Session Log 或已发布 Skill。"), (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.actions }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
4796
- variant: "outline",
4797
- icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16),
4798
- disabled,
4799
- onClick: (event) => {
4800
- restoreRef.current = event.currentTarget;
4801
- props.controller.preview("PROJECT");
4802
- }
4803
- }, "预览并清理当前 PROJECT 数据"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
4825
+ return (0, react.createElement)("section", { "aria-labelledby": "run2skill-purge-heading" }, (0, react.createElement)("h3", { id: "run2skill-purge-heading" }, "缓存清理"), (0, react.createElement)("p", null, "清理 Run2Skill 自己产生的中间缓存数据"), (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.actions }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
4804
4826
  variant: "outline",
4805
4827
  icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16),
4806
4828
  disabled,
4807
4829
  onClick: (event) => {
4808
4830
  restoreRef.current = event.currentTarget;
4809
- props.controller.preview("USER");
4831
+ props.controller.preview("ALL");
4810
4832
  }
4811
- }, "预览并清理 USER 数据")), state.statusPhase === "LOADING" ? (0, react.createElement)("p", { role: "status" }, "正在读取 Purge 状态…") : null, state.statusPhase === "UNAVAILABLE" ? (0, react.createElement)("p", { role: "alert" }, "Purge 状态暂不可用") : null, state.statusPhase === "STALE" ? (0, react.createElement)("p", { role: "status" }, "Purge 状态可能已过期") : null, state.previewPending ? (0, react.createElement)("p", { role: "status" }, "正在生成清理预览…") : null, activePhase === void 0 ? null : (0, react.createElement)("div", {
4833
+ }, "清理所有缓存")), state.statusPhase === "LOADING" ? (0, react.createElement)("p", { role: "status" }, "正在读取数据清理状态…") : null, state.statusPhase === "UNAVAILABLE" ? (0, react.createElement)("p", { role: "alert" }, "数据清理状态暂不可用") : null, state.statusPhase === "STALE" ? (0, react.createElement)("p", { role: "status" }, "数据清理状态可能已过期") : null, state.previewPending ? (0, react.createElement)("p", { role: "status" }, "正在生成清理预览…") : null, activePhase === void 0 ? null : (0, react.createElement)("div", {
4812
4834
  role: "status",
4813
- "aria-label": "当前 Purge 状态"
4814
- }, (0, react.createElement)("p", null, phaseCopy[activePhase]), (0, react.createElement)("p", null, `已删除 ${String(active?.deletedWorkItems ?? activeReceipt?.deletedWorkItems ?? 0)} 条待处理数据和 ${String(active?.deletedLineages ?? activeReceipt?.deletedLineages ?? 0)} 条发布沿袭记录。`), active?.lastError === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("p", { role: "alert" }, `清理失败:${active.lastError.code}`), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
4835
+ "aria-label": "当前数据清理状态"
4836
+ }, (0, react.createElement)("p", null, phaseCopy[activePhase]), (0, react.createElement)("p", null, `已删除 ${String(active?.deletedWorkItems ?? activeReceipt?.deletedWorkItems ?? 0)} 条待处理数据和 ${String(active?.deletedLineages ?? activeReceipt?.deletedLineages ?? 0)} 条 Skill 关联记录。`), active?.lastError === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("p", { role: "alert" }, `清理失败:${active.lastError.code}`), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
4815
4837
  variant: "outline",
4816
4838
  icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16),
4817
4839
  disabled: state.mutationPending,
@@ -4820,7 +4842,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4820
4842
  }
4821
4843
  }, state.mutationPending ? "正在重试…" : "重试清理"))), state.error === void 0 ? null : (0, react.createElement)("p", { role: "alert" }, state.announcement), (0, react.createElement)("div", {
4822
4844
  role: "status",
4823
- "aria-label": "Purge 状态播报",
4845
+ "aria-label": "数据清理状态播报",
4824
4846
  "aria-live": "polite",
4825
4847
  "aria-atomic": true
4826
4848
  }, state.announcement), (0, react.createElement)(PurgeConfirmationDialog, {
@@ -4899,14 +4921,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4899
4921
  onClick: () => {
4900
4922
  setOpen((value) => !value);
4901
4923
  }
4902
- }, "run2skill", (0, react.createElement)("span", null, "将真实执行中的明确经验转为待审核 Skill Proposal")), open ? (0, react.createElement)("div", null, (0, react.createElement)("label", null, (0, react.createElement)("input", {
4924
+ }, "Run2Skill", (0, react.createElement)("span", null, "将真实执行中的明确经验整理为待确认的技能草稿")), open ? (0, react.createElement)("div", null, (0, react.createElement)("label", null, (0, react.createElement)("input", {
4903
4925
  type: "checkbox",
4904
4926
  checked: state.automaticLearning === true,
4905
4927
  disabled,
4906
4928
  onChange: (event) => {
4907
4929
  props.controller.setAutomaticLearning(event.currentTarget.checked);
4908
4930
  }
4909
- }), "Automatic Learning"), (0, react.createElement)("p", null, "关闭后暂停普通自动学习;显式“保存为 Skill”仍会持久保存。已开始的分析继续使用启动时快照。"), (0, react.createElement)("p", null, "Learning 模型沿用发起 Session 的 provider/model(inherit-session)。"), state.error === void 0 ? null : (0, react.createElement)("p", { role: "status" }, "设置已变化,请刷新后重试。"), (0, react.createElement)(PurgeSettingsSection, { controller: props.purgeController })) : null);
4931
+ }), "自动学习"), (0, react.createElement)("p", null, "关闭后暂停普通自动学习;显式“保存为 Skill”仍会持久保存。已开始的分析继续使用启动时快照。"), (0, react.createElement)("p", null, "分析时沿用发起会话已经选择的模型。"), state.error === void 0 ? null : (0, react.createElement)("p", { role: "status" }, "设置已变化,请刷新后重试。"), (0, react.createElement)(PurgeSettingsSection, { controller: props.purgeController })) : null);
4910
4932
  }
4911
4933
  function applyAutomaticLearningSettingsClient(context) {
4912
4934
  const controller = new AutomaticLearningSettingsController(context.settingsScope.bind({ namespace: "run2skill" }));
@@ -4955,6 +4977,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4955
4977
  "PUBLISHED",
4956
4978
  "PUBLISH_FAILED"
4957
4979
  ]);
4980
+ const attentionAction = object({
4981
+ actionKey: string().regex(/^act_[a-f0-9]{64}$/),
4982
+ subjectId: workItemId,
4983
+ kind: _enum([
4984
+ "REVIEW_PROPOSAL",
4985
+ "REFRESH_PROPOSAL",
4986
+ "RETRY_PUBLICATION"
4987
+ ]),
4988
+ proposalRef
4989
+ }).strict();
4958
4990
  const rootDisplay = object({
4959
4991
  state: _enum(["EXISTING", "ABSENT"]),
4960
4992
  scope: _enum(["PROJECT", "USER"]),
@@ -5028,12 +5060,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5028
5060
  supportingExperienceIds: array(string().regex(/^exp_[a-f0-9]{64}$/)).min(1).max(3),
5029
5061
  catalogObservationDigest: sha256,
5030
5062
  curationRationale: string().min(1).max(4096),
5031
- actionBinding,
5063
+ actionBinding: actionBinding.optional(),
5032
5064
  proposalId,
5033
5065
  digest: sha256
5034
- }).strict().refine((value) => value.kind === value.actionBinding.kind, {
5035
- path: ["actionBinding"],
5036
- message: "action binding kind must match proposal kind"
5066
+ }).strict().superRefine((value, context) => {
5067
+ if (value.actionBinding !== void 0 && value.kind !== value.actionBinding.kind) context.addIssue({
5068
+ code: "custom",
5069
+ path: ["actionBinding"],
5070
+ message: "action binding kind must match proposal kind"
5071
+ });
5037
5072
  });
5038
5073
  const evidence = object({
5039
5074
  source: literal("USER_DIRECT"),
@@ -5125,8 +5160,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5125
5160
  turnEndSeq: nonNegativeInteger
5126
5161
  }).strict(),
5127
5162
  evidenceRefs: array(evidence).max(16),
5128
- experiences: array(experience).max(3)
5129
- }).strict();
5163
+ experiences: array(experience).max(3),
5164
+ action: attentionAction.optional()
5165
+ }).strict().superRefine((value, context) => {
5166
+ if (value.processingState === "READY_FOR_REVIEW" && value.publicationOutcome === "PENDING_REVIEW" && value.proposal.actionBinding === void 0) context.addIssue({
5167
+ code: "custom",
5168
+ path: ["proposal", "actionBinding"],
5169
+ message: "approvable Proposal requires a safe action binding"
5170
+ });
5171
+ });
5130
5172
  const receipt = object({
5131
5173
  apiVersion: literal(1),
5132
5174
  workItemId,
@@ -5171,38 +5213,51 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5171
5213
  approve: "proposals/approve",
5172
5214
  reject: "proposals/reject",
5173
5215
  retry: "proposals/retry",
5216
+ refresh: "proposals/refresh",
5174
5217
  confirmDiscard: "coverage/confirm-discard"
5175
5218
  };
5219
+ function describeProposalKind(kind) {
5220
+ if (kind === "CREATE") return "新建技能";
5221
+ if (kind === "MERGE") return "更新已有技能";
5222
+ return "无需新建技能";
5223
+ }
5224
+ function describePersistenceScope(scope) {
5225
+ return scope === "PROJECT" ? "仅当前项目可用" : "所有项目可用";
5226
+ }
5227
+ function describeProposalScope(kind, scope) {
5228
+ if (kind !== "DISCARD") return describePersistenceScope(scope);
5229
+ return scope === "PROJECT" ? "本次经验来自当前项目" : "本次经验适用于所有项目";
5230
+ }
5176
5231
  function describeProposalOutcome(detail) {
5177
- if (detail.publicationOutcome === "PUBLISHED") return "Skill 已发布并完成 Registry 回读";
5178
- if (detail.publicationOutcome === "DISCARDED") return "Proposal 已离开待处理队列,Skill 未更改";
5179
- if (detail.publicationOutcome === "NEEDS_REFRESH") return "发布绑定已变化,需要生成新的 Proposal";
5180
- if (detail.publicationOutcome === "PUBLISH_FAILED") return "发布失败,可重试";
5232
+ if (detail.publicationOutcome === "PUBLISHED") return "Skill 已保存,DSH 已确认可以使用";
5233
+ if (detail.publicationOutcome === "DISCARDED") return "技能草稿已放弃,Skill 未更改";
5234
+ if (detail.publicationOutcome === "NEEDS_REFRESH") return "保存目标已变化,需要生成新的技能草稿";
5235
+ if (detail.publicationOutcome === "PUBLISH_FAILED") return "保存失败,可重试";
5181
5236
  if (detail.processingState === "NEEDS_ATTENTION") return "需要处理后才能继续";
5182
- if (detail.processingState === "PUBLISHING") return "已批准,正在发布";
5237
+ if (detail.processingState === "PUBLISHING") return "已确认,正在保存";
5183
5238
  return "待审核";
5184
5239
  }
5185
5240
  function describeProposalListItem(item) {
5186
5241
  return describeProposalOutcome(item);
5187
5242
  }
5188
5243
  function describeReviewDecision(decision) {
5189
- if (decision === "APPROVED") return "已批准";
5190
- if (decision === "REJECTED") return "已拒绝";
5244
+ if (decision === "APPROVED") return "已确认";
5245
+ if (decision === "REJECTED") return "已放弃";
5191
5246
  return "待决定";
5192
5247
  }
5193
5248
  function describeProcessingState(state) {
5194
- if (state === "PUBLISHING") return "正在发布";
5249
+ if (state === "PUBLISHING") return "正在保存";
5195
5250
  if (state === "NEEDS_ATTENTION") return "需要处理";
5196
5251
  if (state === "TERMINAL") return "已结束";
5197
5252
  return "待审核";
5198
5253
  }
5199
5254
  function describePublicationOutcome(outcome) {
5200
- if (outcome === "PUBLISHED") return "已发布并完成 Registry 回读";
5201
- if (outcome === "DISCARDED") return "未修改 Skill,Proposal 已离开队列";
5202
- if (outcome === "NEEDS_REFRESH") return "发布绑定已变化,需要新 Proposal";
5203
- if (outcome === "PUBLISH_FAILED") return "发布失败,可重试";
5204
- if (outcome === "NEEDS_ATTENTION") return "发布前事实需要处理";
5205
- return "尚未产生发布结果";
5255
+ if (outcome === "PUBLISHED") return "已保存,DSH 已确认可以使用";
5256
+ if (outcome === "DISCARDED") return "未修改 Skill,技能草稿已放弃";
5257
+ if (outcome === "NEEDS_REFRESH") return "保存目标已变化,需要新的技能草稿";
5258
+ if (outcome === "PUBLISH_FAILED") return "保存失败,可重试";
5259
+ if (outcome === "NEEDS_ATTENTION") return "保存前需要先处理当前问题";
5260
+ return "尚未产生保存结果";
5206
5261
  }
5207
5262
  function browserEnvironment$1() {
5208
5263
  return {
@@ -5317,7 +5372,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5317
5372
  open: true
5318
5373
  });
5319
5374
  await this.whenIdle();
5320
- if (!this.#disposed && this.#state.open) await this.#loadList();
5375
+ if (this.#disposed || !this.#state.open) return;
5376
+ if (this.options.attentionDriven === true && this.#scopeAccess().actions.length === 0) {
5377
+ this.#publish({
5378
+ ...this.#state,
5379
+ listPhase: "READY",
5380
+ items: [],
5381
+ selectedProposalId: void 0,
5382
+ detailPhase: "IDLE",
5383
+ detail: void 0
5384
+ });
5385
+ return;
5386
+ }
5387
+ await this.#loadList();
5321
5388
  }
5322
5389
  close() {
5323
5390
  if (this.#disposed) return;
@@ -5366,19 +5433,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5366
5433
  await this.whenIdle();
5367
5434
  const detail = this.#state.detail;
5368
5435
  if (this.#disposed || detail === void 0 || this.#state.mutationPending) return;
5369
- const proposalRef = {
5436
+ const proposalRef = detail.action?.proposalRef ?? {
5370
5437
  proposalId: detail.proposal.proposalId,
5371
5438
  revision: detail.proposal.revision,
5372
5439
  digest: detail.proposal.digest
5373
5440
  };
5374
- const targetEndpoint = action === "APPROVE" ? endpoint.approve : action === "REJECT" ? endpoint.reject : action === "RETRY" ? endpoint.retry : endpoint.confirmDiscard;
5441
+ const targetEndpoint = action === "APPROVE" ? endpoint.approve : action === "REJECT" ? endpoint.reject : action === "REFRESH" ? endpoint.refresh : action === "RETRY" ? endpoint.retry : endpoint.confirmDiscard;
5375
5442
  const request = {
5376
5443
  apiVersion: 1,
5377
5444
  workItemId: detail.workItemId,
5378
5445
  workItemRevision: detail.workItemRevision,
5379
5446
  proposalRef,
5380
5447
  currentScope: this.#scopeAccess().currentScope,
5381
- action: this.#scopeAccess().actions.find((candidate) => candidate.proposalRef.proposalId === proposalRef.proposalId),
5448
+ action: detail.action ?? this.#scopeAccess().actions.find((candidate) => candidate.proposalRef.proposalId === proposalRef.proposalId),
5382
5449
  ...action === "REJECT" ? { confirm: true } : {}
5383
5450
  };
5384
5451
  await this.#execute(async (signal) => {
@@ -5390,7 +5457,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5390
5457
  });
5391
5458
  const receipt = parseMutationReceipt(await this.call(targetEndpoint, request, signal));
5392
5459
  if (receipt === void 0) throw new Error("invalid mutation receipt");
5393
- const announcement = describeProposalOutcome(receipt) || "Proposal 状态已更新";
5460
+ const announcement = describeProposalOutcome(receipt) || "技能草稿状态已更新";
5394
5461
  this.#publish({
5395
5462
  ...this.#state,
5396
5463
  mutationPending: false,
@@ -5447,6 +5514,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5447
5514
  async #refreshWithin(signal) {
5448
5515
  if (this.options.attentionDriven === true) {
5449
5516
  if (!this.#state.open) return;
5517
+ if (this.#scopeAccess().actions.length === 0) {
5518
+ this.#publish({
5519
+ ...this.#state,
5520
+ listPhase: "READY",
5521
+ items: [],
5522
+ selectedProposalId: void 0,
5523
+ detailPhase: "IDLE",
5524
+ detail: void 0
5525
+ });
5526
+ return;
5527
+ }
5450
5528
  await this.#loadListWithin(signal);
5451
5529
  await this.#refreshPublishingDetailWithin(signal);
5452
5530
  return;
@@ -5496,7 +5574,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5496
5574
  });
5497
5575
  }
5498
5576
  async #loadListWithin(signal) {
5499
- this.#publish({
5577
+ if (this.#state.listPhase !== "READY") this.#publish({
5500
5578
  ...this.#state,
5501
5579
  listPhase: "LOADING"
5502
5580
  });
@@ -5542,7 +5620,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5542
5620
  }
5543
5621
  #schedule() {
5544
5622
  if (this.#disposed || !this.#active) return;
5545
- const delay = this.#state.open ? PROPOSAL_ACTIVE_POLL_INTERVAL_MS : PROPOSAL_POLL_INTERVAL_MS;
5623
+ const hasVisibleWork = this.options.attentionDriven !== true || this.#scopeAccess().actions.length > 0;
5624
+ const delay = this.#state.open && hasVisibleWork ? PROPOSAL_ACTIVE_POLL_INTERVAL_MS : PROPOSAL_POLL_INTERVAL_MS;
5546
5625
  if (this.#timer !== void 0 && this.#timerDelay === delay) return;
5547
5626
  this.#unschedule();
5548
5627
  this.#timerDelay = delay;
@@ -5654,10 +5733,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5654
5733
  //#endregion
5655
5734
  //#region src/client/status-copy.ts
5656
5735
  function describeRun2skillHealth(status) {
5657
- if (status === "INCOMPATIBLE") return "run2skill 当前版本不兼容";
5658
- if (status === "DEGRADED") return "run2skill 暂时降级";
5659
- if (status === "RECOVERING") return "run2skill 正在恢复历史观察";
5660
- return "run2skill 已就绪";
5736
+ if (status === "INCOMPATIBLE") return "Run2Skill 当前版本不兼容";
5737
+ if (status === "DEGRADED") return "Run2Skill 当前功能受限";
5738
+ if (status === "RECOVERING") return "Run2Skill 正在恢复历史观察";
5739
+ return "Run2Skill 已就绪";
5661
5740
  }
5662
5741
  //#endregion
5663
5742
  //#region src/client/proposal-inbox-view.ts
@@ -5689,22 +5768,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5689
5768
  }
5690
5769
  function countLabel(state) {
5691
5770
  const queue = state.summary?.queue;
5692
- if (queue === void 0 || queue.completeness === "UNKNOWN") return "Skill 提案,待处理数量未知";
5771
+ if (queue === void 0 || queue.completeness === "UNKNOWN") return "技能草稿待处理数量未知";
5693
5772
  const total = queue.pendingReview + queue.publishing + queue.needsAttention;
5694
5773
  const facts = [
5695
- queue.pendingReview > 0 ? `${String(queue.pendingReview)} 条待审核` : void 0,
5696
- queue.publishing > 0 ? `${String(queue.publishing)} 条正在发布` : void 0,
5697
- queue.needsAttention > 0 ? `${String(queue.needsAttention)} 条需要处理` : void 0
5774
+ queue.pendingReview > 0 ? `${String(queue.pendingReview)} 份待审核` : void 0,
5775
+ queue.publishing > 0 ? `${String(queue.publishing)} 份正在保存` : void 0,
5776
+ queue.needsAttention > 0 ? `${String(queue.needsAttention)} 份需要处理` : void 0
5698
5777
  ].filter((fact) => fact !== void 0);
5699
- return facts.length === 0 ? "当前没有待处理 Skill 提案" : `${String(total)} 条 Skill 提案待处理:${facts.join(",")}`;
5778
+ return facts.length === 0 ? "当前没有待处理的技能草稿" : `${String(total)} 份技能草稿待处理:${facts.join(",")}`;
5700
5779
  }
5701
5780
  function describeProposalSummaryState(state) {
5702
- if (state.summaryPhase === "LOADING") return "Proposal 队列状态加载中";
5703
- if (state.summaryPhase === "UNAVAILABLE") return "Proposal 队列状态暂不可用";
5704
- if (state.summary === void 0) return "Proposal 队列状态未知";
5781
+ if (state.summaryPhase === "LOADING") return "正在加载技能草稿队列";
5782
+ if (state.summaryPhase === "UNAVAILABLE") return "技能草稿队列暂不可用";
5783
+ if (state.summary === void 0) return "技能草稿队列状态未知";
5705
5784
  const health = describeRun2skillHealth(state.summary.status);
5706
- const queue = state.summary.queue.completeness === "UNKNOWN" ? "待处理数量未知" : countLabel(state);
5707
- return state.summaryPhase === "STALE" ? `Proposal 队列状态可能已过期:${health};${queue}` : `${health};${queue}`;
5785
+ const queue = state.summary.queue.completeness === "UNKNOWN" ? "技能草稿待处理数量未知" : countLabel(state);
5786
+ return state.summaryPhase === "STALE" ? `技能草稿队列状态可能已过期:${health};${queue}` : `${health};${queue}`;
5708
5787
  }
5709
5788
  function ProposalInboxHeaderAction(props) {
5710
5789
  const controller = (0, react.useMemo)(() => new ProposalInboxController(props.workspaceId, props.callReview, void 0, props.scopeAccess === void 0 ? {} : { scopeAccess: props.scopeAccess }), [
@@ -5776,9 +5855,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5776
5855
  inert: props.rejectConfirm ? "" : void 0,
5777
5856
  className: props.rejectConfirm ? _run2skill_css_run2skill_settings_page_module_css_default.blocked : void 0
5778
5857
  }, (0, react.createElement)("section", {
5779
- "aria-label": "Proposal 待处理队列",
5858
+ "aria-label": "技能草稿待处理队列",
5780
5859
  className: _run2skill_css_run2skill_settings_page_module_css_default.queue
5781
- }, (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.legacyHeader }, (0, react.createElement)("h2", { id: "run2skill-proposal-inbox-title" }, "Skill Proposal Inbox"), (0, react.createElement)("button", {
5860
+ }, (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.legacyHeader }, (0, react.createElement)("h2", { id: "run2skill-proposal-inbox-title" }, "技能草稿"), (0, react.createElement)("button", {
5782
5861
  type: "button",
5783
5862
  "data-initial-focus": true,
5784
5863
  onClick: () => {
@@ -5787,7 +5866,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5787
5866
  }, "关闭")), (0, react.createElement)("p", { role: "status" }, countLabel(state)), (0, react.createElement)("p", {
5788
5867
  role: "status",
5789
5868
  "aria-live": "polite"
5790
- }, describeProposalSummaryState(state)), state.listPhase === "LOADING" ? (0, react.createElement)("p", null, "正在加载待处理队列…") : null, state.listPhase === "ERROR" ? (0, react.createElement)("p", { role: "alert" }, "待处理队列暂不可用") : null, state.listPhase === "READY" && state.items.length === 0 ? (0, react.createElement)("p", null, "当前没有待处理 Proposal") : null, (0, react.createElement)("ul", { className: _run2skill_css_run2skill_settings_page_module_css_default.legacyList }, ...state.items.map((item) => (0, react.createElement)("li", { key: item.proposalRef.proposalId }, (0, react.createElement)("button", {
5869
+ }, describeProposalSummaryState(state)), state.listPhase === "LOADING" ? (0, react.createElement)("p", null, "正在加载待处理队列…") : null, state.listPhase === "ERROR" ? (0, react.createElement)("p", { role: "alert" }, "待处理队列暂不可用") : null, state.listPhase === "READY" && state.items.length === 0 ? (0, react.createElement)("p", null, "当前没有待处理的技能草稿") : null, (0, react.createElement)("ul", { className: _run2skill_css_run2skill_settings_page_module_css_default.legacyList }, ...state.items.map((item) => (0, react.createElement)("li", { key: item.proposalRef.proposalId }, (0, react.createElement)("button", {
5791
5870
  type: "button",
5792
5871
  disabled: contentBlocked || state.detailPhase === "LOADING",
5793
5872
  "aria-current": state.selectedProposalId === item.proposalRef.proposalId ? "true" : void 0,
@@ -5795,10 +5874,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5795
5874
  controller.select(item.proposalRef.proposalId);
5796
5875
  },
5797
5876
  className: _run2skill_css_run2skill_settings_page_module_css_default.proposalListButton
5798
- }, `${item.kind} · ${makeSafeText(item.name)} · ${item.persistenceScope} · ${describeProposalListItem(item)}`))))), (0, react.createElement)("section", {
5799
- "aria-label": "Proposal 详情",
5877
+ }, `${describeProposalKind(item.kind)} · ${makeSafeText(item.name)} · ${describeProposalScope(item.kind, item.persistenceScope)} · ${describeProposalListItem(item)}`))))), (0, react.createElement)("section", {
5878
+ "aria-label": "技能草稿详情",
5800
5879
  className: _run2skill_css_run2skill_settings_page_module_css_default.legacyDetail
5801
- }, state.detailPhase === "IDLE" ? (0, react.createElement)("p", null, "选择一个 Proposal 查看完整事实") : null, state.detailPhase === "LOADING" ? (0, react.createElement)("p", null, "正在加载 Proposal 详情…") : null, state.detailPhase === "ERROR" ? (0, react.createElement)("p", { role: "alert" }, "Proposal 详情暂不可用") : null, state.detail === void 0 ? null : (0, react.createElement)(ProposalDetailView, {
5880
+ }, state.detailPhase === "IDLE" ? (0, react.createElement)("p", null, "选择一份技能草稿查看完整内容") : null, state.detailPhase === "LOADING" ? (0, react.createElement)("p", null, "正在加载技能草稿详情…") : null, state.detailPhase === "ERROR" ? (0, react.createElement)("p", { role: "alert" }, "技能草稿详情暂不可用") : null, state.detail === void 0 ? null : (0, react.createElement)(ProposalDetailView, {
5802
5881
  detail: state.detail,
5803
5882
  textMode: props.textMode,
5804
5883
  setTextMode: props.setTextMode,
@@ -5812,6 +5891,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5812
5891
  onRetry: () => {
5813
5892
  controller.mutate("RETRY");
5814
5893
  },
5894
+ onRefresh: () => {
5895
+ controller.mutate("REFRESH");
5896
+ },
5815
5897
  onConfirmDiscard: () => {
5816
5898
  controller.mutate("CONFIRM_DISCARD");
5817
5899
  }
@@ -5831,40 +5913,80 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5831
5913
  }
5832
5914
  function factsFromAction(detail) {
5833
5915
  const action = detail.proposal.actionBinding;
5916
+ if (action === void 0) {
5917
+ if (detail.publicationOutcome === "NEEDS_REFRESH") return "这份草稿的保存目标已失效;请生成新草稿后重新审核。";
5918
+ if (detail.publicationOutcome === "PUBLISH_FAILED") return "这份草稿的保存目标暂时不可确认;请等待目录恢复后重试保存。";
5919
+ return "这份草稿的保存目标暂时不可确认;请等待目录恢复后重新打开详情。";
5920
+ }
5834
5921
  if (action.kind === "CREATE") return [
5835
- `Root contract: ${action.rootBinding.rootContractVersion}`,
5836
- `Root resolver: ${action.rootBinding.resolverVersion}`,
5837
- `Expected provider/source: ${action.rootBinding.expectedProvider} / ${action.rootBinding.expectedSource}`,
5838
- `Resolution digest: ${action.rootBinding.resolutionContractDigest}`,
5839
- `Root state: ${action.rootBinding.state}`,
5840
- `Skill name: ${action.targetBinding.skillName}`,
5841
- `Skill bytes digest: ${detail.proposal.skillBytesDigest}`,
5842
- `Expected absence observed: ${action.expectedAbsence.observedAt}`,
5843
- "Bundle absent: yes",
5844
- "Skill file absent: yes",
5845
- "Flat Skill file absent: yes"
5922
+ `Skill 存储规则版本:${action.rootBinding.rootContractVersion}`,
5923
+ `Skill 存储定位器版本:${action.rootBinding.resolverVersion}`,
5924
+ `保存位置:${describeRootSource(action.rootBinding.expectedSource)}`,
5925
+ `存储定位规则校验值:${action.rootBinding.resolutionContractDigest}`,
5926
+ `保存目录:${describeRootState(action.rootBinding.state)}`,
5927
+ `Skill 名称:${action.targetBinding.skillName}`,
5928
+ `Skill 内容校验值:${detail.proposal.skillBytesDigest}`,
5929
+ `确认目标不存在的时间:${action.expectedAbsence.observedAt}`,
5930
+ "目标文件夹不存在:是",
5931
+ "目标 SKILL.md 不存在:是",
5932
+ "同名扁平 Skill 文件不存在:是"
5846
5933
  ].join("\n");
5847
5934
  if (action.kind === "MERGE") return [
5848
- `Root contract: ${action.rootBinding.rootContractVersion}`,
5849
- `Root resolver: ${action.rootBinding.resolverVersion}`,
5850
- `Expected provider/source: ${action.rootBinding.expectedProvider} / ${action.rootBinding.expectedSource}`,
5851
- `Resolution digest: ${action.rootBinding.resolutionContractDigest}`,
5852
- `Root state: ${action.rootBinding.state}`,
5853
- `Target identity: ${action.baseBinding.candidateKey}`,
5854
- `Skill name: ${action.targetBinding.skillName}`,
5855
- `Base digest: ${action.baseBinding.bytesDigest}`,
5856
- `Base observed: ${action.baseBinding.observedAt}`
5935
+ `Skill 存储规则版本:${action.rootBinding.rootContractVersion}`,
5936
+ `Skill 存储定位器版本:${action.rootBinding.resolverVersion}`,
5937
+ `保存位置:${describeRootSource(action.rootBinding.expectedSource)}`,
5938
+ `存储定位规则校验值:${action.rootBinding.resolutionContractDigest}`,
5939
+ `保存目录:${describeRootState(action.rootBinding.state)}`,
5940
+ `现有 Skill 标识:${action.baseBinding.candidateKey}`,
5941
+ `Skill 名称:${action.targetBinding.skillName}`,
5942
+ `原内容校验值:${action.baseBinding.bytesDigest}`,
5943
+ `原内容确认时间:${action.baseBinding.observedAt}`
5857
5944
  ].join("\n");
5858
5945
  return [
5859
- `Covering candidate: ${action.coveringCandidateBinding.candidateKey}`,
5860
- `Name: ${action.coveringCandidateBinding.name}`,
5861
- `Source: ${action.coveringCandidateBinding.source}`,
5862
- `Digest: ${action.coveringCandidateBinding.contentDigest}`,
5863
- `Observed: ${action.coveringCandidateBinding.observedAt}`
5946
+ `匹配到的现有 Skill 标识:${action.coveringCandidateBinding.candidateKey}`,
5947
+ `名称:${action.coveringCandidateBinding.name}`,
5948
+ `已有技能来源:${describeCandidateSource(action.coveringCandidateBinding.source)}`,
5949
+ `内容校验值:${action.coveringCandidateBinding.contentDigest}`,
5950
+ `确认时间:${action.coveringCandidateBinding.observedAt}`
5864
5951
  ].join("\n");
5865
5952
  }
5953
+ function describeRootSource(source) {
5954
+ return source === "project-dsh" ? "当前项目的 DSH 技能目录" : "个人 DSH 技能目录(所有项目可用)";
5955
+ }
5956
+ function describeRootState(state) {
5957
+ return state === "EXISTING" ? "已存在" : "尚未建立,保存时会自动创建";
5958
+ }
5959
+ function describeCandidateSource(source) {
5960
+ if (source === "project-dsh") return "当前项目的 DSH 技能";
5961
+ if (source === "project-agents") return "当前项目的 Agent 技能";
5962
+ if (source === "user-dsh") return "个人 DSH 技能(所有项目可用)";
5963
+ if (source === "user-agents") return "个人 Agent 技能(所有项目可用)";
5964
+ if (source === "bundled") return "DSH 内置技能";
5965
+ if (source === "runtime") return "当前会话加载的技能";
5966
+ if (source === "custom") return "自定义技能目录";
5967
+ return "其他已加载位置";
5968
+ }
5969
+ function describeProposalAction(detail) {
5970
+ const proposal = detail.proposal;
5971
+ if (proposal.actionBinding === void 0) return factsFromAction(detail);
5972
+ if (proposal.actionBinding.kind === "CREATE") return `确认后会新建技能“${makeSafeText(proposal.name)}”。`;
5973
+ if (proposal.actionBinding.kind === "MERGE") return `确认后会把这次经验补充到已有技能“${makeSafeText(proposal.name)}”中。`;
5974
+ const existingName = proposal.actionBinding.coveringCandidateBinding.name;
5975
+ return `已有技能“${makeSafeText(existingName)}”已包含这次经验。这份草稿不会保存,确认后将继续使用该已有技能。`;
5976
+ }
5977
+ function describeExperienceType(type) {
5978
+ if (type === "CORRECTION") return "纠错经验";
5979
+ if (type === "CONSTRAINT") return "使用约束";
5980
+ return "操作流程";
5981
+ }
5982
+ function describeResolutionKind(kind) {
5983
+ if (kind === "CONFIGURATION") return "由 DSH 配置指定";
5984
+ if (kind === "ENVIRONMENT") return "由运行环境指定";
5985
+ return "使用 DSH 默认位置";
5986
+ }
5866
5987
  function proposalDetailAction(detail, mutationPending) {
5867
5988
  if (mutationPending) return "NONE";
5989
+ if (detail.processingState === "NEEDS_ATTENTION" && detail.publicationOutcome === "NEEDS_REFRESH") return "REFRESH";
5868
5990
  if (detail.reviewDecision === "PENDING" && detail.processingState === "READY_FOR_REVIEW" && detail.publicationOutcome === "PENDING_REVIEW") return "REVIEW";
5869
5991
  if (detail.reviewDecision === "APPROVED" && detail.processingState === "NEEDS_ATTENTION" && detail.publicationOutcome === "PUBLISH_FAILED") return "RETRY_PUBLICATION";
5870
5992
  return "NONE";
@@ -5875,18 +5997,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5875
5997
  const action = proposalDetailAction(detail, mutationPending);
5876
5998
  const actionable = action === "REVIEW";
5877
5999
  const coordinate = detail.sessionCoordinate;
5878
- const baseBytes = proposal.actionBinding.kind === "MERGE" ? proposal.actionBinding.baseBinding.exactBytes : void 0;
5879
- const coveringBytes = proposal.actionBinding.kind === "DISCARD" ? proposal.actionBinding.coveringCandidateBinding.content : void 0;
6000
+ const baseBytes = proposal.actionBinding?.kind === "MERGE" ? proposal.actionBinding.baseBinding.exactBytes : void 0;
6001
+ const coveringBytes = proposal.actionBinding?.kind === "DISCARD" ? proposal.actionBinding.coveringCandidateBinding.content : void 0;
6002
+ const coveringCandidate = proposal.actionBinding?.kind === "DISCARD" ? proposal.actionBinding.coveringCandidateBinding : void 0;
5880
6003
  const diff = baseBytes === void 0 ? [] : makeExactLineDiff(baseBytes, proposal.exactSkillBytes);
5881
- return (0, react.createElement)(react.Fragment, null, (0, react.createElement)("h3", null, `${proposal.kind}: ${makeSafeText(proposal.name)}`), (0, react.createElement)("dl", null, (0, react.createElement)("dt", null, "说明"), (0, react.createElement)("dd", null, makeSafeText(proposal.description)), (0, react.createElement)("dt", null, "何时使用"), (0, react.createElement)("dd", null, makeSafeText(proposal.whenToUse)), (0, react.createElement)("dt", null, "Scope"), (0, react.createElement)("dd", null, proposal.persistenceScope), (0, react.createElement)("dt", null, "Proposal revision"), (0, react.createElement)("dd", null, String(proposal.revision)), (0, react.createElement)("dt", null, "Proposal digest"), (0, react.createElement)("dd", null, proposal.digest), (0, react.createElement)("dt", null, "Session / Turn"), (0, react.createElement)("dd", null, `${coordinate.rootSessionId} / ${String(coordinate.turn)} / seq ${String(coordinate.turnEndSeq)}`), proposal.workspaceBinding === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("dt", null, "Workspace"), (0, react.createElement)("dd", null, `PROJECT · ${proposal.workspaceBinding.workspaceId}`)), proposal.dshHomeBinding === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("dt", null, "DSH Home"), (0, react.createElement)("dd", null, `USER · ${proposal.dshHomeBinding.resolutionKind}`), (0, react.createElement)("dt", null, "DSH Home identity"), (0, react.createElement)("dd", null, proposal.dshHomeBinding.identityDigest)), (0, react.createElement)("dt", null, "审核决定"), (0, react.createElement)("dd", null, describeReviewDecision(detail.reviewDecision)), (0, react.createElement)("dt", null, "处理状态"), (0, react.createElement)("dd", null, describeProcessingState(detail.processingState)), (0, react.createElement)("dt", null, "发布结果"), (0, react.createElement)("dd", null, describePublicationOutcome(detail.publicationOutcome))), (0, react.createElement)("h4", null, "Why learned"), (0, react.createElement)("p", null, makeSafeText(proposal.curationRationale)), ...detail.experiences.map((experience) => (0, react.createElement)("article", { key: experience.experienceId }, (0, react.createElement)("strong", null, `${experience.type} · ${experience.evidenceStrength}`), (0, react.createElement)("p", null, makeSafeText(experience.lesson)))), (0, react.createElement)("h4", null, "过滤后的 Evidence"), ...detail.evidenceRefs.map((evidence) => (0, react.createElement)("article", { key: `${String(evidence.messageSeq)}:${evidence.excerptDigest}` }, (0, react.createElement)("strong", null, `message seq ${String(evidence.messageSeq)}${evidence.truncated ? " · 已截断" : ""}`), (0, react.createElement)(ProposalTextView, {
6004
+ return (0, react.createElement)(react.Fragment, null, (0, react.createElement)("h3", null, coveringCandidate === void 0 ? `${describeProposalKind(proposal.kind)}:${makeSafeText(proposal.name)}` : `无需新建技能:继续使用 ${makeSafeText(coveringCandidate.name)}`), (0, react.createElement)("dl", { className: _run2skill_css_run2skill_settings_page_module_css_default.detailFacts }, coveringCandidate === void 0 ? (0, react.createElement)(react.Fragment, null, (0, react.createElement)("dt", null, "这个技能有什么用"), (0, react.createElement)("dd", null, makeSafeText(proposal.description)), (0, react.createElement)("dt", null, "什么时候会用到"), (0, react.createElement)("dd", null, makeSafeText(proposal.whenToUse)), (0, react.createElement)("dt", null, "保存后在哪里可用"), (0, react.createElement)("dd", null, describePersistenceScope(proposal.persistenceScope))) : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("dt", null, "原本想保存的经验"), (0, react.createElement)("dd", null, makeSafeText(proposal.description)), (0, react.createElement)("dt", null, "适用场景"), (0, react.createElement)("dd", null, makeSafeText(proposal.whenToUse)), (0, react.createElement)("dt", null, "这次经验的范围"), (0, react.createElement)("dd", null, describeProposalScope(proposal.kind, proposal.persistenceScope))), (0, react.createElement)("dt", null, "当前进度"), (0, react.createElement)("dd", null, describeProposalOutcome(detail))), (0, react.createElement)("h4", null, coveringCandidate === void 0 ? "为什么建议保存" : "为什么无需新建"), (0, react.createElement)("p", null, makeSafeText(proposal.curationRationale)), ...detail.experiences.map((experience) => (0, react.createElement)("article", { key: experience.experienceId }, (0, react.createElement)("strong", null, `${describeExperienceType(experience.type)} · 来自明确表达`), (0, react.createElement)("p", null, makeSafeText(experience.lesson)))), (0, react.createElement)("h4", null, "参考的对话内容"), (0, react.createElement)("p", { className: _run2skill_css_run2skill_settings_page_module_css_default.muted }, "以下片段来自本次对话,并已过滤不可安全展示的内容。"), ...detail.evidenceRefs.map((evidence, index) => (0, react.createElement)("article", { key: `${String(evidence.messageSeq)}:${evidence.excerptDigest}` }, (0, react.createElement)("strong", null, `对话片段 ${String(index + 1)}${evidence.truncated ? "(内容较长,已节选)" : ""}`), (0, react.createElement)(ProposalTextView, {
5882
6005
  value: evidence.excerpt,
5883
6006
  mode: "SAFE",
5884
- label: `Evidence ${String(evidence.messageSeq)}`
5885
- }))), (0, react.createElement)("h4", null, "绑定事实"), (0, react.createElement)(ProposalTextView, {
6007
+ label: `参考的对话内容 ${String(index + 1)}`
6008
+ }))), (0, react.createElement)("h4", null, "这次会怎么处理"), (0, react.createElement)("p", null, describeProposalAction(detail)), (0, react.createElement)("details", { className: _run2skill_css_run2skill_settings_page_module_css_default.technicalDetails }, (0, react.createElement)("summary", null, "技术信息(排查问题时使用)"), (0, react.createElement)("dl", { className: _run2skill_css_run2skill_settings_page_module_css_default.detailFacts }, (0, react.createElement)("dt", null, "草稿版本"), (0, react.createElement)("dd", null, String(proposal.revision)), (0, react.createElement)("dt", null, "草稿内容指纹"), (0, react.createElement)("dd", null, proposal.digest), (0, react.createElement)("dt", null, "来源会话"), (0, react.createElement)("dd", null, `${coordinate.rootSessionId} / 第 ${String(coordinate.turn)} 回合 / 记录 ${String(coordinate.turnEndSeq)}`), proposal.workspaceBinding === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("dt", null, "项目标识"), (0, react.createElement)("dd", null, proposal.workspaceBinding.workspaceId)), proposal.dshHomeBinding === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("dt", null, "保存位置识别方式"), (0, react.createElement)("dd", null, describeResolutionKind(proposal.dshHomeBinding.resolutionKind)), (0, react.createElement)("dt", null, "用户技能目录指纹"), (0, react.createElement)("dd", null, proposal.dshHomeBinding.identityDigest)), (0, react.createElement)("dt", null, "用户决定"), (0, react.createElement)("dd", null, describeReviewDecision(detail.reviewDecision)), (0, react.createElement)("dt", null, "处理进度"), (0, react.createElement)("dd", null, describeProcessingState(detail.processingState)), (0, react.createElement)("dt", null, coveringCandidate === void 0 ? "保存结果" : "处理结果"), (0, react.createElement)("dd", null, coveringCandidate === void 0 ? describePublicationOutcome(detail.publicationOutcome) : describeProposalOutcome(detail))), (0, react.createElement)("h4", null, "对话证据定位信息"), (0, react.createElement)("ul", null, ...detail.evidenceRefs.map((evidence) => (0, react.createElement)("li", { key: `${String(evidence.messageSeq)}:${evidence.excerptDigest}` }, `记录 ${String(evidence.messageSeq)} · 内容指纹 ${evidence.excerptDigest}`))), (0, react.createElement)(ProposalTextView, {
5886
6009
  value: factsFromAction(detail),
5887
6010
  mode: "SAFE",
5888
- label: "绑定事实"
5889
- }), (0, react.createElement)("div", {
6011
+ label: coveringCandidate === void 0 ? "保存目标技术信息" : "已有技能匹配技术信息"
6012
+ })), (0, react.createElement)("div", {
5890
6013
  role: "group",
5891
6014
  "aria-label": "内容显示方式",
5892
6015
  className: _run2skill_css_run2skill_settings_page_module_css_default.modeGroup
@@ -5896,33 +6019,37 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5896
6019
  onClick: () => {
5897
6020
  props.setTextMode("SAFE");
5898
6021
  }
5899
- }, "安全视图"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
6022
+ }, "标出隐藏字符"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
5900
6023
  "aria-pressed": props.textMode === "RAW",
5901
6024
  active: props.textMode === "RAW",
5902
6025
  onClick: () => {
5903
6026
  props.setTextMode("RAW");
5904
6027
  }
5905
- }, "原始内容")), (0, react.createElement)("h4", null, "将要批准的完整 SKILL.md"), (0, react.createElement)(ProposalTextView, {
6028
+ }, "按原文显示")), (0, react.createElement)("h4", null, coveringCandidate === void 0 ? "确认要保存的技能说明" : "用于判断的草稿内容"), (0, react.createElement)("p", { className: _run2skill_css_run2skill_settings_page_module_css_default.muted }, coveringCandidate === void 0 ? "这是 Agent 以后会遵循的完整说明。开头是技能名称和设置,标题下方是具体规则。" : "这份草稿不会保存,仅用于核对已有技能是否已经包含相同经验。"), (0, react.createElement)(ProposalTextView, {
5906
6029
  value: proposal.exactSkillBytes,
5907
6030
  mode: props.textMode,
5908
- label: "将要批准的完整 SKILL.md"
5909
- }), baseBytes === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("h4", null, "MERGE Base"), (0, react.createElement)(ProposalTextView, {
6031
+ label: coveringCandidate === void 0 ? "确认要保存的技能说明" : "用于判断的草稿内容"
6032
+ }), baseBytes === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("h4", null, "现有技能内容"), (0, react.createElement)(ProposalTextView, {
5910
6033
  value: baseBytes,
5911
6034
  mode: props.textMode,
5912
- label: "MERGE Base"
5913
- }), (0, react.createElement)("h4", null, "精确 Diff"), (0, react.createElement)("pre", { "aria-label": "精确 Diff" }, diff.map((line) => `${line.kind === "ADD" ? "+" : line.kind === "REMOVE" ? "-" : " "} ${makeSafeText(line.text)}`).join("\n"))), coveringBytes === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("h4", null, "覆盖已有 Skill 的完整内容"), (0, react.createElement)(ProposalTextView, {
6035
+ label: "现有技能内容"
6036
+ }), (0, react.createElement)("h4", null, "将发生的内容变化"), (0, react.createElement)("p", { className: _run2skill_css_run2skill_settings_page_module_css_default.muted }, "“+”表示新增内容,“-”表示将被替换的内容。"), (0, react.createElement)("pre", { "aria-label": "将发生的内容变化" }, diff.map((line) => `${line.kind === "ADD" ? "+" : line.kind === "REMOVE" ? "-" : " "} ${makeSafeText(line.text)}`).join("\n"))), coveringBytes === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("h4", null, "将继续使用的已有技能内容"), (0, react.createElement)(ProposalTextView, {
5914
6037
  value: coveringBytes,
5915
6038
  mode: props.textMode,
5916
- label: "覆盖已有 Skill 的完整内容"
6039
+ label: "将继续使用的已有技能内容"
5917
6040
  })), (0, react.createElement)("div", {
5918
6041
  role: "group",
5919
- "aria-label": "Proposal 操作",
6042
+ "aria-label": "技能草稿操作",
5920
6043
  className: _run2skill_css_run2skill_settings_page_module_css_default.actions
5921
6044
  }, action === "RETRY_PUBLICATION" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
5922
6045
  variant: "primary",
5923
6046
  disabled: mutationPending,
5924
6047
  onClick: props.onRetry
5925
- }, "重试发布") : proposal.kind === "DISCARD" ? (0, react.createElement)(react.Fragment, null, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6048
+ }, "重试保存") : action === "REFRESH" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6049
+ variant: "primary",
6050
+ disabled: mutationPending,
6051
+ onClick: props.onRefresh
6052
+ }, "生成新草稿") : proposal.kind === "DISCARD" ? (0, react.createElement)(react.Fragment, null, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
5926
6053
  variant: "primary",
5927
6054
  disabled: !actionable,
5928
6055
  onClick: props.onConfirmDiscard
@@ -5934,16 +6061,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5934
6061
  variant: "primary",
5935
6062
  disabled: !actionable,
5936
6063
  onClick: props.onApprove
5937
- }, detail.processingState === "PUBLISHING" ? "正在发布…" : "批准并发布"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6064
+ }, detail.processingState === "PUBLISHING" ? "正在保存…" : "确认并保存"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
5938
6065
  variant: "outline",
5939
6066
  disabled: !actionable,
5940
6067
  onClick: (event) => {
5941
6068
  props.onReject(event.currentTarget);
5942
6069
  }
5943
- }, "拒绝 Proposal"))));
6070
+ }, "放弃草稿"))));
5944
6071
  }
5945
6072
  function RejectConfirmationBody(props) {
5946
- return (0, react.createElement)(react.Fragment, null, (0, react.createElement)("h3", { id: "run2skill-reject-title" }, "确认拒绝 Proposal?"), (0, react.createElement)("p", { id: "run2skill-reject-description" }, "现有 Skill 不会改变;该 Proposal 将离开待处理队列;过滤后的 Evidence 仍按项目策略保留。"), (0, react.createElement)("button", {
6073
+ return (0, react.createElement)(react.Fragment, null, (0, react.createElement)("h3", { id: "run2skill-reject-title" }, "确认放弃这份技能草稿?"), (0, react.createElement)("p", { id: "run2skill-reject-description" }, "现有 Skill 不会改变;这份技能草稿将离开待处理队列;经过筛选的学习材料仍按项目规则保留。"), (0, react.createElement)("button", {
5947
6074
  type: "button",
5948
6075
  "data-initial-focus": true,
5949
6076
  disabled: props.disabled,
@@ -5952,7 +6079,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5952
6079
  type: "button",
5953
6080
  disabled: props.disabled,
5954
6081
  onClick: props.onConfirm
5955
- }, "确认拒绝"));
6082
+ }, "确认放弃"));
5956
6083
  }
5957
6084
  function RejectConfirmation(props) {
5958
6085
  const dialogRef = (0, react.useRef)(null);
@@ -5991,6 +6118,155 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5991
6118
  }
5992
6119
  //#endregion
5993
6120
  //#region src/client/run2skill-settings-page.ts
6121
+ const recentSkillActivityResultSchema = object({
6122
+ ok: literal(true),
6123
+ value: object({
6124
+ apiVersion: literal(1),
6125
+ visibilityRevision: string().regex(/^visibility_[a-f0-9]{64}$/),
6126
+ items: array(object({
6127
+ activityId: string().regex(/^activity_[a-f0-9]{64}$/),
6128
+ skillName: string().min(1).max(128),
6129
+ operation: _enum(["CREATED", "UPDATED"]),
6130
+ scope: _enum(["PROJECT", "USER"]),
6131
+ occurredAt: string().datetime({ offset: true })
6132
+ }).strict()).max(256)
6133
+ }).strict()
6134
+ }).strict();
6135
+ const recentSkillActivityVisibilityStaleSchema = object({
6136
+ ok: literal(false),
6137
+ error: object({ code: literal("visibility-stale") }).passthrough()
6138
+ }).passthrough();
6139
+ const RECENT_SKILL_ACTIVITY_VISIBILITY_POLL_MS = 2e3;
6140
+ function waitForActivityVisibilityPoll(signal, delayMs) {
6141
+ if (signal.aborted) return Promise.resolve();
6142
+ return new Promise((resolve) => {
6143
+ const finish = () => {
6144
+ globalThis.clearTimeout(timer);
6145
+ signal.removeEventListener("abort", finish);
6146
+ resolve();
6147
+ };
6148
+ const timer = globalThis.setTimeout(finish, delayMs);
6149
+ signal.addEventListener("abort", finish, { once: true });
6150
+ });
6151
+ }
6152
+ function formatActivityTime(value) {
6153
+ return new Intl.DateTimeFormat("zh-CN", {
6154
+ dateStyle: "medium",
6155
+ timeStyle: "short"
6156
+ }).format(new Date(value));
6157
+ }
6158
+ function usefulActivityScope(items, selected) {
6159
+ return items.some((item) => item.skillName === selected.skillName && item.scope !== selected.scope);
6160
+ }
6161
+ function RecentSkillActivitySection(props) {
6162
+ const scopeIdentity = JSON.stringify([
6163
+ props.workspaceId ?? null,
6164
+ props.scopeGeneration,
6165
+ props.hostDataEpoch ?? 0
6166
+ ]);
6167
+ const [state, setState] = (0, react.useState)({
6168
+ phase: "IDLE",
6169
+ items: []
6170
+ });
6171
+ const visibleState = state.scopeIdentity === scopeIdentity ? state : {
6172
+ phase: "IDLE",
6173
+ items: []
6174
+ };
6175
+ (0, react.useEffect)(() => {
6176
+ if (!props.active) return;
6177
+ const abort = new AbortController();
6178
+ setState({
6179
+ phase: "LOADING",
6180
+ items: [],
6181
+ scopeIdentity
6182
+ });
6183
+ (async () => {
6184
+ const readStable = async () => {
6185
+ let expectedVisibilityRevision;
6186
+ let confirmedReads = 0;
6187
+ for (let attempt = 0; attempt < 8; attempt += 1) {
6188
+ const result = await props.call({
6189
+ apiVersion: 1,
6190
+ currentScope: currentScope(props.workspaceId, props.scopeGeneration),
6191
+ ...expectedVisibilityRevision === void 0 ? {} : { expectedVisibilityRevision }
6192
+ }, abort.signal);
6193
+ if (abort.signal.aborted) return void 0;
6194
+ if (recentSkillActivityVisibilityStaleSchema.safeParse(result).success) {
6195
+ expectedVisibilityRevision = void 0;
6196
+ confirmedReads = 0;
6197
+ continue;
6198
+ }
6199
+ const parsed = recentSkillActivityResultSchema.safeParse(result);
6200
+ if (!parsed.success) throw new Error("RECENT_ACTIVITY_UNAVAILABLE");
6201
+ if (parsed.data.value.visibilityRevision === expectedVisibilityRevision) {
6202
+ confirmedReads += 1;
6203
+ if (confirmedReads >= 2) return parsed.data.value;
6204
+ } else {
6205
+ expectedVisibilityRevision = parsed.data.value.visibilityRevision;
6206
+ confirmedReads = 0;
6207
+ }
6208
+ }
6209
+ throw new Error("RECENT_ACTIVITY_VISIBILITY_UNSTABLE");
6210
+ };
6211
+ let current = await readStable();
6212
+ if (current === void 0 || abort.signal.aborted) return;
6213
+ setState({
6214
+ phase: "READY",
6215
+ items: current.items,
6216
+ scopeIdentity
6217
+ });
6218
+ while (!abort.signal.aborted) {
6219
+ await waitForActivityVisibilityPoll(abort.signal, props.visibilityPollMs ?? RECENT_SKILL_ACTIVITY_VISIBILITY_POLL_MS);
6220
+ if (abort.signal.aborted) return;
6221
+ const result = await props.call({
6222
+ apiVersion: 1,
6223
+ currentScope: currentScope(props.workspaceId, props.scopeGeneration),
6224
+ expectedVisibilityRevision: current.visibilityRevision
6225
+ }, abort.signal);
6226
+ if (abort.signal.aborted) return;
6227
+ const parsed = recentSkillActivityResultSchema.safeParse(result);
6228
+ if (recentSkillActivityVisibilityStaleSchema.safeParse(result).success || !parsed.success || parsed.data.value.visibilityRevision !== current.visibilityRevision) {
6229
+ setState({
6230
+ phase: "LOADING",
6231
+ items: [],
6232
+ scopeIdentity
6233
+ });
6234
+ current = await readStable();
6235
+ if (current === void 0 || abort.signal.aborted) return;
6236
+ } else current = parsed.data.value;
6237
+ setState({
6238
+ phase: "READY",
6239
+ items: current.items,
6240
+ scopeIdentity
6241
+ });
6242
+ }
6243
+ })().catch(() => {
6244
+ if (!abort.signal.aborted) setState({
6245
+ phase: "ERROR",
6246
+ items: [],
6247
+ scopeIdentity
6248
+ });
6249
+ });
6250
+ return () => {
6251
+ abort.abort();
6252
+ };
6253
+ }, [
6254
+ props.active,
6255
+ props.call,
6256
+ props.hostDataEpoch,
6257
+ props.scopeGeneration,
6258
+ props.visibilityPollMs,
6259
+ props.workspaceId,
6260
+ scopeIdentity
6261
+ ]);
6262
+ return (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.sectionBody }, (0, react.createElement)("p", { className: _run2skill_css_run2skill_settings_page_module_css_default.muted }, "展示最近沉淀的 Skill"), visibleState.phase === "LOADING" ? (0, react.createElement)("p", { role: "status" }, "正在读取最近活动…") : null, visibleState.phase === "ERROR" ? (0, react.createElement)("p", { role: "alert" }, "最近活动暂不可用。") : null, visibleState.phase === "READY" && visibleState.items.length === 0 ? (0, react.createElement)("p", null, "最近 7 天没有成功沉淀的 Skill。") : null, visibleState.items.length === 0 ? null : (0, react.createElement)("ul", { className: _run2skill_css_run2skill_settings_page_module_css_default.activityList }, ...visibleState.items.map((item) => (0, react.createElement)("li", {
6263
+ className: _run2skill_css_run2skill_settings_page_module_css_default.activityItem,
6264
+ key: item.activityId
6265
+ }, (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.activitySummary }, (0, react.createElement)("strong", null, item.skillName), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, item.operation === "CREATED" ? "新建技能" : "更新技能"), usefulActivityScope(visibleState.items, item) ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, describePersistenceScope(item.scope)) : null), (0, react.createElement)("time", {
6266
+ dateTime: item.occurredAt,
6267
+ className: _run2skill_css_run2skill_settings_page_module_css_default.muted
6268
+ }, formatActivityTime(item.occurredAt))))));
6269
+ }
5994
6270
  const learningIssueSchema = object({
5995
6271
  workItemId: string().regex(/^wi_[a-f0-9]{64}$/),
5996
6272
  workItemRevision: number().int().safe().positive(),
@@ -6011,7 +6287,43 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6011
6287
  inputTokens: number().int().nonnegative().optional(),
6012
6288
  outputTokens: number().int().nonnegative().optional(),
6013
6289
  outcome: string().min(1).max(256)
6014
- }).strict()).max(2)
6290
+ }).strict()).max(2),
6291
+ attentionKind: _enum([
6292
+ "SAFETY_STOP",
6293
+ "PROCESSING_FAILURE",
6294
+ "STALE_RESULT",
6295
+ "NEEDS_DECISION"
6296
+ ]).optional(),
6297
+ currentStage: _enum([
6298
+ "DETECTION",
6299
+ "OWNERSHIP",
6300
+ "RECALL",
6301
+ "COVERAGE",
6302
+ "GENERATION"
6303
+ ]).optional(),
6304
+ stages: array(object({
6305
+ stage: _enum([
6306
+ "DETECTION",
6307
+ "OWNERSHIP",
6308
+ "RECALL",
6309
+ "COVERAGE",
6310
+ "GENERATION"
6311
+ ]),
6312
+ state: _enum([
6313
+ "NOT_STARTED",
6314
+ "COMPLETED",
6315
+ "STOPPED"
6316
+ ]),
6317
+ modelCalls: object({
6318
+ total: number().int().nonnegative(),
6319
+ reserved: number().int().nonnegative(),
6320
+ succeeded: number().int().nonnegative(),
6321
+ failed: number().int().nonnegative(),
6322
+ aborted: number().int().nonnegative(),
6323
+ timedOut: number().int().nonnegative(),
6324
+ outcomeUnknown: number().int().nonnegative()
6325
+ }).strict()
6326
+ }).strict()).max(5).optional()
6015
6327
  }).strict();
6016
6328
  const learningIssuePageSchema = object({
6017
6329
  ok: literal(true),
@@ -6021,6 +6333,75 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6021
6333
  nextCursor: string().regex(/^c_[1-9][0-9]*_[1-9][0-9]*_[a-f0-9]{64}$/).optional()
6022
6334
  }).strict()
6023
6335
  }).strict();
6336
+ const learningStageLabels = {
6337
+ DETECTION: "语义检测",
6338
+ OWNERSHIP: "重复保存检查",
6339
+ RECALL: "已有 Skill 检索",
6340
+ COVERAGE: "重复与合并判断",
6341
+ GENERATION: "Skill 草稿生成"
6342
+ };
6343
+ function learningIssueDescription(item) {
6344
+ if (item.failureCode === "BASELINE_INCOMPLETE") return {
6345
+ title: "自动沉淀已停止",
6346
+ detail: "缺少任务开始前的 Skill 状态记录,无法确认 Agent 是否已经保存过同类 Skill。为避免重复生成,本次已停止。已有 Skill 和原始会话记录不受影响。"
6347
+ };
6348
+ if (item.failureCode === "MODEL_TERMINAL_FAILURE") return {
6349
+ title: "自动沉淀未完成",
6350
+ detail: "模型没有返回可用的结果,本次自动沉淀未完成。已有 Skill 和原始会话记录不受影响。"
6351
+ };
6352
+ if (item.failureCode === "MODEL_OUTPUT_TRUNCATED") return {
6353
+ title: "语义判断没有完成",
6354
+ detail: "模型在返回简短判断前用完了本次输出额度,因此没有继续生成 Skill 草稿。已有 Skill 和原始会话记录不受影响。"
6355
+ };
6356
+ if (item.failureCode === "SESSION_CONTEXT_UNAVAILABLE") return {
6357
+ title: "自动沉淀已停止",
6358
+ detail: "任务结束后没能恢复当时的会话信息,无法确认 Agent 是否已经保存过同类 Skill。为避免重复生成,本次已停止。已有 Skill 和原始会话记录不受影响。"
6359
+ };
6360
+ if (item.failureCode === "SESSION_SNAPSHOT_UNAVAILABLE") return {
6361
+ title: "自动沉淀已停止",
6362
+ detail: "没能读取任务结束时的会话快照,无法确认 Skill 状态是否稳定。为避免重复生成,本次已停止。已有 Skill 和原始会话记录不受影响。"
6363
+ };
6364
+ if (item.failureCode === "SESSION_LOG_UNAVAILABLE") return {
6365
+ title: "自动沉淀已停止",
6366
+ detail: "没能完整读取本次任务的会话记录,无法确认 Agent 是否已经保存过同类 Skill。为避免重复生成,本次已停止。已有 Skill 和原始会话记录不受影响。"
6367
+ };
6368
+ if (item.failureCode === "SESSION_WINDOW_INCOMPLETE") return {
6369
+ title: "自动沉淀已停止",
6370
+ detail: "本次任务的会话记录不完整或超出安全检查范围,无法可靠判断是否已经生成过 Skill。为避免重复生成,本次已停止。"
6371
+ };
6372
+ if (item.failureCode === "SESSION_CHANGED_DURING_CHECK") return {
6373
+ title: "自动沉淀已停止",
6374
+ detail: "核对期间会话又发生了变化,当前结果已经失效。为避免使用过期记录或重复生成,本次已停止。"
6375
+ };
6376
+ if (item.failureCode === "OWNERSHIP_ANALYSIS_UNAVAILABLE" || item.failureCode === "OBSERVATION_FAILED") return {
6377
+ title: "自动沉淀已停止",
6378
+ detail: "系统没能完整核对本次任务结束时的 Skill 状态和 Agent 操作记录,因此无法确认是否已经保存过同类 Skill。为避免重复生成,本次已停止。已有 Skill 和原始会话记录不受影响。"
6379
+ };
6380
+ if (item.attentionKind === "STALE_RESULT") return {
6381
+ title: "自动沉淀结果已过期",
6382
+ detail: "生成依据已经发生变化,本次结果已停止使用,以免覆盖新的 Skill 状态。"
6383
+ };
6384
+ if (item.attentionKind === "NEEDS_DECISION") return {
6385
+ title: "自动沉淀需要确认",
6386
+ detail: "系统无法明确判断是否还需要生成 Skill,因此没有自动继续。"
6387
+ };
6388
+ if (item.attentionKind === "SAFETY_STOP") return {
6389
+ title: "自动沉淀已停止",
6390
+ detail: "系统无法确认继续处理是否安全,因此本次自动沉淀已停止。已有 Skill 和原始会话记录不受影响。"
6391
+ };
6392
+ return {
6393
+ title: "自动沉淀未完成",
6394
+ detail: "处理过程中出现问题,本次自动沉淀未能继续。已有 Skill 和原始会话记录不受影响。"
6395
+ };
6396
+ }
6397
+ function stageDescription(stage) {
6398
+ const label = learningStageLabels[stage.stage];
6399
+ if (stage.state === "NOT_STARTED") return `${label}:未开始`;
6400
+ if (stage.state === "STOPPED") return `${label}:未完成`;
6401
+ if (stage.modelCalls.total === 0) return `${label}:已完成`;
6402
+ const succeeded = stage.modelCalls.succeeded === 0 ? "" : `,成功 ${String(stage.modelCalls.succeeded)} 次`;
6403
+ return `${label}:已完成(模型调用 ${String(stage.modelCalls.total)} 次${succeeded})`;
6404
+ }
6024
6405
  function attentionValue(value) {
6025
6406
  if (value === null || typeof value !== "object" || !("ok" in value) || value.ok !== true || !("value" in value)) return;
6026
6407
  const projection = value.value;
@@ -6028,6 +6409,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6028
6409
  return projection;
6029
6410
  }
6030
6411
  const seenAttentionKeys = /* @__PURE__ */ new Set();
6412
+ const ATTENTION_SETTINGS_POLL_INTERVAL_MS = 1e4;
6031
6413
  function currentScope(workspaceId, generation) {
6032
6414
  return workspaceId === void 0 ? {
6033
6415
  kind: "USER_ONLY",
@@ -6083,7 +6465,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6083
6465
  return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Toast, {
6084
6466
  key: toast.sequence,
6085
6467
  icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutline16),
6086
- text: `run2skill 有 ${String(toast.count)} 项需要处理,请前往设置 → 插件 → run2skill`,
6468
+ text: `Run2Skill 有 ${String(toast.count)} 项需要处理,请前往设置 → 插件 → Run2Skill`,
6087
6469
  onDone: () => {
6088
6470
  setToast(void 0);
6089
6471
  }
@@ -6092,14 +6474,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6092
6474
  function AutomaticLearningSection(props) {
6093
6475
  const state = (0, react.useSyncExternalStore)(props.controller.subscribe, props.controller.getSnapshot, props.controller.getSnapshot);
6094
6476
  const disabled = state.status !== "ready" || !state.writable || state.saving;
6095
- return (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.sectionBody }, (0, react.createElement)("p", { className: _run2skill_css_run2skill_settings_page_module_css_default.muted }, "在后台识别可复用经验并生成待审核 Proposal;关闭后仍保留明确“保存为 Skill”的持久化信号。"), (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.actions }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6477
+ return (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.sectionBody }, (0, react.createElement)("p", { className: _run2skill_css_run2skill_settings_page_module_css_default.muted }, "在后台识别可复用经验并生成待确认的技能草稿;关闭后,明确说“保存为 Skill”仍然有效。"), (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.actions }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6096
6478
  variant: state.automaticLearning ? "primary" : "outline",
6097
6479
  "aria-pressed": state.automaticLearning === true,
6098
6480
  disabled,
6099
6481
  onClick: () => {
6100
6482
  props.controller.setAutomaticLearning(state.automaticLearning !== true);
6101
6483
  }
6102
- }, state.saving ? "正在保存…" : state.automaticLearning ? "自动学习已开启" : "自动学习已关闭"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, "inherit-session")), state.error === void 0 ? null : (0, react.createElement)("p", {
6484
+ }, state.saving ? "正在保存…" : state.automaticLearning ? "自动学习已开启" : "自动学习已关闭"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, "沿用当前会话模型")), state.error === void 0 ? null : (0, react.createElement)("p", {
6103
6485
  role: "status",
6104
6486
  className: _run2skill_css_run2skill_settings_page_module_css_default.danger
6105
6487
  }, "设置已变化,请刷新后重试。"));
@@ -6111,7 +6493,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6111
6493
  });
6112
6494
  scopeAccessRef.current = {
6113
6495
  currentScope: currentScope(props.workspaceId, props.scopeGeneration),
6114
- actions: props.actions.flatMap((action) => action.subjectId === void 0 || action.proposalRef === void 0 || !["REVIEW_PROPOSAL", "RETRY_PUBLICATION"].includes(action.kind ?? "") ? [] : [{
6496
+ actions: props.actions.flatMap((action) => action.subjectId === void 0 || action.proposalRef === void 0 || ![
6497
+ "REVIEW_PROPOSAL",
6498
+ "REFRESH_PROPOSAL",
6499
+ "RETRY_PUBLICATION"
6500
+ ].includes(action.kind ?? "") ? [] : [{
6115
6501
  actionKey: action.actionKey,
6116
6502
  subjectId: action.subjectId,
6117
6503
  kind: action.kind,
@@ -6147,30 +6533,38 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6147
6533
  const [textMode, setTextMode] = (0, react.useState)("SAFE");
6148
6534
  const [rejectConfirm, setRejectConfirm] = (0, react.useState)(false);
6149
6535
  const rejectTriggerRef = (0, react.useRef)(null);
6150
- const items = actionableProposalItems(props.actions, state.items).filter((item) => `${item.name} ${item.description} ${item.kind}`.toLocaleLowerCase().includes(filter.trim().toLocaleLowerCase()));
6536
+ const actionableItems = actionableProposalItems(props.actions, state.items);
6537
+ const showFilter = actionableItems.length > 1;
6538
+ const items = showFilter ? actionableItems.filter((item) => `${item.name} ${item.description} ${item.kind}`.toLocaleLowerCase().includes(filter.trim().toLocaleLowerCase())) : actionableItems;
6151
6539
  const selectedActionable = items.some((item) => item.proposalRef.proposalId === state.selectedProposalId);
6152
- return (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.sectionBody }, (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.toolbar }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
6540
+ if (props.actions.length === 0) return (0, react.createElement)(react.Fragment);
6541
+ return (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.attentionGroup }, (0, react.createElement)("div", { className: showFilter ? _run2skill_css_run2skill_settings_page_module_css_default.proposalToolbar : `${_run2skill_css_run2skill_settings_page_module_css_default.proposalToolbar} ${_run2skill_css_run2skill_settings_page_module_css_default.proposalToolbarCompact}` }, showFilter ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
6153
6542
  value: filter,
6154
- placeholder: "筛选 Proposal",
6155
- "aria-label": "筛选 Proposal",
6543
+ placeholder: "筛选技能草稿",
6544
+ "aria-label": "筛选技能草稿",
6156
6545
  onChange: (event) => {
6157
6546
  setFilter(event.currentTarget.value);
6158
6547
  }
6159
- }), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6548
+ }) : null, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6160
6549
  variant: "outline",
6161
6550
  size: "sm",
6162
6551
  icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16),
6163
6552
  onClick: () => {
6164
6553
  controller.open();
6165
6554
  }
6166
- }, "刷新")), state.listPhase === "LOADING" ? (0, react.createElement)("p", { role: "status" }, "正在加载待处理事项…") : null, state.listPhase === "ERROR" ? (0, react.createElement)("p", { role: "alert" }, "待处理事项暂不可用。") : null, props.attentionAvailable && props.actions.length === 0 ? (0, react.createElement)("p", null, props.workspaceId === void 0 ? "当前没有 USER 待处理事项;未选择当前项目。" : "当前 PROJECT 与 USER 没有待处理事项。") : null, (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.proposalLayout }, (0, react.createElement)("ul", { className: _run2skill_css_run2skill_settings_page_module_css_default.proposalList }, ...items.map((item) => (0, react.createElement)("li", { key: item.proposalRef.proposalId }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6167
- variant: state.selectedProposalId === item.proposalRef.proposalId ? "primary" : "outline",
6555
+ }, "刷新")), state.listPhase === "LOADING" ? (0, react.createElement)("p", { role: "status" }, "正在加载待处理事项…") : null, state.listPhase === "ERROR" ? (0, react.createElement)("p", { role: "alert" }, "待处理事项暂不可用。") : null, (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.proposalLayout }, (0, react.createElement)("ul", { className: _run2skill_css_run2skill_settings_page_module_css_default.proposalList }, ...items.map((item) => (0, react.createElement)("li", { key: item.proposalRef.proposalId }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6556
+ variant: "outline",
6168
6557
  className: _run2skill_css_run2skill_settings_page_module_css_default.proposalListButton,
6558
+ "aria-current": state.selectedProposalId === item.proposalRef.proposalId ? "true" : void 0,
6559
+ "aria-label": `${item.name},${describeProposalKind(item.kind)},${describeProposalScope(item.kind, item.persistenceScope)},${describeProposalListItem(item)}`,
6169
6560
  disabled: state.mutationPending || state.detailPhase === "LOADING",
6170
6561
  onClick: () => {
6171
6562
  controller.select(item.proposalRef.proposalId);
6172
6563
  }
6173
- }, `${item.kind} · ${item.name} · ${item.persistenceScope} · ${describeProposalListItem(item)}`)))), (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.detail }, !selectedActionable || state.detailPhase === "IDLE" ? (0, react.createElement)("p", null, "选择一项查看审核事实。") : null, selectedActionable && state.detailPhase === "LOADING" ? (0, react.createElement)("p", { role: "status" }, "正在加载详情…") : null, selectedActionable && state.detailPhase === "ERROR" ? (0, react.createElement)("p", { role: "alert" }, "详情暂不可用。") : null, !selectedActionable || state.detail === void 0 ? null : (0, react.createElement)(ProposalDetailView, {
6564
+ }, (0, react.createElement)("span", { className: _run2skill_css_run2skill_settings_page_module_css_default.proposalName }, item.name), (0, react.createElement)("span", { className: _run2skill_css_run2skill_settings_page_module_css_default.proposalMeta }, `${describeProposalKind(item.kind)} · ${describeProposalScope(item.kind, item.persistenceScope)} · ${describeProposalListItem(item)}`))))), (0, react.createElement)("section", {
6565
+ className: _run2skill_css_run2skill_settings_page_module_css_default.detail,
6566
+ "aria-label": "技能草稿详情"
6567
+ }, !selectedActionable || state.detailPhase === "IDLE" ? (0, react.createElement)("p", null, "选择一项查看审核事实。") : null, selectedActionable && state.detailPhase === "LOADING" ? (0, react.createElement)("p", { role: "status" }, "正在加载详情…") : null, selectedActionable && state.detailPhase === "ERROR" ? (0, react.createElement)("p", { role: "alert" }, "详情暂不可用。") : null, !selectedActionable || state.detail === void 0 ? null : (0, react.createElement)(ProposalDetailView, {
6174
6568
  detail: state.detail,
6175
6569
  textMode,
6176
6570
  setTextMode,
@@ -6185,6 +6579,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6185
6579
  onRetry: () => {
6186
6580
  controller.mutate("RETRY").finally(props.onMutationSettled);
6187
6581
  },
6582
+ onRefresh: () => {
6583
+ controller.mutate("REFRESH").finally(props.onMutationSettled);
6584
+ },
6188
6585
  onConfirmDiscard: () => {
6189
6586
  controller.mutate("CONFIRM_DISCARD").finally(props.onMutationSettled);
6190
6587
  }
@@ -6290,9 +6687,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6290
6687
  };
6291
6688
  if (learningActions.size === 0) return (0, react.createElement)(react.Fragment);
6292
6689
  return (0, react.createElement)("section", {
6293
- className: _run2skill_css_run2skill_settings_page_module_css_default.sectionBody,
6294
- "aria-label": "学习失败恢复"
6295
- }, (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.toolbar }, (0, react.createElement)("strong", null, `学习失败 · ${String(learningActions.size)} 项`), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6690
+ className: _run2skill_css_run2skill_settings_page_module_css_default.attentionGroup,
6691
+ "aria-label": "自动沉淀未继续"
6692
+ }, (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.toolbar }, (0, react.createElement)("strong", null, `自动沉淀未继续 · ${String(learningActions.size)} 项`), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6296
6693
  variant: "outline",
6297
6694
  size: "sm",
6298
6695
  icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16),
@@ -6300,36 +6697,41 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6300
6697
  onClick: () => {
6301
6698
  setRefreshGeneration((value) => value + 1);
6302
6699
  }
6303
- }, "刷新失败详情")), phase === "LOADING" ? (0, react.createElement)("p", { role: "status" }, "正在加载学习失败详情…") : null, phase === "ERROR" ? (0, react.createElement)("p", { role: "alert" }, "学习失败详情暂不可用,请保持 DSH 运行并稍后重试。") : null, ...items.map((item) => {
6700
+ }, "刷新详情")), phase === "LOADING" ? (0, react.createElement)("p", { role: "status" }, "正在加载自动沉淀详情…") : null, phase === "ERROR" ? (0, react.createElement)("p", { role: "alert" }, "自动沉淀详情暂不可用,请保持 DSH 运行并稍后重试。") : null, ...items.map((item) => {
6304
6701
  const action = learningActions.get(item.workItemId);
6305
6702
  const busy = pending === item.workItemId;
6703
+ const isCoverageConfirmation = item.failureCode === "COVERED_NEEDS_CONFIRMATION";
6704
+ const description = isCoverageConfirmation ? {
6705
+ title: "发现可能重复的 Skill",
6706
+ detail: "Run2Skill 发现已有 Skill 可能已经包含这次经验,因此暂停生成新草稿。请选择下一步。"
6707
+ } : learningIssueDescription(item);
6306
6708
  return (0, react.createElement)("article", {
6307
6709
  className: _run2skill_css_run2skill_settings_page_module_css_default.detail,
6308
6710
  key: item.workItemId
6309
- }, (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.toolbar }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, item.failureCode), item.failureDetail === void 0 ? null : (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, item.failureDetail)), (0, react.createElement)("p", null, `第 ${String(item.attempt)} 轮 · 已使用 ${String(item.requestBudgetUsed)} 次模型请求`), item.modelRoute === void 0 ? null : (0, react.createElement)("p", null, `模型路由:${item.modelRoute.provider} / ${item.modelRoute.model}`), (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.actions }, action?.availableActions?.includes("RETRY") === true ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6711
+ }, (0, react.createElement)("strong", null, description.title), (0, react.createElement)("p", null, description.detail), item.stages === void 0 ? item.calls.length === 0 ? null : (0, react.createElement)("p", null, `已记录模型调用 ${String(item.calls.length)} 次`) : (0, react.createElement)("div", null, ...item.stages.map((stage) => (0, react.createElement)("p", { key: stage.stage }, stageDescription(stage)))), item.modelRoute === void 0 ? null : (0, react.createElement)("details", { className: _run2skill_css_run2skill_settings_page_module_css_default.technicalDetails }, (0, react.createElement)("summary", null, "本次处理的技术信息"), (0, react.createElement)("p", null, `使用的模型:${item.modelRoute.model}(${item.modelRoute.provider})`)), (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.actions }, action?.availableActions?.includes("RETRY") === true ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6310
6712
  variant: "primary",
6311
6713
  disabled: busy || pending !== void 0,
6312
6714
  onClick: () => {
6313
6715
  mutate("learning/issues/retry", item);
6314
6716
  }
6315
- }, busy ? "正在重试…" : "重试学习") : null, action?.availableActions?.includes("DISMISS") === true ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6717
+ }, busy ? "正在处理…" : isCoverageConfirmation ? "继续生成新 Skill 草稿" : "重试学习") : null, action?.availableActions?.includes("DISMISS") === true ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6316
6718
  variant: "outline",
6317
6719
  disabled: busy || pending !== void 0,
6318
6720
  onClick: (event) => {
6319
6721
  dismissTriggerRef.current = event.currentTarget;
6320
6722
  setDismiss(item);
6321
6723
  }
6322
- }, "关闭此失败") : null));
6724
+ }, isCoverageConfirmation ? "使用已有 Skill,不生成草稿" : "关闭此事项") : null));
6323
6725
  }), (0, react.createElement)(ManagedConfirmationModal, {
6324
6726
  open: dismiss !== void 0,
6325
- title: "确认关闭此学习失败?",
6326
- description: "该失败会从待处理列表隐藏;已有 Skill 和 DSH Session Log 不会改变。",
6727
+ title: dismiss?.failureCode === "COVERED_NEEDS_CONFIRMATION" ? "使用已有 Skill,不生成新草稿?" : "确认关闭此待处理事项?",
6728
+ description: dismiss?.failureCode === "COVERED_NEEDS_CONFIRMATION" ? "确认后,此项将从待处理列表移除,Run2Skill 不会为这次经验生成新草稿;已有 Skill 和 DSH 原始会话记录不会改变。" : "关闭后,本次自动沉淀不会继续,也不会生成草稿;已有 Skill 和 DSH 的原始会话记录不会改变。",
6327
6729
  disabled: pending !== void 0,
6328
6730
  triggerRef: dismissTriggerRef,
6329
6731
  onClose: () => {
6330
6732
  setDismiss(void 0);
6331
6733
  },
6332
- confirmLabel: "确认关闭",
6734
+ confirmLabel: dismiss?.failureCode === "COVERED_NEEDS_CONFIRMATION" ? "使用已有 Skill" : "确认关闭",
6333
6735
  onConfirm: () => {
6334
6736
  const selected = dismiss;
6335
6737
  setDismiss(void 0);
@@ -6340,9 +6742,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6340
6742
  function RejectProposalModal(props) {
6341
6743
  return (0, react.createElement)(ManagedConfirmationModal, {
6342
6744
  ...props,
6343
- title: "确认拒绝 Proposal?",
6344
- description: "现有 Skill 不会改变;该 Proposal 将离开待处理队列。",
6345
- confirmLabel: "确认拒绝"
6745
+ title: "确认放弃这份技能草稿?",
6746
+ description: "现有 Skill 不会改变;这份技能草稿将离开待处理队列。",
6747
+ confirmLabel: "确认放弃"
6346
6748
  });
6347
6749
  }
6348
6750
  function ManagedConfirmationModal(props) {
@@ -6394,7 +6796,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6394
6796
  }, (0, react.createElement)("div", { ref: contentRef }));
6395
6797
  }
6396
6798
  function actionableProposalItems(actions, items) {
6397
- const identities = new Set(actions.flatMap((action) => action.subjectId === void 0 || action.proposalRef === void 0 || !["REVIEW_PROPOSAL", "RETRY_PUBLICATION"].includes(action.kind ?? "") ? [] : [`${action.subjectId}\u0000${action.proposalRef.proposalId}\u0000${String(action.proposalRef.revision)}\u0000${action.proposalRef.digest}`]));
6799
+ const identities = new Set(actions.flatMap((action) => action.subjectId === void 0 || action.proposalRef === void 0 || ![
6800
+ "REVIEW_PROPOSAL",
6801
+ "REFRESH_PROPOSAL",
6802
+ "RETRY_PUBLICATION"
6803
+ ].includes(action.kind ?? "") ? [] : [`${action.subjectId}\u0000${action.proposalRef.proposalId}\u0000${String(action.proposalRef.revision)}\u0000${action.proposalRef.digest}`]));
6398
6804
  return items.filter((item) => identities.has(`${item.workItemId}\u0000${item.proposalRef.proposalId}\u0000${String(item.proposalRef.revision)}\u0000${item.proposalRef.digest}`));
6399
6805
  }
6400
6806
  function hostTabVisible(element) {
@@ -6431,13 +6837,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6431
6837
  const [state, setState] = (0, react.useState)({ phase: "LOADING" });
6432
6838
  const requestGeneration = (0, react.useRef)(0);
6433
6839
  const activeAbort = (0, react.useRef)();
6840
+ const currentValue = (0, react.useRef)();
6841
+ const currentScopeIdentity = (0, react.useRef)();
6842
+ const scopeIdentity = `${props.sessionId ?? ""}:${props.workspaceId ?? ""}`;
6434
6843
  const refresh = (0, react.useCallback)(() => {
6435
6844
  activeAbort.current?.abort();
6436
6845
  const abort = new AbortController();
6437
6846
  activeAbort.current = abort;
6438
6847
  const generation = ++requestGeneration.current;
6439
- setState({ phase: "LOADING" });
6440
- props.onProjection(void 0);
6848
+ const scopeChanged = currentScopeIdentity.current !== scopeIdentity;
6849
+ currentScopeIdentity.current = scopeIdentity;
6850
+ if (scopeChanged) currentValue.current = void 0;
6851
+ if (currentValue.current === void 0) {
6852
+ setState({ phase: "LOADING" });
6853
+ props.onProjection(void 0);
6854
+ }
6441
6855
  props.callAttention({
6442
6856
  apiVersion: 1,
6443
6857
  currentScope: currentScope(props.workspaceId, generation),
@@ -6445,15 +6859,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6445
6859
  }, abort.signal).then((result) => {
6446
6860
  if (abort.signal.aborted || requestGeneration.current !== generation) return;
6447
6861
  const value = attentionValue(result);
6448
- setState(value === void 0 ? { phase: "UNAVAILABLE" } : {
6862
+ if (value === void 0) {
6863
+ if (currentValue.current === void 0) {
6864
+ setState({ phase: "UNAVAILABLE" });
6865
+ props.onProjection(void 0);
6866
+ }
6867
+ return;
6868
+ }
6869
+ currentValue.current = value;
6870
+ setState({
6449
6871
  phase: "READY",
6450
6872
  value
6451
6873
  });
6452
6874
  props.onProjection(value);
6453
6875
  }, () => {
6454
6876
  if (abort.signal.aborted || requestGeneration.current !== generation) return;
6455
- setState({ phase: "UNAVAILABLE" });
6456
- props.onProjection(void 0);
6877
+ if (currentValue.current === void 0) {
6878
+ setState({ phase: "UNAVAILABLE" });
6879
+ props.onProjection(void 0);
6880
+ }
6457
6881
  });
6458
6882
  return () => {
6459
6883
  abort.abort();
@@ -6464,21 +6888,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6464
6888
  props.onProjection,
6465
6889
  props.refreshGeneration,
6466
6890
  props.sessionId,
6467
- props.workspaceId
6891
+ props.workspaceId,
6892
+ scopeIdentity
6468
6893
  ]);
6469
- (0, react.useEffect)(() => refresh(), [refresh]);
6894
+ (0, react.useEffect)(() => {
6895
+ if (props.active === false) {
6896
+ activeAbort.current?.abort();
6897
+ activeAbort.current = void 0;
6898
+ return;
6899
+ }
6900
+ refresh();
6901
+ const timer = setInterval(() => {
6902
+ refresh();
6903
+ }, ATTENTION_SETTINGS_POLL_INTERVAL_MS);
6904
+ return () => {
6905
+ clearInterval(timer);
6906
+ activeAbort.current?.abort();
6907
+ activeAbort.current = void 0;
6908
+ };
6909
+ }, [props.active, refresh]);
6470
6910
  const value = state.value;
6471
- return (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.toolbar }, state.phase === "LOADING" ? (0, react.createElement)("span", { role: "status" }, "正在读取当前事项…") : null, state.phase === "UNAVAILABLE" ? (0, react.createElement)("span", { role: "alert" }, "当前事项暂不可用,未按空队列处理。") : null, value === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, `${String(value.actions.length)} 项可操作事项`), value.projectCompleteness === "UNAVAILABLE" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, "未选择当前项目") : value.projectCompleteness === "UNKNOWN" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, "PROJECT 状态未知") : null, value.runtimeCompleteness === "UNKNOWN" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, "未保存数量未知") : null, ...value.runtimeWarnings.map((warning) => (0, react.createElement)("span", {
6911
+ if (value === void 0 || value.actions.length === 0 && value.runtimeWarnings.length === 0 && value.projectCompleteness !== "UNKNOWN" && value.runtimeCompleteness !== "UNKNOWN") return (0, react.createElement)(react.Fragment);
6912
+ return (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.toolbar }, (0, react.createElement)(react.Fragment, null, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, `${String(value.actions.length)} 项可操作事项`), value.projectCompleteness === "UNAVAILABLE" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, "未选择当前项目") : value.projectCompleteness === "UNKNOWN" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, "当前项目的待处理状态暂时无法确认") : null, value.runtimeCompleteness === "UNKNOWN" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, "未保存数量未知") : null, ...value.runtimeWarnings.map((warning) => (0, react.createElement)("span", {
6472
6913
  key: warning.noticeKey,
6473
6914
  role: "alert"
6474
- }, warning.message ?? "存在尚未持久化的学习信号。"))), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6475
- variant: "outline",
6476
- size: "sm",
6477
- icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16),
6478
- onClick: () => {
6479
- refresh();
6480
- }
6481
- }, "刷新状态"));
6915
+ }, warning.message ?? "存在尚未持久化的学习信号。"))));
6482
6916
  }
6483
6917
  function Run2skillSettingsPage(props) {
6484
6918
  const liveSessionId = props.useSessions?.((state) => state.current);
@@ -6490,16 +6924,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6490
6924
  const [attention, setAttention] = (0, react.useState)();
6491
6925
  const [attentionRefresh, setAttentionRefresh] = (0, react.useState)(0);
6492
6926
  const [scopeGeneration, setScopeGeneration] = (0, react.useState)(1);
6927
+ const purgeState = (0, react.useSyncExternalStore)(props.purgeController.subscribe, props.purgeController.snapshot, props.purgeController.snapshot);
6928
+ const purgeDataChanging = purgeState.mutationPending || purgeState.status?.state === "IN_PROGRESS" || purgeState.inProgressReceipt?.state === "IN_PROGRESS";
6493
6929
  (0, react.useEffect)(() => {
6494
6930
  setAttention(void 0);
6495
6931
  setScopeGeneration((value) => value + 1);
6496
6932
  }, [sessionId, workspaceId]);
6933
+ const attentionEmpty = attention !== void 0 && attention.actions.length === 0 && attention.runtimeWarnings.length === 0 && attention.projectCompleteness !== "UNKNOWN" && attention.runtimeCompleteness !== "UNKNOWN";
6497
6934
  const disclosure = (id, title, icon, content, collapsedContent) => (0, react.createElement)("section", {
6498
6935
  className: _run2skill_css_run2skill_settings_page_module_css_default.section,
6499
6936
  key: id
6500
6937
  }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
6501
6938
  icon,
6502
6939
  title,
6940
+ rowClassName: _run2skill_css_run2skill_settings_page_module_css_default.sectionHeader,
6941
+ titleClassName: _run2skill_css_run2skill_settings_page_module_css_default.sectionTitle,
6503
6942
  open: open.has(id),
6504
6943
  expandable: true,
6505
6944
  expandOnRowClick: true,
@@ -6517,23 +6956,27 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6517
6956
  ref: hostTab.ref,
6518
6957
  className: _run2skill_css_run2skill_settings_page_module_css_default.page,
6519
6958
  "data-run2skill-settings-page": true
6520
- }, (0, react.createElement)("p", { className: _run2skill_css_run2skill_settings_page_module_css_default.intro }, "run2skill 在后台自动沉淀经验;这里只展示需要处理的事项和持久设置。"), disclosure("attention", "需要处理", (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutline16), (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.sectionBody }, (0, react.createElement)(AttentionSettingsSummary, {
6959
+ }, (0, react.createElement)("p", { className: _run2skill_css_run2skill_settings_page_module_css_default.intro }, "Run2Skill 在后台自动沉淀经验;这里只展示需要处理的事项和持久设置。"), disclosure("attention", "需要处理", (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutline16), (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.sectionBody }, (0, react.createElement)(AttentionSettingsSummary, {
6960
+ active: hostTab.visible && open.has("attention"),
6521
6961
  ...sessionId === void 0 ? {} : { sessionId },
6522
6962
  ...workspaceId === void 0 ? {} : { workspaceId },
6523
6963
  callAttention: props.callAttention,
6524
6964
  refreshGeneration: attentionRefresh,
6525
6965
  onProjection: setAttention
6526
- }), (0, react.createElement)(ProposalSettingsSection, {
6966
+ }), attention?.actions.some((action) => [
6967
+ "REVIEW_PROPOSAL",
6968
+ "REFRESH_PROPOSAL",
6969
+ "RETRY_PUBLICATION"
6970
+ ].includes(action.kind ?? "")) === true ? (0, react.createElement)(ProposalSettingsSection, {
6527
6971
  ...workspaceId === void 0 ? {} : { workspaceId },
6528
6972
  callReview: props.callReview,
6529
6973
  active: hostTab.visible && open.has("attention"),
6530
- actions: attention?.actions ?? [],
6531
- attentionAvailable: attention !== void 0,
6974
+ actions: attention.actions,
6532
6975
  onMutationSettled: () => {
6533
6976
  setAttentionRefresh((value) => value + 1);
6534
6977
  },
6535
6978
  scopeGeneration
6536
- }), (0, react.createElement)(LearningFailureSection, {
6979
+ }) : null, (0, react.createElement)(LearningFailureSection, {
6537
6980
  ...workspaceId === void 0 ? {} : { workspaceId },
6538
6981
  call: props.callReview,
6539
6982
  active: hostTab.visible && open.has("attention"),
@@ -6542,9 +6985,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6542
6985
  setAttentionRefresh((value) => value + 1);
6543
6986
  },
6544
6987
  scopeGeneration
6545
- }))), disclosure("activity", "最近活动", (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconSparkle16), (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.sectionBody }, (0, react.createElement)("p", { className: _run2skill_css_run2skill_settings_page_module_css_default.muted }, "当前版本仅展示仍保留的待处理记录;完整历史不在本 Issue 范围内。")), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, "有界记录")), disclosure("automatic", "自动学习", (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconSettingsOutline16), (0, react.createElement)(AutomaticLearningSection, { controller: props.controller })), disclosure("data", "数据管理", (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16), (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.sectionBody }, (0, react.createElement)(PurgeSettingsSection, {
6988
+ }), attentionEmpty ? (0, react.createElement)("p", { className: _run2skill_css_run2skill_settings_page_module_css_default.empty }, "暂无") : null)), disclosure("activity", "最近活动", (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconSparkle16), (0, react.createElement)(RecentSkillActivitySection, {
6989
+ key: JSON.stringify([
6990
+ workspaceId ?? null,
6991
+ scopeGeneration,
6992
+ purgeState.hostDataEpoch,
6993
+ hostTab.visible && open.has("activity") && !purgeDataChanging
6994
+ ]),
6995
+ ...workspaceId === void 0 ? {} : { workspaceId },
6996
+ call: props.callActivity,
6997
+ active: hostTab.visible && open.has("activity") && !purgeDataChanging,
6998
+ scopeGeneration,
6999
+ hostDataEpoch: purgeState.hostDataEpoch
7000
+ }), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, null, "最近 7 天")), disclosure("automatic", "自动学习", (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconSettingsOutline16), (0, react.createElement)(AutomaticLearningSection, { controller: props.controller })), disclosure("purge", "缓存清理", (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16), (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.sectionBody }, (0, react.createElement)(PurgeSettingsSection, {
6546
7001
  controller: props.purgeController,
6547
- active: hostTab.visible && open.has("data")
7002
+ active: hostTab.visible && open.has("purge"),
7003
+ onCompleted: () => {
7004
+ setAttentionRefresh((value) => value + 1);
7005
+ }
6548
7006
  }))));
6549
7007
  }
6550
7008
  function currentSessionId(context) {
@@ -6558,6 +7016,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6558
7016
  const controller = new AutomaticLearningSettingsController(context.settingsScope.bind({ namespace: "run2skill" }));
6559
7017
  const callReview = async (endpoint, payload, signal) => await context.connection.rpc.call(RUN2SKILL_RPC_CHANNEL, endpoint, payload, signal);
6560
7018
  const callAttention = async (payload, signal) => await context.connection.rpc.call(RUN2SKILL_RPC_CHANNEL, "attention", payload, signal);
7019
+ const callActivity = async (payload, signal) => await context.connection.rpc.call(RUN2SKILL_RPC_CHANNEL, "recent-activity/list", payload, signal);
6561
7020
  const callPurge = async (endpoint, payload, signal) => await context.connection.rpc.call(RUN2SKILL_RPC_CHANNEL, endpoint, payload, signal);
6562
7021
  const purgeController = new PurgeSettingsController(callPurge, () => workspaceFor(context, currentSessionId(context)));
6563
7022
  context.effect(() => {
@@ -6572,14 +7031,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6572
7031
  name: "settings.plugins.tab",
6573
7032
  id: "run2skill",
6574
7033
  order: 20,
6575
- label: "run2skill",
7034
+ label: "Run2Skill",
6576
7035
  inject: () => ({
6577
7036
  controller,
6578
7037
  purgeController,
6579
7038
  workspaceId: workspaceFor(context, currentSessionId(context)),
6580
7039
  sessionId: currentSessionId(context),
6581
7040
  callAttention,
6582
- callReview
7041
+ callReview,
7042
+ callActivity
6583
7043
  })
6584
7044
  }, Run2skillSettingsPage));
6585
7045
  context.slots.inject("conversation.session.header.actions", () => context.slots.register({
@@ -6759,6 +7219,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6759
7219
  exports.ProposalTextView = ProposalTextView;
6760
7220
  exports.PurgeSettingsController = PurgeSettingsController;
6761
7221
  exports.PurgeSettingsSection = PurgeSettingsSection;
7222
+ exports.RecentSkillActivitySection = RecentSkillActivitySection;
6762
7223
  exports.RejectConfirmationBody = RejectConfirmationBody;
6763
7224
  exports.RejectProposalModal = RejectProposalModal;
6764
7225
  exports.Run2skillAttentionToast = Run2skillAttentionToast;
@@ -6767,9 +7228,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6767
7228
  exports.apply = apply;
6768
7229
  exports.applyAutomaticLearningSettingsClient = applyAutomaticLearningSettingsClient;
6769
7230
  exports.applyRun2skillClient = applyRun2skillClient;
7231
+ exports.describePersistenceScope = describePersistenceScope;
6770
7232
  exports.describeProcessingState = describeProcessingState;
7233
+ exports.describeProposalKind = describeProposalKind;
6771
7234
  exports.describeProposalListItem = describeProposalListItem;
6772
7235
  exports.describeProposalOutcome = describeProposalOutcome;
7236
+ exports.describeProposalScope = describeProposalScope;
6773
7237
  exports.describeProposalSummaryState = describeProposalSummaryState;
6774
7238
  exports.describePublicationOutcome = describePublicationOutcome;
6775
7239
  exports.describeReviewDecision = describeReviewDecision;