dsh-run2skill 0.1.0-alpha → 0.1.1-alpha
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/README.md +14 -11
- package/lib/client.js +1778 -1167
- package/lib/index.d.ts +113 -1
- package/lib/index.js +1414 -273
- package/package.json +8 -3
package/lib/client.js
CHANGED
|
@@ -5,6 +5,7 @@ window.__ModuleLoader__.load({
|
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
let react = require("react");
|
|
8
|
+
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
8
9
|
//#region node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js
|
|
9
10
|
var _a$1;
|
|
10
11
|
function $constructor(name, initializer, params) {
|
|
@@ -4153,11 +4154,188 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4153
4154
|
//#endregion
|
|
4154
4155
|
//#region src/adapters/dsh-connection/observe-summary-rpc.ts
|
|
4155
4156
|
const RUN2SKILL_RPC_CHANNEL = "/run2skill";
|
|
4156
|
-
const OBSERVE_SUMMARY_ENDPOINT = "observe-summary";
|
|
4157
4157
|
object({ apiVersion: literal(1) }).strict();
|
|
4158
4158
|
//#endregion
|
|
4159
|
-
//#region src/client/
|
|
4160
|
-
const
|
|
4159
|
+
//#region src/client/dialog-focus.ts
|
|
4160
|
+
const focusableSelector = [
|
|
4161
|
+
"button:not([disabled])",
|
|
4162
|
+
"[href]",
|
|
4163
|
+
"input:not([disabled])",
|
|
4164
|
+
"select:not([disabled])",
|
|
4165
|
+
"textarea:not([disabled])",
|
|
4166
|
+
"[tabindex]:not([tabindex=\"-1\"])"
|
|
4167
|
+
].join(",");
|
|
4168
|
+
function trapDialogTab(key, backwards, preventDefault, root, activeElement) {
|
|
4169
|
+
if (key !== "Tab") return;
|
|
4170
|
+
const focusable = Array.from(root.querySelectorAll(focusableSelector));
|
|
4171
|
+
if (focusable.length === 0) {
|
|
4172
|
+
preventDefault();
|
|
4173
|
+
return;
|
|
4174
|
+
}
|
|
4175
|
+
const first = focusable[0];
|
|
4176
|
+
const last = focusable.at(-1);
|
|
4177
|
+
if (!focusable.includes(activeElement)) {
|
|
4178
|
+
preventDefault();
|
|
4179
|
+
(backwards ? last : first).focus();
|
|
4180
|
+
return;
|
|
4181
|
+
}
|
|
4182
|
+
if (backwards && activeElement === first) {
|
|
4183
|
+
preventDefault();
|
|
4184
|
+
last.focus();
|
|
4185
|
+
} else if (!backwards && activeElement === last) {
|
|
4186
|
+
preventDefault();
|
|
4187
|
+
first.focus();
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
//#endregion
|
|
4191
|
+
//#region src/client/style-lifecycle.ts
|
|
4192
|
+
const RUN2SKILL_STYLE_ID = "dsh-run2skill/native-ui";
|
|
4193
|
+
function styleSelector() {
|
|
4194
|
+
return `style[data-plugin-css="${RUN2SKILL_STYLE_ID}"]`;
|
|
4195
|
+
}
|
|
4196
|
+
function upsertRun2skillStyle(css) {
|
|
4197
|
+
const existing = document.querySelector(styleSelector());
|
|
4198
|
+
const tag = existing ?? document.createElement("style");
|
|
4199
|
+
tag.dataset.plugin = "dsh-run2skill";
|
|
4200
|
+
tag.dataset.pluginCss = RUN2SKILL_STYLE_ID;
|
|
4201
|
+
tag.textContent = css;
|
|
4202
|
+
if (existing === null) document.head.appendChild(tag);
|
|
4203
|
+
return tag;
|
|
4204
|
+
}
|
|
4205
|
+
function acquireRun2skillStyle() {
|
|
4206
|
+
if (typeof document === "undefined") return () => void 0;
|
|
4207
|
+
const tag = document.querySelector(styleSelector());
|
|
4208
|
+
if (tag === null) return () => void 0;
|
|
4209
|
+
const count = Number(tag.dataset.pluginMounts ?? "0");
|
|
4210
|
+
tag.dataset.pluginMounts = String(Number.isSafeInteger(count) && count >= 0 ? count + 1 : 1);
|
|
4211
|
+
let disposed = false;
|
|
4212
|
+
return () => {
|
|
4213
|
+
if (disposed) return;
|
|
4214
|
+
disposed = true;
|
|
4215
|
+
const current = Number(tag.dataset.pluginMounts ?? "1");
|
|
4216
|
+
if (current <= 1) tag.remove();
|
|
4217
|
+
else tag.dataset.pluginMounts = String(current - 1);
|
|
4218
|
+
};
|
|
4219
|
+
}
|
|
4220
|
+
//#endregion
|
|
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}}";
|
|
4223
|
+
if (typeof document !== "undefined") upsertRun2skillStyle(css);
|
|
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"
|
|
4251
|
+
};
|
|
4252
|
+
//#endregion
|
|
4253
|
+
//#region src/client/purge-settings.ts
|
|
4254
|
+
const PURGE_IDLE_POLL_INTERVAL_MS = 1e4;
|
|
4255
|
+
const PURGE_ACTIVE_POLL_INTERVAL_MS = 2e3;
|
|
4256
|
+
const previewId = string().regex(/^purv_[a-f0-9]{64}$/);
|
|
4257
|
+
const purgeId = string().regex(/^purge_[a-f0-9]{64}$/);
|
|
4258
|
+
const digest = string().regex(/^[a-f0-9]{64}$/);
|
|
4259
|
+
const isoDateTime = string().datetime({ offset: true });
|
|
4260
|
+
const count = number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
4261
|
+
const scopeBinding = discriminatedUnion("scope", [object({
|
|
4262
|
+
scope: literal("PROJECT"),
|
|
4263
|
+
workspaceId: string().min(1).max(256)
|
|
4264
|
+
}).strict(), object({ scope: literal("USER") }).strict()]);
|
|
4265
|
+
const previewSchema = object({
|
|
4266
|
+
apiVersion: literal(1),
|
|
4267
|
+
previewId,
|
|
4268
|
+
digest,
|
|
4269
|
+
expiresAt: isoDateTime,
|
|
4270
|
+
scopeBinding,
|
|
4271
|
+
hideBefore: isoDateTime,
|
|
4272
|
+
workItemCount: count,
|
|
4273
|
+
lineageCount: count,
|
|
4274
|
+
blockedOrUnprovenCount: count,
|
|
4275
|
+
willDelete: array(object({
|
|
4276
|
+
kind: _enum(["WORK_ITEMS", "LINEAGES"]),
|
|
4277
|
+
count
|
|
4278
|
+
}).strict()).length(2),
|
|
4279
|
+
willKeep: array(object({
|
|
4280
|
+
reason: _enum([
|
|
4281
|
+
"KEEP_NEW",
|
|
4282
|
+
"KEEP_SCOPE",
|
|
4283
|
+
"KEEP_UNPROVEN"
|
|
4284
|
+
]),
|
|
4285
|
+
count
|
|
4286
|
+
}).strict()).length(3),
|
|
4287
|
+
busyPublicationCount: count
|
|
4288
|
+
}).strict();
|
|
4289
|
+
const receiptSchema = object({
|
|
4290
|
+
apiVersion: literal(1),
|
|
4291
|
+
purgeId,
|
|
4292
|
+
state: _enum(["COMPLETED", "IN_PROGRESS"]),
|
|
4293
|
+
phase: _enum([
|
|
4294
|
+
"HIDING",
|
|
4295
|
+
"DELETING_LINEAGES",
|
|
4296
|
+
"DELETING_WORK_ITEMS",
|
|
4297
|
+
"VERIFYING"
|
|
4298
|
+
]).optional(),
|
|
4299
|
+
deletedWorkItems: count,
|
|
4300
|
+
deletedLineages: count
|
|
4301
|
+
}).strict();
|
|
4302
|
+
const statusSchema = discriminatedUnion("state", [object({
|
|
4303
|
+
apiVersion: literal(1),
|
|
4304
|
+
state: literal("IDLE")
|
|
4305
|
+
}).strict(), object({
|
|
4306
|
+
apiVersion: literal(1),
|
|
4307
|
+
state: literal("IN_PROGRESS"),
|
|
4308
|
+
purgeId,
|
|
4309
|
+
hideBefore: isoDateTime,
|
|
4310
|
+
startedAt: isoDateTime,
|
|
4311
|
+
phase: _enum([
|
|
4312
|
+
"HIDING",
|
|
4313
|
+
"DELETING_LINEAGES",
|
|
4314
|
+
"DELETING_WORK_ITEMS",
|
|
4315
|
+
"VERIFYING"
|
|
4316
|
+
]),
|
|
4317
|
+
deletedWorkItems: count,
|
|
4318
|
+
deletedLineages: count,
|
|
4319
|
+
lastError: object({
|
|
4320
|
+
code: string().regex(/^[A-Z0-9_]+$/),
|
|
4321
|
+
occurredAt: isoDateTime
|
|
4322
|
+
}).strict().optional()
|
|
4323
|
+
}).strict()]);
|
|
4324
|
+
const errorSchema = object({
|
|
4325
|
+
ok: literal(false),
|
|
4326
|
+
error: object({
|
|
4327
|
+
code: string().min(1).max(128),
|
|
4328
|
+
message: string().max(512),
|
|
4329
|
+
details: object({ busyPublicationCount: count.optional() }).strict().optional()
|
|
4330
|
+
}).strict()
|
|
4331
|
+
}).strict();
|
|
4332
|
+
var PurgeResponseError = class extends Error {
|
|
4333
|
+
facts;
|
|
4334
|
+
constructor(facts) {
|
|
4335
|
+
super(facts.code);
|
|
4336
|
+
this.facts = facts;
|
|
4337
|
+
}
|
|
4338
|
+
};
|
|
4161
4339
|
function browserEnvironment$2() {
|
|
4162
4340
|
return {
|
|
4163
4341
|
isVisible: () => typeof document === "undefined" || document.visibilityState === "visible",
|
|
@@ -4165,13 +4343,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4165
4343
|
clearInterval: (handle) => {
|
|
4166
4344
|
globalThis.clearInterval(handle);
|
|
4167
4345
|
},
|
|
4168
|
-
onFocus: (listener) => {
|
|
4169
|
-
if (typeof window === "undefined") return () => void 0;
|
|
4170
|
-
window.addEventListener("focus", listener);
|
|
4171
|
-
return () => {
|
|
4172
|
-
window.removeEventListener("focus", listener);
|
|
4173
|
-
};
|
|
4174
|
-
},
|
|
4175
4346
|
onVisibilityChange: (listener) => {
|
|
4176
4347
|
if (typeof document === "undefined") return () => void 0;
|
|
4177
4348
|
document.addEventListener("visibilitychange", listener);
|
|
@@ -4181,25 +4352,62 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4181
4352
|
}
|
|
4182
4353
|
};
|
|
4183
4354
|
}
|
|
4184
|
-
function
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4355
|
+
function parseValue$1(schema, response) {
|
|
4356
|
+
const success = object({
|
|
4357
|
+
ok: literal(true),
|
|
4358
|
+
value: schema
|
|
4359
|
+
}).strict().safeParse(response);
|
|
4360
|
+
if (success.success) return success.data.value;
|
|
4361
|
+
const failure = errorSchema.safeParse(response);
|
|
4362
|
+
if (failure.success) {
|
|
4363
|
+
const busy = failure.data.error.details?.busyPublicationCount;
|
|
4364
|
+
throw new PurgeResponseError({
|
|
4365
|
+
code: failure.data.error.code,
|
|
4366
|
+
...typeof busy === "number" && Number.isSafeInteger(busy) && busy >= 0 ? { busyPublicationCount: busy } : {}
|
|
4367
|
+
});
|
|
4368
|
+
}
|
|
4369
|
+
throw new PurgeResponseError({ code: "PURGE_STORAGE_UNAVAILABLE" });
|
|
4188
4370
|
}
|
|
4189
|
-
|
|
4371
|
+
function completionAnnouncement(scope, receipt) {
|
|
4372
|
+
return `${scope === void 0 ? "run2skill 数据" : `${scope} run2skill 数据`}清理完成:${String(receipt.deletedWorkItems)} 条待处理数据,${String(receipt.deletedLineages)} 条发布沿袭记录。`;
|
|
4373
|
+
}
|
|
4374
|
+
function polledCompletionAnnouncement(scope) {
|
|
4375
|
+
return `${scope === void 0 ? "" : `${scope} `}run2skill 数据清理完成。`;
|
|
4376
|
+
}
|
|
4377
|
+
function errorAnnouncement(error, durableBoundary = false) {
|
|
4378
|
+
if (error.code === "PURGE_PREVIEW_STALE") return "清理预览已失效,请重新预览后确认。";
|
|
4379
|
+
if (error.code === "PURGE_BUSY") return `当前有 ${String(error.busyPublicationCount ?? 0)} 条正在发布;请等待发布完成后重新预览。`;
|
|
4380
|
+
if (error.code === "PURGE_ALREADY_RUNNING") return "已有一项数据清理正在运行,请等待完成。";
|
|
4381
|
+
if (error.code === "PURGE_SCOPE_UNAVAILABLE") return "当前作用域无法可靠确认,未执行清理。";
|
|
4382
|
+
if (error.code === "PURGE_INCOMPATIBLE") return "当前数据版本不兼容,未执行清理。";
|
|
4383
|
+
if (error.code === "PURGE_FENCE_LIMIT") return "PROJECT 清理保护记录已达上限,未执行清理。";
|
|
4384
|
+
return durableBoundary ? "数据清理未完成;已建立的清理边界继续隐藏,可重试。" : "数据清理暂不可用;未确认已建立清理边界,请稍后重试。";
|
|
4385
|
+
}
|
|
4386
|
+
const initialState$1 = {
|
|
4387
|
+
statusPhase: "LOADING",
|
|
4388
|
+
previewPending: false,
|
|
4389
|
+
mutationPending: false,
|
|
4390
|
+
announcement: ""
|
|
4391
|
+
};
|
|
4392
|
+
var PurgeSettingsController = class {
|
|
4190
4393
|
call;
|
|
4394
|
+
getWorkspaceId;
|
|
4191
4395
|
environment;
|
|
4192
4396
|
#listeners = /* @__PURE__ */ new Set();
|
|
4193
|
-
#state =
|
|
4397
|
+
#state = initialState$1;
|
|
4194
4398
|
#started = false;
|
|
4399
|
+
#active = true;
|
|
4195
4400
|
#disposed = false;
|
|
4196
|
-
#timer;
|
|
4197
4401
|
#pending;
|
|
4198
4402
|
#abort;
|
|
4199
|
-
#
|
|
4403
|
+
#statusPending;
|
|
4404
|
+
#statusAbort;
|
|
4405
|
+
#timer;
|
|
4406
|
+
#timerDelay;
|
|
4200
4407
|
#removeVisibility;
|
|
4201
|
-
constructor(call, environment = browserEnvironment$2()) {
|
|
4408
|
+
constructor(call, getWorkspaceId, environment = browserEnvironment$2()) {
|
|
4202
4409
|
this.call = call;
|
|
4410
|
+
this.getWorkspaceId = getWorkspaceId;
|
|
4203
4411
|
this.environment = environment;
|
|
4204
4412
|
}
|
|
4205
4413
|
snapshot = () => this.#state;
|
|
@@ -4212,87 +4420,521 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4212
4420
|
start() {
|
|
4213
4421
|
if (this.#started || this.#disposed) return;
|
|
4214
4422
|
this.#started = true;
|
|
4215
|
-
this.#removeFocus = this.environment.onFocus(() => {
|
|
4216
|
-
if (this.environment.isVisible()) this.#refresh();
|
|
4217
|
-
});
|
|
4218
4423
|
this.#removeVisibility = this.environment.onVisibilityChange(() => {
|
|
4219
|
-
if (this.environment.isVisible()) {
|
|
4424
|
+
if (this.#active && this.environment.isVisible()) {
|
|
4220
4425
|
this.#schedule();
|
|
4221
|
-
this.#
|
|
4426
|
+
this.#refreshStatus();
|
|
4222
4427
|
} else this.#unschedule();
|
|
4223
4428
|
});
|
|
4224
|
-
if (this.environment.isVisible()) {
|
|
4429
|
+
if (this.#active && this.environment.isVisible()) {
|
|
4225
4430
|
this.#schedule();
|
|
4226
|
-
this.#
|
|
4431
|
+
this.#refreshStatus();
|
|
4227
4432
|
}
|
|
4228
4433
|
}
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
dispose() {
|
|
4233
|
-
if (this.#disposed) return;
|
|
4234
|
-
this.#disposed = true;
|
|
4434
|
+
pause() {
|
|
4435
|
+
if (this.#disposed || !this.#active) return;
|
|
4436
|
+
this.#active = false;
|
|
4235
4437
|
this.#unschedule();
|
|
4236
|
-
this.#
|
|
4237
|
-
this.#removeVisibility?.();
|
|
4238
|
-
this.#removeFocus = void 0;
|
|
4239
|
-
this.#removeVisibility = void 0;
|
|
4240
|
-
this.#abort?.abort();
|
|
4241
|
-
this.#listeners.clear();
|
|
4242
|
-
}
|
|
4243
|
-
#schedule() {
|
|
4244
|
-
if (this.#timer !== void 0 || this.#disposed) return;
|
|
4245
|
-
this.#timer = this.environment.setInterval(() => {
|
|
4246
|
-
this.#refresh();
|
|
4247
|
-
}, OBSERVE_SUMMARY_POLL_INTERVAL_MS);
|
|
4248
|
-
}
|
|
4249
|
-
#unschedule() {
|
|
4250
|
-
if (this.#timer === void 0) return;
|
|
4251
|
-
this.environment.clearInterval(this.#timer);
|
|
4252
|
-
this.#timer = void 0;
|
|
4438
|
+
this.#statusAbort?.abort();
|
|
4253
4439
|
}
|
|
4254
|
-
|
|
4255
|
-
if (this.#disposed || this.#
|
|
4256
|
-
|
|
4257
|
-
this.#
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
if (this.#disposed) return;
|
|
4262
|
-
if (summary === void 0) this.#markUnavailable();
|
|
4263
|
-
else this.#publish({
|
|
4264
|
-
phase: "READY",
|
|
4265
|
-
summary
|
|
4266
|
-
});
|
|
4267
|
-
} catch {
|
|
4268
|
-
if (!this.#disposed && !abort.signal.aborted) this.#markUnavailable();
|
|
4269
|
-
}
|
|
4270
|
-
})();
|
|
4271
|
-
this.#pending = pending;
|
|
4272
|
-
pending.finally(() => {
|
|
4273
|
-
if (this.#pending === pending) this.#pending = void 0;
|
|
4274
|
-
if (this.#abort === abort) this.#abort = void 0;
|
|
4440
|
+
resume() {
|
|
4441
|
+
if (this.#disposed || this.#active) return;
|
|
4442
|
+
this.#active = true;
|
|
4443
|
+
if (!this.#started || !this.environment.isVisible()) return;
|
|
4444
|
+
this.#schedule();
|
|
4445
|
+
this.whenIdle().then(() => {
|
|
4446
|
+
if (this.#active && !this.#disposed) this.#refreshStatus();
|
|
4275
4447
|
});
|
|
4276
|
-
return pending;
|
|
4277
|
-
}
|
|
4278
|
-
#markUnavailable() {
|
|
4279
|
-
this.#publish("summary" in this.#state ? {
|
|
4280
|
-
phase: "STALE",
|
|
4281
|
-
summary: this.#state.summary
|
|
4282
|
-
} : { phase: "UNAVAILABLE" });
|
|
4283
4448
|
}
|
|
4284
|
-
|
|
4285
|
-
this.#
|
|
4286
|
-
for (const listener of this.#listeners) listener();
|
|
4449
|
+
whenIdle() {
|
|
4450
|
+
return Promise.all([this.#pending ?? Promise.resolve(), this.#statusPending ?? Promise.resolve()]).then(() => void 0);
|
|
4287
4451
|
}
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4452
|
+
async preview(scope) {
|
|
4453
|
+
if (this.#disposed || this.#state.previewPending || this.#state.mutationPending) return;
|
|
4454
|
+
const workspaceId = this.getWorkspaceId();
|
|
4455
|
+
if (scope === "PROJECT" && workspaceId === void 0) {
|
|
4456
|
+
const error = { code: "PURGE_SCOPE_UNAVAILABLE" };
|
|
4457
|
+
this.#publish({
|
|
4458
|
+
...this.#state,
|
|
4459
|
+
error,
|
|
4460
|
+
announcement: errorAnnouncement(error)
|
|
4461
|
+
});
|
|
4462
|
+
return;
|
|
4463
|
+
}
|
|
4464
|
+
await this.#execute(async (signal) => {
|
|
4465
|
+
this.#publish({
|
|
4466
|
+
...this.#state,
|
|
4467
|
+
previewPending: true,
|
|
4468
|
+
previewScope: scope,
|
|
4469
|
+
preview: void 0,
|
|
4470
|
+
error: void 0,
|
|
4471
|
+
announcement: ""
|
|
4472
|
+
});
|
|
4473
|
+
const preview = parseValue$1(previewSchema, await this.call("purge/preview", scope === "PROJECT" ? {
|
|
4474
|
+
apiVersion: 1,
|
|
4475
|
+
scope,
|
|
4476
|
+
workspaceId
|
|
4477
|
+
} : {
|
|
4478
|
+
apiVersion: 1,
|
|
4479
|
+
scope
|
|
4480
|
+
}, signal));
|
|
4481
|
+
this.#publish({
|
|
4482
|
+
...this.#state,
|
|
4483
|
+
previewPending: false,
|
|
4484
|
+
preview,
|
|
4485
|
+
error: void 0
|
|
4486
|
+
});
|
|
4487
|
+
}, (error) => {
|
|
4488
|
+
this.#publish({
|
|
4489
|
+
...this.#state,
|
|
4490
|
+
previewPending: false,
|
|
4491
|
+
preview: void 0,
|
|
4492
|
+
error,
|
|
4493
|
+
announcement: errorAnnouncement(error)
|
|
4494
|
+
});
|
|
4495
|
+
});
|
|
4496
|
+
}
|
|
4497
|
+
cancelPreview() {
|
|
4498
|
+
if (this.#disposed || this.#state.mutationPending) return;
|
|
4499
|
+
this.#publish({
|
|
4500
|
+
...this.#state,
|
|
4501
|
+
preview: void 0,
|
|
4502
|
+
previewScope: void 0,
|
|
4503
|
+
error: void 0,
|
|
4504
|
+
announcement: ""
|
|
4505
|
+
});
|
|
4506
|
+
}
|
|
4507
|
+
async confirm() {
|
|
4508
|
+
const preview = this.#state.preview;
|
|
4509
|
+
const scope = this.#state.previewScope;
|
|
4510
|
+
if (this.#disposed || preview === void 0 || scope === void 0 || this.#state.mutationPending) return;
|
|
4511
|
+
const currentWorkspaceId = this.getWorkspaceId();
|
|
4512
|
+
if (scope === "PROJECT" && (currentWorkspaceId === void 0 || preview.scopeBinding.scope !== "PROJECT" || preview.scopeBinding.workspaceId !== currentWorkspaceId)) {
|
|
4513
|
+
const error = { code: "PURGE_PREVIEW_STALE" };
|
|
4514
|
+
this.#publish({
|
|
4515
|
+
...this.#state,
|
|
4516
|
+
preview: void 0,
|
|
4517
|
+
previewScope: void 0,
|
|
4518
|
+
error,
|
|
4519
|
+
announcement: errorAnnouncement(error)
|
|
4520
|
+
});
|
|
4521
|
+
return;
|
|
4522
|
+
}
|
|
4523
|
+
await this.#execute(async (signal) => {
|
|
4524
|
+
this.#publish({
|
|
4525
|
+
...this.#state,
|
|
4526
|
+
mutationPending: true,
|
|
4527
|
+
error: void 0,
|
|
4528
|
+
announcement: ""
|
|
4529
|
+
});
|
|
4530
|
+
const receipt = parseValue$1(receiptSchema, await this.call("purge/confirm", scope === "PROJECT" ? {
|
|
4531
|
+
apiVersion: 1,
|
|
4532
|
+
scope,
|
|
4533
|
+
workspaceId: currentWorkspaceId,
|
|
4534
|
+
previewId: preview.previewId,
|
|
4535
|
+
digest: preview.digest
|
|
4536
|
+
} : {
|
|
4537
|
+
apiVersion: 1,
|
|
4538
|
+
scope,
|
|
4539
|
+
previewId: preview.previewId,
|
|
4540
|
+
digest: preview.digest
|
|
4541
|
+
}, signal));
|
|
4542
|
+
this.#acceptReceipt(scope, receipt);
|
|
4543
|
+
}, async (error) => {
|
|
4544
|
+
this.#publish({
|
|
4545
|
+
...this.#state,
|
|
4546
|
+
mutationPending: false,
|
|
4547
|
+
error,
|
|
4548
|
+
announcement: errorAnnouncement(error),
|
|
4549
|
+
preview: void 0,
|
|
4550
|
+
previewScope: void 0
|
|
4551
|
+
});
|
|
4552
|
+
await this.#readStatusAfterFailure(error);
|
|
4553
|
+
});
|
|
4554
|
+
}
|
|
4555
|
+
async retry() {
|
|
4556
|
+
const status = this.#state.status;
|
|
4557
|
+
if (this.#disposed || status?.state !== "IN_PROGRESS" || status.lastError === void 0 || this.#state.mutationPending) return;
|
|
4558
|
+
await this.#execute(async (signal) => {
|
|
4559
|
+
this.#publish({
|
|
4560
|
+
...this.#state,
|
|
4561
|
+
mutationPending: true,
|
|
4562
|
+
error: void 0,
|
|
4563
|
+
announcement: "正在重试数据清理。"
|
|
4564
|
+
});
|
|
4565
|
+
const receipt = parseValue$1(receiptSchema, await this.call("purge/retry", {
|
|
4566
|
+
apiVersion: 1,
|
|
4567
|
+
purgeId: status.purgeId
|
|
4568
|
+
}, signal));
|
|
4569
|
+
this.#acceptReceipt(this.#state.previewScope, receipt);
|
|
4570
|
+
}, async (error) => {
|
|
4571
|
+
this.#publish({
|
|
4572
|
+
...this.#state,
|
|
4573
|
+
mutationPending: false,
|
|
4574
|
+
error,
|
|
4575
|
+
announcement: errorAnnouncement(error, true)
|
|
4576
|
+
});
|
|
4577
|
+
await this.#readStatusAfterFailure(error, true);
|
|
4578
|
+
});
|
|
4579
|
+
}
|
|
4580
|
+
dispose() {
|
|
4581
|
+
if (this.#disposed) return;
|
|
4582
|
+
this.#disposed = true;
|
|
4583
|
+
this.#unschedule();
|
|
4584
|
+
this.#removeVisibility?.();
|
|
4585
|
+
this.#removeVisibility = void 0;
|
|
4586
|
+
this.#abort?.abort();
|
|
4587
|
+
this.#statusAbort?.abort();
|
|
4588
|
+
this.#listeners.clear();
|
|
4589
|
+
}
|
|
4590
|
+
#acceptReceipt(scope, receipt) {
|
|
4591
|
+
if (receipt.state === "COMPLETED") {
|
|
4592
|
+
this.#publish({
|
|
4593
|
+
...this.#state,
|
|
4594
|
+
statusPhase: "READY",
|
|
4595
|
+
status: {
|
|
4596
|
+
apiVersion: 1,
|
|
4597
|
+
state: "IDLE"
|
|
4598
|
+
},
|
|
4599
|
+
inProgressReceipt: void 0,
|
|
4600
|
+
preview: void 0,
|
|
4601
|
+
previewScope: void 0,
|
|
4602
|
+
mutationPending: false,
|
|
4603
|
+
error: void 0,
|
|
4604
|
+
announcement: completionAnnouncement(scope, receipt)
|
|
4605
|
+
});
|
|
4606
|
+
return;
|
|
4607
|
+
}
|
|
4608
|
+
this.#publish({
|
|
4609
|
+
...this.#state,
|
|
4610
|
+
mutationPending: false,
|
|
4611
|
+
preview: void 0,
|
|
4612
|
+
inProgressReceipt: receipt,
|
|
4613
|
+
announcement: `run2skill 数据清理进行中:${receipt.phase ?? "HIDING"}。`
|
|
4614
|
+
});
|
|
4615
|
+
}
|
|
4616
|
+
async #readStatusAfterFailure(error, durableBoundary = false) {
|
|
4617
|
+
try {
|
|
4618
|
+
const status = parseValue$1(statusSchema, await this.call("purge/status", { apiVersion: 1 }, new AbortController().signal));
|
|
4619
|
+
this.#publish({
|
|
4620
|
+
...this.#state,
|
|
4621
|
+
statusPhase: "READY",
|
|
4622
|
+
status,
|
|
4623
|
+
inProgressReceipt: status.state === "IDLE" ? void 0 : this.#state.inProgressReceipt,
|
|
4624
|
+
announcement: errorAnnouncement(error, durableBoundary || status.state === "IN_PROGRESS")
|
|
4625
|
+
});
|
|
4626
|
+
} catch {}
|
|
4627
|
+
}
|
|
4628
|
+
async #refreshStatus() {
|
|
4629
|
+
if (this.#disposed || !this.#active || !this.environment.isVisible()) return;
|
|
4630
|
+
if (this.#statusPending !== void 0) return this.#statusPending;
|
|
4631
|
+
const abort = new AbortController();
|
|
4632
|
+
this.#statusAbort = abort;
|
|
4633
|
+
const pending = (async () => {
|
|
4634
|
+
try {
|
|
4635
|
+
const status = parseValue$1(statusSchema, await this.call("purge/status", { apiVersion: 1 }, abort.signal));
|
|
4636
|
+
if (this.#disposed || abort.signal.aborted) return;
|
|
4637
|
+
const completed = status.state === "IDLE" && (this.#state.status?.state === "IN_PROGRESS" || this.#state.inProgressReceipt?.state === "IN_PROGRESS");
|
|
4638
|
+
this.#publish({
|
|
4639
|
+
...this.#state,
|
|
4640
|
+
statusPhase: "READY",
|
|
4641
|
+
status,
|
|
4642
|
+
inProgressReceipt: status.state === "IDLE" ? void 0 : this.#state.inProgressReceipt,
|
|
4643
|
+
previewScope: completed ? void 0 : this.#state.previewScope,
|
|
4644
|
+
announcement: completed ? polledCompletionAnnouncement(this.#state.previewScope) : this.#state.announcement
|
|
4645
|
+
});
|
|
4646
|
+
} catch {
|
|
4647
|
+
if (this.#disposed || abort.signal.aborted) return;
|
|
4648
|
+
this.#publish({
|
|
4649
|
+
...this.#state,
|
|
4650
|
+
statusPhase: this.#state.status === void 0 ? "UNAVAILABLE" : "STALE"
|
|
4651
|
+
});
|
|
4652
|
+
}
|
|
4653
|
+
})();
|
|
4654
|
+
this.#statusPending = pending;
|
|
4655
|
+
await pending.finally(() => {
|
|
4656
|
+
if (this.#statusPending === pending) this.#statusPending = void 0;
|
|
4657
|
+
if (this.#statusAbort === abort) this.#statusAbort = void 0;
|
|
4658
|
+
});
|
|
4659
|
+
}
|
|
4660
|
+
async #execute(task, onError) {
|
|
4661
|
+
if (this.#disposed || this.#pending !== void 0) return this.#pending ?? Promise.resolve();
|
|
4662
|
+
const abort = new AbortController();
|
|
4663
|
+
this.#abort = abort;
|
|
4664
|
+
const pending = (async () => {
|
|
4665
|
+
try {
|
|
4666
|
+
await task(abort.signal);
|
|
4667
|
+
} catch (error) {
|
|
4668
|
+
if (!this.#disposed && !abort.signal.aborted) await onError(error instanceof PurgeResponseError ? error.facts : { code: "PURGE_STORAGE_UNAVAILABLE" });
|
|
4669
|
+
}
|
|
4670
|
+
})();
|
|
4671
|
+
this.#pending = pending;
|
|
4672
|
+
await pending.finally(() => {
|
|
4673
|
+
if (this.#pending === pending) this.#pending = void 0;
|
|
4674
|
+
if (this.#abort === abort) this.#abort = void 0;
|
|
4675
|
+
});
|
|
4676
|
+
}
|
|
4677
|
+
#schedule() {
|
|
4678
|
+
if (this.#disposed || !this.#active) return;
|
|
4679
|
+
const delay = this.#state.status?.state === "IN_PROGRESS" || this.#state.inProgressReceipt?.state === "IN_PROGRESS" || this.#state.mutationPending ? PURGE_ACTIVE_POLL_INTERVAL_MS : PURGE_IDLE_POLL_INTERVAL_MS;
|
|
4680
|
+
if (this.#timer !== void 0 && this.#timerDelay === delay) return;
|
|
4681
|
+
this.#unschedule();
|
|
4682
|
+
this.#timerDelay = delay;
|
|
4683
|
+
this.#timer = this.environment.setInterval(() => {
|
|
4684
|
+
this.#refreshStatus();
|
|
4685
|
+
}, delay);
|
|
4686
|
+
}
|
|
4687
|
+
#unschedule() {
|
|
4688
|
+
if (this.#timer === void 0) return;
|
|
4689
|
+
this.environment.clearInterval(this.#timer);
|
|
4690
|
+
this.#timer = void 0;
|
|
4691
|
+
this.#timerDelay = void 0;
|
|
4692
|
+
}
|
|
4693
|
+
#publish(state) {
|
|
4694
|
+
if (this.#disposed) return;
|
|
4695
|
+
this.#state = state;
|
|
4696
|
+
if (this.#started && this.#active && this.environment.isVisible()) this.#schedule();
|
|
4697
|
+
for (const listener of this.#listeners) listener();
|
|
4698
|
+
}
|
|
4699
|
+
};
|
|
4700
|
+
const phaseCopy = {
|
|
4701
|
+
HIDING: "正在隐藏命中数据",
|
|
4702
|
+
DELETING_LINEAGES: "正在删除发布沿袭记录",
|
|
4703
|
+
DELETING_WORK_ITEMS: "正在删除待处理数据",
|
|
4704
|
+
VERIFYING: "正在验证清理结果"
|
|
4705
|
+
};
|
|
4706
|
+
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)} 条;存在时确认会安全拒绝`));
|
|
4709
|
+
}
|
|
4710
|
+
function PurgeConfirmationDialog(props) {
|
|
4711
|
+
const dialogRef = (0, react.useRef)(null);
|
|
4712
|
+
const preview = props.state.preview;
|
|
4713
|
+
const scope = props.state.previewScope;
|
|
4714
|
+
(0, react.useEffect)(() => {
|
|
4715
|
+
if (preview === void 0 || typeof document === "undefined") return;
|
|
4716
|
+
const dialog = dialogRef.current?.closest("[role=\"dialog\"]");
|
|
4717
|
+
const initial = dialog?.querySelector("[autofocus]");
|
|
4718
|
+
const recapture = (event) => {
|
|
4719
|
+
if (dialog != null && event.target instanceof Node && !dialog.contains(event.target)) initial?.focus();
|
|
4720
|
+
};
|
|
4721
|
+
const captureKeyboard = (event) => {
|
|
4722
|
+
if (dialog == null || event.key !== "Escape" && event.key !== "Tab") return;
|
|
4723
|
+
if (event.key === "Escape") {
|
|
4724
|
+
event.preventDefault();
|
|
4725
|
+
event.stopImmediatePropagation();
|
|
4726
|
+
props.controller.cancelPreview();
|
|
4727
|
+
return;
|
|
4728
|
+
}
|
|
4729
|
+
trapDialogTab(event.key, event.shiftKey, () => {
|
|
4730
|
+
event.preventDefault();
|
|
4731
|
+
}, dialog, document.activeElement);
|
|
4732
|
+
};
|
|
4733
|
+
document.addEventListener("focusin", recapture, true);
|
|
4734
|
+
document.addEventListener("keydown", captureKeyboard, true);
|
|
4735
|
+
initial?.focus();
|
|
4736
|
+
return () => {
|
|
4737
|
+
document.removeEventListener("focusin", recapture, true);
|
|
4738
|
+
document.removeEventListener("keydown", captureKeyboard, true);
|
|
4739
|
+
props.restoreFocusRef.current?.focus();
|
|
4740
|
+
};
|
|
4741
|
+
}, [preview?.previewId, props.restoreFocusRef]);
|
|
4742
|
+
if (preview === void 0 || scope === void 0) return null;
|
|
4743
|
+
return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
4744
|
+
open: true,
|
|
4745
|
+
title: `确认清理 ${scope} run2skill 数据?`,
|
|
4746
|
+
description: "此操作只清理本次预览边界内的 run2skill 数据,不会卸载插件。",
|
|
4747
|
+
closeLabel: "关闭清理确认框",
|
|
4748
|
+
onClose: () => {
|
|
4749
|
+
props.controller.cancelPreview();
|
|
4750
|
+
},
|
|
4751
|
+
footer: (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.actions }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
4752
|
+
variant: "ghost",
|
|
4753
|
+
autoFocus: true,
|
|
4754
|
+
disabled: props.state.mutationPending,
|
|
4755
|
+
onClick: () => {
|
|
4756
|
+
props.controller.cancelPreview();
|
|
4757
|
+
}
|
|
4758
|
+
}, "取消清理"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
4759
|
+
variant: "primary",
|
|
4760
|
+
icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16),
|
|
4761
|
+
disabled: props.state.mutationPending,
|
|
4762
|
+
onClick: () => {
|
|
4763
|
+
props.controller.confirm();
|
|
4764
|
+
}
|
|
4765
|
+
}, props.state.mutationPending ? "正在清理…" : "确认清理"))
|
|
4766
|
+
}, (0, react.createElement)("div", {
|
|
4767
|
+
ref: dialogRef,
|
|
4768
|
+
onKeyDown: (event) => {
|
|
4769
|
+
event.stopPropagation();
|
|
4770
|
+
if (event.key === "Escape") {
|
|
4771
|
+
event.preventDefault();
|
|
4772
|
+
props.controller.cancelPreview();
|
|
4773
|
+
} else if (dialogRef.current !== null) trapDialogTab(event.key, event.shiftKey, () => {
|
|
4774
|
+
event.preventDefault();
|
|
4775
|
+
}, dialogRef.current, typeof document === "undefined" ? void 0 : document.activeElement);
|
|
4776
|
+
}
|
|
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 })));
|
|
4778
|
+
}
|
|
4779
|
+
function PurgeSettingsSection(props) {
|
|
4780
|
+
const surfaceActive = props.active ?? true;
|
|
4781
|
+
(0, react.useEffect)(() => {
|
|
4782
|
+
if (!surfaceActive) props.controller.pause();
|
|
4783
|
+
props.controller.start();
|
|
4784
|
+
}, [props.controller]);
|
|
4785
|
+
(0, react.useEffect)(() => {
|
|
4786
|
+
if (surfaceActive) props.controller.resume();
|
|
4787
|
+
else props.controller.pause();
|
|
4788
|
+
}, [surfaceActive, props.controller]);
|
|
4789
|
+
const state = (0, react.useSyncExternalStore)(props.controller.subscribe, props.controller.snapshot, props.controller.snapshot);
|
|
4790
|
+
const restoreRef = (0, react.useMemo)(() => ({ current: null }), []);
|
|
4791
|
+
const active = state.status?.state === "IN_PROGRESS" ? state.status : void 0;
|
|
4792
|
+
const activeReceipt = state.inProgressReceipt?.state === "IN_PROGRESS" ? state.inProgressReceipt : void 0;
|
|
4793
|
+
const activePhase = active?.phase ?? activeReceipt?.phase ?? (activeReceipt === void 0 ? void 0 : "HIDING");
|
|
4794
|
+
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, {
|
|
4804
|
+
variant: "outline",
|
|
4805
|
+
icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16),
|
|
4806
|
+
disabled,
|
|
4807
|
+
onClick: (event) => {
|
|
4808
|
+
restoreRef.current = event.currentTarget;
|
|
4809
|
+
props.controller.preview("USER");
|
|
4810
|
+
}
|
|
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", {
|
|
4812
|
+
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, {
|
|
4815
|
+
variant: "outline",
|
|
4816
|
+
icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16),
|
|
4817
|
+
disabled: state.mutationPending,
|
|
4818
|
+
onClick: () => {
|
|
4819
|
+
props.controller.retry();
|
|
4820
|
+
}
|
|
4821
|
+
}, state.mutationPending ? "正在重试…" : "重试清理"))), state.error === void 0 ? null : (0, react.createElement)("p", { role: "alert" }, state.announcement), (0, react.createElement)("div", {
|
|
4822
|
+
role: "status",
|
|
4823
|
+
"aria-label": "Purge 状态播报",
|
|
4824
|
+
"aria-live": "polite",
|
|
4825
|
+
"aria-atomic": true
|
|
4826
|
+
}, state.announcement), (0, react.createElement)(PurgeConfirmationDialog, {
|
|
4827
|
+
controller: props.controller,
|
|
4828
|
+
state,
|
|
4829
|
+
restoreFocusRef: restoreRef
|
|
4830
|
+
}));
|
|
4831
|
+
}
|
|
4832
|
+
//#endregion
|
|
4833
|
+
//#region src/client/automatic-learning-settings.ts
|
|
4834
|
+
var AutomaticLearningSettingsController = class {
|
|
4835
|
+
scope;
|
|
4836
|
+
#listeners = /* @__PURE__ */ new Set();
|
|
4837
|
+
#snapshot;
|
|
4838
|
+
#saving = false;
|
|
4839
|
+
#error;
|
|
4840
|
+
#unsubscribe;
|
|
4841
|
+
constructor(scope) {
|
|
4842
|
+
this.scope = scope;
|
|
4843
|
+
this.#snapshot = this.#project();
|
|
4844
|
+
this.#unsubscribe = scope.subscribe(() => {
|
|
4845
|
+
this.#publish();
|
|
4846
|
+
});
|
|
4847
|
+
}
|
|
4848
|
+
getSnapshot = () => this.#snapshot;
|
|
4849
|
+
subscribe = (listener) => {
|
|
4850
|
+
this.#listeners.add(listener);
|
|
4851
|
+
return () => {
|
|
4852
|
+
this.#listeners.delete(listener);
|
|
4853
|
+
};
|
|
4854
|
+
};
|
|
4855
|
+
async setAutomaticLearning(value) {
|
|
4856
|
+
const before = this.scope.getSnapshot();
|
|
4857
|
+
if (before.status !== "ready" || !before.writable || this.#saving) return;
|
|
4858
|
+
this.#saving = true;
|
|
4859
|
+
this.#error = void 0;
|
|
4860
|
+
this.#publish();
|
|
4861
|
+
try {
|
|
4862
|
+
await this.scope.set("automaticLearning", value);
|
|
4863
|
+
const after = this.scope.getSnapshot();
|
|
4864
|
+
this.#error = after.status === "ready" && after.value?.automaticLearning === value ? void 0 : "SETTINGS_CHANGED";
|
|
4865
|
+
} catch {
|
|
4866
|
+
this.#error = "SETTINGS_CHANGED";
|
|
4867
|
+
} finally {
|
|
4868
|
+
this.#saving = false;
|
|
4869
|
+
this.#publish();
|
|
4870
|
+
}
|
|
4871
|
+
}
|
|
4872
|
+
dispose() {
|
|
4873
|
+
this.#unsubscribe();
|
|
4874
|
+
this.#listeners.clear();
|
|
4875
|
+
}
|
|
4876
|
+
#project() {
|
|
4877
|
+
const snapshot = this.scope.getSnapshot();
|
|
4878
|
+
return Object.freeze({
|
|
4879
|
+
status: snapshot.status,
|
|
4880
|
+
automaticLearning: snapshot.value?.automaticLearning,
|
|
4881
|
+
writable: snapshot.writable,
|
|
4882
|
+
saving: this.#saving,
|
|
4883
|
+
error: this.#error
|
|
4884
|
+
});
|
|
4885
|
+
}
|
|
4886
|
+
#publish() {
|
|
4887
|
+
this.#snapshot = this.#project();
|
|
4888
|
+
for (const listener of this.#listeners) listener();
|
|
4889
|
+
}
|
|
4890
|
+
};
|
|
4891
|
+
function AutomaticLearningSettingsCard(props) {
|
|
4892
|
+
const state = (0, react.useSyncExternalStore)(props.controller.subscribe, props.controller.getSnapshot, props.controller.getSnapshot);
|
|
4893
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
4894
|
+
if (state.status === "unavailable") return null;
|
|
4895
|
+
const disabled = state.status !== "ready" || !state.writable || state.saving;
|
|
4896
|
+
return (0, react.createElement)("li", { "data-run2skill-settings-card": true }, (0, react.createElement)("button", {
|
|
4897
|
+
type: "button",
|
|
4898
|
+
"aria-expanded": open,
|
|
4899
|
+
onClick: () => {
|
|
4900
|
+
setOpen((value) => !value);
|
|
4901
|
+
}
|
|
4902
|
+
}, "run2skill", (0, react.createElement)("span", null, "将真实执行中的明确经验转为待审核 Skill Proposal")), open ? (0, react.createElement)("div", null, (0, react.createElement)("label", null, (0, react.createElement)("input", {
|
|
4903
|
+
type: "checkbox",
|
|
4904
|
+
checked: state.automaticLearning === true,
|
|
4905
|
+
disabled,
|
|
4906
|
+
onChange: (event) => {
|
|
4907
|
+
props.controller.setAutomaticLearning(event.currentTarget.checked);
|
|
4908
|
+
}
|
|
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);
|
|
4910
|
+
}
|
|
4911
|
+
function applyAutomaticLearningSettingsClient(context) {
|
|
4912
|
+
const controller = new AutomaticLearningSettingsController(context.settingsScope.bind({ namespace: "run2skill" }));
|
|
4913
|
+
const callPurge = async (endpoint, payload, signal) => await context.connection.rpc.call(RUN2SKILL_RPC_CHANNEL, endpoint, payload, signal);
|
|
4914
|
+
const purgeController = new PurgeSettingsController(callPurge, () => {
|
|
4915
|
+
return context.workspaces.list.getSnapshot().recentWorkspaceId;
|
|
4916
|
+
});
|
|
4917
|
+
purgeController.start();
|
|
4918
|
+
context.effect?.(() => () => {
|
|
4919
|
+
controller.dispose();
|
|
4920
|
+
purgeController.dispose();
|
|
4921
|
+
}, "run2skill: settings and purge");
|
|
4922
|
+
context.slots.inject("settings.plugin.item", () => context.slots.register({
|
|
4923
|
+
name: "settings.plugin.item",
|
|
4924
|
+
key: "run2skill",
|
|
4925
|
+
inject: () => ({
|
|
4926
|
+
controller,
|
|
4927
|
+
purgeController
|
|
4928
|
+
})
|
|
4929
|
+
}, AutomaticLearningSettingsCard));
|
|
4930
|
+
}
|
|
4931
|
+
//#endregion
|
|
4932
|
+
//#region src/client/proposal-inbox-wire.ts
|
|
4933
|
+
const identity = string().min(1).max(256);
|
|
4934
|
+
const sha256 = string().regex(/^[a-f0-9]{64}$/);
|
|
4935
|
+
const positiveInteger = number().int().safe().positive();
|
|
4936
|
+
const nonNegativeInteger = number().int().safe().nonnegative();
|
|
4937
|
+
const proposalId = string().regex(/^prop_[a-f0-9]{64}$/);
|
|
4296
4938
|
const workItemId = string().regex(/^wi_[a-f0-9]{64}$/);
|
|
4297
4939
|
const proposalRef = object({
|
|
4298
4940
|
proposalId,
|
|
@@ -4320,35 +4962,27 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4320
4962
|
expectedSource: _enum(["project-dsh", "user-dsh"]),
|
|
4321
4963
|
resolverVersion: identity,
|
|
4322
4964
|
rootContractVersion: identity,
|
|
4323
|
-
resolutionContractDigest: sha256
|
|
4324
|
-
|
|
4325
|
-
}).
|
|
4326
|
-
const targetDisplay = object({
|
|
4327
|
-
bundlePath: string().min(1).max(8192),
|
|
4328
|
-
skillFilePath: string().min(1).max(8192)
|
|
4329
|
-
}).passthrough();
|
|
4965
|
+
resolutionContractDigest: sha256
|
|
4966
|
+
}).strict();
|
|
4967
|
+
const targetDisplay = object({ skillName: identity }).strict();
|
|
4330
4968
|
const actionBinding = discriminatedUnion("kind", [
|
|
4331
4969
|
object({
|
|
4332
4970
|
kind: literal("CREATE"),
|
|
4333
4971
|
rootBinding: rootDisplay,
|
|
4334
4972
|
targetBinding: targetDisplay,
|
|
4335
|
-
expectedAbsence: object({
|
|
4336
|
-
|
|
4337
|
-
flatSkillFilePath: string().min(1).max(8192)
|
|
4338
|
-
}).passthrough()
|
|
4339
|
-
}).passthrough(),
|
|
4973
|
+
expectedAbsence: object({ observedAt: string().min(1).max(64) }).strict()
|
|
4974
|
+
}).strict(),
|
|
4340
4975
|
object({
|
|
4341
4976
|
kind: literal("MERGE"),
|
|
4342
4977
|
rootBinding: rootDisplay,
|
|
4343
4978
|
targetBinding: targetDisplay,
|
|
4344
4979
|
baseBinding: object({
|
|
4345
4980
|
candidateKey: string().regex(/^cand_[a-f0-9]{64}$/),
|
|
4346
|
-
path: string().min(1).max(8192),
|
|
4347
4981
|
exactBytes: string().min(1).max(65536),
|
|
4348
4982
|
bytesDigest: sha256,
|
|
4349
4983
|
observedAt: string().min(1).max(64)
|
|
4350
|
-
}).
|
|
4351
|
-
}).
|
|
4984
|
+
}).strict()
|
|
4985
|
+
}).strict(),
|
|
4352
4986
|
object({
|
|
4353
4987
|
kind: literal("DISCARD"),
|
|
4354
4988
|
coveringCandidateBinding: object({
|
|
@@ -4357,10 +4991,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4357
4991
|
source: identity,
|
|
4358
4992
|
content: string().min(1).max(65536),
|
|
4359
4993
|
contentDigest: sha256,
|
|
4360
|
-
observedAt: string().min(1).max(64)
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
}).passthrough()
|
|
4994
|
+
observedAt: string().min(1).max(64)
|
|
4995
|
+
}).strict()
|
|
4996
|
+
}).strict()
|
|
4364
4997
|
]);
|
|
4365
4998
|
const proposal = object({
|
|
4366
4999
|
schemaVersion: literal(1),
|
|
@@ -4383,20 +5016,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4383
5016
|
skillBytesDigest: sha256,
|
|
4384
5017
|
rendererVersion: identity,
|
|
4385
5018
|
persistenceScope: _enum(["PROJECT", "USER"]),
|
|
4386
|
-
workspaceBinding: object({
|
|
4387
|
-
workspaceId: identity,
|
|
4388
|
-
canonicalPath: string().min(1).max(8192),
|
|
4389
|
-
observedAt: string().min(1).max(64)
|
|
4390
|
-
}).strict().optional(),
|
|
5019
|
+
workspaceBinding: object({ workspaceId: identity }).strict().optional(),
|
|
4391
5020
|
dshHomeBinding: object({
|
|
4392
5021
|
resolutionKind: _enum([
|
|
4393
5022
|
"CONFIGURATION",
|
|
4394
5023
|
"ENVIRONMENT",
|
|
4395
5024
|
"DEFAULT"
|
|
4396
5025
|
]),
|
|
4397
|
-
|
|
4398
|
-
identityDigest: sha256,
|
|
4399
|
-
observedAt: string().min(1).max(64)
|
|
5026
|
+
identityDigest: sha256
|
|
4400
5027
|
}).strict().optional(),
|
|
4401
5028
|
supportingExperienceIds: array(string().regex(/^exp_[a-f0-9]{64}$/)).min(1).max(3),
|
|
4402
5029
|
catalogObservationDigest: sha256,
|
|
@@ -4477,7 +5104,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4477
5104
|
const listPage = object({
|
|
4478
5105
|
apiVersion: literal(1),
|
|
4479
5106
|
items: array(listItem).max(20),
|
|
4480
|
-
nextCursor: string().regex(/^c_[0-9]
|
|
5107
|
+
nextCursor: string().regex(/^c_[1-9][0-9]*_[1-9][0-9]*_[a-f0-9]{64}$/).optional()
|
|
4481
5108
|
}).strict();
|
|
4482
5109
|
const detail = object({
|
|
4483
5110
|
apiVersion: literal(1),
|
|
@@ -4514,7 +5141,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4514
5141
|
]),
|
|
4515
5142
|
publicationOutcome
|
|
4516
5143
|
}).strict();
|
|
4517
|
-
function parseValue
|
|
5144
|
+
function parseValue(schema, value) {
|
|
4518
5145
|
const parsed = object({
|
|
4519
5146
|
ok: literal(true),
|
|
4520
5147
|
value: schema
|
|
@@ -4522,16 +5149,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4522
5149
|
return parsed.success ? parsed.data.value : void 0;
|
|
4523
5150
|
}
|
|
4524
5151
|
function parseProposalSummary(value) {
|
|
4525
|
-
return parseValue
|
|
5152
|
+
return parseValue(summary, value);
|
|
4526
5153
|
}
|
|
4527
5154
|
function parseProposalList(value) {
|
|
4528
|
-
return parseValue
|
|
5155
|
+
return parseValue(listPage, value);
|
|
4529
5156
|
}
|
|
4530
5157
|
function parseProposalDetail(value) {
|
|
4531
|
-
return parseValue
|
|
5158
|
+
return parseValue(detail, value);
|
|
4532
5159
|
}
|
|
4533
5160
|
function parseMutationReceipt(value) {
|
|
4534
|
-
return parseValue
|
|
5161
|
+
return parseValue(receipt, value);
|
|
4535
5162
|
}
|
|
4536
5163
|
//#endregion
|
|
4537
5164
|
//#region src/client/proposal-inbox.ts
|
|
@@ -4607,7 +5234,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4607
5234
|
}
|
|
4608
5235
|
};
|
|
4609
5236
|
}
|
|
4610
|
-
const initialState
|
|
5237
|
+
const initialState = {
|
|
4611
5238
|
open: false,
|
|
4612
5239
|
summaryPhase: "LOADING",
|
|
4613
5240
|
listPhase: "IDLE",
|
|
@@ -4620,9 +5247,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4620
5247
|
workspaceId;
|
|
4621
5248
|
call;
|
|
4622
5249
|
environment;
|
|
5250
|
+
options;
|
|
4623
5251
|
#listeners = /* @__PURE__ */ new Set();
|
|
4624
|
-
#state = initialState
|
|
5252
|
+
#state = initialState;
|
|
4625
5253
|
#started = false;
|
|
5254
|
+
#active = true;
|
|
4626
5255
|
#disposed = false;
|
|
4627
5256
|
#pending;
|
|
4628
5257
|
#abort;
|
|
@@ -4631,10 +5260,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4631
5260
|
#removeFocus;
|
|
4632
5261
|
#removeVisibility;
|
|
4633
5262
|
#removeOnline;
|
|
4634
|
-
constructor(workspaceId, call, environment = browserEnvironment$1()) {
|
|
5263
|
+
constructor(workspaceId, call, environment = browserEnvironment$1(), options = {}) {
|
|
4635
5264
|
this.workspaceId = workspaceId;
|
|
4636
5265
|
this.call = call;
|
|
4637
5266
|
this.environment = environment;
|
|
5267
|
+
this.options = options;
|
|
4638
5268
|
}
|
|
4639
5269
|
snapshot = () => this.#state;
|
|
4640
5270
|
subscribe = (listener) => {
|
|
@@ -4647,21 +5277,36 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4647
5277
|
if (this.#started || this.#disposed) return;
|
|
4648
5278
|
this.#started = true;
|
|
4649
5279
|
const refresh = () => {
|
|
4650
|
-
if (this.environment.isVisible()) this.#refreshVisible();
|
|
5280
|
+
if (this.#active && this.environment.isVisible()) this.#refreshVisible();
|
|
4651
5281
|
};
|
|
4652
5282
|
this.#removeFocus = this.environment.onFocus(refresh);
|
|
4653
5283
|
this.#removeOnline = this.environment.onOnline(refresh);
|
|
4654
5284
|
this.#removeVisibility = this.environment.onVisibilityChange(() => {
|
|
4655
|
-
if (this.environment.isVisible()) {
|
|
5285
|
+
if (this.#active && this.environment.isVisible()) {
|
|
4656
5286
|
this.#schedule();
|
|
4657
5287
|
this.#refreshVisible();
|
|
4658
5288
|
} else this.#unschedule();
|
|
4659
5289
|
});
|
|
4660
|
-
if (this.environment.isVisible()) {
|
|
5290
|
+
if (this.#active && this.environment.isVisible()) {
|
|
4661
5291
|
this.#schedule();
|
|
4662
5292
|
this.#refreshVisible();
|
|
4663
5293
|
}
|
|
4664
5294
|
}
|
|
5295
|
+
pause() {
|
|
5296
|
+
if (this.#disposed || !this.#active) return;
|
|
5297
|
+
this.#active = false;
|
|
5298
|
+
this.#unschedule();
|
|
5299
|
+
this.#abort?.abort();
|
|
5300
|
+
}
|
|
5301
|
+
resume() {
|
|
5302
|
+
if (this.#disposed || this.#active) return;
|
|
5303
|
+
this.#active = true;
|
|
5304
|
+
if (!this.#started || !this.environment.isVisible()) return;
|
|
5305
|
+
this.#schedule();
|
|
5306
|
+
this.whenIdle().then(() => {
|
|
5307
|
+
if (this.#active && !this.#disposed) this.#refreshVisible();
|
|
5308
|
+
});
|
|
5309
|
+
}
|
|
4665
5310
|
whenIdle() {
|
|
4666
5311
|
return this.#pending ?? Promise.resolve();
|
|
4667
5312
|
}
|
|
@@ -4693,9 +5338,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4693
5338
|
detail: void 0,
|
|
4694
5339
|
announcement: ""
|
|
4695
5340
|
});
|
|
5341
|
+
const scopeAccess = this.#scopeAccess();
|
|
5342
|
+
const action = scopeAccess.actions.find((candidate) => candidate.proposalRef.proposalId === proposalId);
|
|
5343
|
+
if (action === void 0) throw new Error("proposal action is stale");
|
|
4696
5344
|
const detail = parseProposalDetail(await this.call(endpoint.get, {
|
|
4697
5345
|
apiVersion: 1,
|
|
4698
|
-
proposalId
|
|
5346
|
+
proposalId,
|
|
5347
|
+
currentScope: scopeAccess.currentScope,
|
|
5348
|
+
action
|
|
4699
5349
|
}, signal));
|
|
4700
5350
|
if (detail === void 0) throw new Error("invalid detail response");
|
|
4701
5351
|
this.#publish({
|
|
@@ -4727,9 +5377,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4727
5377
|
workItemId: detail.workItemId,
|
|
4728
5378
|
workItemRevision: detail.workItemRevision,
|
|
4729
5379
|
proposalRef,
|
|
5380
|
+
currentScope: this.#scopeAccess().currentScope,
|
|
5381
|
+
action: this.#scopeAccess().actions.find((candidate) => candidate.proposalRef.proposalId === proposalRef.proposalId),
|
|
4730
5382
|
...action === "REJECT" ? { confirm: true } : {}
|
|
4731
5383
|
};
|
|
4732
5384
|
await this.#execute(async (signal) => {
|
|
5385
|
+
if (request.action === void 0) throw new Error("proposal action is stale");
|
|
4733
5386
|
this.#publish({
|
|
4734
5387
|
...this.#state,
|
|
4735
5388
|
mutationPending: true,
|
|
@@ -4781,7 +5434,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4781
5434
|
this.#listeners.clear();
|
|
4782
5435
|
}
|
|
4783
5436
|
async #refreshVisible() {
|
|
4784
|
-
if (this.#disposed || !this.environment.isVisible()) return;
|
|
5437
|
+
if (this.#disposed || !this.#active || !this.environment.isVisible()) return;
|
|
4785
5438
|
await this.#execute(async (signal) => {
|
|
4786
5439
|
await this.#refreshWithin(signal);
|
|
4787
5440
|
}, () => {
|
|
@@ -4792,6 +5445,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4792
5445
|
});
|
|
4793
5446
|
}
|
|
4794
5447
|
async #refreshWithin(signal) {
|
|
5448
|
+
if (this.options.attentionDriven === true) {
|
|
5449
|
+
if (!this.#state.open) return;
|
|
5450
|
+
await this.#loadListWithin(signal);
|
|
5451
|
+
await this.#refreshPublishingDetailWithin(signal);
|
|
5452
|
+
return;
|
|
5453
|
+
}
|
|
4795
5454
|
const summary = parseProposalSummary(await this.call(endpoint.summary, {
|
|
4796
5455
|
apiVersion: 1,
|
|
4797
5456
|
workspaceId: this.workspaceId
|
|
@@ -4804,11 +5463,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4804
5463
|
});
|
|
4805
5464
|
if (!this.#state.open) return;
|
|
4806
5465
|
await this.#loadListWithin(signal);
|
|
5466
|
+
await this.#refreshPublishingDetailWithin(signal);
|
|
5467
|
+
}
|
|
5468
|
+
async #refreshPublishingDetailWithin(signal) {
|
|
4807
5469
|
const selected = this.#state.selectedProposalId;
|
|
4808
5470
|
if (selected !== void 0 && this.#state.detail?.processingState === "PUBLISHING") {
|
|
5471
|
+
const scopeAccess = this.#scopeAccess();
|
|
5472
|
+
const action = scopeAccess.actions.find((candidate) => candidate.proposalRef.proposalId === selected);
|
|
5473
|
+
if (action === void 0) return;
|
|
4809
5474
|
const detail = parseProposalDetail(await this.call(endpoint.get, {
|
|
4810
5475
|
apiVersion: 1,
|
|
4811
|
-
proposalId: selected
|
|
5476
|
+
proposalId: selected,
|
|
5477
|
+
currentScope: scopeAccess.currentScope,
|
|
5478
|
+
action
|
|
4812
5479
|
}, signal));
|
|
4813
5480
|
if (detail !== void 0) this.#publish({
|
|
4814
5481
|
...this.#state,
|
|
@@ -4838,7 +5505,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4838
5505
|
for (let pageIndex = 0; pageIndex < 10; pageIndex += 1) {
|
|
4839
5506
|
const page = parseProposalList(await this.call(endpoint.list, {
|
|
4840
5507
|
apiVersion: 1,
|
|
4841
|
-
|
|
5508
|
+
currentScope: this.#scopeAccess().currentScope,
|
|
5509
|
+
limit: 20,
|
|
4842
5510
|
...cursor === void 0 ? {} : { cursor }
|
|
4843
5511
|
}, signal));
|
|
4844
5512
|
if (page === void 0) throw new Error("invalid list response");
|
|
@@ -4873,7 +5541,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4873
5541
|
});
|
|
4874
5542
|
}
|
|
4875
5543
|
#schedule() {
|
|
4876
|
-
if (this.#disposed) return;
|
|
5544
|
+
if (this.#disposed || !this.#active) return;
|
|
4877
5545
|
const delay = this.#state.open ? PROPOSAL_ACTIVE_POLL_INTERVAL_MS : PROPOSAL_POLL_INTERVAL_MS;
|
|
4878
5546
|
if (this.#timer !== void 0 && this.#timerDelay === delay) return;
|
|
4879
5547
|
this.#unschedule();
|
|
@@ -4891,9 +5559,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4891
5559
|
#publish(state) {
|
|
4892
5560
|
if (this.#disposed) return;
|
|
4893
5561
|
this.#state = state;
|
|
4894
|
-
if (this.#started && this.environment.isVisible()) this.#schedule();
|
|
5562
|
+
if (this.#started && this.#active && this.environment.isVisible()) this.#schedule();
|
|
4895
5563
|
for (const listener of this.#listeners) listener();
|
|
4896
5564
|
}
|
|
5565
|
+
#scopeAccess() {
|
|
5566
|
+
return this.options.scopeAccess?.() ?? {
|
|
5567
|
+
currentScope: {
|
|
5568
|
+
kind: "WORKSPACE",
|
|
5569
|
+
generation: 1,
|
|
5570
|
+
workspaceId: this.workspaceId
|
|
5571
|
+
},
|
|
5572
|
+
actions: []
|
|
5573
|
+
};
|
|
5574
|
+
}
|
|
4897
5575
|
};
|
|
4898
5576
|
const formatCharacters = /* @__PURE__ */ new Map([
|
|
4899
5577
|
[0, "NULL"],
|
|
@@ -4933,16 +5611,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4933
5611
|
return (0, react.createElement)("pre", {
|
|
4934
5612
|
"aria-label": props.label,
|
|
4935
5613
|
"data-run2skill-text-mode": props.mode,
|
|
4936
|
-
|
|
4937
|
-
whiteSpace: "pre-wrap",
|
|
4938
|
-
overflowWrap: "anywhere",
|
|
4939
|
-
maxHeight: "24rem",
|
|
4940
|
-
overflow: "auto",
|
|
4941
|
-
padding: "0.75rem",
|
|
4942
|
-
border: "1px solid currentColor",
|
|
4943
|
-
borderRadius: "0.375rem",
|
|
4944
|
-
unicodeBidi: "isolate"
|
|
4945
|
-
}
|
|
5614
|
+
className: _run2skill_css_run2skill_settings_page_module_css_default.textBlock
|
|
4946
5615
|
}, props.mode === "SAFE" ? makeSafeText(props.value) : props.value);
|
|
4947
5616
|
}
|
|
4948
5617
|
function makeExactLineDiff(before, after) {
|
|
@@ -4983,38 +5652,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4983
5652
|
return result;
|
|
4984
5653
|
}
|
|
4985
5654
|
//#endregion
|
|
4986
|
-
//#region src/client/dialog-focus.ts
|
|
4987
|
-
const focusableSelector = [
|
|
4988
|
-
"button:not([disabled])",
|
|
4989
|
-
"[href]",
|
|
4990
|
-
"input:not([disabled])",
|
|
4991
|
-
"select:not([disabled])",
|
|
4992
|
-
"textarea:not([disabled])",
|
|
4993
|
-
"[tabindex]:not([tabindex=\"-1\"])"
|
|
4994
|
-
].join(",");
|
|
4995
|
-
function trapDialogTab(key, backwards, preventDefault, root, activeElement) {
|
|
4996
|
-
if (key !== "Tab") return;
|
|
4997
|
-
const focusable = Array.from(root.querySelectorAll(focusableSelector));
|
|
4998
|
-
if (focusable.length === 0) {
|
|
4999
|
-
preventDefault();
|
|
5000
|
-
return;
|
|
5001
|
-
}
|
|
5002
|
-
const first = focusable[0];
|
|
5003
|
-
const last = focusable.at(-1);
|
|
5004
|
-
if (!focusable.includes(activeElement)) {
|
|
5005
|
-
preventDefault();
|
|
5006
|
-
(backwards ? last : first).focus();
|
|
5007
|
-
return;
|
|
5008
|
-
}
|
|
5009
|
-
if (backwards && activeElement === first) {
|
|
5010
|
-
preventDefault();
|
|
5011
|
-
last.focus();
|
|
5012
|
-
} else if (!backwards && activeElement === last) {
|
|
5013
|
-
preventDefault();
|
|
5014
|
-
first.focus();
|
|
5015
|
-
}
|
|
5016
|
-
}
|
|
5017
|
-
//#endregion
|
|
5018
5655
|
//#region src/client/status-copy.ts
|
|
5019
5656
|
function describeRun2skillHealth(status) {
|
|
5020
5657
|
if (status === "INCOMPATIBLE") return "run2skill 当前版本不兼容";
|
|
@@ -5065,853 +5702,263 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5065
5702
|
if (state.summaryPhase === "LOADING") return "Proposal 队列状态加载中";
|
|
5066
5703
|
if (state.summaryPhase === "UNAVAILABLE") return "Proposal 队列状态暂不可用";
|
|
5067
5704
|
if (state.summary === void 0) return "Proposal 队列状态未知";
|
|
5068
|
-
const health = describeRun2skillHealth(state.summary.status);
|
|
5069
|
-
const queue = state.summary.queue.completeness === "UNKNOWN" ? "待处理数量未知" : countLabel(state);
|
|
5070
|
-
return state.summaryPhase === "STALE" ? `Proposal 队列状态可能已过期:${health};${queue}` : `${health};${queue}`;
|
|
5071
|
-
}
|
|
5072
|
-
function ProposalInboxHeaderAction(props) {
|
|
5073
|
-
const controller = (0, react.useMemo)(() => new ProposalInboxController(props.workspaceId, props.callReview), [props.callReview, props.workspaceId]);
|
|
5074
|
-
(0, react.useEffect)(() => {
|
|
5075
|
-
controller.start();
|
|
5076
|
-
return () => {
|
|
5077
|
-
controller.dispose();
|
|
5078
|
-
};
|
|
5079
|
-
}, [controller]);
|
|
5080
|
-
const state = (0, react.useSyncExternalStore)(controller.subscribe, controller.snapshot, controller.snapshot);
|
|
5081
|
-
const triggerRef = (0, react.useRef)(null);
|
|
5082
|
-
const dialogRef = (0, react.useRef)(null);
|
|
5083
|
-
const [textMode, setTextMode] = (0, react.useState)("SAFE");
|
|
5084
|
-
const [rejectConfirm, setRejectConfirm] = (0, react.useState)(false);
|
|
5085
|
-
const focusTrapSuspended = (0, react.useRef)(false);
|
|
5086
|
-
focusTrapSuspended.current = rejectConfirm;
|
|
5087
|
-
useDialogFocus(state.open, triggerRef, dialogRef, focusTrapSuspended);
|
|
5088
|
-
const label = countLabel(state);
|
|
5089
|
-
return (0, react.createElement)(react.Fragment, null, (0, react.createElement)("button", {
|
|
5090
|
-
ref: triggerRef,
|
|
5091
|
-
type: "button",
|
|
5092
|
-
"aria-label": label,
|
|
5093
|
-
"aria-haspopup": "dialog",
|
|
5094
|
-
"aria-expanded": state.open,
|
|
5095
|
-
"data-run2skill-proposal-trigger": true,
|
|
5096
|
-
onClick: () => {
|
|
5097
|
-
controller.open();
|
|
5098
|
-
},
|
|
5099
|
-
style: { outlineOffset: "0.2rem" }
|
|
5100
|
-
}, label), state.open ? (0, react.createElement)(ProposalInboxPanel, {
|
|
5101
|
-
controller,
|
|
5102
|
-
state,
|
|
5103
|
-
dialogRef,
|
|
5104
|
-
textMode,
|
|
5105
|
-
setTextMode,
|
|
5106
|
-
rejectConfirm,
|
|
5107
|
-
setRejectConfirm
|
|
5108
|
-
}) : null);
|
|
5109
|
-
}
|
|
5110
|
-
function closeOnKeyboard(event, controller, dialog) {
|
|
5111
|
-
if (event.key === "Escape") {
|
|
5112
|
-
event.preventDefault();
|
|
5113
|
-
controller.close();
|
|
5114
|
-
} else if (dialog !== null) trapDialogTab(event.key, event.shiftKey, () => {
|
|
5115
|
-
event.preventDefault();
|
|
5116
|
-
}, dialog, typeof document === "undefined" ? void 0 : document.activeElement);
|
|
5117
|
-
}
|
|
5118
|
-
function ProposalInboxPanel(props) {
|
|
5119
|
-
const { controller, state } = props;
|
|
5120
|
-
const contentBlocked = proposalInboxContentBlocked(state.mutationPending, props.rejectConfirm);
|
|
5121
|
-
return (0, react.createElement)(react.Fragment, null, (0, react.createElement)("div", {
|
|
5122
|
-
"aria-hidden": true,
|
|
5123
|
-
"data-run2skill-proposal-backdrop": true,
|
|
5124
|
-
style: {
|
|
5125
|
-
position: "fixed",
|
|
5126
|
-
inset: 0,
|
|
5127
|
-
zIndex: 999,
|
|
5128
|
-
background: "rgb(0 0 0 / 35%)"
|
|
5129
|
-
}
|
|
5130
|
-
}), (0, react.createElement)("div", {
|
|
5131
|
-
ref: props.dialogRef,
|
|
5132
|
-
role: "dialog",
|
|
5133
|
-
"aria-modal": true,
|
|
5134
|
-
"aria-labelledby": "run2skill-proposal-inbox-title",
|
|
5135
|
-
onKeyDown: (event) => {
|
|
5136
|
-
closeOnKeyboard(event, controller, props.dialogRef.current);
|
|
5137
|
-
},
|
|
5138
|
-
style: {
|
|
5139
|
-
position: "fixed",
|
|
5140
|
-
inset: "5vh 5vw",
|
|
5141
|
-
zIndex: 1e3,
|
|
5142
|
-
display: "grid",
|
|
5143
|
-
gridTemplateColumns: "minmax(16rem, 24rem) minmax(0, 1fr)",
|
|
5144
|
-
gap: "1rem",
|
|
5145
|
-
padding: "1rem",
|
|
5146
|
-
overflow: "hidden",
|
|
5147
|
-
background: "Canvas",
|
|
5148
|
-
color: "CanvasText",
|
|
5149
|
-
border: "2px solid currentColor",
|
|
5150
|
-
borderRadius: "0.5rem",
|
|
5151
|
-
boxShadow: "0 1rem 3rem rgb(0 0 0 / 35%)"
|
|
5152
|
-
}
|
|
5153
|
-
}, (0, react.createElement)("div", {
|
|
5154
|
-
"aria-hidden": props.rejectConfirm || void 0,
|
|
5155
|
-
inert: props.rejectConfirm ? "" : void 0,
|
|
5156
|
-
style: {
|
|
5157
|
-
display: "contents",
|
|
5158
|
-
pointerEvents: props.rejectConfirm ? "none" : void 0
|
|
5159
|
-
}
|
|
5160
|
-
}, (0, react.createElement)("section", {
|
|
5161
|
-
"aria-label": "Proposal 待处理队列",
|
|
5162
|
-
style: { overflow: "auto" }
|
|
5163
|
-
}, (0, react.createElement)("div", { style: {
|
|
5164
|
-
display: "flex",
|
|
5165
|
-
alignItems: "center",
|
|
5166
|
-
justifyContent: "space-between"
|
|
5167
|
-
} }, (0, react.createElement)("h2", { id: "run2skill-proposal-inbox-title" }, "Skill Proposal Inbox"), (0, react.createElement)("button", {
|
|
5168
|
-
type: "button",
|
|
5169
|
-
"data-initial-focus": true,
|
|
5170
|
-
onClick: () => {
|
|
5171
|
-
controller.close();
|
|
5172
|
-
}
|
|
5173
|
-
}, "关闭")), (0, react.createElement)("p", { role: "status" }, countLabel(state)), (0, react.createElement)("p", {
|
|
5174
|
-
role: "status",
|
|
5175
|
-
"aria-live": "polite"
|
|
5176
|
-
}, 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", { style: {
|
|
5177
|
-
listStyle: "none",
|
|
5178
|
-
padding: 0
|
|
5179
|
-
} }, ...state.items.map((item) => (0, react.createElement)("li", { key: item.proposalRef.proposalId }, (0, react.createElement)("button", {
|
|
5180
|
-
type: "button",
|
|
5181
|
-
disabled: contentBlocked || state.detailPhase === "LOADING",
|
|
5182
|
-
"aria-current": state.selectedProposalId === item.proposalRef.proposalId ? "true" : void 0,
|
|
5183
|
-
onClick: () => {
|
|
5184
|
-
controller.select(item.proposalRef.proposalId);
|
|
5185
|
-
},
|
|
5186
|
-
style: {
|
|
5187
|
-
display: "block",
|
|
5188
|
-
width: "100%",
|
|
5189
|
-
padding: "0.75rem",
|
|
5190
|
-
marginBlock: "0.25rem",
|
|
5191
|
-
textAlign: "start",
|
|
5192
|
-
outlineOffset: "0.15rem"
|
|
5193
|
-
}
|
|
5194
|
-
}, `${item.kind} · ${makeSafeText(item.name)} · ${item.persistenceScope} · ${describeProposalListItem(item)}`))))), (0, react.createElement)("section", {
|
|
5195
|
-
"aria-label": "Proposal 详情",
|
|
5196
|
-
style: {
|
|
5197
|
-
overflow: "auto",
|
|
5198
|
-
minWidth: 0
|
|
5199
|
-
}
|
|
5200
|
-
}, 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, {
|
|
5201
|
-
detail: state.detail,
|
|
5202
|
-
textMode: props.textMode,
|
|
5203
|
-
setTextMode: props.setTextMode,
|
|
5204
|
-
mutationPending: contentBlocked,
|
|
5205
|
-
onApprove: () => {
|
|
5206
|
-
controller.mutate("APPROVE");
|
|
5207
|
-
},
|
|
5208
|
-
onReject: () => {
|
|
5209
|
-
props.setRejectConfirm(true);
|
|
5210
|
-
},
|
|
5211
|
-
onRetry: () => {
|
|
5212
|
-
controller.mutate("RETRY");
|
|
5213
|
-
},
|
|
5214
|
-
onConfirmDiscard: () => {
|
|
5215
|
-
controller.mutate("CONFIRM_DISCARD");
|
|
5216
|
-
}
|
|
5217
|
-
}), (0, react.createElement)("div", {
|
|
5218
|
-
"aria-live": "polite",
|
|
5219
|
-
"aria-atomic": true
|
|
5220
|
-
}, state.announcement))), props.rejectConfirm ? (0, react.createElement)(RejectConfirmation, {
|
|
5221
|
-
disabled: state.mutationPending,
|
|
5222
|
-
onCancel: () => {
|
|
5223
|
-
props.setRejectConfirm(false);
|
|
5224
|
-
},
|
|
5225
|
-
onConfirm: () => {
|
|
5226
|
-
props.setRejectConfirm(false);
|
|
5227
|
-
controller.mutate("REJECT");
|
|
5228
|
-
}
|
|
5229
|
-
}) : null));
|
|
5230
|
-
}
|
|
5231
|
-
function factsFromAction(detail) {
|
|
5232
|
-
const action = detail.proposal.actionBinding;
|
|
5233
|
-
if (action.kind === "CREATE") return [
|
|
5234
|
-
`Root contract: ${action.rootBinding.rootContractVersion}`,
|
|
5235
|
-
`Root resolver: ${action.rootBinding.resolverVersion}`,
|
|
5236
|
-
`Expected provider/source: ${action.rootBinding.expectedProvider} / ${action.rootBinding.expectedSource}`,
|
|
5237
|
-
`Resolution digest: ${action.rootBinding.resolutionContractDigest}`,
|
|
5238
|
-
`Root state: ${action.rootBinding.state}`,
|
|
5239
|
-
`Declared root: ${action.rootBinding.declaredRootPath}`,
|
|
5240
|
-
`Bundle target: ${action.targetBinding.bundlePath}`,
|
|
5241
|
-
`Skill target: ${action.targetBinding.skillFilePath}`,
|
|
5242
|
-
`Flat target checked: ${action.expectedAbsence.flatSkillFilePath}`,
|
|
5243
|
-
`Expected absence observed: ${action.expectedAbsence.observedAt}`,
|
|
5244
|
-
"Bundle absent: yes",
|
|
5245
|
-
"Skill file absent: yes",
|
|
5246
|
-
"Flat Skill file absent: yes"
|
|
5247
|
-
].join("\n");
|
|
5248
|
-
if (action.kind === "MERGE") return [
|
|
5249
|
-
`Root contract: ${action.rootBinding.rootContractVersion}`,
|
|
5250
|
-
`Root resolver: ${action.rootBinding.resolverVersion}`,
|
|
5251
|
-
`Expected provider/source: ${action.rootBinding.expectedProvider} / ${action.rootBinding.expectedSource}`,
|
|
5252
|
-
`Resolution digest: ${action.rootBinding.resolutionContractDigest}`,
|
|
5253
|
-
`Root state: ${action.rootBinding.state}`,
|
|
5254
|
-
`Declared root: ${action.rootBinding.declaredRootPath}`,
|
|
5255
|
-
`Target identity: ${action.baseBinding.candidateKey}`,
|
|
5256
|
-
`Observed target path: ${action.baseBinding.path}`,
|
|
5257
|
-
`Bundle target: ${action.targetBinding.bundlePath}`,
|
|
5258
|
-
`Skill target: ${action.targetBinding.skillFilePath}`,
|
|
5259
|
-
`Base digest: ${action.baseBinding.bytesDigest}`,
|
|
5260
|
-
`Base observed: ${action.baseBinding.observedAt}`
|
|
5261
|
-
].join("\n");
|
|
5262
|
-
return [
|
|
5263
|
-
`Covering candidate: ${action.coveringCandidateBinding.candidateKey}`,
|
|
5264
|
-
`Name: ${action.coveringCandidateBinding.name}`,
|
|
5265
|
-
`Source: ${action.coveringCandidateBinding.source}`,
|
|
5266
|
-
`Digest: ${action.coveringCandidateBinding.contentDigest}`,
|
|
5267
|
-
`Observed: ${action.coveringCandidateBinding.observedAt}`,
|
|
5268
|
-
...action.coveringCandidateBinding.path === void 0 ? [] : [`Path: ${action.coveringCandidateBinding.path}`]
|
|
5269
|
-
].join("\n");
|
|
5270
|
-
}
|
|
5271
|
-
function ProposalDetailView(props) {
|
|
5272
|
-
const { detail, mutationPending } = props;
|
|
5273
|
-
const proposal = detail.proposal;
|
|
5274
|
-
const actionable = detail.reviewDecision === "PENDING" && detail.processingState === "READY_FOR_REVIEW" && !mutationPending;
|
|
5275
|
-
const coordinate = detail.sessionCoordinate;
|
|
5276
|
-
const baseBytes = proposal.actionBinding.kind === "MERGE" ? proposal.actionBinding.baseBinding.exactBytes : void 0;
|
|
5277
|
-
const coveringBytes = proposal.actionBinding.kind === "DISCARD" ? proposal.actionBinding.coveringCandidateBinding.content : void 0;
|
|
5278
|
-
const diff = baseBytes === void 0 ? [] : makeExactLineDiff(baseBytes, proposal.exactSkillBytes);
|
|
5279
|
-
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, `${proposal.workspaceBinding.workspaceId} · ${makeSafeText(proposal.workspaceBinding.canonicalPath)}`)), proposal.dshHomeBinding === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("dt", null, "DSH Home"), (0, react.createElement)("dd", null, `${proposal.dshHomeBinding.resolutionKind} · ${makeSafeText(proposal.dshHomeBinding.canonicalPath)}`), (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, {
|
|
5280
|
-
value: evidence.excerpt,
|
|
5281
|
-
mode: "SAFE",
|
|
5282
|
-
label: `Evidence ${String(evidence.messageSeq)}`
|
|
5283
|
-
}))), (0, react.createElement)("h4", null, "绑定事实"), (0, react.createElement)(ProposalTextView, {
|
|
5284
|
-
value: factsFromAction(detail),
|
|
5285
|
-
mode: "SAFE",
|
|
5286
|
-
label: "绑定事实"
|
|
5287
|
-
}), (0, react.createElement)("div", {
|
|
5288
|
-
role: "group",
|
|
5289
|
-
"aria-label": "内容显示方式"
|
|
5290
|
-
}, (0, react.createElement)("button", {
|
|
5291
|
-
type: "button",
|
|
5292
|
-
"aria-pressed": props.textMode === "SAFE",
|
|
5293
|
-
onClick: () => {
|
|
5294
|
-
props.setTextMode("SAFE");
|
|
5295
|
-
}
|
|
5296
|
-
}, "安全视图"), (0, react.createElement)("button", {
|
|
5297
|
-
type: "button",
|
|
5298
|
-
"aria-pressed": props.textMode === "RAW",
|
|
5299
|
-
onClick: () => {
|
|
5300
|
-
props.setTextMode("RAW");
|
|
5301
|
-
}
|
|
5302
|
-
}, "原始内容")), (0, react.createElement)("h4", null, "将要批准的完整 SKILL.md"), (0, react.createElement)(ProposalTextView, {
|
|
5303
|
-
value: proposal.exactSkillBytes,
|
|
5304
|
-
mode: props.textMode,
|
|
5305
|
-
label: "将要批准的完整 SKILL.md"
|
|
5306
|
-
}), baseBytes === void 0 ? null : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("h4", null, "MERGE Base"), (0, react.createElement)(ProposalTextView, {
|
|
5307
|
-
value: baseBytes,
|
|
5308
|
-
mode: props.textMode,
|
|
5309
|
-
label: "MERGE Base"
|
|
5310
|
-
}), (0, react.createElement)("h4", null, "精确 Diff"), (0, react.createElement)("pre", {
|
|
5311
|
-
"aria-label": "精确 Diff",
|
|
5312
|
-
style: {
|
|
5313
|
-
whiteSpace: "pre-wrap",
|
|
5314
|
-
unicodeBidi: "isolate"
|
|
5315
|
-
}
|
|
5316
|
-
}, 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, {
|
|
5317
|
-
value: coveringBytes,
|
|
5318
|
-
mode: props.textMode,
|
|
5319
|
-
label: "覆盖已有 Skill 的完整内容"
|
|
5320
|
-
})), (0, react.createElement)("div", {
|
|
5321
|
-
role: "group",
|
|
5322
|
-
"aria-label": "Proposal 操作"
|
|
5323
|
-
}, proposal.kind === "DISCARD" ? (0, react.createElement)(react.Fragment, null, (0, react.createElement)("button", {
|
|
5324
|
-
type: "button",
|
|
5325
|
-
disabled: !actionable,
|
|
5326
|
-
onClick: props.onConfirmDiscard
|
|
5327
|
-
}, "确认无需新建 Skill"), (0, react.createElement)("button", {
|
|
5328
|
-
type: "button",
|
|
5329
|
-
disabled: !actionable,
|
|
5330
|
-
onClick: props.onRetry
|
|
5331
|
-
}, "不同意,重新分析一次")) : (0, react.createElement)(react.Fragment, null, (0, react.createElement)("button", {
|
|
5332
|
-
type: "button",
|
|
5333
|
-
disabled: !actionable,
|
|
5334
|
-
onClick: props.onApprove
|
|
5335
|
-
}, detail.processingState === "PUBLISHING" ? "正在发布…" : "批准并发布"), (0, react.createElement)("button", {
|
|
5336
|
-
type: "button",
|
|
5337
|
-
disabled: !actionable,
|
|
5338
|
-
onClick: props.onReject
|
|
5339
|
-
}, "拒绝 Proposal"))));
|
|
5340
|
-
}
|
|
5341
|
-
function RejectConfirmationBody(props) {
|
|
5342
|
-
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", {
|
|
5343
|
-
type: "button",
|
|
5344
|
-
"data-initial-focus": true,
|
|
5345
|
-
disabled: props.disabled,
|
|
5346
|
-
onClick: props.onCancel
|
|
5347
|
-
}, "取消"), (0, react.createElement)("button", {
|
|
5348
|
-
type: "button",
|
|
5349
|
-
disabled: props.disabled,
|
|
5350
|
-
onClick: props.onConfirm
|
|
5351
|
-
}, "确认拒绝"));
|
|
5705
|
+
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}`;
|
|
5352
5708
|
}
|
|
5353
|
-
function
|
|
5354
|
-
const
|
|
5709
|
+
function ProposalInboxHeaderAction(props) {
|
|
5710
|
+
const controller = (0, react.useMemo)(() => new ProposalInboxController(props.workspaceId, props.callReview, void 0, props.scopeAccess === void 0 ? {} : { scopeAccess: props.scopeAccess }), [
|
|
5711
|
+
props.scopeAccess,
|
|
5712
|
+
props.callReview,
|
|
5713
|
+
props.workspaceId
|
|
5714
|
+
]);
|
|
5355
5715
|
(0, react.useEffect)(() => {
|
|
5356
|
-
|
|
5357
|
-
const previous = document.activeElement;
|
|
5358
|
-
const dialog = dialogRef.current;
|
|
5359
|
-
const initial = dialog?.querySelector("[data-initial-focus]");
|
|
5360
|
-
const recapture = (event) => {
|
|
5361
|
-
if (dialog !== null && event.target instanceof Node && !dialog.contains(event.target)) initial?.focus();
|
|
5362
|
-
};
|
|
5363
|
-
document.addEventListener("focusin", recapture, true);
|
|
5364
|
-
initial?.focus();
|
|
5716
|
+
controller.start();
|
|
5365
5717
|
return () => {
|
|
5366
|
-
|
|
5367
|
-
previous?.focus();
|
|
5718
|
+
controller.dispose();
|
|
5368
5719
|
};
|
|
5369
|
-
}, []);
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5720
|
+
}, [controller]);
|
|
5721
|
+
const state = (0, react.useSyncExternalStore)(controller.subscribe, controller.snapshot, controller.snapshot);
|
|
5722
|
+
const triggerRef = (0, react.useRef)(null);
|
|
5723
|
+
const dialogRef = (0, react.useRef)(null);
|
|
5724
|
+
const [textMode, setTextMode] = (0, react.useState)("SAFE");
|
|
5725
|
+
const [rejectConfirm, setRejectConfirm] = (0, react.useState)(false);
|
|
5726
|
+
const focusTrapSuspended = (0, react.useRef)(false);
|
|
5727
|
+
focusTrapSuspended.current = rejectConfirm;
|
|
5728
|
+
useDialogFocus(state.open, triggerRef, dialogRef, focusTrapSuspended);
|
|
5729
|
+
const label = countLabel(state);
|
|
5730
|
+
return (0, react.createElement)(react.Fragment, null, (0, react.createElement)("button", {
|
|
5731
|
+
ref: triggerRef,
|
|
5732
|
+
type: "button",
|
|
5733
|
+
"aria-label": label,
|
|
5734
|
+
"aria-haspopup": "dialog",
|
|
5735
|
+
"aria-expanded": state.open,
|
|
5736
|
+
"data-run2skill-proposal-trigger": true,
|
|
5737
|
+
onClick: () => {
|
|
5738
|
+
controller.open();
|
|
5739
|
+
}
|
|
5740
|
+
}, label), state.open ? (0, react.createElement)(ProposalInboxPanel, {
|
|
5741
|
+
controller,
|
|
5742
|
+
state,
|
|
5743
|
+
dialogRef,
|
|
5744
|
+
textMode,
|
|
5745
|
+
setTextMode,
|
|
5746
|
+
rejectConfirm,
|
|
5747
|
+
setRejectConfirm
|
|
5748
|
+
}) : null);
|
|
5749
|
+
}
|
|
5750
|
+
function closeOnKeyboard(event, controller, dialog) {
|
|
5751
|
+
if (event.key === "Escape") {
|
|
5752
|
+
event.preventDefault();
|
|
5753
|
+
controller.close();
|
|
5754
|
+
} else if (dialog !== null) trapDialogTab(event.key, event.shiftKey, () => {
|
|
5755
|
+
event.preventDefault();
|
|
5756
|
+
}, dialog, typeof document === "undefined" ? void 0 : document.activeElement);
|
|
5757
|
+
}
|
|
5758
|
+
function ProposalInboxPanel(props) {
|
|
5759
|
+
const { controller, state } = props;
|
|
5760
|
+
const contentBlocked = proposalInboxContentBlocked(state.mutationPending, props.rejectConfirm);
|
|
5761
|
+
return (0, react.createElement)(react.Fragment, null, (0, react.createElement)("div", {
|
|
5762
|
+
"aria-hidden": true,
|
|
5763
|
+
"data-run2skill-proposal-backdrop": true,
|
|
5764
|
+
className: _run2skill_css_run2skill_settings_page_module_css_default.backdrop
|
|
5765
|
+
}), (0, react.createElement)("div", {
|
|
5766
|
+
ref: props.dialogRef,
|
|
5767
|
+
role: "dialog",
|
|
5373
5768
|
"aria-modal": true,
|
|
5374
|
-
"aria-labelledby": "run2skill-
|
|
5375
|
-
"aria-describedby": "run2skill-reject-description",
|
|
5769
|
+
"aria-labelledby": "run2skill-proposal-inbox-title",
|
|
5376
5770
|
onKeyDown: (event) => {
|
|
5377
|
-
event.
|
|
5378
|
-
if (event.key === "Escape") {
|
|
5379
|
-
event.preventDefault();
|
|
5380
|
-
props.onCancel();
|
|
5381
|
-
} else if (dialogRef.current !== null) trapDialogTab(event.key, event.shiftKey, () => {
|
|
5382
|
-
event.preventDefault();
|
|
5383
|
-
}, dialogRef.current, typeof document === "undefined" ? void 0 : document.activeElement);
|
|
5771
|
+
closeOnKeyboard(event, controller, props.dialogRef.current);
|
|
5384
5772
|
},
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5773
|
+
className: _run2skill_css_run2skill_settings_page_module_css_default.legacyDialog
|
|
5774
|
+
}, (0, react.createElement)("div", {
|
|
5775
|
+
"aria-hidden": props.rejectConfirm || void 0,
|
|
5776
|
+
inert: props.rejectConfirm ? "" : void 0,
|
|
5777
|
+
className: props.rejectConfirm ? _run2skill_css_run2skill_settings_page_module_css_default.blocked : void 0
|
|
5778
|
+
}, (0, react.createElement)("section", {
|
|
5779
|
+
"aria-label": "Proposal 待处理队列",
|
|
5780
|
+
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", {
|
|
5782
|
+
type: "button",
|
|
5783
|
+
"data-initial-focus": true,
|
|
5784
|
+
onClick: () => {
|
|
5785
|
+
controller.close();
|
|
5393
5786
|
}
|
|
5394
|
-
}, (0, react.createElement)("
|
|
5395
|
-
maxWidth: "32rem",
|
|
5396
|
-
padding: "1rem",
|
|
5397
|
-
background: "Canvas",
|
|
5398
|
-
color: "CanvasText",
|
|
5399
|
-
border: "2px solid currentColor",
|
|
5400
|
-
borderRadius: "0.5rem"
|
|
5401
|
-
} }, (0, react.createElement)(RejectConfirmationBody, props)));
|
|
5402
|
-
}
|
|
5403
|
-
//#endregion
|
|
5404
|
-
//#region src/client/observe-header-action.ts
|
|
5405
|
-
function summaryFacts(state) {
|
|
5406
|
-
const { summary } = state;
|
|
5407
|
-
const facts = [];
|
|
5408
|
-
if (summary.status !== "READY") facts.push(describeRun2skillHealth(summary.status));
|
|
5409
|
-
facts.push(`已记录 ${summary.capturedCount} 条待处理事项`);
|
|
5410
|
-
if (summary.learning !== void 0) {
|
|
5411
|
-
if (summary.learning.learned > 0) facts.push(`${summary.learning.learned} 条已学习草案`);
|
|
5412
|
-
if (summary.learning.analyzing > 0) facts.push(`${summary.learning.analyzing} 条正在学习`);
|
|
5413
|
-
if (summary.learning.needsAttention > 0) facts.push(`${summary.learning.needsAttention} 条学习需处理`);
|
|
5414
|
-
}
|
|
5415
|
-
if (summary.blockedCaptureCount > 0) facts.push(`另有 ${summary.blockedCaptureCount} 条观察不完整`);
|
|
5416
|
-
if (summary.unsaved.completeness === "UNKNOWN") facts.push(summary.unsaved.knownCount > 0 ? `至少有 ${summary.unsaved.knownCount} 条尚未保存,完整数量未知` : "尚未保存数量未知");
|
|
5417
|
-
else facts.push(summary.unsaved.knownCount > 0 ? `${summary.unsaved.knownCount} 条尚未保存` : "没有尚未保存的事项");
|
|
5418
|
-
return facts;
|
|
5419
|
-
}
|
|
5420
|
-
function describeObserveState(state) {
|
|
5421
|
-
if (state.phase === "LOADING") return "run2skill 状态加载中";
|
|
5422
|
-
if (state.phase === "UNAVAILABLE") return "run2skill 状态暂不可用";
|
|
5423
|
-
const description = summaryFacts(state).join(";");
|
|
5424
|
-
return state.phase === "STALE" ? `run2skill 状态可能已过期:${description}` : description;
|
|
5425
|
-
}
|
|
5426
|
-
function ObserveStatusPill({ state }) {
|
|
5427
|
-
const description = describeObserveState(state);
|
|
5428
|
-
const semanticStatus = "summary" in state ? state.summary.status : state.phase;
|
|
5429
|
-
return (0, react.createElement)("span", {
|
|
5787
|
+
}, "关闭")), (0, react.createElement)("p", { role: "status" }, countLabel(state)), (0, react.createElement)("p", {
|
|
5430
5788
|
role: "status",
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
"
|
|
5434
|
-
"
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
alignItems: "center",
|
|
5439
|
-
maxWidth: "28rem",
|
|
5440
|
-
padding: "0.25rem 0.5rem",
|
|
5441
|
-
border: "1px solid currentColor",
|
|
5442
|
-
borderRadius: "0.375rem",
|
|
5443
|
-
fontSize: "0.75rem",
|
|
5444
|
-
lineHeight: 1.25
|
|
5445
|
-
}
|
|
5446
|
-
}, description);
|
|
5447
|
-
}
|
|
5448
|
-
function ObserveHeaderAction({ callSummary }) {
|
|
5449
|
-
const poller = (0, react.useMemo)(() => new ObserveSummaryPoller(callSummary), [callSummary]);
|
|
5450
|
-
(0, react.useEffect)(() => {
|
|
5451
|
-
poller.start();
|
|
5452
|
-
return () => {
|
|
5453
|
-
poller.dispose();
|
|
5454
|
-
};
|
|
5455
|
-
}, [poller]);
|
|
5456
|
-
const state = (0, react.useSyncExternalStore)(poller.subscribe, poller.snapshot, poller.snapshot);
|
|
5457
|
-
return (0, react.createElement)(ObserveStatusPill, { state });
|
|
5458
|
-
}
|
|
5459
|
-
function Run2skillHeaderAction(props) {
|
|
5460
|
-
return (0, react.createElement)(react.Fragment, null, (0, react.createElement)(ObserveHeaderAction, { callSummary: props.callSummary }), (0, react.createElement)(ProposalInboxHeaderAction, {
|
|
5461
|
-
workspaceId: props.getWorkspaceId(props.sessionId),
|
|
5462
|
-
callReview: props.callReview
|
|
5463
|
-
}));
|
|
5464
|
-
}
|
|
5465
|
-
function applyObserveSummaryClient(ctx) {
|
|
5466
|
-
const callSummary = async (payload, signal) => await ctx.connection.rpc.call(RUN2SKILL_RPC_CHANNEL, OBSERVE_SUMMARY_ENDPOINT, payload, signal);
|
|
5467
|
-
const callReview = async (endpoint, payload, signal) => await ctx.connection.rpc.call(RUN2SKILL_RPC_CHANNEL, endpoint, payload, signal);
|
|
5468
|
-
const getWorkspaceId = (sessionId) => ctx.workspaces.list.getSnapshot().items.find((workspace) => workspace.sessionIds.includes(sessionId))?.workspaceId ?? sessionId;
|
|
5469
|
-
ctx.slots.inject("conversation.session.header.actions", () => ctx.slots.register({
|
|
5470
|
-
name: "conversation.session.header.actions",
|
|
5471
|
-
id: "run2skill-observe-summary",
|
|
5472
|
-
order: 30,
|
|
5473
|
-
inject: () => ({
|
|
5474
|
-
callSummary,
|
|
5475
|
-
callReview,
|
|
5476
|
-
getWorkspaceId
|
|
5477
|
-
})
|
|
5478
|
-
}, Run2skillHeaderAction));
|
|
5479
|
-
}
|
|
5480
|
-
//#endregion
|
|
5481
|
-
//#region src/client/purge-settings.ts
|
|
5482
|
-
const PURGE_IDLE_POLL_INTERVAL_MS = 1e4;
|
|
5483
|
-
const PURGE_ACTIVE_POLL_INTERVAL_MS = 2e3;
|
|
5484
|
-
const previewId = string().regex(/^purv_[a-f0-9]{64}$/);
|
|
5485
|
-
const purgeId = string().regex(/^purge_[a-f0-9]{64}$/);
|
|
5486
|
-
const digest = string().regex(/^[a-f0-9]{64}$/);
|
|
5487
|
-
const isoDateTime = string().datetime({ offset: true });
|
|
5488
|
-
const count = number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
5489
|
-
const scopeBinding = discriminatedUnion("scope", [object({
|
|
5490
|
-
scope: literal("PROJECT"),
|
|
5491
|
-
workspaceId: string().min(1).max(256),
|
|
5492
|
-
canonicalWorkspacePath: string().min(1).max(32768),
|
|
5493
|
-
workspaceObservedAt: isoDateTime,
|
|
5494
|
-
canonicalRootPath: string().min(1).max(32768),
|
|
5495
|
-
rootContractVersion: literal("stock-dsh-web-default-roots-v1"),
|
|
5496
|
-
resolverVersion: literal("stock-root-resolver-v2"),
|
|
5497
|
-
resolutionContractDigest: digest
|
|
5498
|
-
}).strict(), object({ scope: literal("USER") }).strict()]);
|
|
5499
|
-
const previewSchema = object({
|
|
5500
|
-
apiVersion: literal(1),
|
|
5501
|
-
previewId,
|
|
5502
|
-
digest,
|
|
5503
|
-
expiresAt: isoDateTime,
|
|
5504
|
-
scopeBinding,
|
|
5505
|
-
hideBefore: isoDateTime,
|
|
5506
|
-
workItemCount: count,
|
|
5507
|
-
lineageCount: count,
|
|
5508
|
-
blockedOrUnprovenCount: count,
|
|
5509
|
-
willDelete: array(object({
|
|
5510
|
-
kind: _enum(["WORK_ITEMS", "LINEAGES"]),
|
|
5511
|
-
count
|
|
5512
|
-
}).strict()).length(2),
|
|
5513
|
-
willKeep: array(object({
|
|
5514
|
-
reason: _enum([
|
|
5515
|
-
"KEEP_NEW",
|
|
5516
|
-
"KEEP_SCOPE",
|
|
5517
|
-
"KEEP_UNPROVEN"
|
|
5518
|
-
]),
|
|
5519
|
-
count
|
|
5520
|
-
}).strict()).length(3),
|
|
5521
|
-
busyPublicationCount: count
|
|
5522
|
-
}).strict();
|
|
5523
|
-
const receiptSchema = object({
|
|
5524
|
-
apiVersion: literal(1),
|
|
5525
|
-
purgeId,
|
|
5526
|
-
state: _enum(["COMPLETED", "IN_PROGRESS"]),
|
|
5527
|
-
phase: _enum([
|
|
5528
|
-
"HIDING",
|
|
5529
|
-
"DELETING_LINEAGES",
|
|
5530
|
-
"DELETING_WORK_ITEMS",
|
|
5531
|
-
"VERIFYING"
|
|
5532
|
-
]).optional(),
|
|
5533
|
-
deletedWorkItems: count,
|
|
5534
|
-
deletedLineages: count
|
|
5535
|
-
}).strict();
|
|
5536
|
-
const statusSchema = discriminatedUnion("state", [object({
|
|
5537
|
-
apiVersion: literal(1),
|
|
5538
|
-
state: literal("IDLE")
|
|
5539
|
-
}).strict(), object({
|
|
5540
|
-
apiVersion: literal(1),
|
|
5541
|
-
state: literal("IN_PROGRESS"),
|
|
5542
|
-
purgeId,
|
|
5543
|
-
hideBefore: isoDateTime,
|
|
5544
|
-
startedAt: isoDateTime,
|
|
5545
|
-
phase: _enum([
|
|
5546
|
-
"HIDING",
|
|
5547
|
-
"DELETING_LINEAGES",
|
|
5548
|
-
"DELETING_WORK_ITEMS",
|
|
5549
|
-
"VERIFYING"
|
|
5550
|
-
]),
|
|
5551
|
-
deletedWorkItems: count,
|
|
5552
|
-
deletedLineages: count,
|
|
5553
|
-
lastError: object({
|
|
5554
|
-
code: string().regex(/^[A-Z0-9_]+$/),
|
|
5555
|
-
occurredAt: isoDateTime
|
|
5556
|
-
}).strict().optional()
|
|
5557
|
-
}).strict()]);
|
|
5558
|
-
const errorSchema = object({
|
|
5559
|
-
ok: literal(false),
|
|
5560
|
-
error: object({
|
|
5561
|
-
code: string().min(1).max(128),
|
|
5562
|
-
message: string().max(512),
|
|
5563
|
-
details: object({ busyPublicationCount: count.optional() }).strict().optional()
|
|
5564
|
-
}).strict()
|
|
5565
|
-
}).strict();
|
|
5566
|
-
var PurgeResponseError = class extends Error {
|
|
5567
|
-
facts;
|
|
5568
|
-
constructor(facts) {
|
|
5569
|
-
super(facts.code);
|
|
5570
|
-
this.facts = facts;
|
|
5571
|
-
}
|
|
5572
|
-
};
|
|
5573
|
-
function browserEnvironment() {
|
|
5574
|
-
return {
|
|
5575
|
-
isVisible: () => typeof document === "undefined" || document.visibilityState === "visible",
|
|
5576
|
-
setInterval: (callback, delayMs) => globalThis.setInterval(callback, delayMs),
|
|
5577
|
-
clearInterval: (handle) => {
|
|
5578
|
-
globalThis.clearInterval(handle);
|
|
5789
|
+
"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", {
|
|
5791
|
+
type: "button",
|
|
5792
|
+
disabled: contentBlocked || state.detailPhase === "LOADING",
|
|
5793
|
+
"aria-current": state.selectedProposalId === item.proposalRef.proposalId ? "true" : void 0,
|
|
5794
|
+
onClick: () => {
|
|
5795
|
+
controller.select(item.proposalRef.proposalId);
|
|
5579
5796
|
},
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5797
|
+
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 详情",
|
|
5800
|
+
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, {
|
|
5802
|
+
detail: state.detail,
|
|
5803
|
+
textMode: props.textMode,
|
|
5804
|
+
setTextMode: props.setTextMode,
|
|
5805
|
+
mutationPending: contentBlocked,
|
|
5806
|
+
onApprove: () => {
|
|
5807
|
+
controller.mutate("APPROVE");
|
|
5808
|
+
},
|
|
5809
|
+
onReject: () => {
|
|
5810
|
+
props.setRejectConfirm(true);
|
|
5811
|
+
},
|
|
5812
|
+
onRetry: () => {
|
|
5813
|
+
controller.mutate("RETRY");
|
|
5814
|
+
},
|
|
5815
|
+
onConfirmDiscard: () => {
|
|
5816
|
+
controller.mutate("CONFIRM_DISCARD");
|
|
5586
5817
|
}
|
|
5587
|
-
}
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
...typeof busy === "number" && Number.isSafeInteger(busy) && busy >= 0 ? { busyPublicationCount: busy } : {}
|
|
5601
|
-
});
|
|
5602
|
-
}
|
|
5603
|
-
throw new PurgeResponseError({ code: "PURGE_STORAGE_UNAVAILABLE" });
|
|
5604
|
-
}
|
|
5605
|
-
function completionAnnouncement(scope, receipt) {
|
|
5606
|
-
return `${scope === void 0 ? "run2skill 数据" : `${scope} run2skill 数据`}清理完成:${String(receipt.deletedWorkItems)} 条待处理数据,${String(receipt.deletedLineages)} 条发布沿袭记录。`;
|
|
5818
|
+
}), (0, react.createElement)("div", {
|
|
5819
|
+
"aria-live": "polite",
|
|
5820
|
+
"aria-atomic": true
|
|
5821
|
+
}, state.announcement))), props.rejectConfirm ? (0, react.createElement)(RejectConfirmation, {
|
|
5822
|
+
disabled: state.mutationPending,
|
|
5823
|
+
onCancel: () => {
|
|
5824
|
+
props.setRejectConfirm(false);
|
|
5825
|
+
},
|
|
5826
|
+
onConfirm: () => {
|
|
5827
|
+
props.setRejectConfirm(false);
|
|
5828
|
+
controller.mutate("REJECT");
|
|
5829
|
+
}
|
|
5830
|
+
}) : null));
|
|
5607
5831
|
}
|
|
5608
|
-
function
|
|
5609
|
-
|
|
5832
|
+
function factsFromAction(detail) {
|
|
5833
|
+
const action = detail.proposal.actionBinding;
|
|
5834
|
+
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"
|
|
5846
|
+
].join("\n");
|
|
5847
|
+
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}`
|
|
5857
|
+
].join("\n");
|
|
5858
|
+
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}`
|
|
5864
|
+
].join("\n");
|
|
5610
5865
|
}
|
|
5611
|
-
function
|
|
5612
|
-
if (
|
|
5613
|
-
if (
|
|
5614
|
-
if (
|
|
5615
|
-
|
|
5616
|
-
if (error.code === "PURGE_INCOMPATIBLE") return "当前数据版本不兼容,未执行清理。";
|
|
5617
|
-
if (error.code === "PURGE_FENCE_LIMIT") return "PROJECT 清理保护记录已达上限,未执行清理。";
|
|
5618
|
-
return durableBoundary ? "数据清理未完成;已建立的清理边界继续隐藏,可重试。" : "数据清理暂不可用;未确认已建立清理边界,请稍后重试。";
|
|
5866
|
+
function proposalDetailAction(detail, mutationPending) {
|
|
5867
|
+
if (mutationPending) return "NONE";
|
|
5868
|
+
if (detail.reviewDecision === "PENDING" && detail.processingState === "READY_FOR_REVIEW" && detail.publicationOutcome === "PENDING_REVIEW") return "REVIEW";
|
|
5869
|
+
if (detail.reviewDecision === "APPROVED" && detail.processingState === "NEEDS_ATTENTION" && detail.publicationOutcome === "PUBLISH_FAILED") return "RETRY_PUBLICATION";
|
|
5870
|
+
return "NONE";
|
|
5619
5871
|
}
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
snapshot = () => this.#state;
|
|
5647
|
-
subscribe = (listener) => {
|
|
5648
|
-
this.#listeners.add(listener);
|
|
5649
|
-
return () => {
|
|
5650
|
-
this.#listeners.delete(listener);
|
|
5651
|
-
};
|
|
5652
|
-
};
|
|
5653
|
-
start() {
|
|
5654
|
-
if (this.#started || this.#disposed) return;
|
|
5655
|
-
this.#started = true;
|
|
5656
|
-
this.#removeVisibility = this.environment.onVisibilityChange(() => {
|
|
5657
|
-
if (this.environment.isVisible()) {
|
|
5658
|
-
this.#schedule();
|
|
5659
|
-
this.#refreshStatus();
|
|
5660
|
-
} else this.#unschedule();
|
|
5661
|
-
});
|
|
5662
|
-
if (this.environment.isVisible()) {
|
|
5663
|
-
this.#schedule();
|
|
5664
|
-
this.#refreshStatus();
|
|
5872
|
+
function ProposalDetailView(props) {
|
|
5873
|
+
const { detail, mutationPending } = props;
|
|
5874
|
+
const proposal = detail.proposal;
|
|
5875
|
+
const action = proposalDetailAction(detail, mutationPending);
|
|
5876
|
+
const actionable = action === "REVIEW";
|
|
5877
|
+
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;
|
|
5880
|
+
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, {
|
|
5882
|
+
value: evidence.excerpt,
|
|
5883
|
+
mode: "SAFE",
|
|
5884
|
+
label: `Evidence ${String(evidence.messageSeq)}`
|
|
5885
|
+
}))), (0, react.createElement)("h4", null, "绑定事实"), (0, react.createElement)(ProposalTextView, {
|
|
5886
|
+
value: factsFromAction(detail),
|
|
5887
|
+
mode: "SAFE",
|
|
5888
|
+
label: "绑定事实"
|
|
5889
|
+
}), (0, react.createElement)("div", {
|
|
5890
|
+
role: "group",
|
|
5891
|
+
"aria-label": "内容显示方式",
|
|
5892
|
+
className: _run2skill_css_run2skill_settings_page_module_css_default.modeGroup
|
|
5893
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
|
|
5894
|
+
"aria-pressed": props.textMode === "SAFE",
|
|
5895
|
+
active: props.textMode === "SAFE",
|
|
5896
|
+
onClick: () => {
|
|
5897
|
+
props.setTextMode("SAFE");
|
|
5665
5898
|
}
|
|
5666
|
-
}
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
if (this.#disposed || this.#state.previewPending || this.#state.mutationPending) return;
|
|
5672
|
-
const workspaceId = this.getWorkspaceId();
|
|
5673
|
-
if (scope === "PROJECT" && workspaceId === void 0) {
|
|
5674
|
-
const error = { code: "PURGE_SCOPE_UNAVAILABLE" };
|
|
5675
|
-
this.#publish({
|
|
5676
|
-
...this.#state,
|
|
5677
|
-
error,
|
|
5678
|
-
announcement: errorAnnouncement(error)
|
|
5679
|
-
});
|
|
5680
|
-
return;
|
|
5899
|
+
}, "安全视图"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
|
|
5900
|
+
"aria-pressed": props.textMode === "RAW",
|
|
5901
|
+
active: props.textMode === "RAW",
|
|
5902
|
+
onClick: () => {
|
|
5903
|
+
props.setTextMode("RAW");
|
|
5681
5904
|
}
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
}
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
preview: void 0,
|
|
5720
|
-
previewScope: void 0,
|
|
5721
|
-
error: void 0,
|
|
5722
|
-
announcement: ""
|
|
5723
|
-
});
|
|
5724
|
-
}
|
|
5725
|
-
async confirm() {
|
|
5726
|
-
const preview = this.#state.preview;
|
|
5727
|
-
const scope = this.#state.previewScope;
|
|
5728
|
-
if (this.#disposed || preview === void 0 || scope === void 0 || this.#state.mutationPending) return;
|
|
5729
|
-
await this.#execute(async (signal) => {
|
|
5730
|
-
this.#publish({
|
|
5731
|
-
...this.#state,
|
|
5732
|
-
mutationPending: true,
|
|
5733
|
-
error: void 0,
|
|
5734
|
-
announcement: ""
|
|
5735
|
-
});
|
|
5736
|
-
const receipt = parseValue(receiptSchema, await this.call("purge/confirm", {
|
|
5737
|
-
apiVersion: 1,
|
|
5738
|
-
previewId: preview.previewId,
|
|
5739
|
-
digest: preview.digest
|
|
5740
|
-
}, signal));
|
|
5741
|
-
this.#acceptReceipt(scope, receipt);
|
|
5742
|
-
}, async (error) => {
|
|
5743
|
-
this.#publish({
|
|
5744
|
-
...this.#state,
|
|
5745
|
-
mutationPending: false,
|
|
5746
|
-
error,
|
|
5747
|
-
announcement: errorAnnouncement(error),
|
|
5748
|
-
preview: void 0,
|
|
5749
|
-
previewScope: void 0
|
|
5750
|
-
});
|
|
5751
|
-
await this.#readStatusAfterFailure(error);
|
|
5752
|
-
});
|
|
5753
|
-
}
|
|
5754
|
-
async retry() {
|
|
5755
|
-
const status = this.#state.status;
|
|
5756
|
-
if (this.#disposed || status?.state !== "IN_PROGRESS" || status.lastError === void 0 || this.#state.mutationPending) return;
|
|
5757
|
-
await this.#execute(async (signal) => {
|
|
5758
|
-
this.#publish({
|
|
5759
|
-
...this.#state,
|
|
5760
|
-
mutationPending: true,
|
|
5761
|
-
error: void 0,
|
|
5762
|
-
announcement: "正在重试数据清理。"
|
|
5763
|
-
});
|
|
5764
|
-
const receipt = parseValue(receiptSchema, await this.call("purge/retry", {
|
|
5765
|
-
apiVersion: 1,
|
|
5766
|
-
purgeId: status.purgeId
|
|
5767
|
-
}, signal));
|
|
5768
|
-
this.#acceptReceipt(this.#state.previewScope, receipt);
|
|
5769
|
-
}, async (error) => {
|
|
5770
|
-
this.#publish({
|
|
5771
|
-
...this.#state,
|
|
5772
|
-
mutationPending: false,
|
|
5773
|
-
error,
|
|
5774
|
-
announcement: errorAnnouncement(error, true)
|
|
5775
|
-
});
|
|
5776
|
-
await this.#readStatusAfterFailure(error, true);
|
|
5777
|
-
});
|
|
5778
|
-
}
|
|
5779
|
-
dispose() {
|
|
5780
|
-
if (this.#disposed) return;
|
|
5781
|
-
this.#disposed = true;
|
|
5782
|
-
this.#unschedule();
|
|
5783
|
-
this.#removeVisibility?.();
|
|
5784
|
-
this.#removeVisibility = void 0;
|
|
5785
|
-
this.#abort?.abort();
|
|
5786
|
-
this.#statusAbort?.abort();
|
|
5787
|
-
this.#listeners.clear();
|
|
5788
|
-
}
|
|
5789
|
-
#acceptReceipt(scope, receipt) {
|
|
5790
|
-
if (receipt.state === "COMPLETED") {
|
|
5791
|
-
this.#publish({
|
|
5792
|
-
...this.#state,
|
|
5793
|
-
statusPhase: "READY",
|
|
5794
|
-
status: {
|
|
5795
|
-
apiVersion: 1,
|
|
5796
|
-
state: "IDLE"
|
|
5797
|
-
},
|
|
5798
|
-
inProgressReceipt: void 0,
|
|
5799
|
-
preview: void 0,
|
|
5800
|
-
previewScope: void 0,
|
|
5801
|
-
mutationPending: false,
|
|
5802
|
-
error: void 0,
|
|
5803
|
-
announcement: completionAnnouncement(scope, receipt)
|
|
5804
|
-
});
|
|
5805
|
-
return;
|
|
5905
|
+
}, "原始内容")), (0, react.createElement)("h4", null, "将要批准的完整 SKILL.md"), (0, react.createElement)(ProposalTextView, {
|
|
5906
|
+
value: proposal.exactSkillBytes,
|
|
5907
|
+
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, {
|
|
5910
|
+
value: baseBytes,
|
|
5911
|
+
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, {
|
|
5914
|
+
value: coveringBytes,
|
|
5915
|
+
mode: props.textMode,
|
|
5916
|
+
label: "覆盖已有 Skill 的完整内容"
|
|
5917
|
+
})), (0, react.createElement)("div", {
|
|
5918
|
+
role: "group",
|
|
5919
|
+
"aria-label": "Proposal 操作",
|
|
5920
|
+
className: _run2skill_css_run2skill_settings_page_module_css_default.actions
|
|
5921
|
+
}, action === "RETRY_PUBLICATION" ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5922
|
+
variant: "primary",
|
|
5923
|
+
disabled: mutationPending,
|
|
5924
|
+
onClick: props.onRetry
|
|
5925
|
+
}, "重试发布") : proposal.kind === "DISCARD" ? (0, react.createElement)(react.Fragment, null, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5926
|
+
variant: "primary",
|
|
5927
|
+
disabled: !actionable,
|
|
5928
|
+
onClick: props.onConfirmDiscard
|
|
5929
|
+
}, "确认无需新建 Skill"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5930
|
+
variant: "outline",
|
|
5931
|
+
disabled: !actionable,
|
|
5932
|
+
onClick: props.onRetry
|
|
5933
|
+
}, "不同意,重新分析一次")) : (0, react.createElement)(react.Fragment, null, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5934
|
+
variant: "primary",
|
|
5935
|
+
disabled: !actionable,
|
|
5936
|
+
onClick: props.onApprove
|
|
5937
|
+
}, detail.processingState === "PUBLISHING" ? "正在发布…" : "批准并发布"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
5938
|
+
variant: "outline",
|
|
5939
|
+
disabled: !actionable,
|
|
5940
|
+
onClick: (event) => {
|
|
5941
|
+
props.onReject(event.currentTarget);
|
|
5806
5942
|
}
|
|
5807
|
-
|
|
5808
|
-
...this.#state,
|
|
5809
|
-
mutationPending: false,
|
|
5810
|
-
preview: void 0,
|
|
5811
|
-
inProgressReceipt: receipt,
|
|
5812
|
-
announcement: `run2skill 数据清理进行中:${receipt.phase ?? "HIDING"}。`
|
|
5813
|
-
});
|
|
5814
|
-
}
|
|
5815
|
-
async #readStatusAfterFailure(error, durableBoundary = false) {
|
|
5816
|
-
try {
|
|
5817
|
-
const status = parseValue(statusSchema, await this.call("purge/status", { apiVersion: 1 }, new AbortController().signal));
|
|
5818
|
-
this.#publish({
|
|
5819
|
-
...this.#state,
|
|
5820
|
-
statusPhase: "READY",
|
|
5821
|
-
status,
|
|
5822
|
-
inProgressReceipt: status.state === "IDLE" ? void 0 : this.#state.inProgressReceipt,
|
|
5823
|
-
announcement: errorAnnouncement(error, durableBoundary || status.state === "IN_PROGRESS")
|
|
5824
|
-
});
|
|
5825
|
-
} catch {}
|
|
5826
|
-
}
|
|
5827
|
-
async #refreshStatus() {
|
|
5828
|
-
if (this.#disposed || !this.environment.isVisible()) return;
|
|
5829
|
-
if (this.#statusPending !== void 0) return this.#statusPending;
|
|
5830
|
-
const abort = new AbortController();
|
|
5831
|
-
this.#statusAbort = abort;
|
|
5832
|
-
const pending = (async () => {
|
|
5833
|
-
try {
|
|
5834
|
-
const status = parseValue(statusSchema, await this.call("purge/status", { apiVersion: 1 }, abort.signal));
|
|
5835
|
-
if (this.#disposed || abort.signal.aborted) return;
|
|
5836
|
-
const completed = status.state === "IDLE" && (this.#state.status?.state === "IN_PROGRESS" || this.#state.inProgressReceipt?.state === "IN_PROGRESS");
|
|
5837
|
-
this.#publish({
|
|
5838
|
-
...this.#state,
|
|
5839
|
-
statusPhase: "READY",
|
|
5840
|
-
status,
|
|
5841
|
-
inProgressReceipt: status.state === "IDLE" ? void 0 : this.#state.inProgressReceipt,
|
|
5842
|
-
previewScope: completed ? void 0 : this.#state.previewScope,
|
|
5843
|
-
announcement: completed ? polledCompletionAnnouncement(this.#state.previewScope) : this.#state.announcement
|
|
5844
|
-
});
|
|
5845
|
-
} catch {
|
|
5846
|
-
if (this.#disposed || abort.signal.aborted) return;
|
|
5847
|
-
this.#publish({
|
|
5848
|
-
...this.#state,
|
|
5849
|
-
statusPhase: this.#state.status === void 0 ? "UNAVAILABLE" : "STALE"
|
|
5850
|
-
});
|
|
5851
|
-
}
|
|
5852
|
-
})();
|
|
5853
|
-
this.#statusPending = pending;
|
|
5854
|
-
await pending.finally(() => {
|
|
5855
|
-
if (this.#statusPending === pending) this.#statusPending = void 0;
|
|
5856
|
-
if (this.#statusAbort === abort) this.#statusAbort = void 0;
|
|
5857
|
-
});
|
|
5858
|
-
}
|
|
5859
|
-
async #execute(task, onError) {
|
|
5860
|
-
if (this.#disposed || this.#pending !== void 0) return this.#pending ?? Promise.resolve();
|
|
5861
|
-
const abort = new AbortController();
|
|
5862
|
-
this.#abort = abort;
|
|
5863
|
-
const pending = (async () => {
|
|
5864
|
-
try {
|
|
5865
|
-
await task(abort.signal);
|
|
5866
|
-
} catch (error) {
|
|
5867
|
-
if (!this.#disposed && !abort.signal.aborted) await onError(error instanceof PurgeResponseError ? error.facts : { code: "PURGE_STORAGE_UNAVAILABLE" });
|
|
5868
|
-
}
|
|
5869
|
-
})();
|
|
5870
|
-
this.#pending = pending;
|
|
5871
|
-
await pending.finally(() => {
|
|
5872
|
-
if (this.#pending === pending) this.#pending = void 0;
|
|
5873
|
-
if (this.#abort === abort) this.#abort = void 0;
|
|
5874
|
-
});
|
|
5875
|
-
}
|
|
5876
|
-
#schedule() {
|
|
5877
|
-
if (this.#disposed) return;
|
|
5878
|
-
const delay = this.#state.status?.state === "IN_PROGRESS" || this.#state.inProgressReceipt?.state === "IN_PROGRESS" || this.#state.mutationPending ? PURGE_ACTIVE_POLL_INTERVAL_MS : PURGE_IDLE_POLL_INTERVAL_MS;
|
|
5879
|
-
if (this.#timer !== void 0 && this.#timerDelay === delay) return;
|
|
5880
|
-
this.#unschedule();
|
|
5881
|
-
this.#timerDelay = delay;
|
|
5882
|
-
this.#timer = this.environment.setInterval(() => {
|
|
5883
|
-
this.#refreshStatus();
|
|
5884
|
-
}, delay);
|
|
5885
|
-
}
|
|
5886
|
-
#unschedule() {
|
|
5887
|
-
if (this.#timer === void 0) return;
|
|
5888
|
-
this.environment.clearInterval(this.#timer);
|
|
5889
|
-
this.#timer = void 0;
|
|
5890
|
-
this.#timerDelay = void 0;
|
|
5891
|
-
}
|
|
5892
|
-
#publish(state) {
|
|
5893
|
-
if (this.#disposed) return;
|
|
5894
|
-
this.#state = state;
|
|
5895
|
-
if (this.#started && this.environment.isVisible()) this.#schedule();
|
|
5896
|
-
for (const listener of this.#listeners) listener();
|
|
5897
|
-
}
|
|
5898
|
-
};
|
|
5899
|
-
const phaseCopy = {
|
|
5900
|
-
HIDING: "正在隐藏命中数据",
|
|
5901
|
-
DELETING_LINEAGES: "正在删除发布沿袭记录",
|
|
5902
|
-
DELETING_WORK_ITEMS: "正在删除待处理数据",
|
|
5903
|
-
VERIFYING: "正在验证清理结果"
|
|
5904
|
-
};
|
|
5905
|
-
function PreviewSummary({ preview }) {
|
|
5906
|
-
const keep = Object.fromEntries(preview.willKeep.map((item) => [item.reason, item.count]));
|
|
5907
|
-
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)} 条;存在时确认会安全拒绝`));
|
|
5943
|
+
}, "拒绝 Proposal"))));
|
|
5908
5944
|
}
|
|
5909
|
-
function
|
|
5945
|
+
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", {
|
|
5947
|
+
type: "button",
|
|
5948
|
+
"data-initial-focus": true,
|
|
5949
|
+
disabled: props.disabled,
|
|
5950
|
+
onClick: props.onCancel
|
|
5951
|
+
}, "取消"), (0, react.createElement)("button", {
|
|
5952
|
+
type: "button",
|
|
5953
|
+
disabled: props.disabled,
|
|
5954
|
+
onClick: props.onConfirm
|
|
5955
|
+
}, "确认拒绝"));
|
|
5956
|
+
}
|
|
5957
|
+
function RejectConfirmation(props) {
|
|
5910
5958
|
const dialogRef = (0, react.useRef)(null);
|
|
5911
|
-
const preview = props.state.preview;
|
|
5912
|
-
const scope = props.state.previewScope;
|
|
5913
5959
|
(0, react.useEffect)(() => {
|
|
5914
|
-
if (
|
|
5960
|
+
if (typeof document === "undefined") return;
|
|
5961
|
+
const previous = document.activeElement;
|
|
5915
5962
|
const dialog = dialogRef.current;
|
|
5916
5963
|
const initial = dialog?.querySelector("[data-initial-focus]");
|
|
5917
5964
|
const recapture = (event) => {
|
|
@@ -5921,205 +5968,765 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5921
5968
|
initial?.focus();
|
|
5922
5969
|
return () => {
|
|
5923
5970
|
document.removeEventListener("focusin", recapture, true);
|
|
5924
|
-
|
|
5971
|
+
previous?.focus();
|
|
5925
5972
|
};
|
|
5926
|
-
}, [
|
|
5927
|
-
|
|
5928
|
-
const titleId = "run2skill-purge-confirm-title";
|
|
5929
|
-
const descriptionId = "run2skill-purge-confirm-description";
|
|
5930
|
-
return (0, react.createElement)(react.Fragment, null, (0, react.createElement)("div", {
|
|
5931
|
-
"aria-hidden": true,
|
|
5932
|
-
style: {
|
|
5933
|
-
position: "fixed",
|
|
5934
|
-
inset: 0,
|
|
5935
|
-
zIndex: 1999,
|
|
5936
|
-
background: "rgb(0 0 0 / 35%)"
|
|
5937
|
-
}
|
|
5938
|
-
}), (0, react.createElement)("div", {
|
|
5973
|
+
}, []);
|
|
5974
|
+
return (0, react.createElement)("div", {
|
|
5939
5975
|
ref: dialogRef,
|
|
5940
5976
|
role: "alertdialog",
|
|
5941
5977
|
"aria-modal": true,
|
|
5942
|
-
"aria-labelledby":
|
|
5943
|
-
"aria-describedby":
|
|
5978
|
+
"aria-labelledby": "run2skill-reject-title",
|
|
5979
|
+
"aria-describedby": "run2skill-reject-description",
|
|
5944
5980
|
onKeyDown: (event) => {
|
|
5981
|
+
event.stopPropagation();
|
|
5945
5982
|
if (event.key === "Escape") {
|
|
5946
5983
|
event.preventDefault();
|
|
5947
|
-
|
|
5948
|
-
props.controller.cancelPreview();
|
|
5984
|
+
props.onCancel();
|
|
5949
5985
|
} else if (dialogRef.current !== null) trapDialogTab(event.key, event.shiftKey, () => {
|
|
5950
5986
|
event.preventDefault();
|
|
5951
5987
|
}, dialogRef.current, typeof document === "undefined" ? void 0 : document.activeElement);
|
|
5952
5988
|
},
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5989
|
+
className: _run2skill_css_run2skill_settings_page_module_css_default.rejectOverlay
|
|
5990
|
+
}, (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.rejectCard }, (0, react.createElement)(RejectConfirmationBody, props)));
|
|
5991
|
+
}
|
|
5992
|
+
//#endregion
|
|
5993
|
+
//#region src/client/run2skill-settings-page.ts
|
|
5994
|
+
const learningIssueSchema = object({
|
|
5995
|
+
workItemId: string().regex(/^wi_[a-f0-9]{64}$/),
|
|
5996
|
+
workItemRevision: number().int().safe().positive(),
|
|
5997
|
+
createdAt: string().datetime({ offset: true }),
|
|
5998
|
+
updatedAt: string().datetime({ offset: true }),
|
|
5999
|
+
failureCode: string().min(1).max(256),
|
|
6000
|
+
failureDetail: string().min(1).max(256).optional(),
|
|
6001
|
+
retryable: boolean(),
|
|
6002
|
+
attempt: number().int().nonnegative().max(3),
|
|
6003
|
+
requestBudgetUsed: number().int().nonnegative().max(2),
|
|
6004
|
+
modelRoute: object({
|
|
6005
|
+
provider: string().min(1).max(256),
|
|
6006
|
+
model: string().min(1).max(256)
|
|
6007
|
+
}).strict().optional(),
|
|
6008
|
+
calls: array(object({
|
|
6009
|
+
requestOrdinal: number().int().positive(),
|
|
6010
|
+
kind: string().min(1).max(256),
|
|
6011
|
+
inputTokens: number().int().nonnegative().optional(),
|
|
6012
|
+
outputTokens: number().int().nonnegative().optional(),
|
|
6013
|
+
outcome: string().min(1).max(256)
|
|
6014
|
+
}).strict()).max(2)
|
|
6015
|
+
}).strict();
|
|
6016
|
+
const learningIssuePageSchema = object({
|
|
6017
|
+
ok: literal(true),
|
|
6018
|
+
value: object({
|
|
6019
|
+
apiVersion: literal(1),
|
|
6020
|
+
items: array(learningIssueSchema).max(20),
|
|
6021
|
+
nextCursor: string().regex(/^c_[1-9][0-9]*_[1-9][0-9]*_[a-f0-9]{64}$/).optional()
|
|
6022
|
+
}).strict()
|
|
6023
|
+
}).strict();
|
|
6024
|
+
function attentionValue(value) {
|
|
6025
|
+
if (value === null || typeof value !== "object" || !("ok" in value) || value.ok !== true || !("value" in value)) return;
|
|
6026
|
+
const projection = value.value;
|
|
6027
|
+
if (projection.apiVersion !== 1 || !Array.isArray(projection.actions) || !Array.isArray(projection.runtimeWarnings)) return void 0;
|
|
6028
|
+
return projection;
|
|
6029
|
+
}
|
|
6030
|
+
const seenAttentionKeys = /* @__PURE__ */ new Set();
|
|
6031
|
+
function currentScope(workspaceId, generation) {
|
|
6032
|
+
return workspaceId === void 0 ? {
|
|
6033
|
+
kind: "USER_ONLY",
|
|
6034
|
+
generation
|
|
6035
|
+
} : {
|
|
6036
|
+
kind: "WORKSPACE",
|
|
6037
|
+
generation,
|
|
6038
|
+
workspaceId
|
|
6039
|
+
};
|
|
6040
|
+
}
|
|
6041
|
+
function Run2skillAttentionToast(props) {
|
|
6042
|
+
const [toast, setToast] = (0, react.useState)();
|
|
6043
|
+
const scopeGeneration = (0, react.useRef)(0);
|
|
6044
|
+
(0, react.useEffect)(() => {
|
|
6045
|
+
const abort = new AbortController();
|
|
6046
|
+
let timer;
|
|
6047
|
+
let sequence = 0;
|
|
6048
|
+
const generation = ++scopeGeneration.current;
|
|
6049
|
+
const refresh = async () => {
|
|
6050
|
+
try {
|
|
6051
|
+
const projection = attentionValue(await props.callAttention({
|
|
6052
|
+
apiVersion: 1,
|
|
6053
|
+
currentScope: currentScope(props.workspaceId, generation),
|
|
6054
|
+
sessionId: props.sessionId
|
|
6055
|
+
}, abort.signal));
|
|
6056
|
+
if (projection === void 0 || abort.signal.aborted) return;
|
|
6057
|
+
const fresh = [...projection.actions.map((action) => action.actionKey), ...projection.runtimeWarnings.map((warning) => warning.noticeKey)].filter((key) => /^act_[a-f0-9]{64}$|^notice_[a-f0-9]{64}$/.test(key)).filter((key) => !seenAttentionKeys.has(key));
|
|
6058
|
+
if (fresh.length > 0) {
|
|
6059
|
+
for (const key of fresh) seenAttentionKeys.add(key);
|
|
6060
|
+
sequence += 1;
|
|
6061
|
+
setToast({
|
|
6062
|
+
sequence,
|
|
6063
|
+
count: fresh.length
|
|
6064
|
+
});
|
|
6065
|
+
}
|
|
6066
|
+
} catch {} finally {
|
|
6067
|
+
if (!abort.signal.aborted) timer = setTimeout(() => {
|
|
6068
|
+
refresh();
|
|
6069
|
+
}, 1e4);
|
|
6070
|
+
}
|
|
6071
|
+
};
|
|
6072
|
+
refresh();
|
|
6073
|
+
return () => {
|
|
6074
|
+
abort.abort();
|
|
6075
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
6076
|
+
};
|
|
6077
|
+
}, [
|
|
6078
|
+
props.callAttention,
|
|
6079
|
+
props.sessionId,
|
|
6080
|
+
props.workspaceId
|
|
6081
|
+
]);
|
|
6082
|
+
if (toast === void 0) return null;
|
|
6083
|
+
return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Toast, {
|
|
6084
|
+
key: toast.sequence,
|
|
6085
|
+
icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutline16),
|
|
6086
|
+
text: `run2skill 有 ${String(toast.count)} 项需要处理,请前往设置 → 插件 → run2skill`,
|
|
6087
|
+
onDone: () => {
|
|
6088
|
+
setToast(void 0);
|
|
5963
6089
|
}
|
|
5964
|
-
}
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
6090
|
+
});
|
|
6091
|
+
}
|
|
6092
|
+
function AutomaticLearningSection(props) {
|
|
6093
|
+
const state = (0, react.useSyncExternalStore)(props.controller.subscribe, props.controller.getSnapshot, props.controller.getSnapshot);
|
|
6094
|
+
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, {
|
|
6096
|
+
variant: state.automaticLearning ? "primary" : "outline",
|
|
6097
|
+
"aria-pressed": state.automaticLearning === true,
|
|
6098
|
+
disabled,
|
|
5968
6099
|
onClick: () => {
|
|
5969
|
-
props.controller.
|
|
6100
|
+
props.controller.setAutomaticLearning(state.automaticLearning !== true);
|
|
5970
6101
|
}
|
|
5971
|
-
}, "
|
|
5972
|
-
|
|
5973
|
-
|
|
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", {
|
|
6103
|
+
role: "status",
|
|
6104
|
+
className: _run2skill_css_run2skill_settings_page_module_css_default.danger
|
|
6105
|
+
}, "设置已变化,请刷新后重试。"));
|
|
6106
|
+
}
|
|
6107
|
+
function ProposalSettingsSection(props) {
|
|
6108
|
+
const scopeAccessRef = (0, react.useRef)({
|
|
6109
|
+
currentScope: currentScope(props.workspaceId, props.scopeGeneration),
|
|
6110
|
+
actions: []
|
|
6111
|
+
});
|
|
6112
|
+
scopeAccessRef.current = {
|
|
6113
|
+
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 ?? "") ? [] : [{
|
|
6115
|
+
actionKey: action.actionKey,
|
|
6116
|
+
subjectId: action.subjectId,
|
|
6117
|
+
kind: action.kind,
|
|
6118
|
+
proposalRef: action.proposalRef
|
|
6119
|
+
}])
|
|
6120
|
+
};
|
|
6121
|
+
const controller = (0, react.useMemo)(() => new ProposalInboxController(props.workspaceId ?? "__run2skill_user_only__", props.callReview, void 0, {
|
|
6122
|
+
attentionDriven: true,
|
|
6123
|
+
scopeAccess: () => scopeAccessRef.current
|
|
6124
|
+
}), [
|
|
6125
|
+
props.callReview,
|
|
6126
|
+
props.scopeGeneration,
|
|
6127
|
+
props.workspaceId
|
|
6128
|
+
]);
|
|
6129
|
+
(0, react.useEffect)(() => {
|
|
6130
|
+
if (!props.active) controller.pause();
|
|
6131
|
+
controller.start();
|
|
6132
|
+
return () => {
|
|
6133
|
+
controller.dispose();
|
|
6134
|
+
};
|
|
6135
|
+
}, [controller]);
|
|
6136
|
+
(0, react.useEffect)(() => {
|
|
6137
|
+
if (props.active) {
|
|
6138
|
+
controller.resume();
|
|
6139
|
+
controller.open();
|
|
6140
|
+
} else {
|
|
6141
|
+
controller.pause();
|
|
6142
|
+
controller.close();
|
|
6143
|
+
}
|
|
6144
|
+
}, [controller, props.active]);
|
|
6145
|
+
const state = (0, react.useSyncExternalStore)(controller.subscribe, controller.snapshot, controller.snapshot);
|
|
6146
|
+
const [filter, setFilter] = (0, react.useState)("");
|
|
6147
|
+
const [textMode, setTextMode] = (0, react.useState)("SAFE");
|
|
6148
|
+
const [rejectConfirm, setRejectConfirm] = (0, react.useState)(false);
|
|
6149
|
+
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()));
|
|
6151
|
+
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, {
|
|
6153
|
+
value: filter,
|
|
6154
|
+
placeholder: "筛选 Proposal",
|
|
6155
|
+
"aria-label": "筛选 Proposal",
|
|
6156
|
+
onChange: (event) => {
|
|
6157
|
+
setFilter(event.currentTarget.value);
|
|
6158
|
+
}
|
|
6159
|
+
}), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
6160
|
+
variant: "outline",
|
|
6161
|
+
size: "sm",
|
|
6162
|
+
icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16),
|
|
6163
|
+
onClick: () => {
|
|
6164
|
+
controller.open();
|
|
6165
|
+
}
|
|
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",
|
|
6168
|
+
className: _run2skill_css_run2skill_settings_page_module_css_default.proposalListButton,
|
|
6169
|
+
disabled: state.mutationPending || state.detailPhase === "LOADING",
|
|
6170
|
+
onClick: () => {
|
|
6171
|
+
controller.select(item.proposalRef.proposalId);
|
|
6172
|
+
}
|
|
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, {
|
|
6174
|
+
detail: state.detail,
|
|
6175
|
+
textMode,
|
|
6176
|
+
setTextMode,
|
|
6177
|
+
mutationPending: state.mutationPending,
|
|
6178
|
+
onApprove: () => {
|
|
6179
|
+
controller.mutate("APPROVE").finally(props.onMutationSettled);
|
|
6180
|
+
},
|
|
6181
|
+
onReject: (trigger) => {
|
|
6182
|
+
rejectTriggerRef.current = trigger ?? null;
|
|
6183
|
+
setRejectConfirm(true);
|
|
6184
|
+
},
|
|
6185
|
+
onRetry: () => {
|
|
6186
|
+
controller.mutate("RETRY").finally(props.onMutationSettled);
|
|
6187
|
+
},
|
|
6188
|
+
onConfirmDiscard: () => {
|
|
6189
|
+
controller.mutate("CONFIRM_DISCARD").finally(props.onMutationSettled);
|
|
6190
|
+
}
|
|
6191
|
+
}))), (0, react.createElement)("p", {
|
|
6192
|
+
role: "status",
|
|
6193
|
+
"aria-live": "polite",
|
|
6194
|
+
"aria-atomic": true,
|
|
6195
|
+
className: _run2skill_css_run2skill_settings_page_module_css_default.status
|
|
6196
|
+
}, state.announcement), (0, react.createElement)(RejectProposalModal, {
|
|
6197
|
+
open: rejectConfirm,
|
|
6198
|
+
disabled: state.mutationPending,
|
|
6199
|
+
triggerRef: rejectTriggerRef,
|
|
6200
|
+
onClose: () => {
|
|
6201
|
+
setRejectConfirm(false);
|
|
6202
|
+
},
|
|
6203
|
+
onConfirm: () => {
|
|
6204
|
+
setRejectConfirm(false);
|
|
6205
|
+
controller.mutate("REJECT").finally(props.onMutationSettled);
|
|
6206
|
+
}
|
|
6207
|
+
}));
|
|
6208
|
+
}
|
|
6209
|
+
function LearningFailureSection(props) {
|
|
6210
|
+
const [phase, setPhase] = (0, react.useState)("IDLE");
|
|
6211
|
+
const [items, setItems] = (0, react.useState)([]);
|
|
6212
|
+
const [refreshGeneration, setRefreshGeneration] = (0, react.useState)(0);
|
|
6213
|
+
const [pending, setPending] = (0, react.useState)();
|
|
6214
|
+
const [dismiss, setDismiss] = (0, react.useState)();
|
|
6215
|
+
const dismissTriggerRef = (0, react.useRef)(null);
|
|
6216
|
+
const learningActions = (0, react.useMemo)(() => new Map(props.actions.flatMap((action) => action.subjectId === void 0 || !["RETRY_LEARNING", "DISMISS_LEARNING"].includes(action.kind ?? "") ? [] : [[action.subjectId, action]])), [props.actions]);
|
|
6217
|
+
(0, react.useEffect)(() => {
|
|
6218
|
+
if (!props.active || learningActions.size === 0) {
|
|
6219
|
+
setPhase("IDLE");
|
|
6220
|
+
setItems([]);
|
|
6221
|
+
return;
|
|
6222
|
+
}
|
|
6223
|
+
const abort = new AbortController();
|
|
6224
|
+
setPhase("LOADING");
|
|
6225
|
+
(async () => {
|
|
6226
|
+
const next = [];
|
|
6227
|
+
let cursor;
|
|
6228
|
+
for (let page = 0; page < 10; page += 1) {
|
|
6229
|
+
const parsed = learningIssuePageSchema.safeParse(await props.call("learning/issues/list", {
|
|
6230
|
+
apiVersion: 1,
|
|
6231
|
+
currentScope: currentScope(props.workspaceId, props.scopeGeneration ?? 1),
|
|
6232
|
+
limit: 20,
|
|
6233
|
+
...cursor === void 0 ? {} : { cursor }
|
|
6234
|
+
}, abort.signal));
|
|
6235
|
+
if (!parsed.success) throw new Error("invalid learning issue response");
|
|
6236
|
+
next.push(...parsed.data.value.items.filter((item) => learningActions.has(item.workItemId)));
|
|
6237
|
+
cursor = parsed.data.value.nextCursor;
|
|
6238
|
+
if (cursor === void 0) {
|
|
6239
|
+
if (!abort.signal.aborted) {
|
|
6240
|
+
setItems(next);
|
|
6241
|
+
setPhase("READY");
|
|
6242
|
+
}
|
|
6243
|
+
return;
|
|
6244
|
+
}
|
|
6245
|
+
}
|
|
6246
|
+
throw new Error("learning issue page limit exceeded");
|
|
6247
|
+
})().catch(() => {
|
|
6248
|
+
if (!abort.signal.aborted) {
|
|
6249
|
+
setItems([]);
|
|
6250
|
+
setPhase("ERROR");
|
|
6251
|
+
}
|
|
6252
|
+
});
|
|
6253
|
+
return () => {
|
|
6254
|
+
abort.abort();
|
|
6255
|
+
};
|
|
6256
|
+
}, [
|
|
6257
|
+
learningActions,
|
|
6258
|
+
props.active,
|
|
6259
|
+
props.call,
|
|
6260
|
+
props.scopeGeneration,
|
|
6261
|
+
props.workspaceId,
|
|
6262
|
+
refreshGeneration
|
|
6263
|
+
]);
|
|
6264
|
+
const mutate = (endpoint, item) => {
|
|
6265
|
+
if (pending !== void 0) return;
|
|
6266
|
+
const selectedAction = learningActions.get(item.workItemId);
|
|
6267
|
+
if (selectedAction?.subjectId === void 0 || selectedAction.kind === void 0) return;
|
|
6268
|
+
setPending(item.workItemId);
|
|
6269
|
+
props.call(endpoint, {
|
|
6270
|
+
apiVersion: 1,
|
|
6271
|
+
workItemId: item.workItemId,
|
|
6272
|
+
workItemRevision: item.workItemRevision,
|
|
6273
|
+
currentScope: currentScope(props.workspaceId, props.scopeGeneration ?? 1),
|
|
6274
|
+
action: {
|
|
6275
|
+
actionKey: selectedAction.actionKey,
|
|
6276
|
+
subjectId: selectedAction.subjectId,
|
|
6277
|
+
kind: selectedAction.kind,
|
|
6278
|
+
...selectedAction.proposalRef === void 0 ? {} : { proposalRef: selectedAction.proposalRef }
|
|
6279
|
+
},
|
|
6280
|
+
...endpoint === "learning/issues/dismiss" ? { confirm: true } : {}
|
|
6281
|
+
}, new AbortController().signal).then((result) => {
|
|
6282
|
+
if (result === null || typeof result !== "object" || !("ok" in result) || result.ok !== true) throw new Error("learning issue mutation rejected");
|
|
6283
|
+
setItems((current) => current.filter((candidate) => candidate.workItemId !== item.workItemId));
|
|
6284
|
+
props.onMutationSettled();
|
|
6285
|
+
}).catch(() => {
|
|
6286
|
+
setPhase("ERROR");
|
|
6287
|
+
}).finally(() => {
|
|
6288
|
+
setPending(void 0);
|
|
6289
|
+
});
|
|
6290
|
+
};
|
|
6291
|
+
if (learningActions.size === 0) return (0, react.createElement)(react.Fragment);
|
|
6292
|
+
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, {
|
|
6296
|
+
variant: "outline",
|
|
6297
|
+
size: "sm",
|
|
6298
|
+
icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline16),
|
|
6299
|
+
disabled: !props.active || pending !== void 0,
|
|
5974
6300
|
onClick: () => {
|
|
5975
|
-
|
|
6301
|
+
setRefreshGeneration((value) => value + 1);
|
|
6302
|
+
}
|
|
6303
|
+
}, "刷新失败详情")), phase === "LOADING" ? (0, react.createElement)("p", { role: "status" }, "正在加载学习失败详情…") : null, phase === "ERROR" ? (0, react.createElement)("p", { role: "alert" }, "学习失败详情暂不可用,请保持 DSH 运行并稍后重试。") : null, ...items.map((item) => {
|
|
6304
|
+
const action = learningActions.get(item.workItemId);
|
|
6305
|
+
const busy = pending === item.workItemId;
|
|
6306
|
+
return (0, react.createElement)("article", {
|
|
6307
|
+
className: _run2skill_css_run2skill_settings_page_module_css_default.detail,
|
|
6308
|
+
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, {
|
|
6310
|
+
variant: "primary",
|
|
6311
|
+
disabled: busy || pending !== void 0,
|
|
6312
|
+
onClick: () => {
|
|
6313
|
+
mutate("learning/issues/retry", item);
|
|
6314
|
+
}
|
|
6315
|
+
}, busy ? "正在重试…" : "重试学习") : null, action?.availableActions?.includes("DISMISS") === true ? (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
6316
|
+
variant: "outline",
|
|
6317
|
+
disabled: busy || pending !== void 0,
|
|
6318
|
+
onClick: (event) => {
|
|
6319
|
+
dismissTriggerRef.current = event.currentTarget;
|
|
6320
|
+
setDismiss(item);
|
|
6321
|
+
}
|
|
6322
|
+
}, "关闭此失败") : null));
|
|
6323
|
+
}), (0, react.createElement)(ManagedConfirmationModal, {
|
|
6324
|
+
open: dismiss !== void 0,
|
|
6325
|
+
title: "确认关闭此学习失败?",
|
|
6326
|
+
description: "该失败会从待处理列表隐藏;已有 Skill 和 DSH Session Log 不会改变。",
|
|
6327
|
+
disabled: pending !== void 0,
|
|
6328
|
+
triggerRef: dismissTriggerRef,
|
|
6329
|
+
onClose: () => {
|
|
6330
|
+
setDismiss(void 0);
|
|
6331
|
+
},
|
|
6332
|
+
confirmLabel: "确认关闭",
|
|
6333
|
+
onConfirm: () => {
|
|
6334
|
+
const selected = dismiss;
|
|
6335
|
+
setDismiss(void 0);
|
|
6336
|
+
if (selected !== void 0) mutate("learning/issues/dismiss", selected);
|
|
6337
|
+
}
|
|
6338
|
+
}));
|
|
6339
|
+
}
|
|
6340
|
+
function RejectProposalModal(props) {
|
|
6341
|
+
return (0, react.createElement)(ManagedConfirmationModal, {
|
|
6342
|
+
...props,
|
|
6343
|
+
title: "确认拒绝 Proposal?",
|
|
6344
|
+
description: "现有 Skill 不会改变;该 Proposal 将离开待处理队列。",
|
|
6345
|
+
confirmLabel: "确认拒绝"
|
|
6346
|
+
});
|
|
6347
|
+
}
|
|
6348
|
+
function ManagedConfirmationModal(props) {
|
|
6349
|
+
const contentRef = (0, react.useRef)(null);
|
|
6350
|
+
const onCloseRef = (0, react.useRef)(props.onClose);
|
|
6351
|
+
onCloseRef.current = props.onClose;
|
|
6352
|
+
(0, react.useEffect)(() => {
|
|
6353
|
+
if (!props.open || typeof document === "undefined") return;
|
|
6354
|
+
const dialog = contentRef.current?.closest("[role=\"dialog\"]");
|
|
6355
|
+
const initial = dialog?.querySelector("[autofocus]") ?? dialog?.querySelector(focusableSelector);
|
|
6356
|
+
const onFocus = (event) => {
|
|
6357
|
+
if (dialog != null && event.target instanceof Node && !dialog.contains(event.target)) initial?.focus();
|
|
6358
|
+
};
|
|
6359
|
+
const onKeyboardEvent = (event) => {
|
|
6360
|
+
if (dialog == null) return;
|
|
6361
|
+
if (event.key === "Escape") {
|
|
6362
|
+
event.preventDefault();
|
|
6363
|
+
event.stopImmediatePropagation();
|
|
6364
|
+
onCloseRef.current?.();
|
|
6365
|
+
} else if (event.key === "Tab") trapDialogTab(event.key, event.shiftKey, () => {
|
|
6366
|
+
event.preventDefault();
|
|
6367
|
+
}, dialog, document.activeElement);
|
|
6368
|
+
};
|
|
6369
|
+
document.addEventListener("focusin", onFocus, true);
|
|
6370
|
+
document.addEventListener("keydown", onKeyboardEvent, true);
|
|
6371
|
+
initial?.focus();
|
|
6372
|
+
return () => {
|
|
6373
|
+
document.removeEventListener("focusin", onFocus, true);
|
|
6374
|
+
document.removeEventListener("keydown", onKeyboardEvent, true);
|
|
6375
|
+
props.triggerRef.current?.focus();
|
|
6376
|
+
};
|
|
6377
|
+
}, [props.open, props.triggerRef]);
|
|
6378
|
+
return (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
6379
|
+
open: props.open,
|
|
6380
|
+
title: props.title,
|
|
6381
|
+
closeLabel: "取消",
|
|
6382
|
+
description: props.description,
|
|
6383
|
+
onClose: props.onClose,
|
|
6384
|
+
footer: (0, react.createElement)("div", { className: _run2skill_css_run2skill_settings_page_module_css_default.actions }, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
6385
|
+
variant: "ghost",
|
|
6386
|
+
autoFocus: true,
|
|
6387
|
+
disabled: props.disabled,
|
|
6388
|
+
onClick: props.onClose
|
|
6389
|
+
}, "取消"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
6390
|
+
variant: "primary",
|
|
6391
|
+
disabled: props.disabled,
|
|
6392
|
+
onClick: props.onConfirm
|
|
6393
|
+
}, props.confirmLabel))
|
|
6394
|
+
}, (0, react.createElement)("div", { ref: contentRef }));
|
|
6395
|
+
}
|
|
6396
|
+
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}`]));
|
|
6398
|
+
return items.filter((item) => identities.has(`${item.workItemId}\u0000${item.proposalRef.proposalId}\u0000${String(item.proposalRef.revision)}\u0000${item.proposalRef.digest}`));
|
|
6399
|
+
}
|
|
6400
|
+
function hostTabVisible(element) {
|
|
6401
|
+
return element !== null && element.closest("[hidden]") === null;
|
|
6402
|
+
}
|
|
6403
|
+
function useHostTabVisibility() {
|
|
6404
|
+
const ref = (0, react.useRef)(null);
|
|
6405
|
+
const [visible, setVisible] = (0, react.useState)(true);
|
|
6406
|
+
(0, react.useEffect)(() => {
|
|
6407
|
+
const update = () => {
|
|
6408
|
+
setVisible(hostTabVisible(ref.current));
|
|
6409
|
+
};
|
|
6410
|
+
update();
|
|
6411
|
+
if (ref.current === null || typeof MutationObserver === "undefined") return;
|
|
6412
|
+
const observer = new MutationObserver(update);
|
|
6413
|
+
let current = ref.current;
|
|
6414
|
+
while (current !== null) {
|
|
6415
|
+
observer.observe(current, {
|
|
6416
|
+
attributes: true,
|
|
6417
|
+
attributeFilter: ["hidden"]
|
|
6418
|
+
});
|
|
6419
|
+
current = current.parentElement;
|
|
5976
6420
|
}
|
|
5977
|
-
|
|
6421
|
+
return () => {
|
|
6422
|
+
observer.disconnect();
|
|
6423
|
+
};
|
|
6424
|
+
}, []);
|
|
6425
|
+
return {
|
|
6426
|
+
ref,
|
|
6427
|
+
visible
|
|
6428
|
+
};
|
|
5978
6429
|
}
|
|
5979
|
-
function
|
|
5980
|
-
const state = (0, react.
|
|
5981
|
-
const
|
|
5982
|
-
const
|
|
5983
|
-
const
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6430
|
+
function AttentionSettingsSummary(props) {
|
|
6431
|
+
const [state, setState] = (0, react.useState)({ phase: "LOADING" });
|
|
6432
|
+
const requestGeneration = (0, react.useRef)(0);
|
|
6433
|
+
const activeAbort = (0, react.useRef)();
|
|
6434
|
+
const refresh = (0, react.useCallback)(() => {
|
|
6435
|
+
activeAbort.current?.abort();
|
|
6436
|
+
const abort = new AbortController();
|
|
6437
|
+
activeAbort.current = abort;
|
|
6438
|
+
const generation = ++requestGeneration.current;
|
|
6439
|
+
setState({ phase: "LOADING" });
|
|
6440
|
+
props.onProjection(void 0);
|
|
6441
|
+
props.callAttention({
|
|
6442
|
+
apiVersion: 1,
|
|
6443
|
+
currentScope: currentScope(props.workspaceId, generation),
|
|
6444
|
+
...props.sessionId === void 0 ? {} : { sessionId: props.sessionId }
|
|
6445
|
+
}, abort.signal).then((result) => {
|
|
6446
|
+
if (abort.signal.aborted || requestGeneration.current !== generation) return;
|
|
6447
|
+
const value = attentionValue(result);
|
|
6448
|
+
setState(value === void 0 ? { phase: "UNAVAILABLE" } : {
|
|
6449
|
+
phase: "READY",
|
|
6450
|
+
value
|
|
6451
|
+
});
|
|
6452
|
+
props.onProjection(value);
|
|
6453
|
+
}, () => {
|
|
6454
|
+
if (abort.signal.aborted || requestGeneration.current !== generation) return;
|
|
6455
|
+
setState({ phase: "UNAVAILABLE" });
|
|
6456
|
+
props.onProjection(void 0);
|
|
6457
|
+
});
|
|
6458
|
+
return () => {
|
|
6459
|
+
abort.abort();
|
|
6460
|
+
if (activeAbort.current === abort) activeAbort.current = void 0;
|
|
6461
|
+
};
|
|
6462
|
+
}, [
|
|
6463
|
+
props.callAttention,
|
|
6464
|
+
props.onProjection,
|
|
6465
|
+
props.refreshGeneration,
|
|
6466
|
+
props.sessionId,
|
|
6467
|
+
props.workspaceId
|
|
6468
|
+
]);
|
|
6469
|
+
(0, react.useEffect)(() => refresh(), [refresh]);
|
|
6470
|
+
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", {
|
|
6472
|
+
key: warning.noticeKey,
|
|
6473
|
+
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),
|
|
6000
6478
|
onClick: () => {
|
|
6001
|
-
|
|
6002
|
-
props.controller.preview("USER");
|
|
6479
|
+
refresh();
|
|
6003
6480
|
}
|
|
6004
|
-
}, "
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6481
|
+
}, "刷新状态"));
|
|
6482
|
+
}
|
|
6483
|
+
function Run2skillSettingsPage(props) {
|
|
6484
|
+
const liveSessionId = props.useSessions?.((state) => state.current);
|
|
6485
|
+
const liveWorkspaceId = props.useWorkspaces?.((state) => state.items.find((workspace) => workspace.sessionIds?.includes(liveSessionId ?? ""))?.workspaceId);
|
|
6486
|
+
const workspaceId = props.useSessions === void 0 ? props.workspaceId : liveWorkspaceId;
|
|
6487
|
+
const sessionId = props.useSessions === void 0 ? props.sessionId : liveSessionId;
|
|
6488
|
+
const [open, setOpen] = (0, react.useState)(() => /* @__PURE__ */ new Set(["attention"]));
|
|
6489
|
+
const hostTab = useHostTabVisibility();
|
|
6490
|
+
const [attention, setAttention] = (0, react.useState)();
|
|
6491
|
+
const [attentionRefresh, setAttentionRefresh] = (0, react.useState)(0);
|
|
6492
|
+
const [scopeGeneration, setScopeGeneration] = (0, react.useState)(1);
|
|
6493
|
+
(0, react.useEffect)(() => {
|
|
6494
|
+
setAttention(void 0);
|
|
6495
|
+
setScopeGeneration((value) => value + 1);
|
|
6496
|
+
}, [sessionId, workspaceId]);
|
|
6497
|
+
const disclosure = (id, title, icon, content, collapsedContent) => (0, react.createElement)("section", {
|
|
6498
|
+
className: _run2skill_css_run2skill_settings_page_module_css_default.section,
|
|
6499
|
+
key: id
|
|
6500
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
|
|
6501
|
+
icon,
|
|
6502
|
+
title,
|
|
6503
|
+
open: open.has(id),
|
|
6504
|
+
expandable: true,
|
|
6505
|
+
expandOnRowClick: true,
|
|
6506
|
+
collapsedContent,
|
|
6507
|
+
onToggle: () => {
|
|
6508
|
+
setOpen((previous) => {
|
|
6509
|
+
const next = new Set(previous);
|
|
6510
|
+
if (next.has(id)) next.delete(id);
|
|
6511
|
+
else next.add(id);
|
|
6512
|
+
return next;
|
|
6513
|
+
});
|
|
6012
6514
|
}
|
|
6013
|
-
},
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
"
|
|
6018
|
-
},
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6515
|
+
}, content));
|
|
6516
|
+
return (0, react.createElement)("div", {
|
|
6517
|
+
ref: hostTab.ref,
|
|
6518
|
+
className: _run2skill_css_run2skill_settings_page_module_css_default.page,
|
|
6519
|
+
"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, {
|
|
6521
|
+
...sessionId === void 0 ? {} : { sessionId },
|
|
6522
|
+
...workspaceId === void 0 ? {} : { workspaceId },
|
|
6523
|
+
callAttention: props.callAttention,
|
|
6524
|
+
refreshGeneration: attentionRefresh,
|
|
6525
|
+
onProjection: setAttention
|
|
6526
|
+
}), (0, react.createElement)(ProposalSettingsSection, {
|
|
6527
|
+
...workspaceId === void 0 ? {} : { workspaceId },
|
|
6528
|
+
callReview: props.callReview,
|
|
6529
|
+
active: hostTab.visible && open.has("attention"),
|
|
6530
|
+
actions: attention?.actions ?? [],
|
|
6531
|
+
attentionAvailable: attention !== void 0,
|
|
6532
|
+
onMutationSettled: () => {
|
|
6533
|
+
setAttentionRefresh((value) => value + 1);
|
|
6534
|
+
},
|
|
6535
|
+
scopeGeneration
|
|
6536
|
+
}), (0, react.createElement)(LearningFailureSection, {
|
|
6537
|
+
...workspaceId === void 0 ? {} : { workspaceId },
|
|
6538
|
+
call: props.callReview,
|
|
6539
|
+
active: hostTab.visible && open.has("attention"),
|
|
6540
|
+
actions: attention?.actions ?? [],
|
|
6541
|
+
onMutationSettled: () => {
|
|
6542
|
+
setAttentionRefresh((value) => value + 1);
|
|
6543
|
+
},
|
|
6544
|
+
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, {
|
|
6546
|
+
controller: props.purgeController,
|
|
6547
|
+
active: hostTab.visible && open.has("data")
|
|
6548
|
+
}))));
|
|
6549
|
+
}
|
|
6550
|
+
function currentSessionId(context) {
|
|
6551
|
+
return context.sessions?.list.getSnapshot().current;
|
|
6552
|
+
}
|
|
6553
|
+
function workspaceFor(context, sessionId) {
|
|
6554
|
+
if (sessionId === void 0) return void 0;
|
|
6555
|
+
return context.workspaces.list.getSnapshot().items.find((workspace) => workspace.sessionIds?.includes(sessionId))?.workspaceId;
|
|
6556
|
+
}
|
|
6557
|
+
function applyRun2skillClient(context) {
|
|
6558
|
+
const controller = new AutomaticLearningSettingsController(context.settingsScope.bind({ namespace: "run2skill" }));
|
|
6559
|
+
const callReview = async (endpoint, payload, signal) => await context.connection.rpc.call(RUN2SKILL_RPC_CHANNEL, endpoint, payload, signal);
|
|
6560
|
+
const callAttention = async (payload, signal) => await context.connection.rpc.call(RUN2SKILL_RPC_CHANNEL, "attention", payload, signal);
|
|
6561
|
+
const callPurge = async (endpoint, payload, signal) => await context.connection.rpc.call(RUN2SKILL_RPC_CHANNEL, endpoint, payload, signal);
|
|
6562
|
+
const purgeController = new PurgeSettingsController(callPurge, () => workspaceFor(context, currentSessionId(context)));
|
|
6563
|
+
context.effect(() => {
|
|
6564
|
+
const disposeStyle = acquireRun2skillStyle();
|
|
6565
|
+
return () => {
|
|
6566
|
+
controller.dispose();
|
|
6567
|
+
purgeController.dispose();
|
|
6568
|
+
disposeStyle();
|
|
6569
|
+
};
|
|
6570
|
+
}, "run2skill: native settings surface");
|
|
6571
|
+
context.slots.inject("settings.plugins.tab", () => context.slots.register({
|
|
6572
|
+
name: "settings.plugins.tab",
|
|
6573
|
+
id: "run2skill",
|
|
6574
|
+
order: 20,
|
|
6575
|
+
label: "run2skill",
|
|
6576
|
+
inject: () => ({
|
|
6577
|
+
controller,
|
|
6578
|
+
purgeController,
|
|
6579
|
+
workspaceId: workspaceFor(context, currentSessionId(context)),
|
|
6580
|
+
sessionId: currentSessionId(context),
|
|
6581
|
+
callAttention,
|
|
6582
|
+
callReview
|
|
6583
|
+
})
|
|
6584
|
+
}, Run2skillSettingsPage));
|
|
6585
|
+
context.slots.inject("conversation.session.header.actions", () => context.slots.register({
|
|
6586
|
+
name: "conversation.session.header.actions",
|
|
6587
|
+
id: "run2skill-attention",
|
|
6588
|
+
order: 30,
|
|
6589
|
+
inject: () => ({ callAttention })
|
|
6590
|
+
}, function HeaderAttention(props) {
|
|
6591
|
+
const workspaceId = props.useWorkspaces((state) => state.items.find((workspace) => workspace.sessionIds?.includes(props.sessionId))?.workspaceId);
|
|
6592
|
+
return (0, react.createElement)(Run2skillAttentionToast, {
|
|
6593
|
+
sessionId: props.sessionId,
|
|
6594
|
+
...workspaceId === void 0 ? {} : { workspaceId },
|
|
6595
|
+
callAttention: props.callAttention
|
|
6596
|
+
});
|
|
6022
6597
|
}));
|
|
6023
6598
|
}
|
|
6024
6599
|
//#endregion
|
|
6025
|
-
//#region src/client/
|
|
6026
|
-
|
|
6027
|
-
|
|
6600
|
+
//#region src/client/observe-summary-poller.ts
|
|
6601
|
+
const OBSERVE_SUMMARY_POLL_INTERVAL_MS = 1e4;
|
|
6602
|
+
function browserEnvironment() {
|
|
6603
|
+
return {
|
|
6604
|
+
isVisible: () => typeof document === "undefined" || document.visibilityState === "visible",
|
|
6605
|
+
setInterval: (callback, delayMs) => globalThis.setInterval(callback, delayMs),
|
|
6606
|
+
clearInterval: (handle) => {
|
|
6607
|
+
globalThis.clearInterval(handle);
|
|
6608
|
+
},
|
|
6609
|
+
onFocus: (listener) => {
|
|
6610
|
+
if (typeof window === "undefined") return () => void 0;
|
|
6611
|
+
window.addEventListener("focus", listener);
|
|
6612
|
+
return () => {
|
|
6613
|
+
window.removeEventListener("focus", listener);
|
|
6614
|
+
};
|
|
6615
|
+
},
|
|
6616
|
+
onVisibilityChange: (listener) => {
|
|
6617
|
+
if (typeof document === "undefined") return () => void 0;
|
|
6618
|
+
document.addEventListener("visibilitychange", listener);
|
|
6619
|
+
return () => {
|
|
6620
|
+
document.removeEventListener("visibilitychange", listener);
|
|
6621
|
+
};
|
|
6622
|
+
}
|
|
6623
|
+
};
|
|
6624
|
+
}
|
|
6625
|
+
function parsedSummary(result) {
|
|
6626
|
+
if (result === null || typeof result !== "object" || !("ok" in result) || result.ok !== true) return;
|
|
6627
|
+
const parsed = ObserveSummaryV1Schema.safeParse("value" in result ? result.value : void 0);
|
|
6628
|
+
return parsed.success ? parsed.data : void 0;
|
|
6629
|
+
}
|
|
6630
|
+
var ObserveSummaryPoller = class {
|
|
6631
|
+
call;
|
|
6632
|
+
environment;
|
|
6028
6633
|
#listeners = /* @__PURE__ */ new Set();
|
|
6029
|
-
#
|
|
6030
|
-
#
|
|
6031
|
-
#
|
|
6032
|
-
#
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6634
|
+
#state = { phase: "LOADING" };
|
|
6635
|
+
#started = false;
|
|
6636
|
+
#disposed = false;
|
|
6637
|
+
#timer;
|
|
6638
|
+
#pending;
|
|
6639
|
+
#abort;
|
|
6640
|
+
#removeFocus;
|
|
6641
|
+
#removeVisibility;
|
|
6642
|
+
constructor(call, environment = browserEnvironment()) {
|
|
6643
|
+
this.call = call;
|
|
6644
|
+
this.environment = environment;
|
|
6039
6645
|
}
|
|
6040
|
-
|
|
6646
|
+
snapshot = () => this.#state;
|
|
6041
6647
|
subscribe = (listener) => {
|
|
6042
6648
|
this.#listeners.add(listener);
|
|
6043
6649
|
return () => {
|
|
6044
6650
|
this.#listeners.delete(listener);
|
|
6045
6651
|
};
|
|
6046
6652
|
};
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
this.#
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
this.#
|
|
6061
|
-
this.#
|
|
6653
|
+
start() {
|
|
6654
|
+
if (this.#started || this.#disposed) return;
|
|
6655
|
+
this.#started = true;
|
|
6656
|
+
this.#removeFocus = this.environment.onFocus(() => {
|
|
6657
|
+
if (this.environment.isVisible()) this.#refresh();
|
|
6658
|
+
});
|
|
6659
|
+
this.#removeVisibility = this.environment.onVisibilityChange(() => {
|
|
6660
|
+
if (this.environment.isVisible()) {
|
|
6661
|
+
this.#schedule();
|
|
6662
|
+
this.#refresh();
|
|
6663
|
+
} else this.#unschedule();
|
|
6664
|
+
});
|
|
6665
|
+
if (this.environment.isVisible()) {
|
|
6666
|
+
this.#schedule();
|
|
6667
|
+
this.#refresh();
|
|
6062
6668
|
}
|
|
6063
6669
|
}
|
|
6670
|
+
whenIdle() {
|
|
6671
|
+
return this.#pending ?? Promise.resolve();
|
|
6672
|
+
}
|
|
6064
6673
|
dispose() {
|
|
6065
|
-
this.#
|
|
6674
|
+
if (this.#disposed) return;
|
|
6675
|
+
this.#disposed = true;
|
|
6676
|
+
this.#unschedule();
|
|
6677
|
+
this.#removeFocus?.();
|
|
6678
|
+
this.#removeVisibility?.();
|
|
6679
|
+
this.#removeFocus = void 0;
|
|
6680
|
+
this.#removeVisibility = void 0;
|
|
6681
|
+
this.#abort?.abort();
|
|
6066
6682
|
this.#listeners.clear();
|
|
6067
6683
|
}
|
|
6068
|
-
#
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6684
|
+
#schedule() {
|
|
6685
|
+
if (this.#timer !== void 0 || this.#disposed) return;
|
|
6686
|
+
this.#timer = this.environment.setInterval(() => {
|
|
6687
|
+
this.#refresh();
|
|
6688
|
+
}, OBSERVE_SUMMARY_POLL_INTERVAL_MS);
|
|
6689
|
+
}
|
|
6690
|
+
#unschedule() {
|
|
6691
|
+
if (this.#timer === void 0) return;
|
|
6692
|
+
this.environment.clearInterval(this.#timer);
|
|
6693
|
+
this.#timer = void 0;
|
|
6694
|
+
}
|
|
6695
|
+
#refresh() {
|
|
6696
|
+
if (this.#disposed || this.#pending !== void 0 || !this.environment.isVisible()) return this.#pending ?? Promise.resolve();
|
|
6697
|
+
const abort = new AbortController();
|
|
6698
|
+
this.#abort = abort;
|
|
6699
|
+
const pending = (async () => {
|
|
6700
|
+
try {
|
|
6701
|
+
const summary = parsedSummary(await this.call({ apiVersion: 1 }, abort.signal));
|
|
6702
|
+
if (this.#disposed) return;
|
|
6703
|
+
if (summary === void 0) this.#markUnavailable();
|
|
6704
|
+
else this.#publish({
|
|
6705
|
+
phase: "READY",
|
|
6706
|
+
summary
|
|
6707
|
+
});
|
|
6708
|
+
} catch {
|
|
6709
|
+
if (!this.#disposed && !abort.signal.aborted) this.#markUnavailable();
|
|
6710
|
+
}
|
|
6711
|
+
})();
|
|
6712
|
+
this.#pending = pending;
|
|
6713
|
+
pending.finally(() => {
|
|
6714
|
+
if (this.#pending === pending) this.#pending = void 0;
|
|
6715
|
+
if (this.#abort === abort) this.#abort = void 0;
|
|
6076
6716
|
});
|
|
6717
|
+
return pending;
|
|
6077
6718
|
}
|
|
6078
|
-
#
|
|
6079
|
-
this.#
|
|
6719
|
+
#markUnavailable() {
|
|
6720
|
+
this.#publish("summary" in this.#state ? {
|
|
6721
|
+
phase: "STALE",
|
|
6722
|
+
summary: this.#state.summary
|
|
6723
|
+
} : { phase: "UNAVAILABLE" });
|
|
6724
|
+
}
|
|
6725
|
+
#publish(state) {
|
|
6726
|
+
this.#state = state;
|
|
6080
6727
|
for (const listener of this.#listeners) listener();
|
|
6081
6728
|
}
|
|
6082
6729
|
};
|
|
6083
|
-
function AutomaticLearningSettingsCard(props) {
|
|
6084
|
-
const state = (0, react.useSyncExternalStore)(props.controller.subscribe, props.controller.getSnapshot, props.controller.getSnapshot);
|
|
6085
|
-
const [open, setOpen] = (0, react.useState)(false);
|
|
6086
|
-
if (state.status === "unavailable") return null;
|
|
6087
|
-
const disabled = state.status !== "ready" || !state.writable || state.saving;
|
|
6088
|
-
return (0, react.createElement)("li", { "data-run2skill-settings-card": true }, (0, react.createElement)("button", {
|
|
6089
|
-
type: "button",
|
|
6090
|
-
"aria-expanded": open,
|
|
6091
|
-
onClick: () => {
|
|
6092
|
-
setOpen((value) => !value);
|
|
6093
|
-
}
|
|
6094
|
-
}, "run2skill", (0, react.createElement)("span", null, "将真实执行中的明确经验转为待审核 Skill Proposal")), open ? (0, react.createElement)("div", null, (0, react.createElement)("label", null, (0, react.createElement)("input", {
|
|
6095
|
-
type: "checkbox",
|
|
6096
|
-
checked: state.automaticLearning === true,
|
|
6097
|
-
disabled,
|
|
6098
|
-
onChange: (event) => {
|
|
6099
|
-
props.controller.setAutomaticLearning(event.currentTarget.checked);
|
|
6100
|
-
}
|
|
6101
|
-
}), "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);
|
|
6102
|
-
}
|
|
6103
|
-
function applyAutomaticLearningSettingsClient(context) {
|
|
6104
|
-
const controller = new AutomaticLearningSettingsController(context.settingsScope.bind({ namespace: "run2skill" }));
|
|
6105
|
-
const callPurge = async (endpoint, payload, signal) => await context.connection.rpc.call(RUN2SKILL_RPC_CHANNEL, endpoint, payload, signal);
|
|
6106
|
-
const purgeController = new PurgeSettingsController(callPurge, () => {
|
|
6107
|
-
return context.workspaces.list.getSnapshot().recentWorkspaceId;
|
|
6108
|
-
});
|
|
6109
|
-
purgeController.start();
|
|
6110
|
-
context.effect?.(() => () => {
|
|
6111
|
-
controller.dispose();
|
|
6112
|
-
purgeController.dispose();
|
|
6113
|
-
}, "run2skill: settings and purge");
|
|
6114
|
-
context.slots.inject("settings.plugin.item", () => context.slots.register({
|
|
6115
|
-
name: "settings.plugin.item",
|
|
6116
|
-
key: "run2skill",
|
|
6117
|
-
inject: () => ({
|
|
6118
|
-
controller,
|
|
6119
|
-
purgeController
|
|
6120
|
-
})
|
|
6121
|
-
}, AutomaticLearningSettingsCard));
|
|
6122
|
-
}
|
|
6123
6730
|
//#endregion
|
|
6124
6731
|
//#region src/client/index.ts
|
|
6125
6732
|
const name = "run2skill-client";
|
|
@@ -6127,19 +6734,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6127
6734
|
"connection",
|
|
6128
6735
|
"slots",
|
|
6129
6736
|
"workspaces",
|
|
6737
|
+
"sessions",
|
|
6130
6738
|
"remote",
|
|
6131
6739
|
"settingsScope"
|
|
6132
6740
|
];
|
|
6133
6741
|
function apply(context) {
|
|
6134
|
-
|
|
6135
|
-
applyAutomaticLearningSettingsClient(context);
|
|
6742
|
+
applyRun2skillClient(context);
|
|
6136
6743
|
}
|
|
6137
6744
|
//#endregion
|
|
6745
|
+
exports.AttentionSettingsSummary = AttentionSettingsSummary;
|
|
6138
6746
|
exports.AutomaticLearningSettingsCard = AutomaticLearningSettingsCard;
|
|
6139
6747
|
exports.AutomaticLearningSettingsController = AutomaticLearningSettingsController;
|
|
6748
|
+
exports.LearningFailureSection = LearningFailureSection;
|
|
6140
6749
|
exports.OBSERVE_SUMMARY_POLL_INTERVAL_MS = OBSERVE_SUMMARY_POLL_INTERVAL_MS;
|
|
6141
|
-
exports.ObserveHeaderAction = ObserveHeaderAction;
|
|
6142
|
-
exports.ObserveStatusPill = ObserveStatusPill;
|
|
6143
6750
|
exports.ObserveSummaryPoller = ObserveSummaryPoller;
|
|
6144
6751
|
exports.PROPOSAL_ACTIVE_POLL_INTERVAL_MS = PROPOSAL_ACTIVE_POLL_INTERVAL_MS;
|
|
6145
6752
|
exports.PROPOSAL_POLL_INTERVAL_MS = PROPOSAL_POLL_INTERVAL_MS;
|
|
@@ -6153,11 +6760,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6153
6760
|
exports.PurgeSettingsController = PurgeSettingsController;
|
|
6154
6761
|
exports.PurgeSettingsSection = PurgeSettingsSection;
|
|
6155
6762
|
exports.RejectConfirmationBody = RejectConfirmationBody;
|
|
6156
|
-
exports.
|
|
6763
|
+
exports.RejectProposalModal = RejectProposalModal;
|
|
6764
|
+
exports.Run2skillAttentionToast = Run2skillAttentionToast;
|
|
6765
|
+
exports.Run2skillSettingsPage = Run2skillSettingsPage;
|
|
6766
|
+
exports.actionableProposalItems = actionableProposalItems;
|
|
6157
6767
|
exports.apply = apply;
|
|
6158
6768
|
exports.applyAutomaticLearningSettingsClient = applyAutomaticLearningSettingsClient;
|
|
6159
|
-
exports.
|
|
6160
|
-
exports.describeObserveState = describeObserveState;
|
|
6769
|
+
exports.applyRun2skillClient = applyRun2skillClient;
|
|
6161
6770
|
exports.describeProcessingState = describeProcessingState;
|
|
6162
6771
|
exports.describeProposalListItem = describeProposalListItem;
|
|
6163
6772
|
exports.describeProposalOutcome = describeProposalOutcome;
|
|
@@ -6166,10 +6775,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6166
6775
|
exports.describeReviewDecision = describeReviewDecision;
|
|
6167
6776
|
exports.describeRun2skillHealth = describeRun2skillHealth;
|
|
6168
6777
|
exports.factsFromAction = factsFromAction;
|
|
6778
|
+
exports.hostTabVisible = hostTabVisible;
|
|
6169
6779
|
exports.inject = inject;
|
|
6170
6780
|
exports.makeExactLineDiff = makeExactLineDiff;
|
|
6171
6781
|
exports.makeSafeText = makeSafeText;
|
|
6172
6782
|
exports.name = name;
|
|
6783
|
+
exports.proposalDetailAction = proposalDetailAction;
|
|
6173
6784
|
exports.proposalInboxContentBlocked = proposalInboxContentBlocked;
|
|
6174
6785
|
exports.trapDialogTab = trapDialogTab;
|
|
6175
6786
|
return module.exports;
|