@godv61/dsh-task-engine 0.30.0 → 0.30.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -38,7 +38,7 @@ __export(index_exports, {
38
38
  });
39
39
  module.exports = __toCommonJS(index_exports);
40
40
 
41
- // ../../dsharness/task-en/node_modules/zod/v3/external.js
41
+ // node_modules/zod/v3/external.js
42
42
  var external_exports = {};
43
43
  __export(external_exports, {
44
44
  BRAND: () => BRAND,
@@ -150,7 +150,7 @@ __export(external_exports, {
150
150
  void: () => voidType
151
151
  });
152
152
 
153
- // ../../dsharness/task-en/node_modules/zod/v3/helpers/util.js
153
+ // node_modules/zod/v3/helpers/util.js
154
154
  var util;
155
155
  (function(util2) {
156
156
  util2.assertEqual = (_) => {
@@ -284,7 +284,7 @@ var getParsedType = (data) => {
284
284
  }
285
285
  };
286
286
 
287
- // ../../dsharness/task-en/node_modules/zod/v3/ZodError.js
287
+ // node_modules/zod/v3/ZodError.js
288
288
  var ZodIssueCode = util.arrayToEnum([
289
289
  "invalid_type",
290
290
  "invalid_literal",
@@ -402,7 +402,7 @@ ZodError.create = (issues) => {
402
402
  return error;
403
403
  };
404
404
 
405
- // ../../dsharness/task-en/node_modules/zod/v3/locales/en.js
405
+ // node_modules/zod/v3/locales/en.js
406
406
  var errorMap = (issue, _ctx) => {
407
407
  let message;
408
408
  switch (issue.code) {
@@ -505,7 +505,7 @@ var errorMap = (issue, _ctx) => {
505
505
  };
506
506
  var en_default = errorMap;
507
507
 
508
- // ../../dsharness/task-en/node_modules/zod/v3/errors.js
508
+ // node_modules/zod/v3/errors.js
509
509
  var overrideErrorMap = en_default;
510
510
  function setErrorMap(map) {
511
511
  overrideErrorMap = map;
@@ -514,7 +514,7 @@ function getErrorMap() {
514
514
  return overrideErrorMap;
515
515
  }
516
516
 
517
- // ../../dsharness/task-en/node_modules/zod/v3/helpers/parseUtil.js
517
+ // node_modules/zod/v3/helpers/parseUtil.js
518
518
  var makeIssue = (params) => {
519
519
  const { data, path, errorMaps, issueData } = params;
520
520
  const fullPath = [...path, ...issueData.path || []];
@@ -624,14 +624,14 @@ var isDirty = (x) => x.status === "dirty";
624
624
  var isValid = (x) => x.status === "valid";
625
625
  var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
626
626
 
627
- // ../../dsharness/task-en/node_modules/zod/v3/helpers/errorUtil.js
627
+ // node_modules/zod/v3/helpers/errorUtil.js
628
628
  var errorUtil;
629
629
  (function(errorUtil2) {
630
630
  errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
631
631
  errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
632
632
  })(errorUtil || (errorUtil = {}));
633
633
 
634
- // ../../dsharness/task-en/node_modules/zod/v3/types.js
634
+ // node_modules/zod/v3/types.js
635
635
  var ParseInputLazyPath = class {
636
636
  constructor(parent, value, path, key) {
637
637
  this._cachedPath = [];
@@ -4267,6 +4267,7 @@ var taskLedgerViewSchema = external_exports.object({
4267
4267
  })).optional(),
4268
4268
  report_path: external_exports.string().optional(),
4269
4269
  scanned_files: external_exports.array(external_exports.string()).optional(),
4270
+ profile_coverage: external_exports.array(external_exports.object({ language: external_exports.string(), active_rules: external_exports.number(), analyzer: external_exports.string() })).optional(),
4270
4271
  findings: external_exports.array(external_exports.object({
4271
4272
  key: external_exports.string(),
4272
4273
  rule: external_exports.string(),
@@ -4309,6 +4310,35 @@ var initDraftSchema = external_exports.object({
4309
4310
  lines: external_exports.number(),
4310
4311
  error: external_exports.string().optional()
4311
4312
  });
4313
+ var projectInitResourceSchema = external_exports.object({
4314
+ kind: external_exports.enum(["skill", "rule"]),
4315
+ name: external_exports.string(),
4316
+ description: external_exports.string().optional(),
4317
+ content: external_exports.string(),
4318
+ meta_skills: external_exports.array(external_exports.string()).optional(),
4319
+ rules: external_exports.array(external_exports.string()).optional()
4320
+ });
4321
+ var projectInitInventorySchema = external_exports.object({
4322
+ project_name: external_exports.string(),
4323
+ root_entries: external_exports.array(external_exports.string()),
4324
+ modules: external_exports.array(external_exports.object({ path: external_exports.string(), entries: external_exports.array(external_exports.string()) })),
4325
+ manifests: external_exports.array(external_exports.object({ path: external_exports.string(), facts: external_exports.array(external_exports.string()) })),
4326
+ suggestions: external_exports.array(external_exports.object({ name: external_exports.string(), kind: external_exports.enum(["skill", "rule"]), meta_skills: external_exports.array(external_exports.string()), why: external_exports.string() })),
4327
+ caution: external_exports.string()
4328
+ });
4329
+ var projectInitPreviewRequestSchema = external_exports.object({ path: external_exports.string(), resources: external_exports.array(projectInitResourceSchema) });
4330
+ var projectInitPreviewSchema = external_exports.object({
4331
+ ok: external_exports.boolean(),
4332
+ inventory: projectInitInventorySchema,
4333
+ resources: external_exports.array(projectInitResourceSchema),
4334
+ files_to_create: external_exports.array(external_exports.string()),
4335
+ project_map_coverage: external_exports.array(external_exports.string()),
4336
+ existing_hash: external_exports.string(),
4337
+ expected_hash: external_exports.string(),
4338
+ error: external_exports.string().optional()
4339
+ });
4340
+ var projectInitApplyRequestSchema = projectInitPreviewRequestSchema.extend({ expected_hash: external_exports.string(), existing_hash: external_exports.string() });
4341
+ var projectInitApplyResultSchema = external_exports.object({ ok: external_exports.boolean(), created: external_exports.array(external_exports.string()), error: external_exports.string().optional() });
4312
4342
  var resourceRequestSchema = external_exports.object({
4313
4343
  kind: external_exports.enum(["skill", "rule"]),
4314
4344
  level: external_exports.enum(["project", "user"]),
@@ -4345,6 +4375,11 @@ var adaptiveViewSchema = external_exports.object({
4345
4375
  var adaptiveWriteRequestSchema = external_exports.object({ path: external_exports.string(), config: adaptiveConfigSchema, expected_hash: external_exports.string() });
4346
4376
  var sonarTokenInfoSchema = external_exports.object({ configured: external_exports.boolean(), source: external_exports.string().optional(), writable: external_exports.boolean() });
4347
4377
  var sonarTokenWriteSchema = external_exports.object({ path: external_exports.string(), token: external_exports.string().min(1) });
4378
+ var sonarAnalyzerStatusSchema = external_exports.object({ profiles: external_exports.array(external_exports.object({
4379
+ language: external_exports.string(),
4380
+ active_rules: external_exports.number(),
4381
+ analyzer: external_exports.string()
4382
+ })) });
4348
4383
  var projectSkillProfileRequestSchema = external_exports.object({ path: external_exports.string(), name: external_exports.string() });
4349
4384
  var projectSkillProfileWriteRequestSchema = projectSkillProfileRequestSchema.extend({
4350
4385
  profile: skillProfileSchema,
@@ -4425,6 +4460,25 @@ var TYPERT_REMOTE = {
4425
4460
  }],
4426
4461
  result: { mode: "strict", typeSymbol: `${PACKAGE}/types#SonarTokenInfo`, create: () => sonarTokenInfoSchema, schema: sonarTokenInfoSchema }
4427
4462
  },
4463
+ {
4464
+ id: `${PACKAGE}#task-engine/prepareSonarAnalyzer`,
4465
+ service: "taskEngineController",
4466
+ namespace: "task-engine",
4467
+ method: "prepareSonarAnalyzer",
4468
+ invocation: { kind: "direct" },
4469
+ parameters: [{
4470
+ name: "path",
4471
+ wire: "path",
4472
+ source: "json",
4473
+ codec: { mode: "strict", typeSymbol: "string", create: () => external_exports.string(), schema: external_exports.string() }
4474
+ }],
4475
+ result: {
4476
+ mode: "strict",
4477
+ typeSymbol: `${PACKAGE}/types#SonarAnalyzerStatus`,
4478
+ create: () => sonarAnalyzerStatusSchema,
4479
+ schema: sonarAnalyzerStatusSchema
4480
+ }
4481
+ },
4428
4482
  {
4429
4483
  id: `${PACKAGE}#task-engine/readProjectSkillProfile`,
4430
4484
  service: "taskEngineController",
@@ -4740,6 +4794,48 @@ var TYPERT_REMOTE = {
4740
4794
  }
4741
4795
  ],
4742
4796
  result: { mode: "strict", typeSymbol: `${PACKAGE}/types#InitDraft`, create: () => initDraftSchema, schema: initDraftSchema }
4797
+ },
4798
+ {
4799
+ id: `${PACKAGE}#task-engine/generateProjectInit`,
4800
+ service: "taskEngineController",
4801
+ namespace: "task-engine",
4802
+ method: "generateProjectInit",
4803
+ invocation: { kind: "direct" },
4804
+ parameters: [{
4805
+ name: "request",
4806
+ wire: "request",
4807
+ source: "json",
4808
+ codec: { mode: "strict", typeSymbol: `${PACKAGE}/types#InitGenerateRequest`, create: () => initGenerateRequestSchema, schema: initGenerateRequestSchema }
4809
+ }],
4810
+ result: { mode: "strict", typeSymbol: `${PACKAGE}/types#ProjectInitPreview`, create: () => projectInitPreviewSchema, schema: projectInitPreviewSchema }
4811
+ },
4812
+ {
4813
+ id: `${PACKAGE}#task-engine/previewProjectInit`,
4814
+ service: "taskEngineController",
4815
+ namespace: "task-engine",
4816
+ method: "previewProjectInit",
4817
+ invocation: { kind: "direct" },
4818
+ parameters: [{
4819
+ name: "request",
4820
+ wire: "request",
4821
+ source: "json",
4822
+ codec: { mode: "strict", typeSymbol: `${PACKAGE}/types#ProjectInitPreviewRequest`, create: () => projectInitPreviewRequestSchema, schema: projectInitPreviewRequestSchema }
4823
+ }],
4824
+ result: { mode: "strict", typeSymbol: `${PACKAGE}/types#ProjectInitPreview`, create: () => projectInitPreviewSchema, schema: projectInitPreviewSchema }
4825
+ },
4826
+ {
4827
+ id: `${PACKAGE}#task-engine/applyProjectInit`,
4828
+ service: "taskEngineController",
4829
+ namespace: "task-engine",
4830
+ method: "applyProjectInit",
4831
+ invocation: { kind: "direct" },
4832
+ parameters: [{
4833
+ name: "request",
4834
+ wire: "request",
4835
+ source: "json",
4836
+ codec: { mode: "strict", typeSymbol: `${PACKAGE}/types#ProjectInitApplyRequest`, create: () => projectInitApplyRequestSchema, schema: projectInitApplyRequestSchema }
4837
+ }],
4838
+ result: { mode: "strict", typeSymbol: `${PACKAGE}/types#ProjectInitApplyResult`, create: () => projectInitApplyResultSchema, schema: projectInitApplyResultSchema }
4743
4839
  }
4744
4840
  ]
4745
4841
  };
@@ -4763,7 +4859,6 @@ var workbenchTheme = `
4763
4859
  .te-workbench h2 { margin:0 0 6px; font-size:24px; letter-spacing:-.5px; }
4764
4860
  .te-workbench h3,.te-modal h3 { margin:0; font-size:16px; overflow-wrap:anywhere; }
4765
4861
  .te-config-layout { display:grid; grid-template-columns:minmax(0,1fr); gap:16px; align-items:start; width:100%; }
4766
- .te-config-layout.is-open { grid-template-columns:minmax(0,1fr) minmax(320px,420px); }
4767
4862
  .te-config-main { min-width:0; }
4768
4863
  .te-inline-panel { position:sticky !important; top:12px; min-width:0; }
4769
4864
  .te-flow-notice { margin:0; padding:10px 12px; border:1px solid var(--dsw-alias-state-warn-primary); border-radius:8px; font-size:13px; }
@@ -4819,10 +4914,28 @@ var workbenchTheme = `
4819
4914
  .te-skill-evidence { display:flex; align-items:center; justify-content:space-between; gap:12px; font-size:13px; font-weight:600; }
4820
4915
  .te-skill-evidence .te-input { min-width:210px; }
4821
4916
  .te-skill-rule-list { display:flex; flex:1; flex-direction:column; gap:4px; min-height:0; overflow:auto; padding:4px; }
4917
+ .te-rule-filters { display:flex; gap:6px; flex-wrap:wrap; }
4918
+ .te-rule-filter { border:1px solid var(--dsw-alias-border-l2); border-radius:999px; padding:5px 10px; background:var(--dsw-alias-bg-layer-1); color:var(--dsw-alias-label-secondary); cursor:pointer; font-size:12px; }
4919
+ .te-rule-filter[aria-pressed="true"] { border-color:var(--dsw-alias-state-business-primary); color:var(--dsw-alias-state-business-primary); }
4822
4920
  .te-skill-rule-row { display:flex; align-items:center; gap:10px; padding:9px 10px; border:1px solid var(--dsw-alias-border-l2); border-radius:8px; cursor:pointer; }
4921
+ .te-skill-rule-row:has(input:checked) { border-color:var(--dsw-alias-state-business-primary); background:var(--dsw-alias-bg-layer-1); }
4823
4922
  .te-skill-rule-row:hover { background:var(--dsw-alias-bg-layer-1); }
4824
4923
  .te-skill-rule-row span { flex:1; min-width:0; overflow-wrap:anywhere; }
4825
4924
  .te-skill-rule-row small { color:var(--dsw-alias-label-secondary); }
4925
+ .te-meta-layout { display:grid; grid-template-columns:minmax(170px,220px) minmax(0,1fr); gap:14px; align-items:start; }
4926
+ .te-meta-nav { display:flex; flex-direction:column; gap:6px; min-width:0; }
4927
+ .te-meta-nav button { width:100%; border:1px solid var(--dsw-alias-border-l2); border-radius:9px; background:var(--dsw-alias-bg-layer-1); color:var(--dsw-alias-label-primary); text-align:left; padding:10px 12px; cursor:pointer; }
4928
+ .te-meta-nav button[aria-current="true"] { border-color:var(--dsw-alias-state-business-primary); color:var(--dsw-alias-state-business-primary); }
4929
+ .te-meta-nav small { display:block; color:var(--dsw-alias-label-secondary); margin-top:3px; }
4930
+ .te-meta-detail { min-width:0; border:1px solid var(--dsw-alias-border-l2); border-radius:12px; padding:16px; display:flex; flex-direction:column; gap:14px; }
4931
+ .te-meta-skill-row { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 12px; border:1px solid var(--dsw-alias-border-l2); border-radius:9px; }
4932
+ .te-meta-skill-row>span { min-width:0; overflow-wrap:anywhere; }
4933
+ .te-meta-skill-actions { display:flex; align-items:center; gap:6px; flex:none; }
4934
+ .te-meta-candidates { display:flex; flex-direction:column; gap:4px; max-height:230px; overflow:auto; }
4935
+ .te-meta-candidate { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:8px 10px; border:1px solid var(--dsw-alias-border-l2); border-radius:8px; }
4936
+ .te-meta-candidate span { min-width:0; overflow-wrap:anywhere; }
4937
+ .te-meta-candidate small { display:block; color:var(--dsw-alias-label-secondary); font-size:11px; }
4938
+ .te-adaptive-savebar { position:sticky; bottom:0; z-index:3; display:flex; align-items:center; gap:10px; flex-wrap:wrap; padding:12px 16px; border:1px solid var(--dsw-alias-border-l2); border-radius:10px; background:var(--dsw-alias-bg-layer-2); box-shadow:var(--dsw-elevation-prominent); }
4826
4939
  .te-workbench p,.te-modal p { color:var(--dsw-alias-label-secondary); line-height:1.65; }
4827
4940
  .te-content { max-width:1600px; margin:auto; width:100%; }
4828
4941
  .te-resource { display:flex; flex-direction:column; gap:20px; }
@@ -4863,8 +4976,8 @@ var workbenchTheme = `
4863
4976
  .te-form { display:flex; flex-direction:column; gap:16px; }
4864
4977
  .te-form label { display:flex; flex-direction:column; gap:8px; font-size:13px; }
4865
4978
  .te-editor { min-height:260px; resize:vertical; line-height:1.6; font-family:monospace; }
4866
- @media(max-width:760px) { .te-transfer {grid-template-columns:1fr;} .te-transfer-arrow {transform:rotate(90deg); height:20px;} .te-transfer-list {max-height:210px;} }
4867
- @media(max-width:1000px) { .te-config-layout.is-open { grid-template-columns:minmax(0,1fr); } .te-inline-panel { position:static !important; height:min(600px,calc(100vh - 32px)) !important; } }
4979
+ @media(max-width:760px) { .te-transfer {grid-template-columns:1fr;} .te-transfer-arrow {transform:rotate(90deg); height:20px;} .te-transfer-list {max-height:210px;} .te-meta-layout {grid-template-columns:1fr;} .te-meta-nav {display:grid; grid-template-columns:repeat(2,minmax(0,1fr));} }
4980
+ @media(max-width:1000px) { .te-inline-panel { position:static !important; height:min(600px,calc(100vh - 32px)) !important; } }
4868
4981
  @media(max-width:640px) { .te-targets {grid-template-columns:1fr;} .te-resource {gap:14px;} .te-section-heading h2 {font-size:21px;} .te-modal:not(.te-drawer) {padding:10px !important;} .te-drawer [role=dialog] {border-radius:0 !important;} .te-skill-evidence {align-items:stretch; flex-direction:column;} .te-skill-evidence .te-input {min-width:0;} }
4869
4982
  `;
4870
4983
 
@@ -5205,6 +5318,7 @@ function SkillRuleDialog({ skill, profile, rules, description, saveLabel, onSave
5205
5318
  const [draftRules, setDraftRules] = (0, import_react2.useState)(profile?.rules ?? []);
5206
5319
  const [evidence, setEvidence] = (0, import_react2.useState)(profile?.evidence ?? "");
5207
5320
  const [query, setQuery] = (0, import_react2.useState)("");
5321
+ const [filter, setFilter] = (0, import_react2.useState)("all");
5208
5322
  const [dirty, setDirty] = (0, import_react2.useState)(false);
5209
5323
  const [busy, setBusy] = (0, import_react2.useState)(false);
5210
5324
  const [error, setError] = (0, import_react2.useState)("");
@@ -5231,17 +5345,20 @@ function SkillRuleDialog({ skill, profile, rules, description, saveLabel, onSave
5231
5345
  setBusy(false);
5232
5346
  }
5233
5347
  };
5348
+ const selectedKeys = new Set(draftRules.map(formatResourceRef));
5234
5349
  const filtered = rules.filter((rule) => {
5235
5350
  const key = formatResourceRef(rule.ref);
5236
- const chosen = draftRules.some((item) => formatResourceRef(item) === key);
5237
- return chosen || `${rule.name} ${rule.sourceLabel}`.toLowerCase().includes(query.trim().toLowerCase());
5238
- });
5351
+ const chosen = selectedKeys.has(key);
5352
+ const matches = `${rule.name} ${rule.sourceLabel} ${rule.source}`.toLowerCase().includes(query.trim().toLowerCase());
5353
+ return matches && (filter === "all" || filter === "selected" && chosen || filter === "project" && (rule.ref.source === "project" || rule.ref.source === "codex-project") || filter === "user" && rule.ref.source === "user" || filter === "bundled" && rule.ref.source === "bundled");
5354
+ }).sort((a, b) => Number(selectedKeys.has(formatResourceRef(b.ref))) - Number(selectedKeys.has(formatResourceRef(a.ref))) || a.name.localeCompare(b.name));
5239
5355
  const catalogKeys = new Set(rules.map((rule) => formatResourceRef(rule.ref)));
5240
5356
  const missingRules = draftRules.filter((rule) => !catalogKeys.has(formatResourceRef(rule)));
5357
+ const visibleMissing = missingRules.filter((rule) => (filter === "all" || filter === "selected") && rule.name.toLowerCase().includes(query.trim().toLowerCase()));
5241
5358
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5242
5359
  ResourceModal,
5243
5360
  {
5244
- placement: "inline",
5361
+ placement: "right",
5245
5362
  title: `\u914D\u7F6E\u89C4\u5219 \xB7 ${skill.name}`,
5246
5363
  description: description ?? "\u89C4\u5219\u5C5E\u4E8E\u6280\u80FD\uFF1B\u6B64\u5904\u7684\u914D\u7F6E\u4F1A\u7528\u4E8E\u6240\u6709\u7ED1\u5B9A\u8BE5\u6280\u80FD\u7684\u8282\u70B9\u3002",
5247
5364
  onClose: close,
@@ -5275,10 +5392,21 @@ function SkillRuleDialog({ skill, profile, rules, description, saveLabel, onSave
5275
5392
  ] })
5276
5393
  ] }),
5277
5394
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { className: "te-input", type: "search", "aria-label": "\u641C\u7D22\u89C4\u5219", placeholder: "\u641C\u7D22\u89C4\u5219\u540D\u79F0\u6216\u6765\u6E90", value: query, onChange: (event) => setQuery(event.target.value) }),
5395
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "te-rule-filters", role: "group", "aria-label": "\u7B5B\u9009\u89C4\u5219", children: [["all", "\u5168\u90E8"], ["selected", `\u5DF2\u9009 ${draftRules.length}`], ["project", "\u9879\u76EE"], ["user", "\u7528\u6237"], ["bundled", "\u5185\u7F6E"]].map(([value, label3]) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5396
+ "button",
5397
+ {
5398
+ type: "button",
5399
+ "aria-pressed": filter === value,
5400
+ className: "te-rule-filter",
5401
+ onClick: () => setFilter(value),
5402
+ children: label3
5403
+ },
5404
+ value
5405
+ )) }),
5278
5406
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "te-skill-rule-list", role: "group", "aria-label": "\u89C4\u5219\u5217\u8868", children: [
5279
5407
  rules.length === 0 && missingRules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "te-binding-empty", children: "\u89C4\u5219\u5E93\u4E3A\u7A7A\uFF0C\u8BF7\u5148\u5230\u201C\u89C4\u5219\u201D\u9875\u521B\u5EFA\u6216\u5B89\u88C5\u3002" }) : null,
5280
- rules.length > 0 && filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "te-binding-empty", children: "\u6CA1\u6709\u5339\u914D\u7684\u89C4\u5219\u3002" }) : null,
5281
- missingRules.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-skill-rule-row", children: [
5408
+ rules.length > 0 && filtered.length === 0 && visibleMissing.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "te-binding-empty", children: "\u6CA1\u6709\u5339\u914D\u7684\u89C4\u5219\u3002" }) : null,
5409
+ visibleMissing.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-skill-rule-row", children: [
5282
5410
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: true, onChange: () => toggle(rule) }),
5283
5411
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: rule.name }),
5284
5412
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("small", { children: [
@@ -5288,7 +5416,7 @@ function SkillRuleDialog({ skill, profile, rules, description, saveLabel, onSave
5288
5416
  ] }, formatResourceRef(rule))),
5289
5417
  filtered.map((rule) => {
5290
5418
  const key = formatResourceRef(rule.ref);
5291
- const checked = draftRules.some((item) => formatResourceRef(item) === key);
5419
+ const checked = selectedKeys.has(key);
5292
5420
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "te-skill-rule-row", children: [
5293
5421
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked, onChange: () => toggle(rule.ref) }),
5294
5422
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: rule.name }),
@@ -5323,7 +5451,7 @@ var input = {
5323
5451
  };
5324
5452
  var SOURCE_ORDER = ["project", "codex-project", "user", "bundled"];
5325
5453
  function effectiveSource(entries, name) {
5326
- return entries.filter((entry) => entry.name === name).sort((a, b) => SOURCE_ORDER.indexOf(a.source) - SOURCE_ORDER.indexOf(b.source))[0]?.source ?? "\u7F3A\u5931";
5454
+ return entries.filter((entry) => entry.name === name).sort((a, b) => SOURCE_ORDER.indexOf(a.source) - SOURCE_ORDER.indexOf(b.source))[0]?.sourceLabel ?? "\u7F3A\u5931";
5327
5455
  }
5328
5456
  function AdaptivePanel({ workspace, remote, onOpenInit }) {
5329
5457
  const [view, setView] = (0, import_react3.useState)(null);
@@ -5331,6 +5459,9 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5331
5459
  const [skills, setSkills] = (0, import_react3.useState)([]);
5332
5460
  const [rules, setRules] = (0, import_react3.useState)([]);
5333
5461
  const [selected, setSelected] = (0, import_react3.useState)(null);
5462
+ const [activeMeta, setActiveMeta] = (0, import_react3.useState)("requirements-analysis");
5463
+ const [metaQuery, setMetaQuery] = (0, import_react3.useState)("");
5464
+ const [skillQuery, setSkillQuery] = (0, import_react3.useState)("");
5334
5465
  const [loading, setLoading] = (0, import_react3.useState)(true);
5335
5466
  const [saving, setSaving] = (0, import_react3.useState)(false);
5336
5467
  const [dirty, setDirty] = (0, import_react3.useState)(false);
@@ -5338,11 +5469,14 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5338
5469
  const [sonarToken, setSonarToken] = (0, import_react3.useState)("");
5339
5470
  const [tokenInfo, setTokenInfo] = (0, import_react3.useState)(null);
5340
5471
  const [tokenBusy, setTokenBusy] = (0, import_react3.useState)(false);
5472
+ const [analyzerBusy, setAnalyzerBusy] = (0, import_react3.useState)(false);
5473
+ const [analyzerProfiles, setAnalyzerProfiles] = (0, import_react3.useState)(null);
5341
5474
  const refresh = (0, import_react3.useCallback)(() => {
5342
5475
  setLoading(true);
5343
5476
  setMessage("");
5344
5477
  setSonarToken("");
5345
5478
  setTokenInfo(null);
5479
+ setAnalyzerProfiles(null);
5346
5480
  void remote.describeSonarToken(workspace).then((result) => {
5347
5481
  if (result.ok) setTokenInfo(result.value);
5348
5482
  }, () => {
@@ -5389,7 +5523,15 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5389
5523
  update({ ...draft, meta_bindings });
5390
5524
  };
5391
5525
  const updateSonar = (patch) => {
5392
- update({ ...draft, sonar: { mode: "branch", token_env: "SONAR_TOKEN", ...draft.sonar, ...patch } });
5526
+ update({ ...draft, sonar: {
5527
+ ...draft.sonar,
5528
+ ...patch,
5529
+ source: "ide-local",
5530
+ mode: "branch",
5531
+ token_env: draft.sonar?.token_env ?? "SONAR_TOKEN",
5532
+ reference_branch: patch.reference_branch ?? draft.sonar?.reference_branch ?? "HEAD",
5533
+ scan_command: void 0
5534
+ } });
5393
5535
  };
5394
5536
  const openRules = (name) => {
5395
5537
  setMessage("");
@@ -5464,7 +5606,14 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5464
5606
  const save = () => {
5465
5607
  if (!view) return;
5466
5608
  setSaving(true);
5467
- void remote.writeAdaptive({ path: workspace, config: draft, expected_hash: view.hash }).then((result) => {
5609
+ const config = { ...draft, ...draft.sonar?.enabled ? { sonar: {
5610
+ ...draft.sonar,
5611
+ source: "ide-local",
5612
+ mode: "branch",
5613
+ reference_branch: draft.sonar.reference_branch?.trim() || "HEAD",
5614
+ scan_command: void 0
5615
+ } } : {} };
5616
+ void remote.writeAdaptive({ path: workspace, config, expected_hash: view.hash }).then((result) => {
5468
5617
  setSaving(false);
5469
5618
  if (!result.ok) {
5470
5619
  setMessage("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(result.error));
@@ -5516,7 +5665,34 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5516
5665
  setMessage("\u79FB\u9664 SonarQube Token \u5931\u8D25\uFF1A" + describeError(error));
5517
5666
  });
5518
5667
  };
5668
+ const prepareAnalyzer = () => {
5669
+ if (dirty) {
5670
+ setMessage("\u8BF7\u5148\u4FDD\u5B58 SonarQube \u5BA1\u6838\u914D\u7F6E\uFF0C\u518D\u68C0\u67E5\u672C\u5730\u5206\u6790\u5668\u3002");
5671
+ return;
5672
+ }
5673
+ setAnalyzerBusy(true);
5674
+ setAnalyzerProfiles(null);
5675
+ setMessage("\u6B63\u5728\u5B89\u88C5\u6216\u68C0\u67E5\u672C\u5730\u5206\u6790\u5668\uFF0C\u5E76\u8FDE\u63A5\u5F53\u524D\u9879\u76EE\u7684 SonarQube\uFF1B\u9996\u6B21\u4E0B\u8F7D\u53EF\u80FD\u9700\u8981\u8F83\u957F\u65F6\u95F4\u3002");
5676
+ void remote.prepareSonarAnalyzer(workspace).then((result) => {
5677
+ setAnalyzerBusy(false);
5678
+ if (!result.ok) {
5679
+ setMessage("\u672C\u5730\u5206\u6790\u5668\u68C0\u67E5\u5931\u8D25\uFF1A" + describeError(result.error));
5680
+ return;
5681
+ }
5682
+ setAnalyzerProfiles(result.value.profiles);
5683
+ setMessage("\u5DF2\u8FDE\u63A5 SonarQube\uFF1B\u8BF7\u67E5\u770B\u4E0B\u65B9\u5404\u8BED\u8A00\u7684\u672C\u5730\u5206\u6790\u5668\u72B6\u6001\u3002");
5684
+ }, (error) => {
5685
+ setAnalyzerBusy(false);
5686
+ setMessage("\u672C\u5730\u5206\u6790\u5668\u68C0\u67E5\u5931\u8D25\uFF1A" + describeError(error));
5687
+ });
5688
+ };
5519
5689
  const candidates = [...new Set(skills.map((skill) => skill.name))].filter((name) => name !== "eng-delivery" && !(name in META_STAGES)).sort();
5690
+ const stageQuery = metaQuery.trim().toLowerCase();
5691
+ const visibleStages = Object.entries(META_STAGES).filter(([id, stage]) => !stageQuery || `${id} ${stage} ${(draft.meta_bindings?.[id] ?? []).join(" ")}`.toLowerCase().includes(stageQuery));
5692
+ const visibleMeta = visibleStages.find(([id]) => id === activeMeta)?.[0] ?? visibleStages[0]?.[0];
5693
+ const mounted = visibleMeta ? draft.meta_bindings?.[visibleMeta] ?? [] : [];
5694
+ const candidateQuery = skillQuery.trim().toLowerCase();
5695
+ const matchingCandidates = candidates.filter((name) => !mounted.includes(name) && (!candidateQuery || name.toLowerCase().includes(candidateQuery) || skills.some((skill) => skill.name === name && `${skill.description} ${skill.sourceLabel}`.toLowerCase().includes(candidateQuery))));
5520
5696
  const sonar = draft.sonar ?? {};
5521
5697
  return (0, import_react3.createElement)(
5522
5698
  "div",
@@ -5528,10 +5704,10 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5528
5704
  (0, import_react3.createElement)("span", { style: label }, "\u626B\u63CF\u9879\u76EE\u540E\u5148\u9884\u89C8\uFF0C\u786E\u8BA4\u540E\u5199\u5165\u3002")
5529
5705
  ),
5530
5706
  (0, import_react3.createElement)(
5531
- "div",
5707
+ "details",
5532
5708
  { style: card },
5533
- (0, import_react3.createElement)("strong", null, "\u6309\u9700\u6C42\u9009\u62E9\u6D41\u7A0B"),
5534
- (0, import_react3.createElement)("span", { style: label }, "\u6BCF\u4E2A\u4EFB\u52A1\u7531\u5927\u6A21\u578B\u5206\u6790\u540E\u9009\u62E9\u590D\u6742\u5EA6\uFF0C\u4EFB\u52A1\u521B\u5EFA\u65F6\u51BB\u7ED3\u9636\u6BB5\u548C\u751F\u6548\u6280\u80FD\uFF1B\u4E0D\u540C\u4F1A\u8BDD\u53EF\u8D70\u4E0D\u540C\u6D41\u7A0B\u3002\u98CE\u9669\u7B49\u7EA7\u72EC\u7ACB\u5224\u65AD\u3002"),
5709
+ (0, import_react3.createElement)("summary", { style: { cursor: "pointer", fontWeight: 600 } }, "\u6309\u9700\u6C42\u9009\u62E9\u6D41\u7A0B \xB7 \u67E5\u770B\u56DB\u6863\u9636\u6BB5"),
5710
+ (0, import_react3.createElement)("span", { style: label }, "\u6BCF\u4E2A\u4EFB\u52A1\u5355\u72EC\u9009\u62E9\u590D\u6742\u5EA6\u5E76\u51BB\u7ED3\u9636\u6BB5\u548C\u6280\u80FD\uFF1B\u4E0D\u540C\u4F1A\u8BDD\u53EF\u8D70\u4E0D\u540C\u6D41\u7A0B\u3002"),
5535
5711
  (0, import_react3.createElement)("div", { style: grid }, ...(view?.grades ?? []).map((grade) => (0, import_react3.createElement)(
5536
5712
  "div",
5537
5713
  { key: grade.id, style: { ...card, gap: 5 } },
@@ -5545,45 +5721,111 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5545
5721
  { style: card },
5546
5722
  (0, import_react3.createElement)("strong", null, "\u5143\u6280\u80FD\u4E0E\u9879\u76EE\u6280\u80FD"),
5547
5723
  (0, import_react3.createElement)("span", { style: label }, "\u6BCF\u4E2A\u5143\u6280\u80FD\u59CB\u7EC8\u52A0\u8F7D\u540C\u540D\u6838\u5FC3 Skill\uFF1B\u540C\u540D\u9879\u76EE Skill \u8986\u76D6\u7528\u6237\u4E0E\u5185\u7F6E\u7248\u672C\u3002\u9644\u52A0\u6280\u80FD\u6309\u540D\u79F0\u6302\u8F7D\uFF0C\u5B9E\u9645\u6765\u6E90\u5728\u4EFB\u52A1\u521B\u5EFA\u65F6\u89E3\u6790\u3002Rule \u4FDD\u5B58\u5728\u5BF9\u5E94 Skill \u7684 profile.json\u3002"),
5548
- ...Object.entries(META_STAGES).map(([id, stage]) => {
5549
- const meta = id;
5550
- const selected2 = draft.meta_bindings?.[meta] ?? [];
5551
- return (0, import_react3.createElement)(
5724
+ (0, import_react3.createElement)("input", {
5725
+ className: "te-input",
5726
+ type: "search",
5727
+ "aria-label": "\u641C\u7D22\u5143\u6280\u80FD\u6216\u5DF2\u6302\u8F7D\u6280\u80FD",
5728
+ placeholder: "\u641C\u7D22\u9636\u6BB5\u6216\u5DF2\u6302\u8F7D\u7684 Skill",
5729
+ value: metaQuery,
5730
+ onChange: (event) => setMetaQuery(event.target.value)
5731
+ }),
5732
+ (0, import_react3.createElement)(
5733
+ "div",
5734
+ { className: "te-meta-layout" },
5735
+ (0, import_react3.createElement)(
5736
+ "nav",
5737
+ { className: "te-meta-nav", "aria-label": "\u5143\u6280\u80FD\u9636\u6BB5" },
5738
+ ...visibleStages.map(([id, stage]) => (0, import_react3.createElement)(
5739
+ "button",
5740
+ {
5741
+ key: id,
5742
+ type: "button",
5743
+ "aria-current": visibleMeta === id ? "true" : void 0,
5744
+ onClick: () => {
5745
+ setActiveMeta(id);
5746
+ setSkillQuery("");
5747
+ }
5748
+ },
5749
+ stage,
5750
+ (0, import_react3.createElement)("small", null, `\u5DF2\u6302\u8F7D ${(draft.meta_bindings?.[id] ?? []).length} \u4E2A Skill`)
5751
+ )),
5752
+ visibleStages.length === 0 ? (0, import_react3.createElement)("span", { style: label }, "\u6CA1\u6709\u5339\u914D\u7684\u9636\u6BB5\u3002") : null
5753
+ ),
5754
+ visibleMeta ? (0, import_react3.createElement)(
5552
5755
  "div",
5553
- { key: id, style: { ...card, gap: 6 } },
5554
- (0, import_react3.createElement)("strong", null, stage),
5555
- (0, import_react3.createElement)("span", { style: label }, `\u6838\u5FC3\uFF1A${id} \xB7 \u751F\u6548\u6765\u6E90\uFF1A${effectiveSource(skills, id)}`),
5556
- (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", onClick: () => openRules(id) }, "\u914D\u7F6E\u6838\u5FC3 Skill \u7684 Rule"),
5756
+ { className: "te-meta-detail" },
5557
5757
  (0, import_react3.createElement)(
5558
5758
  "div",
5559
- { style: row },
5560
- ...selected2.map((name) => (0, import_react3.createElement)("button", {
5561
- key: name,
5562
- type: "button",
5563
- title: "\u79FB\u9664\u6302\u8F7D",
5564
- style: { ...input, minWidth: 0, cursor: "pointer" },
5565
- onClick: () => removeSkill(meta, name)
5566
- }, `${name} \xB7 ${effectiveSource(skills, name)} \xD7`)),
5567
- ...selected2.map((name) => (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, {
5568
- key: `rules-${name}`,
5569
- variant: "outline",
5570
- size: "sm",
5571
- onClick: () => openRules(name)
5572
- }, `\u914D\u7F6E ${name} \u7684 Rule`))
5759
+ null,
5760
+ (0, import_react3.createElement)("strong", null, META_STAGES[visibleMeta]),
5761
+ (0, import_react3.createElement)("div", { style: label }, "\u6838\u5FC3 Skill \u4E0E\u9644\u52A0 Skill \u7684 Rule \u5206\u522B\u4FDD\u5B58\u5728\u5404\u81EA\u7684\u914D\u7F6E\u4E2D\u3002")
5573
5762
  ),
5574
5763
  (0, import_react3.createElement)(
5575
- "select",
5576
- {
5577
- style: input,
5578
- "aria-label": `\u7ED9${stage}\u6302\u8F7D\u9879\u76EE\u6280\u80FD`,
5579
- value: "",
5580
- onChange: (event) => addSkill(meta, event.target.value)
5581
- },
5582
- (0, import_react3.createElement)("option", { value: "" }, "\u6302\u8F7D\u9644\u52A0\u6280\u80FD\u2026"),
5583
- ...candidates.filter((name) => !selected2.includes(name)).map((name) => (0, import_react3.createElement)("option", { key: name, value: name }, `${name} \xB7 ${effectiveSource(skills, name)}`))
5764
+ "div",
5765
+ { className: "te-meta-skill-row" },
5766
+ (0, import_react3.createElement)(
5767
+ "span",
5768
+ null,
5769
+ (0, import_react3.createElement)("strong", null, visibleMeta),
5770
+ (0, import_react3.createElement)("small", { style: { ...label, display: "block" } }, `\u6838\u5FC3 \xB7 ${effectiveSource(skills, visibleMeta)}`)
5771
+ ),
5772
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", onClick: () => openRules(visibleMeta) }, "\u914D\u7F6E Rule")
5773
+ ),
5774
+ (0, import_react3.createElement)("strong", { style: { fontSize: 13 } }, `\u9644\u52A0 Skill \xB7 ${mounted.length}`),
5775
+ ...mounted.map((name) => (0, import_react3.createElement)(
5776
+ "div",
5777
+ { key: name, className: "te-meta-skill-row" },
5778
+ (0, import_react3.createElement)(
5779
+ "span",
5780
+ null,
5781
+ (0, import_react3.createElement)("strong", null, name),
5782
+ (0, import_react3.createElement)("small", { style: { ...label, display: "block" } }, effectiveSource(skills, name))
5783
+ ),
5784
+ (0, import_react3.createElement)(
5785
+ "div",
5786
+ { className: "te-meta-skill-actions" },
5787
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", onClick: () => openRules(name) }, "\u914D\u7F6E Rule"),
5788
+ (0, import_react3.createElement)("button", {
5789
+ type: "button",
5790
+ className: "te-transfer-remove",
5791
+ "aria-label": `\u4ECE${META_STAGES[visibleMeta]}\u79FB\u9664 ${name}`,
5792
+ onClick: () => removeSkill(visibleMeta, name)
5793
+ }, "\xD7")
5794
+ )
5795
+ )),
5796
+ mounted.length === 0 ? (0, import_react3.createElement)("span", { style: label }, "\u5C1A\u672A\u6302\u8F7D\u9644\u52A0 Skill\u3002") : null,
5797
+ (0, import_react3.createElement)(
5798
+ "div",
5799
+ { style: { display: "flex", flexDirection: "column", gap: 7 } },
5800
+ (0, import_react3.createElement)("strong", { style: { fontSize: 13 } }, "\u6302\u8F7D\u9644\u52A0 Skill"),
5801
+ (0, import_react3.createElement)("input", {
5802
+ className: "te-input",
5803
+ type: "search",
5804
+ "aria-label": "\u641C\u7D22\u53EF\u6302\u8F7D\u6280\u80FD",
5805
+ placeholder: "\u641C\u7D22 Skill \u540D\u79F0\u3001\u8BF4\u660E\u6216\u6765\u6E90",
5806
+ value: skillQuery,
5807
+ onChange: (event) => setSkillQuery(event.target.value)
5808
+ }),
5809
+ (0, import_react3.createElement)("span", { style: label }, `\u53EF\u9009 ${matchingCandidates.length} \u4E2A${matchingCandidates.length > 12 ? "\uFF0C\u5148\u663E\u793A\u524D 12 \u4E2A\uFF1B\u53EF\u7EE7\u7EED\u8F93\u5165\u7F29\u5C0F\u8303\u56F4" : ""}`),
5810
+ (0, import_react3.createElement)(
5811
+ "div",
5812
+ { className: "te-meta-candidates" },
5813
+ ...matchingCandidates.slice(0, 12).map((name) => (0, import_react3.createElement)(
5814
+ "div",
5815
+ { key: name, className: "te-meta-candidate" },
5816
+ (0, import_react3.createElement)(
5817
+ "span",
5818
+ null,
5819
+ (0, import_react3.createElement)("strong", null, name),
5820
+ (0, import_react3.createElement)("small", null, effectiveSource(skills, name))
5821
+ ),
5822
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", onClick: () => addSkill(visibleMeta, name) }, "\u6302\u8F7D")
5823
+ )),
5824
+ matchingCandidates.length === 0 ? (0, import_react3.createElement)("span", { style: label }, "\u6CA1\u6709\u5339\u914D\u7684 Skill\u3002") : null
5825
+ )
5584
5826
  )
5585
- );
5586
- })
5827
+ ) : null
5828
+ )
5587
5829
  ),
5588
5830
  (0, import_react3.createElement)(
5589
5831
  "div",
@@ -5603,35 +5845,16 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5603
5845
  "\u542F\u7528\uFF08\u4EC5\u4EE3\u7801\u5BA1\u6838\u9636\u6BB5\uFF09"
5604
5846
  )
5605
5847
  ),
5606
- (0, import_react3.createElement)("span", { style: label }, "\u53EF\u590D\u7528 CI \u626B\u63CF\uFF0C\u6216\u5728\u672C\u673A\u6309\u670D\u52A1\u7AEF\u89C4\u5219\u5BA1\u6838\u65B0\u4EE3\u7801\u3002Token \u6309\u5F53\u524D\u9879\u76EE\u4FDD\u5B58\u5728\u672C\u673A DSH \u51ED\u636E\u5B58\u50A8\uFF0C\u4E0D\u5199\u5165\u4EE3\u7801\u4ED3\u5E93\uFF1B\u4ECD\u517C\u5BB9\u5DF2\u6709\u7684\u73AF\u5883\u53D8\u91CF\u3002"),
5848
+ (0, import_react3.createElement)("span", { style: label }, "\u6D4B\u8BD5\u901A\u8FC7\u540E\uFF0C\u4EE3\u7801\u5BA1\u6838\u5143\u6280\u80FD\u4F1A\u68C0\u67E5\u63D0\u4EA4\u524D\u7684\u65B0\u589E\u4EE3\u7801\u3002\u9996\u6B21\u5BA1\u6838\u81EA\u52A8\u51C6\u5907\u672C\u5730\u5206\u6790\u7EC4\u4EF6\uFF0C\u5E76\u4ECE SonarQube \u540C\u6B65\u5F53\u524D\u9879\u76EE\u7684\u89C4\u5219\u3002Token \u6309\u9879\u76EE\u4FDD\u5B58\u5728\u672C\u673A DSH \u51ED\u636E\u5B58\u50A8\u3002"),
5849
+ sonar.enabled === true && sonar.source && sonar.source !== "ide-local" ? (0, import_react3.createElement)(
5850
+ "span",
5851
+ { style: label },
5852
+ "\u6B64\u9879\u76EE\u4ECD\u662F\u65E7\u5BA1\u6838\u6A21\u5F0F\uFF1B\u4FDD\u5B58\u914D\u7F6E\u540E\uFF0C\u65B0\u4EFB\u52A1\u5C06\u4F7F\u7528\u63D0\u4EA4\u524D\u672C\u5730\u5BA1\u6838\u3002\u5DF2\u6709\u4EFB\u52A1\u6309\u521B\u5EFA\u65F6\u7684\u914D\u7F6E\u7EE7\u7EED\u3002"
5853
+ ) : null,
5607
5854
  sonar.enabled === true ? (0, import_react3.createElement)(
5608
5855
  "div",
5609
5856
  { style: grid },
5610
- (0, import_react3.createElement)(
5611
- "label",
5612
- { style: { display: "flex", flexDirection: "column", gap: 4 } },
5613
- (0, import_react3.createElement)("span", { style: label }, "\u626B\u63CF\u6765\u6E90"),
5614
- (0, import_react3.createElement)(
5615
- "select",
5616
- {
5617
- style: input,
5618
- value: sonar.source ?? "ci",
5619
- onChange: (event) => updateSonar({
5620
- source: event.target.value,
5621
- ...event.target.value !== "ci" ? { mode: "branch" } : {},
5622
- ...event.target.value !== "ide-local" ? { include_paths: [] } : {}
5623
- })
5624
- },
5625
- (0, import_react3.createElement)("option", { value: "ci" }, "CI \u5DF2\u6709\u7ED3\u679C"),
5626
- (0, import_react3.createElement)("option", { value: "ide-local" }, "\u672C\u5730\u89C4\u5219\u5BA1\u6838\uFF08\u65E0\u9700\u63D0\u4EA4\u6216\u63A8\u9001\uFF09"),
5627
- (0, import_react3.createElement)("option", { value: "local" }, "\u672C\u673A\u626B\u63CF\u5E76\u4E0A\u4F20\uFF08\u9700 Developer Edition\uFF09")
5628
- )
5629
- ),
5630
- ...[
5631
- ["host_url", "\u670D\u52A1\u5730\u5740", "https://sonar.example"],
5632
- ["project_key", "\u9879\u76EE Key", "my-project"],
5633
- ["token_env", "Token \u73AF\u5883\u53D8\u91CF\u540D\uFF08\u53EF\u9009\u540E\u5907\uFF09", "SONAR_TOKEN"]
5634
- ].map(([key, title, placeholder]) => (0, import_react3.createElement)(
5857
+ ...[["host_url", "\u670D\u52A1\u5730\u5740", "https://sonar.example"], ["project_key", "\u9879\u76EE Key", "my-project"]].map(([key, title, placeholder]) => (0, import_react3.createElement)(
5635
5858
  "label",
5636
5859
  { key, style: { display: "flex", flexDirection: "column", gap: 4 } },
5637
5860
  (0, import_react3.createElement)("span", { style: label }, title),
@@ -5643,65 +5866,62 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5643
5866
  })
5644
5867
  )),
5645
5868
  (0, import_react3.createElement)(
5646
- "label",
5647
- { style: { display: "flex", flexDirection: "column", gap: 4 } },
5648
- (0, import_react3.createElement)("span", { style: label }, "\u5206\u6790\u5BF9\u8C61"),
5869
+ "details",
5870
+ { style: { gridColumn: "1 / -1" } },
5871
+ (0, import_react3.createElement)("summary", null, "\u9AD8\u7EA7\u8BBE\u7F6E\uFF1A\u65B0\u589E\u4EE3\u7801\u53C2\u8003\u7248\u672C\u4E0E\u5BA1\u6838\u8303\u56F4"),
5649
5872
  (0, import_react3.createElement)(
5650
- "select",
5651
- {
5652
- style: input,
5653
- value: sonar.mode ?? "branch",
5654
- disabled: sonar.source === "local" || sonar.source === "ide-local",
5655
- onChange: (event) => updateSonar({ mode: event.target.value })
5656
- },
5657
- (0, import_react3.createElement)("option", { value: "branch" }, "\u5206\u652F"),
5658
- (0, import_react3.createElement)("option", { value: "pull-request" }, "\u5408\u5E76\u8BF7\u6C42")
5873
+ "div",
5874
+ { style: { ...grid, marginTop: 8 } },
5875
+ (0, import_react3.createElement)(
5876
+ "label",
5877
+ { style: { display: "flex", flexDirection: "column", gap: 4 } },
5878
+ (0, import_react3.createElement)("span", { style: label }, "Git \u53C2\u8003\u7248\u672C\uFF08\u9ED8\u8BA4 HEAD\uFF0C\u5373\u672A\u63D0\u4EA4\u53D8\u66F4\uFF09"),
5879
+ (0, import_react3.createElement)("input", {
5880
+ style: input,
5881
+ value: sonar.reference_branch ?? "HEAD",
5882
+ placeholder: "HEAD",
5883
+ onChange: (event) => updateSonar({ reference_branch: event.target.value })
5884
+ })
5885
+ ),
5886
+ (0, import_react3.createElement)(
5887
+ "label",
5888
+ { style: { display: "flex", flexDirection: "column", gap: 4 } },
5889
+ (0, import_react3.createElement)("span", { style: label }, "\u5BA1\u6838\u8DEF\u5F84\uFF08\u6BCF\u884C\u4E00\u4E2A\uFF1B\u7559\u7A7A\u4E3A\u672C\u6B21\u4EFB\u52A1\u7684\u5168\u90E8\u4EE3\u7801\uFF09"),
5890
+ (0, import_react3.createElement)("textarea", {
5891
+ style: { ...input, minHeight: 76 },
5892
+ value: (sonar.include_paths ?? []).join("\n"),
5893
+ onChange: (event) => updateSonar({
5894
+ include_paths: event.target.value.split(/\r?\n|,/u).map((path) => path.trim()).filter(Boolean)
5895
+ })
5896
+ })
5897
+ )
5659
5898
  )
5660
5899
  ),
5661
- sonar.source === "local" || sonar.source === "ide-local" ? (0, import_react3.createElement)(
5662
- "label",
5663
- { style: { display: "flex", flexDirection: "column", gap: 4 } },
5664
- (0, import_react3.createElement)("span", { style: label }, sonar.source === "local" ? "\u65B0\u4EE3\u7801\u53C2\u8003\u5206\u652F\uFF08\u987B\u5DF2\u6709 Sonar \u5206\u6790\uFF09" : "\u65B0\u4EE3\u7801\u53C2\u8003\u5206\u652F\uFF08\u672C\u673A Git \u5206\u652F\uFF09"),
5665
- (0, import_react3.createElement)("input", {
5666
- style: input,
5667
- value: sonar.reference_branch ?? "",
5668
- placeholder: "\u4F8B\u5982 qdm_sit",
5669
- onChange: (event) => updateSonar({ reference_branch: event.target.value })
5670
- })
5671
- ) : null,
5672
- sonar.source === "local" ? (0, import_react3.createElement)(
5673
- "label",
5674
- { style: { display: "flex", flexDirection: "column", gap: 4 } },
5675
- (0, import_react3.createElement)("span", { style: label }, "\u672C\u673A\u626B\u63CF\u547D\u4EE4\uFF08\u53EF\u9009\uFF1B\u4E0D\u586B\u5219\u81EA\u52A8\u9009\u62E9 Maven / sonar-scanner\uFF09"),
5676
- (0, import_react3.createElement)("input", {
5677
- style: input,
5678
- value: sonar.scan_command ?? "",
5679
- placeholder: "mvn org.sonarsource.scanner.maven:sonar-maven-plugin:5.5.0.6356:sonar",
5680
- onChange: (event) => updateSonar({ scan_command: event.target.value })
5681
- })
5682
- ) : null,
5683
- sonar.source === "local" ? (0, import_react3.createElement)(
5684
- "span",
5685
- { style: label },
5686
- "\u672C\u673A\u5206\u652F\u626B\u63CF\u9700\u8981 SonarQube Developer Edition \u6216\u66F4\u9AD8\u7248\u672C\u3001\u5DF2\u6709\u5206\u6790\u7684\u53C2\u8003\u5206\u652F\u53CA\u672C\u673A\u626B\u63CF\u5668/JDK\uFF1BCommunity Build \u4F1A\u5728\u4E0A\u4F20\u524D\u62D2\u7EDD\u3002"
5687
- ) : null,
5688
- sonar.source === "ide-local" ? (0, import_react3.createElement)(
5689
- "label",
5690
- { style: { display: "flex", flexDirection: "column", gap: 4 } },
5691
- (0, import_react3.createElement)("span", { style: label }, "\u672C\u5730\u5BA1\u6838\u8303\u56F4\uFF08\u6BCF\u884C\u4E00\u4E2A\u9879\u76EE\u76F8\u5BF9\u76EE\u5F55\u6216\u6587\u4EF6\uFF1B\u7559\u7A7A\u4E3A\u4EFB\u52A1\u5168\u90E8\u4EE3\u7801\uFF09"),
5692
- (0, import_react3.createElement)("textarea", {
5693
- style: { ...input, minHeight: 76 },
5694
- value: (sonar.include_paths ?? []).join("\n"),
5695
- placeholder: "\u4F8B\u5982 fp-bussiness\nfp-ruoyi\nfp-ruoyi-spring-boot\npom.xml",
5696
- onChange: (event) => updateSonar({
5697
- include_paths: event.target.value.split(/\r?\n|,/u).map((path) => path.trim()).filter(Boolean)
5698
- })
5699
- })
5700
- ) : null,
5701
- sonar.source === "ide-local" ? (0, import_react3.createElement)(
5900
+ (0, import_react3.createElement)(
5702
5901
  "span",
5703
- { style: label },
5704
- "\u672C\u5730\u89C4\u5219\u5BA1\u6838\u4ECE SonarQube \u540C\u6B65\u9879\u76EE\u89C4\u5219\uFF0C\u6309\u4E0A\u65B9\u8303\u56F4\u7B5B\u9009\u4EFB\u52A1\u65B0\u589E\u4EE3\u7801\uFF0C\u4E0D\u4E0A\u4F20\u7ED3\u679C\u3002\u626B\u63CF\u8303\u56F4\u7531 CI \u6784\u5EFA\u4E0E\u9879\u76EE\u914D\u7F6E\u51B3\u5B9A\uFF0CQuality Profile \u672C\u8EAB\u4E0D\u51B3\u5B9A\u626B\u63CF\u54EA\u4E9B\u76EE\u5F55\u3002\u5176\u4ED6\u8BED\u8A00\u4EC5\u5728\u8BE5\u9879\u76EE\u5B58\u5728\u751F\u6548\u89C4\u5219\u800C\u672C\u5730\u65E0\u6CD5\u5206\u6790\u65F6\u5217\u4E3A\u672A\u8986\u76D6\u3002\u9700\u5B89\u88C5 SonarLint \u540E\u53F0\u7EC4\u4EF6\u5E76\u914D\u7F6E DSH_SONARLINT_JAVA\u3001DSH_SONARLINT_LIB\u3001DSH_SONARLINT_PLUGINS\u3002"
5902
+ { style: { ...label, gridColumn: "1 / -1" } },
5903
+ "\u65E0\u9700\u5B89\u88C5 IDEA\u3001Maven \u6216 SonarScanner\u3002\u9996\u6B21\u5BA1\u6838\u4F1A\u4E0B\u8F7D\u5B98\u65B9\u672C\u5730\u5206\u6790\u540E\u53F0\uFF1B\u8BED\u8A00\u5206\u6790\u5668\u7531\u540E\u53F0\u4ECE SonarQube \u540C\u6B65\u3002\u90E8\u5206\u670D\u52A1\u7AEF\u89C4\u5219\u65E0\u6CD5\u5728\u672C\u5730\u6267\u884C\uFF0C\u672C\u5730\u901A\u8FC7\u4E0D\u7B49\u4E8E\u670D\u52A1\u7AEF\u8D28\u91CF\u95E8\u7981\u901A\u8FC7\u3002"
5904
+ ),
5905
+ (0, import_react3.createElement)(
5906
+ "div",
5907
+ { style: { ...row, gridColumn: "1 / -1" } },
5908
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, {
5909
+ variant: "outline",
5910
+ size: "sm",
5911
+ disabled: analyzerBusy || saving || dirty,
5912
+ onClick: prepareAnalyzer
5913
+ }, analyzerBusy ? "\u5B89\u88C5\u4E0E\u68C0\u67E5\u4E2D\u2026" : "\u5B89\u88C5\u6216\u68C0\u67E5\u672C\u5730\u5206\u6790\u5668"),
5914
+ (0, import_react3.createElement)("span", { style: label }, "\u5148\u4FDD\u5B58\u670D\u52A1\u5730\u5740\u3001\u9879\u76EE Key \u548C Token\uFF1B\u68C0\u67E5\u4E0D\u4F1A\u5BA1\u6838\u6216\u4E0A\u4F20\u9879\u76EE\u4EE3\u7801\u3002")
5915
+ ),
5916
+ analyzerProfiles ? (0, import_react3.createElement)(
5917
+ "div",
5918
+ { style: { ...label, gridColumn: "1 / -1" } },
5919
+ analyzerProfiles.length ? analyzerProfiles.map((profile) => (0, import_react3.createElement)(
5920
+ "div",
5921
+ { key: profile.language },
5922
+ `${profile.language}\uFF1A\u670D\u52A1\u7AEF ${profile.active_rules} \u6761\u89C4\u5219\uFF1B\u672C\u5730\u5206\u6790\u5668 ${profile.analyzer}`
5923
+ )) : "\u9879\u76EE\u6CA1\u6709\u8FD4\u56DE\u5DF2\u542F\u7528\u89C4\u5219\u7684\u8BED\u8A00\u3002",
5924
+ (0, import_react3.createElement)("div", null, "\u5DF2\u540C\u6B65\u8868\u793A\u8BE5\u8BED\u8A00\u5206\u6790\u5668\u53EF\u7528\uFF0C\u4E0D\u4EE3\u8868\u670D\u52A1\u7AEF\u5168\u90E8\u89C4\u5219\u90FD\u80FD\u5728\u672C\u5730\u6267\u884C\u3002")
5705
5925
  ) : null,
5706
5926
  (0, import_react3.createElement)(
5707
5927
  "div",
@@ -5736,16 +5956,16 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5736
5956
  ),
5737
5957
  (0, import_react3.createElement)(
5738
5958
  "div",
5739
- { style: row },
5959
+ { className: "te-adaptive-savebar" },
5740
5960
  (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", disabled: loading || saving, onClick: refresh }, "\u5237\u65B0"),
5741
5961
  (0, import_react3.createElement)(
5742
5962
  import_dsh_client_ui_primitives2.Button,
5743
5963
  { variant: "primary", size: "sm", disabled: loading || saving || !dirty, onClick: save },
5744
5964
  saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58\u81EA\u9002\u5E94\u914D\u7F6E"
5745
5965
  ),
5746
- (0, import_react3.createElement)("span", { style: label }, "\u9879\u76EE Skill / Rule \u521D\u59CB\u5316\u5165\u53E3\u4F4D\u4E8E\u201C\u9879\u76EE\u521D\u59CB\u5316\u201D\u9875\u3002")
5966
+ (0, import_react3.createElement)("span", { style: label }, dirty ? "\u6709\u672A\u4FDD\u5B58\u7684\u9879\u76EE\u914D\u7F6E" : "\u9879\u76EE\u914D\u7F6E\u5DF2\u4FDD\u5B58"),
5967
+ message ? (0, import_react3.createElement)("span", { role: "status", style: { ...label, flexBasis: "100%" } }, message) : null
5747
5968
  ),
5748
- message ? (0, import_react3.createElement)("p", { role: "status", style: styles.status }, message) : null,
5749
5969
  view?.problems.length ? (0, import_react3.createElement)("p", { role: "alert", style: styles.status }, view.problems.join("\uFF1B")) : null,
5750
5970
  selected ? (0, import_react3.createElement)(SkillRuleDialog, {
5751
5971
  key: `${selected.skill.source}:${selected.skill.name}`,
@@ -5773,7 +5993,6 @@ var card2 = {
5773
5993
  borderRadius: 8,
5774
5994
  padding: "12px 14px"
5775
5995
  };
5776
- var projectInitPrompt = (workspace) => `\u8BF7\u5728\u5F53\u524D\u9879\u76EE\u6839\u5DE5\u4F5C\u533A ${workspace} \u4F7F\u7528\u5DE5\u7A0B\u5316\u5F00\u53D1\u5F15\u64CE\u521D\u59CB\u5316\u9879\u76EE Skill \u548C Rule\u3002\u5148\u8C03\u7528 dev_task init_project\uFF08phase=inspect\uFF09\uFF0C\u7ED3\u5408\u4EE3\u8868\u6027\u6E90\u7801\u3001\u6784\u5EFA\u6587\u4EF6\u3001\u6D4B\u8BD5\u548C\u5DF2\u6709\u89C4\u8303\u6838\u5B9E\u626B\u63CF\u7ED3\u679C\u3002\u6309\u9879\u76EE\u5B9E\u9645\u60C5\u51B5\u62DF\u5B9A\u9879\u76EE\u7ED3\u6784\u5730\u56FE\u3001\u6280\u672F\u6808\u3001\u7F16\u7801\u65B9\u6CD5\u7B49 Skill \u548C\u5FC5\u8981\u7684 Rule\uFF0C\u5E76\u6807\u660E\u9002\u7528\u7684\u5143\u6280\u80FD\u3002\u9879\u76EE\u5730\u56FE\u5FC5\u987B\u603B\u7ED3\u6574\u4E2A\u4ED3\u5E93\u7684\u6A21\u5757\u804C\u8D23\u3001\u4F9D\u8D56\u548C\u901A\u7528\u4EE3\u7801\u5165\u53E3\uFF0C\u80FD\u591F\u4F9B\u4E0D\u540C\u9700\u6C42\u590D\u7528\uFF1B\u4E0D\u8981\u628A\u5F53\u524D\u4F1A\u8BDD\u7684\u9700\u6C42\u3001\u4E13\u5C5E\u8C03\u7528\u94FE\u6216\u5B9E\u73B0\u65B9\u6848\u5199\u6210\u9879\u76EE\u5730\u56FE\uFF0C\u76F8\u5173\u5185\u5BB9\u5E94\u8FDB\u5165\u8BE5\u4EFB\u52A1\u4EA7\u7269\u6216\u5355\u72EC\u7684\u9886\u57DF Skill\u3002\u8C03\u7528 phase=propose \u5C55\u793A\u62DF\u521B\u5EFA\u7684\u6587\u4EF6\u3001\u5185\u5BB9\u548C\u6302\u8F7D\u5173\u7CFB\uFF1B\u7B49\u6211\u5BA1\u9605\u786E\u8BA4\u540E\u518D\u8C03\u7528 phase=apply\u3002\u4E0D\u8981\u8986\u76D6\u540C\u540D\u8D44\u6E90\uFF0C\u4E5F\u4E0D\u8981\u628A\u5076\u53D1\u4EE3\u7801\u5199\u6CD5\u5F53\u6210\u56E2\u961F\u89C4\u8303\u3002`;
5777
5996
  function InitPanel({ workspace, remote }) {
5778
5997
  const [view, setView] = (0, import_react4.useState)(null);
5779
5998
  const [generating, setGenerating] = (0, import_react4.useState)(false);
@@ -5783,8 +6002,11 @@ function InitPanel({ workspace, remote }) {
5783
6002
  const [body2, setBody] = (0, import_react4.useState)("");
5784
6003
  const [msg, setMsg] = (0, import_react4.useState)("");
5785
6004
  const [projectInitMsg, setProjectInitMsg] = (0, import_react4.useState)("");
6005
+ const [projectBusy, setProjectBusy] = (0, import_react4.useState)(false);
6006
+ const [projectDraft, setProjectDraft] = (0, import_react4.useState)(null);
6007
+ const [projectResources, setProjectResources] = (0, import_react4.useState)([]);
5786
6008
  (0, import_react4.useEffect)(() => {
5787
- if (!generating) {
6009
+ if (!generating && !projectBusy) {
5788
6010
  setElapsed(0);
5789
6011
  return;
5790
6012
  }
@@ -5796,7 +6018,73 @@ function InitPanel({ workspace, remote }) {
5796
6018
  return () => {
5797
6019
  clearInterval(timer);
5798
6020
  };
5799
- }, [generating]);
6021
+ }, [generating, projectBusy]);
6022
+ (0, import_react4.useEffect)(() => {
6023
+ setProjectDraft(null);
6024
+ setProjectResources([]);
6025
+ setProjectInitMsg("");
6026
+ }, [workspace]);
6027
+ const generateProject = async () => {
6028
+ setProjectBusy(true);
6029
+ setProjectDraft(null);
6030
+ setProjectResources([]);
6031
+ setProjectInitMsg("");
6032
+ try {
6033
+ const result = await remote.generateProjectInit({ path: workspace });
6034
+ if (!result.ok) throw new Error(describeError(result.error));
6035
+ if (!result.value.ok) throw new Error(result.value.error ?? "\u9879\u76EE\u521D\u59CB\u5316\u63D0\u6848\u65E0\u6548");
6036
+ setProjectDraft(result.value);
6037
+ setProjectResources(result.value.resources);
6038
+ setProjectInitMsg("\u63D0\u6848\u5DF2\u751F\u6210\u5E76\u6821\u9A8C\u3002\u8BF7\u9010\u9879\u5BA1\u9605\u5185\u5BB9\u4E0E\u6302\u8F7D\u5173\u7CFB\uFF0C\u786E\u8BA4\u540E\u518D\u5199\u5165\u3002");
6039
+ } catch (error) {
6040
+ setProjectInitMsg(`\u751F\u6210\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`);
6041
+ } finally {
6042
+ setProjectBusy(false);
6043
+ }
6044
+ };
6045
+ const updateProjectResource = (index, change) => {
6046
+ setProjectResources((current) => current.map((resource, at) => at === index ? { ...resource, ...change } : resource));
6047
+ setProjectDraft(null);
6048
+ setProjectInitMsg("\u63D0\u6848\u5DF2\u4FEE\u6539\u3002\u8BF7\u5148\u70B9\u51FB\u201C\u68C0\u67E5\u4FEE\u6539\u201D\uFF0C\u901A\u8FC7\u540E\u624D\u80FD\u5199\u5165\u3002");
6049
+ };
6050
+ const checkProject = async () => {
6051
+ setProjectBusy(true);
6052
+ setProjectInitMsg("");
6053
+ try {
6054
+ const result = await remote.previewProjectInit({ path: workspace, resources: projectResources });
6055
+ if (!result.ok) throw new Error(describeError(result.error));
6056
+ if (!result.value.ok) throw new Error(result.value.error ?? "\u63D0\u6848\u6821\u9A8C\u5931\u8D25");
6057
+ setProjectDraft(result.value);
6058
+ setProjectInitMsg("\u63D0\u6848\u68C0\u67E5\u901A\u8FC7\uFF0C\u53EF\u4EE5\u786E\u8BA4\u5199\u5165\u3002");
6059
+ } catch (error) {
6060
+ setProjectDraft(null);
6061
+ setProjectInitMsg(`\u68C0\u67E5\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`);
6062
+ } finally {
6063
+ setProjectBusy(false);
6064
+ }
6065
+ };
6066
+ const applyProject = async () => {
6067
+ if (projectDraft === null || !window.confirm(`\u786E\u8BA4\u5728 ${workspace} \u521B\u5EFA ${projectDraft.files_to_create.length} \u4E2A Skill / Rule \u6587\u4EF6\u5E76\u66F4\u65B0 .dsh/meta.json\uFF1F`)) return;
6068
+ setProjectBusy(true);
6069
+ setProjectInitMsg("");
6070
+ try {
6071
+ const result = await remote.applyProjectInit({
6072
+ path: workspace,
6073
+ resources: projectDraft.resources,
6074
+ expected_hash: projectDraft.expected_hash,
6075
+ existing_hash: projectDraft.existing_hash
6076
+ });
6077
+ if (!result.ok) throw new Error(describeError(result.error));
6078
+ if (!result.value.ok) throw new Error(result.value.error ?? "\u5199\u5165\u5931\u8D25");
6079
+ setProjectInitMsg(`\u5DF2\u521B\u5EFA ${result.value.created.length} \u4E2A\u9879\u76EE\u914D\u7F6E\u6587\u4EF6\uFF1A${result.value.created.join("\u3001")}`);
6080
+ setProjectDraft(null);
6081
+ setProjectResources([]);
6082
+ } catch (error) {
6083
+ setProjectInitMsg(`\u5199\u5165\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}\u3002\u82E5\u5DF2\u6709\u90E8\u5206\u6587\u4EF6\uFF0C\u8BF7\u5237\u65B0\u5E76\u68C0\u67E5\u3002`);
6084
+ } finally {
6085
+ setProjectBusy(false);
6086
+ }
6087
+ };
5800
6088
  const refresh = (0, import_react4.useCallback)(() => {
5801
6089
  void remote.readInit(workspace).then((r) => {
5802
6090
  if (r.ok) setView(r.value);
@@ -5856,39 +6144,108 @@ function InitPanel({ workspace, remote }) {
5856
6144
  (0, import_react4.createElement)(
5857
6145
  "p",
5858
6146
  { style: styles.muted },
5859
- "\u626B\u63CF\u53EA\u8FD4\u56DE\u9879\u76EE\u8BC1\u636E\u4E0E\u5EFA\u8BAE\u540D\u79F0\uFF1B\u4F1A\u8BDD\u6A21\u578B\u636E\u6B64\u62DF\u5B9A\u8986\u76D6\u6574\u4E2A\u4ED3\u5E93\u7684\u9879\u76EE\u5730\u56FE\u3001\u6280\u672F\u6808\u3001\u7F16\u7801 Skill \u548C Rule\u3002\u5F53\u524D\u9700\u6C42\u7684\u4E13\u5C5E\u4FE1\u606F\u5E94\u5199\u5165\u4EFB\u52A1\u4EA7\u7269\u3002\u5148\u9884\u89C8\u751F\u6210\u5185\u5BB9\uFF0C\u786E\u8BA4\u540E\u624D\u5199\u5165\u9879\u76EE\uFF1B\u5DF2\u6709\u540C\u540D\u8D44\u6E90\u4E0D\u4F1A\u88AB\u8986\u76D6\u3002"
6147
+ "\u5728\u6B64\u626B\u63CF\u4ED3\u5E93\u5E76\u751F\u6210\u9879\u76EE Skill / Rule \u63D0\u6848\u3002\u9879\u76EE\u5730\u56FE\u8986\u76D6\u6574\u4E2A\u4ED3\u5E93\uFF0C\u5F53\u524D\u9700\u6C42\u7684\u4E13\u5C5E\u4FE1\u606F\u5E94\u5199\u5165\u4EFB\u52A1\u4EA7\u7269\u3002\u9010\u9879\u5BA1\u9605\u540E\u786E\u8BA4\u5199\u5165\uFF1B\u5DF2\u6709\u540C\u540D\u8D44\u6E90\u4E0D\u4F1A\u88AB\u8986\u76D6\u3002"
5860
6148
  ),
5861
6149
  (0, import_react4.createElement)(
5862
6150
  "p",
5863
6151
  { style: styles.muted },
5864
6152
  "\u56E2\u961F\u5171\u4EAB\u65F6\uFF0C\u8BF7\u5C06\u751F\u6210\u7684 .dsh/skills\u3001.dsh/rules \u548C .dsh/meta.json \u7EB3\u5165 Git\uFF1B\u5BA1\u6838\u62A5\u544A\u53EF\u4FDD\u7559\u5728\u672C\u5730\u3002"
5865
6153
  ),
5866
- (0, import_react4.createElement)(
5867
- "p",
5868
- { style: styles.muted },
5869
- "\u4F7F\u7528\u65B9\u6CD5\uFF1A\u5173\u95ED\u6B64\u9762\u677F\uFF0C\u5728\u5F53\u524D\u9879\u76EE\u6839\u5DE5\u4F5C\u533A\u9009\u62E9\u201C\u5DE5\u7A0B\u5316\u5F00\u53D1\u5F15\u64CE\u201D\uFF0C\u628A\u4E0B\u9762\u7684\u8BF7\u6C42\u53D1\u7ED9\u65B0\u4F1A\u8BDD\u3002"
5870
- ),
5871
- (0, import_react4.createElement)("textarea", {
5872
- style: { ...styles.textarea, minHeight: 100 },
5873
- readOnly: true,
5874
- "aria-label": "\u9879\u76EE Skill \u548C Rule \u521D\u59CB\u5316\u8BF7\u6C42",
5875
- value: projectInitPrompt(workspace)
5876
- }),
5877
6154
  (0, import_react4.createElement)(
5878
6155
  "div",
5879
6156
  { style: styles.row },
5880
- (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, { variant: "primary", size: "md", onClick: () => {
5881
- if (!navigator.clipboard?.writeText) {
5882
- setProjectInitMsg("\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u4E00\u952E\u590D\u5236\u3002\u8BF7\u76F4\u63A5\u9009\u4E2D\u4E0A\u65B9\u8BF7\u6C42\u6587\u672C\u5E76\u590D\u5236\u3002");
5883
- return;
6157
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, {
6158
+ variant: "primary",
6159
+ size: "md",
6160
+ disabled: projectBusy,
6161
+ onClick: () => {
6162
+ void generateProject();
5884
6163
  }
5885
- void navigator.clipboard.writeText(projectInitPrompt(workspace)).then(
5886
- () => setProjectInitMsg("\u5DF2\u590D\u5236\u521D\u59CB\u5316\u8BF7\u6C42\u3002\u8BF7\u5728\u5DE5\u7A0B\u5316\u5F00\u53D1\u5F15\u64CE\u4F1A\u8BDD\u4E2D\u7C98\u8D34\u53D1\u9001\u3002"),
5887
- () => setProjectInitMsg("\u590D\u5236\u5931\u8D25\u3002\u8BF7\u76F4\u63A5\u9009\u4E2D\u4E0A\u65B9\u8BF7\u6C42\u6587\u672C\u5E76\u590D\u5236\u3002")
5888
- );
5889
- } }, "\u590D\u5236\u521D\u59CB\u5316\u8BF7\u6C42"),
5890
- projectInitMsg ? (0, import_react4.createElement)("span", { role: "status", style: styles.status }, projectInitMsg) : null
5891
- )
6164
+ }, projectBusy ? "\u626B\u63CF\u4E0E\u751F\u6210\u4E2D\u2026" : "\u626B\u63CF\u5E76\u751F\u6210\u63D0\u6848"),
6165
+ projectBusy ? (0, import_react4.createElement)("span", { style: styles.status }, `\u5DF2\u8017\u65F6 ${elapsed} \u79D2`) : null
6166
+ ),
6167
+ projectResources.length > 0 ? (0, import_react4.createElement)(
6168
+ "div",
6169
+ { style: styles.section },
6170
+ (0, import_react4.createElement)(
6171
+ "p",
6172
+ { style: styles.muted },
6173
+ `\u9879\u76EE\uFF1A${workspace}\u3002\u63D0\u6848\u5305\u542B ${projectResources.length} \u4E2A Skill / Rule\uFF1B\u9879\u76EE\u5730\u56FE\u9700\u8986\u76D6\uFF1A${projectDraft?.project_map_coverage.join("\u3001") ?? "\u68C0\u67E5\u4FEE\u6539\u540E\u663E\u793A"}\u3002`
6174
+ ),
6175
+ ...projectResources.map((resource, index) => (0, import_react4.createElement)(
6176
+ "div",
6177
+ { key: `${resource.kind}-${resource.name}`, style: card2 },
6178
+ (0, import_react4.createElement)(
6179
+ "div",
6180
+ { style: styles.row },
6181
+ (0, import_react4.createElement)("strong", null, `${resource.kind === "skill" ? "Skill" : "Rule"} \xB7 ${resource.name}`),
6182
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, {
6183
+ variant: "ghost",
6184
+ size: "sm",
6185
+ disabled: projectBusy,
6186
+ onClick: () => {
6187
+ setProjectResources((current) => current.filter((_, at) => at !== index));
6188
+ setProjectDraft(null);
6189
+ setProjectInitMsg("\u5DF2\u79FB\u9664\u5EFA\u8BAE\u3002\u8BF7\u91CD\u65B0\u68C0\u67E5\u63D0\u6848\u3002");
6190
+ }
6191
+ }, "\u79FB\u9664\u5EFA\u8BAE")
6192
+ ),
6193
+ resource.kind === "skill" ? (0, import_react4.createElement)(
6194
+ "div",
6195
+ { style: styles.section },
6196
+ (0, import_react4.createElement)("label", null, "\u7B80\u4ECB", (0, import_react4.createElement)("input", {
6197
+ style: styles.input,
6198
+ value: resource.description ?? "",
6199
+ onChange: (event) => {
6200
+ updateProjectResource(index, { description: event.target.value });
6201
+ }
6202
+ })),
6203
+ (0, import_react4.createElement)("label", null, "\u6302\u8F7D\u5143\u6280\u80FD\uFF08\u9017\u53F7\u5206\u9694\uFF09", (0, import_react4.createElement)("input", {
6204
+ style: styles.input,
6205
+ value: (resource.meta_skills ?? []).join(", "),
6206
+ onChange: (event) => {
6207
+ updateProjectResource(index, { meta_skills: event.target.value.split(",").map((item) => item.trim()).filter(Boolean) });
6208
+ }
6209
+ })),
6210
+ (0, import_react4.createElement)("label", null, "\u5173\u8054 Rule\uFF08\u9017\u53F7\u5206\u9694\uFF09", (0, import_react4.createElement)("input", {
6211
+ style: styles.input,
6212
+ value: (resource.rules ?? []).join(", "),
6213
+ onChange: (event) => {
6214
+ updateProjectResource(index, { rules: event.target.value.split(",").map((item) => item.trim()).filter(Boolean) });
6215
+ }
6216
+ }))
6217
+ ) : null,
6218
+ (0, import_react4.createElement)("label", null, "\u5185\u5BB9", (0, import_react4.createElement)("textarea", {
6219
+ style: { ...styles.textarea, minHeight: 180 },
6220
+ value: resource.content,
6221
+ onChange: (event) => {
6222
+ updateProjectResource(index, { content: event.target.value });
6223
+ }
6224
+ }))
6225
+ )),
6226
+ (0, import_react4.createElement)(
6227
+ "div",
6228
+ { style: styles.row },
6229
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, {
6230
+ variant: "outline",
6231
+ size: "md",
6232
+ disabled: projectBusy,
6233
+ onClick: () => {
6234
+ void checkProject();
6235
+ }
6236
+ }, "\u68C0\u67E5\u4FEE\u6539"),
6237
+ (0, import_react4.createElement)(import_dsh_client_ui_primitives3.Button, {
6238
+ variant: "primary",
6239
+ size: "md",
6240
+ disabled: projectBusy || projectDraft === null,
6241
+ onClick: () => {
6242
+ void applyProject();
6243
+ }
6244
+ }, "\u786E\u8BA4\u5199\u5165\u9879\u76EE")
6245
+ ),
6246
+ projectDraft !== null ? (0, import_react4.createElement)("p", { style: styles.muted }, `\u5C06\u521B\u5EFA\uFF1A${projectDraft.files_to_create.join("\u3001")}\uFF0C\u5E76\u66F4\u65B0 .dsh/meta.json`) : null
6247
+ ) : null,
6248
+ projectInitMsg ? (0, import_react4.createElement)("p", { role: "status", style: styles.status }, projectInitMsg) : null
5892
6249
  ),
5893
6250
  (0, import_react4.createElement)(
5894
6251
  "div",
@@ -6625,7 +6982,7 @@ function SkillManager({ workspace, remote }) {
6625
6982
  setMessage(`\u5DF2\u4FDD\u5B58 ${selected.name} \u7684\u89C4\u5219\u914D\u7F6E\u3002`);
6626
6983
  setSelected(null);
6627
6984
  };
6628
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `te-config-layout${selected ? " is-open" : ""}`, children: [
6985
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "te-config-layout", children: [
6629
6986
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "te-config-main", children: [
6630
6987
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ResourceManager, { workspace, remote, kind: "skill", onConfigureSkill: config ? (ref) => {
6631
6988
  setMessage("");
@@ -6768,6 +7125,17 @@ function sonarAudit(task) {
6768
7125
  (0, import_react8.createElement)("summary", { style: { cursor: "pointer", fontSize: 12 } }, `\u672C\u6B21\u5206\u6790\u6587\u4EF6\uFF08${audit.scanned_files.length}\uFF09`),
6769
7126
  ...audit.scanned_files.map((file) => (0, import_react8.createElement)("div", { key: file, style: metaLine }, file))
6770
7127
  ) : null,
7128
+ audit.profile_coverage?.length ? (0, import_react8.createElement)(
7129
+ "details",
7130
+ null,
7131
+ (0, import_react8.createElement)("summary", { style: { cursor: "pointer", fontSize: 12 } }, "\u9879\u76EE\u89C4\u5219\u4E0E\u672C\u5730\u5206\u6790\u5668"),
7132
+ ...audit.profile_coverage.map((profile) => (0, import_react8.createElement)(
7133
+ "div",
7134
+ { key: profile.language, style: metaLine },
7135
+ `${profile.language}\uFF1A\u670D\u52A1\u7AEF\u542F\u7528 ${profile.active_rules} \u6761\u89C4\u5219\uFF1B\u672C\u5730\u5206\u6790\u5668 ${profile.analyzer}`
7136
+ )),
7137
+ (0, import_react8.createElement)("div", { style: metaLine }, "\u6B64\u5904\u663E\u793A\u8BED\u8A00\u5206\u6790\u5668\u72B6\u6001\uFF0C\u4E0D\u80FD\u8BC1\u660E\u6BCF\u6761\u670D\u52A1\u7AEF\u89C4\u5219\u90FD\u53EF\u5728\u672C\u5730\u6267\u884C\u3002")
7138
+ ) : null,
6771
7139
  ...audit.uncovered_files.map((file) => (0, import_react8.createElement)(
6772
7140
  "div",
6773
7141
  { key: `uncovered-${file}`, style: metaLine },