dsh-code-index 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js CHANGED
@@ -22,6 +22,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
22
22
  // src/client/index.tsx
23
23
  var client_exports = {};
24
24
  __export(client_exports, {
25
+ SETTINGS_EN: () => SETTINGS_EN,
26
+ SETTINGS_ZH: () => SETTINGS_ZH,
25
27
  apply: () => apply,
26
28
  inject: () => inject,
27
29
  name: () => name
@@ -104,7 +106,6 @@ function CodeToolCard(props) {
104
106
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { style: { margin: "4px 0 0", whiteSpace: "pre-wrap", maxHeight: 220, overflow: "auto" }, children: resultText(block) })
105
107
  ] });
106
108
  }
107
- var activeScope = null;
108
109
  var CARD_CSS = `
109
110
  .dci-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}
110
111
  .dci-card:hover{border-color:var(--dsw-alias-label-dimmed)}
@@ -136,8 +137,37 @@ var CARD_CSS = `
136
137
  var CHEVRON_PATH = "M11.8486 5.5L11.4238 5.92383L8.69727 8.65137C8.44157 8.90706 8.21562 9.13382 8.01172 9.29785C7.79912 9.46883 7.55595 9.61756 7.25 9.66602C7.08435 9.69222 6.91565 9.69222 6.75 9.66602C6.44405 9.61756 6.20088 9.46883 5.98828 9.29785C5.78438 9.13382 5.55843 8.90706 5.30273 8.65137L2.57617 5.92383L2.15137 5.5L3 4.65137L3.42383 5.07617L6.15137 7.80273C6.42595 8.07732 6.59876 8.24849 6.74023 8.3623C6.87291 8.46904 6.92272 8.47813 6.9375 8.48047C6.97895 8.48703 7.02105 8.48703 7.0625 8.48047C7.07728 8.47813 7.12709 8.46904 7.25977 8.3623C7.40124 8.24849 7.57405 8.07732 7.84863 7.80273L10.5762 5.07617L11 4.65137L11.8486 5.5Z";
137
138
  var SETTINGS_DEFAULTS = { autoInject: true, codeHealth: false, mapTopFiles: 24 };
138
139
  var SETTINGS_FIELDS = ["autoInject", "codeHealth", "mapTopFiles"];
139
- function CodeIndexSettingsCard() {
140
- const scope = activeScope;
140
+ var SETTINGS_EN = {
141
+ collapse: "Collapse settings",
142
+ expand: "Expand settings",
143
+ description: "Project-aware live structural context: symbol search, repo map, and call graph.",
144
+ autoInject: "Inject repo map",
145
+ autoInjectHint: "Add a compact ranked map of the current project to the system prompt.",
146
+ codeHealth: "Code health tool",
147
+ codeHealthHint: "Register code_health for dependency cycles and orphan modules (restart required).",
148
+ mapFiles: "Map files",
149
+ mapFilesHint: "Maximum number of files shown in each repo map.",
150
+ discard: "Discard changes",
151
+ save: "Save",
152
+ unavailable: "Settings service unavailable."
153
+ };
154
+ var SETTINGS_ZH = {
155
+ collapse: "\u6536\u8D77\u8BBE\u7F6E",
156
+ expand: "\u5C55\u5F00\u8BBE\u7F6E",
157
+ description: "\u9879\u76EE\u611F\u77E5\u7684\u5B9E\u65F6\u7ED3\u6784\u5316\u4E0A\u4E0B\u6587\uFF1A\u7B26\u53F7\u641C\u7D22\u3001\u4ED3\u5E93\u5730\u56FE\u4E0E\u8C03\u7528\u56FE\u3002",
158
+ autoInject: "\u81EA\u52A8\u6CE8\u5165\u4ED3\u5E93\u5730\u56FE",
159
+ autoInjectHint: "\u628A\u5F53\u524D\u9879\u76EE\u7684\u7CBE\u7B80\u6392\u540D\u5730\u56FE\u6CE8\u5165\u7CFB\u7EDF\u63D0\u793A\u8BCD\u3002",
160
+ codeHealth: "\u4EE3\u7801\u5065\u5EB7\u5DE5\u5177",
161
+ codeHealthHint: "\u6CE8\u518C code_health \u5DE5\u5177\uFF0C\u62A5\u544A\u73AF\u4F9D\u8D56\u4E0E\u5B64\u513F\u6A21\u5757\uFF08\u91CD\u542F\u540E\u751F\u6548\uFF09\u3002",
162
+ mapFiles: "\u5730\u56FE\u6587\u4EF6\u6570",
163
+ mapFilesHint: "\u4ED3\u5E93\u5730\u56FE\u4E2D\u6700\u591A\u5C55\u793A\u7684\u6587\u4EF6\u6570\u3002",
164
+ discard: "\u653E\u5F03\u4FEE\u6539",
165
+ save: "\u4FDD\u5B58",
166
+ unavailable: "\u8BBE\u7F6E\u670D\u52A1\u4E0D\u53EF\u7528\u3002"
167
+ };
168
+ function CodeIndexSettingsCard(props) {
169
+ const scope = props.scope ?? null;
170
+ const t = props.t ?? ((key) => SETTINGS_EN[key] ?? key);
141
171
  const [open, setOpen] = (0, import_react.useState)(false);
142
172
  const [snapshot, setSnapshot] = (0, import_react.useState)(
143
173
  scope ? scope.getSnapshot() : null
@@ -175,14 +205,14 @@ function CodeIndexSettingsCard() {
175
205
  type: "button",
176
206
  className: "dci-header",
177
207
  "aria-expanded": open,
178
- "aria-label": `${open ? "\u6536\u8D77\u8BBE\u7F6E" : "\u5C55\u5F00\u8BBE\u7F6E"}: dsh-code-index`,
208
+ "aria-label": `${t(open ? "collapse" : "expand")}: dsh-code-index`,
179
209
  onClick: () => {
180
210
  setOpen(!open);
181
211
  },
182
212
  children: [
183
213
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dci-headText", children: [
184
214
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dci-name", children: "dsh-code-index" }),
185
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dci-description", children: "\u7ED3\u6784\u5316\u4ED3\u5E93\u7D22\u5F15\uFF1A\u7B26\u53F7\u641C\u7D22\u3001\u4ED3\u5E93\u5730\u56FE\u4E0E\u8C03\u7528\u56FE\u3002" })
215
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dci-description", children: t("description") })
186
216
  ] }),
187
217
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: open ? "dci-chevron dci-chevronOpen" : "dci-chevron", width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: CHEVRON_PATH, fill: "currentColor" }) })
188
218
  ]
@@ -191,7 +221,7 @@ function CodeIndexSettingsCard() {
191
221
  open ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dci-body", children: [
192
222
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dci-field", children: [
193
223
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dci-head", children: [
194
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "dci-label", htmlFor: "dci-auto-inject", children: "\u81EA\u52A8\u6CE8\u5165\u4ED3\u5E93\u5730\u56FE" }),
224
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "dci-label", htmlFor: "dci-auto-inject", children: t("autoInject") }),
195
225
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
196
226
  "input",
197
227
  {
@@ -206,11 +236,11 @@ function CodeIndexSettingsCard() {
206
236
  }
207
237
  )
208
238
  ] }),
209
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dci-hint", children: "\u628A\u7CBE\u7B80\u7684\u6392\u540D\u4ED3\u5E93\u5730\u56FE\u6CE8\u5165\u7CFB\u7EDF\u63D0\u793A\u8BCD\u3002" })
239
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dci-hint", children: t("autoInjectHint") })
210
240
  ] }),
211
241
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dci-field", children: [
212
242
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dci-head", children: [
213
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "dci-label", htmlFor: "dci-code-health", children: "\u4EE3\u7801\u5065\u5EB7\u5DE5\u5177" }),
243
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "dci-label", htmlFor: "dci-code-health", children: t("codeHealth") }),
214
244
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
215
245
  "input",
216
246
  {
@@ -225,10 +255,10 @@ function CodeIndexSettingsCard() {
225
255
  }
226
256
  )
227
257
  ] }),
228
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dci-hint", children: "\u6CE8\u518C code_health \u5DE5\u5177\uFF0C\u62A5\u544A\u73AF\u4F9D\u8D56\u4E0E\u5B64\u513F\u6A21\u5757\uFF08\u91CD\u542F\u540E\u751F\u6548\uFF09\u3002" })
258
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dci-hint", children: t("codeHealthHint") })
229
259
  ] }),
230
260
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dci-field", children: [
231
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dci-head", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "dci-label", htmlFor: "dci-map-files", children: "\u5730\u56FE\u6587\u4EF6\u6570" }) }),
261
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dci-head", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: "dci-label", htmlFor: "dci-map-files", children: t("mapFiles") }) }),
232
262
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
233
263
  "input",
234
264
  {
@@ -243,16 +273,16 @@ function CodeIndexSettingsCard() {
243
273
  }
244
274
  }
245
275
  ),
246
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dci-hint", children: "\u4ED3\u5E93\u5730\u56FE\u4E2D\u6700\u591A\u5C55\u793A\u7684\u6587\u4EF6\u6570\u3002" })
276
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dci-hint", children: t("mapFilesHint") })
247
277
  ] }),
248
278
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dci-footer", children: [
249
279
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "dci-discard", disabled: !dirty || !writable, onClick: () => {
250
280
  setDraft(null);
251
- }, children: "\u653E\u5F03\u4FEE\u6539" }),
252
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "dci-save", disabled: !dirty || !writable, onClick: save, children: "\u4FDD\u5B58" })
281
+ }, children: t("discard") }),
282
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "dci-save", disabled: !dirty || !writable, onClick: save, children: t("save") })
253
283
  ] })
254
284
  ] }) : null,
255
- scope ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dci-hint", style: { padding: "0 16px 12px" }, children: "\u8BBE\u7F6E\u670D\u52A1\u4E0D\u53EF\u7528\u3002" })
285
+ scope ? null : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dci-hint", style: { padding: "0 16px 12px" }, children: t("unavailable") })
256
286
  ] });
257
287
  }
258
288
  var name = "dsh-code-index";
@@ -269,16 +299,41 @@ var TOOLVIEW_KEYS = [
269
299
  ];
270
300
  function apply(ctx) {
271
301
  const card = CodeToolCard;
302
+ ctx.inject?.(["locale"], (localized) => {
303
+ if (localized.locale) localized.effect(() => localized.locale.register("settings.codeIndex", { zh: SETTINGS_ZH, en: SETTINGS_EN }));
304
+ });
272
305
  ctx.slots.inject("tool.call.toolview", function* () {
273
306
  for (const key of TOOLVIEW_KEYS) {
274
307
  yield ctx.slots.register({ name: "tool.call.toolview", key }, card);
275
308
  }
276
309
  });
277
- ctx.inject(["settingsScope"], (scoped) => {
278
- activeScope = scoped.settingsScope?.bind({ namespace: "code-index" }) ?? null;
279
- ctx.slots.inject("settings.plugin.item", function* () {
280
- yield ctx.slots.register(
281
- { name: "settings.plugin.item", key: "code-index" },
310
+ ctx.inject?.(["configForms"], (configured) => {
311
+ const form = configured.configForms?.get("dsh-code-index") ?? configured.configForms?.get("code-index");
312
+ if (!form) return;
313
+ configured.slots.inject("settings.plugins.tab", function* () {
314
+ yield configured.slots.register(
315
+ {
316
+ name: "settings.plugins.tab",
317
+ id: "code-index",
318
+ order: 60,
319
+ label: "Code Index",
320
+ locale: "settings.codeIndex",
321
+ inject: () => ({ scope: form })
322
+ },
323
+ CodeIndexSettingsCard
324
+ );
325
+ });
326
+ });
327
+ ctx.inject?.(["settingsScope"], (legacy) => {
328
+ const settingsScope = legacy.settingsScope?.bind({ namespace: "code-index" });
329
+ legacy.slots.inject("settings.plugin.item", function* () {
330
+ yield legacy.slots.register(
331
+ {
332
+ name: "settings.plugin.item",
333
+ key: "code-index",
334
+ locale: "settings.codeIndex",
335
+ inject: () => ({ scope: settingsScope })
336
+ },
282
337
  CodeIndexSettingsCard
283
338
  );
284
339
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/index.tsx"],"sourcesContent":["/**\n * Browser half of dsh-code-index: structured result cards for the code_* tools\n * plus a settings card for the `code-index` namespace.\n *\n * Deliberately imports no harness client package: this bundle only needs\n * `react` (a shell platform module) plus the slot registry and settings scope\n * services reached through the plugin context. Keeping the surface local avoids\n * a dependency on a synchronized client-package version.\n */\n\nimport { useEffect, useState, type ReactNode } from 'react'\n\n/** Minimal structural view of the client plugin context this bundle uses. */\ninterface ClientContextLike {\n slots: {\n inject(name: string, run: () => Iterable<unknown>): void\n register(entry: Record<string, unknown>, component: (props: never) => ReactNode): () => void\n }\n inject(deps: string[], run: (ctx: ClientContextLike) => void): unknown\n settingsScope?: { bind(spec: { namespace: string }): SettingsScopeLike<CodeIndexSettings> }\n}\n\ninterface SettingsSnapshot<T> {\n status: 'loading' | 'ready' | 'unavailable'\n value: T | undefined\n writable: boolean\n}\n\ninterface SettingsScopeLike<T> {\n getSnapshot(): SettingsSnapshot<T>\n subscribe(listener: () => void): () => void\n set(field: string, value: unknown): Promise<void>\n unset(field: string): Promise<void>\n}\n\ninterface CodeIndexSettings {\n excludeDirs?: string[]\n mapTopFiles?: number\n mapMaxChars?: number\n mapTtlMs?: number\n autoInject?: boolean\n codeHealth?: boolean\n toolSurface?: 'full' | 'compact'\n}\n\ninterface ToolCallHead {\n name?: string\n argsRaw?: string\n}\n\ninterface TextContent {\n type?: string\n text?: string\n}\n\ninterface ToolResultLike {\n call?: ToolCallHead | null\n content?: readonly TextContent[]\n isError?: boolean\n resultView?: unknown\n}\n\ninterface SearchView {\n card: 'search'\n shape?: 'matches' | 'paths'\n files?: Array<{ path: string; matches?: Array<{ lineNumber: number; line: string }> }>\n paths?: string[]\n truncated?: boolean\n total?: number\n}\n\ninterface ToolViewProps {\n toolName: string\n block: ToolResultLike & ToolCallHead\n openFile?: (path: string, options?: unknown) => void\n}\n\nconst CARD_STYLE: Record<string, string | number> = {\n border: '1px solid var(--dsh-border, #333)',\n borderRadius: 6,\n padding: '6px 8px',\n fontFamily: 'var(--dsh-mono-font, monospace)',\n fontSize: 12,\n margin: '4px 0',\n}\n\nconst ROW_STYLE: Record<string, string | number> = {\n display: 'flex',\n gap: 8,\n alignItems: 'baseline',\n}\n\nfunction parseArgs(raw: string | undefined): Record<string, unknown> {\n if (!raw) return {}\n try {\n const value: unknown = JSON.parse(raw)\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {}\n } catch {\n return {}\n }\n}\n\nfunction summarizeArgs(args: Record<string, unknown>): string {\n const parts: string[] = []\n for (const key of ['task', 'query', 'symbol', 'action', 'direction', 'kind', 'budgetChars']) {\n const value = args[key]\n if (typeof value === 'string' && value) parts.push(`${key}=${value}`)\n }\n return parts.join(' ')\n}\n\nfunction asSearchView(view: unknown): SearchView | undefined {\n if (typeof view !== 'object' || view === null || Array.isArray(view)) return undefined\n const record = view as Record<string, unknown>\n return record.card === 'search' ? (record as unknown as SearchView) : undefined\n}\n\nfunction resultText(block: ToolResultLike): string {\n return (block.content ?? [])\n .filter((part) => part.type === 'text' && typeof part.text === 'string')\n .map((part) => part.text ?? '')\n .join('\\n')\n}\n\n/** One code tool's card: argument summary, structured search matches, or text. */\nfunction CodeToolCard(props: ToolViewProps): ReactNode {\n const { toolName, block, openFile } = props\n const head: ToolCallHead = block.call ?? block\n const summary = summarizeArgs(parseArgs(head.argsRaw))\n const search = asSearchView(block.resultView)\n const isError = block.isError === true\n\n return (\n <div style={CARD_STYLE}>\n <div style={ROW_STYLE}>\n <strong>{toolName}</strong>\n {summary ? <span style={{ opacity: 0.75 }}>{summary}</span> : null}\n {isError ? <span style={{ color: '#e5534b' }}>error</span> : null}\n </div>\n {search?.shape === 'matches' && search.files ? (\n <div style={{ marginTop: 4 }}>\n {search.files.map((file) => (\n <div key={file.path}>\n <div style={{ opacity: 0.85 }}>{file.path}</div>\n {(file.matches ?? []).map((match, index) => (\n <div\n key={`${match.lineNumber}-${index}`}\n style={{ paddingLeft: 12, cursor: openFile ? 'pointer' : 'default' }}\n onClick={() => openFile?.(file.path, { line: match.lineNumber })}\n >\n <span style={{ opacity: 0.6 }}>{match.lineNumber}</span> {match.line}\n </div>\n ))}\n </div>\n ))}\n {search.truncated ? <div style={{ opacity: 0.6 }}>… truncated ({search.total} total)</div> : null}\n </div>\n ) : (\n <pre style={{ margin: '4px 0 0', whiteSpace: 'pre-wrap', maxHeight: 220, overflow: 'auto' }}>\n {resultText(block)}\n </pre>\n )}\n </div>\n )\n}\n\n/** The scope is captured at apply() time; the card reads it through React state. */\nlet activeScope: SettingsScopeLike<CodeIndexSettings> | null = null\n\n/** Mirrors the first-party plugin card + field CSS modules, under our own class names. */\nconst CARD_CSS = `\n.dci-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}\n.dci-card:hover{border-color:var(--dsw-alias-label-dimmed)}\n.dci-cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}\n.dci-header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}\n.dci-header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}\n.dci-headText{flex-direction:column;flex:1 1 0%;gap:4px;min-width:0;display:flex}\n.dci-name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}\n.dci-description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}\n.dci-chevron{color:var(--dsw-alias-label-tertiary);flex:0 0 auto;transition:transform .16s}\n.dci-chevronOpen{transform:rotate(180deg)}\n.dci-body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}\n.dci-field{flex-direction:column;gap:6px;padding:12px 0;display:flex}\n.dci-field+.dci-field{border-top:1px solid var(--dsw-alias-border-l2)}\n.dci-head{align-items:center;gap:8px;display:flex}\n.dci-label{min-width:0;color:var(--dsw-alias-label-primary);flex:1 1 0%;font-size:13px;font-weight:500;line-height:1.5}\n.dci-input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font:inherit;font-size:13px;line-height:1.5}\n.dci-input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}\n.dci-input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}\n.dci-check{width:16px;height:16px;flex:0 0 auto;accent-color:var(--dsw-alias-brand-primary)}\n.dci-hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}\n.dci-footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}\n.dci-discard,.dci-save{appearance:none;font:inherit;cursor:pointer;border:1px solid transparent;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}\n.dci-discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}\n.dci-discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}\n.dci-save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}\n.dci-discard:disabled,.dci-save:disabled{opacity:.4;cursor:default}\n`\n\nconst CHEVRON_PATH =\n 'M11.8486 5.5L11.4238 5.92383L8.69727 8.65137C8.44157 8.90706 8.21562 9.13382 8.01172 9.29785C7.79912 9.46883 7.55595 9.61756 7.25 9.66602C7.08435 9.69222 6.91565 9.69222 6.75 9.66602C6.44405 9.61756 6.20088 9.46883 5.98828 9.29785C5.78438 9.13382 5.55843 8.90706 5.30273 8.65137L2.57617 5.92383L2.15137 5.5L3 4.65137L3.42383 5.07617L6.15137 7.80273C6.42595 8.07732 6.59876 8.24849 6.74023 8.3623C6.87291 8.46904 6.92272 8.47813 6.9375 8.48047C6.97895 8.48703 7.02105 8.48703 7.0625 8.48047C7.07728 8.47813 7.12709 8.46904 7.25977 8.3623C7.40124 8.24849 7.57405 8.07732 7.84863 7.80273L10.5762 5.07617L11 4.65137L11.8486 5.5Z'\n\nconst SETTINGS_DEFAULTS = { autoInject: true, codeHealth: false, mapTopFiles: 24 }\nconst SETTINGS_FIELDS = ['autoInject', 'codeHealth', 'mapTopFiles'] as const\n\n/** Settings card for `code-index`, laid out like the first-party plugin cards. */\nfunction CodeIndexSettingsCard(): ReactNode {\n const scope = activeScope\n const [open, setOpen] = useState(false)\n const [snapshot, setSnapshot] = useState<SettingsSnapshot<CodeIndexSettings> | null>(\n scope ? scope.getSnapshot() : null,\n )\n const [draft, setDraft] = useState<CodeIndexSettings | null>(null)\n\n useEffect(() => {\n if (!scope) return\n setSnapshot(scope.getSnapshot())\n return scope.subscribe(() => setSnapshot(scope.getSnapshot()))\n }, [scope])\n\n const resolved = snapshot?.value ?? {}\n const form: CodeIndexSettings = { ...SETTINGS_DEFAULTS, ...resolved, ...draft }\n const writable = snapshot?.writable ?? false\n const changed = (key: (typeof SETTINGS_FIELDS)[number]): boolean =>\n form[key] !== (resolved[key] ?? SETTINGS_DEFAULTS[key])\n const dirty = draft !== null && SETTINGS_FIELDS.some(changed)\n\n const edit = (key: (typeof SETTINGS_FIELDS)[number], value: string | number | boolean): void => {\n setDraft({ ...form, [key]: value })\n }\n const save = (): void => {\n if (!scope) return\n for (const key of SETTINGS_FIELDS) {\n if (changed(key)) {\n scope.set(key, form[key]).catch((error: unknown) => {\n console.error('[dsh-code-index] settings save failed', error)\n })\n }\n }\n setDraft(null)\n }\n\n return (\n <li className={open ? 'dci-card dci-cardOpen' : 'dci-card'}>\n <style>{CARD_CSS}</style>\n <button\n type=\"button\"\n className=\"dci-header\"\n aria-expanded={open}\n aria-label={`${open ? '收起设置' : '展开设置'}: dsh-code-index`}\n onClick={() => { setOpen(!open) }}\n >\n <span className=\"dci-headText\">\n <span className=\"dci-name\">dsh-code-index</span>\n <span className=\"dci-description\">结构化仓库索引:符号搜索、仓库地图与调用图。</span>\n </span>\n <svg className={open ? 'dci-chevron dci-chevronOpen' : 'dci-chevron'} width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d={CHEVRON_PATH} fill=\"currentColor\" />\n </svg>\n </button>\n {open ? (\n <div className=\"dci-body\">\n <div className=\"dci-field\">\n <div className=\"dci-head\">\n <label className=\"dci-label\" htmlFor=\"dci-auto-inject\">自动注入仓库地图</label>\n <input\n id=\"dci-auto-inject\"\n className=\"dci-check\"\n type=\"checkbox\"\n checked={form.autoInject}\n disabled={!writable}\n onChange={(event) => { edit('autoInject', event.target.checked) }}\n />\n </div>\n <p className=\"dci-hint\">把精简的排名仓库地图注入系统提示词。</p>\n </div>\n <div className=\"dci-field\">\n <div className=\"dci-head\">\n <label className=\"dci-label\" htmlFor=\"dci-code-health\">代码健康工具</label>\n <input\n id=\"dci-code-health\"\n className=\"dci-check\"\n type=\"checkbox\"\n checked={form.codeHealth}\n disabled={!writable}\n onChange={(event) => { edit('codeHealth', event.target.checked) }}\n />\n </div>\n <p className=\"dci-hint\">注册 code_health 工具,报告环依赖与孤儿模块(重启后生效)。</p>\n </div>\n <div className=\"dci-field\">\n <div className=\"dci-head\">\n <label className=\"dci-label\" htmlFor=\"dci-map-files\">地图文件数</label>\n </div>\n <input\n id=\"dci-map-files\"\n className=\"dci-input\"\n type=\"text\"\n inputMode=\"numeric\"\n value={String(form.mapTopFiles)}\n disabled={!writable}\n onChange={(event) => { edit('mapTopFiles', Number(event.target.value)) }}\n />\n <p className=\"dci-hint\">仓库地图中最多展示的文件数。</p>\n </div>\n <div className=\"dci-footer\">\n <button type=\"button\" className=\"dci-discard\" disabled={!dirty || !writable} onClick={() => { setDraft(null) }}>\n 放弃修改\n </button>\n <button type=\"button\" className=\"dci-save\" disabled={!dirty || !writable} onClick={save}>保存</button>\n </div>\n </div>\n ) : null}\n {scope ? null : <p className=\"dci-hint\" style={{ padding: '0 16px 12px' }}>设置服务不可用。</p>}\n </li>\n )\n}\n\nexport const name = 'dsh-code-index'\n\n/** `slots` is required for direct access; `settingsScope` binds lazily below. */\nexport const inject = ['slots']\n\nconst TOOLVIEW_KEYS = [\n 'code_index',\n 'code_symbols',\n 'code_search',\n 'code_map',\n 'code_refs',\n 'code_change_context',\n 'code_context',\n 'code_health',\n]\n\nexport function apply(ctx: ClientContextLike): void {\n const card = CodeToolCard as unknown as (props: never) => ReactNode\n ctx.slots.inject('tool.call.toolview', function* () {\n for (const key of TOOLVIEW_KEYS) {\n yield ctx.slots.register({ name: 'tool.call.toolview', key }, card)\n }\n })\n\n ctx.inject(['settingsScope'], (scoped: ClientContextLike) => {\n activeScope = scoped.settingsScope?.bind({ namespace: 'code-index' }) ?? null\n ctx.slots.inject('settings.plugin.item', function* () {\n yield ctx.slots.register(\n { name: 'settings.plugin.item', key: 'code-index' },\n CodeIndexSettingsCard as unknown as (props: never) => ReactNode,\n )\n })\n })\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/client/index.tsx"],"sourcesContent":["/**\n * Browser half of dsh-code-index: structured result cards for the code_* tools\n * plus a settings card for the `code-index` namespace.\n *\n * Deliberately imports no harness client package: this bundle only needs\n * `react` (a shell platform module) plus the slot registry and settings scope\n * services reached through the plugin context. Keeping the surface local avoids\n * a dependency on a synchronized client-package version.\n */\n\nimport { useEffect, useState, type ReactNode } from 'react'\n\n/** Minimal structural view of the client plugin context this bundle uses. */\ninterface ClientContextLike {\n effect(fn: () => (() => void) | void): void\n slots: {\n inject(name: string, run: () => Iterable<unknown>): void\n register(entry: Record<string, unknown>, component: (props: never) => ReactNode): () => void\n }\n inject?(deps: string[], run: (ctx: ClientContextLike) => void): unknown\n settingsScope?: { bind(spec: { namespace: string }): SettingsScopeLike<CodeIndexSettings> }\n configForms?: { get(id: string): SettingsScopeLike<CodeIndexSettings> | undefined }\n locale?: { register(namespace: string, dictionaries: { zh: Record<string, string>; en: Record<string, string> }): () => void }\n}\n\ninterface SettingsSnapshot<T> {\n status: 'loading' | 'ready' | 'unavailable'\n value: T | undefined\n writable: boolean\n}\n\ninterface SettingsScopeLike<T> {\n getSnapshot(): SettingsSnapshot<T>\n subscribe(listener: () => void): () => void\n set(field: string, value: unknown): Promise<void>\n unset(field: string): Promise<void>\n}\n\ninterface CodeIndexSettings {\n excludeDirs?: string[]\n mapTopFiles?: number\n mapMaxChars?: number\n mapTtlMs?: number\n autoInject?: boolean\n codeHealth?: boolean\n toolSurface?: 'full' | 'compact'\n}\n\ninterface ToolCallHead {\n name?: string\n argsRaw?: string\n}\n\ninterface TextContent {\n type?: string\n text?: string\n}\n\ninterface ToolResultLike {\n call?: ToolCallHead | null\n content?: readonly TextContent[]\n isError?: boolean\n resultView?: unknown\n}\n\ninterface SearchView {\n card: 'search'\n shape?: 'matches' | 'paths'\n files?: Array<{ path: string; matches?: Array<{ lineNumber: number; line: string }> }>\n paths?: string[]\n truncated?: boolean\n total?: number\n}\n\ninterface ToolViewProps {\n toolName: string\n block: ToolResultLike & ToolCallHead\n openFile?: (path: string, options?: unknown) => void\n}\n\nconst CARD_STYLE: Record<string, string | number> = {\n border: '1px solid var(--dsh-border, #333)',\n borderRadius: 6,\n padding: '6px 8px',\n fontFamily: 'var(--dsh-mono-font, monospace)',\n fontSize: 12,\n margin: '4px 0',\n}\n\nconst ROW_STYLE: Record<string, string | number> = {\n display: 'flex',\n gap: 8,\n alignItems: 'baseline',\n}\n\nfunction parseArgs(raw: string | undefined): Record<string, unknown> {\n if (!raw) return {}\n try {\n const value: unknown = JSON.parse(raw)\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {}\n } catch {\n return {}\n }\n}\n\nfunction summarizeArgs(args: Record<string, unknown>): string {\n const parts: string[] = []\n for (const key of ['task', 'query', 'symbol', 'action', 'direction', 'kind', 'budgetChars']) {\n const value = args[key]\n if (typeof value === 'string' && value) parts.push(`${key}=${value}`)\n }\n return parts.join(' ')\n}\n\nfunction asSearchView(view: unknown): SearchView | undefined {\n if (typeof view !== 'object' || view === null || Array.isArray(view)) return undefined\n const record = view as Record<string, unknown>\n return record.card === 'search' ? (record as unknown as SearchView) : undefined\n}\n\nfunction resultText(block: ToolResultLike): string {\n return (block.content ?? [])\n .filter((part) => part.type === 'text' && typeof part.text === 'string')\n .map((part) => part.text ?? '')\n .join('\\n')\n}\n\n/** One code tool's card: argument summary, structured search matches, or text. */\nfunction CodeToolCard(props: ToolViewProps): ReactNode {\n const { toolName, block, openFile } = props\n const head: ToolCallHead = block.call ?? block\n const summary = summarizeArgs(parseArgs(head.argsRaw))\n const search = asSearchView(block.resultView)\n const isError = block.isError === true\n\n return (\n <div style={CARD_STYLE}>\n <div style={ROW_STYLE}>\n <strong>{toolName}</strong>\n {summary ? <span style={{ opacity: 0.75 }}>{summary}</span> : null}\n {isError ? <span style={{ color: '#e5534b' }}>error</span> : null}\n </div>\n {search?.shape === 'matches' && search.files ? (\n <div style={{ marginTop: 4 }}>\n {search.files.map((file) => (\n <div key={file.path}>\n <div style={{ opacity: 0.85 }}>{file.path}</div>\n {(file.matches ?? []).map((match, index) => (\n <div\n key={`${match.lineNumber}-${index}`}\n style={{ paddingLeft: 12, cursor: openFile ? 'pointer' : 'default' }}\n onClick={() => openFile?.(file.path, { line: match.lineNumber })}\n >\n <span style={{ opacity: 0.6 }}>{match.lineNumber}</span> {match.line}\n </div>\n ))}\n </div>\n ))}\n {search.truncated ? <div style={{ opacity: 0.6 }}>… truncated ({search.total} total)</div> : null}\n </div>\n ) : (\n <pre style={{ margin: '4px 0 0', whiteSpace: 'pre-wrap', maxHeight: 220, overflow: 'auto' }}>\n {resultText(block)}\n </pre>\n )}\n </div>\n )\n}\n\n/** Mirrors the first-party plugin card + field CSS modules, under our own class names. */\nconst CARD_CSS = `\n.dci-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}\n.dci-card:hover{border-color:var(--dsw-alias-label-dimmed)}\n.dci-cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}\n.dci-header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}\n.dci-header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}\n.dci-headText{flex-direction:column;flex:1 1 0%;gap:4px;min-width:0;display:flex}\n.dci-name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}\n.dci-description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}\n.dci-chevron{color:var(--dsw-alias-label-tertiary);flex:0 0 auto;transition:transform .16s}\n.dci-chevronOpen{transform:rotate(180deg)}\n.dci-body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}\n.dci-field{flex-direction:column;gap:6px;padding:12px 0;display:flex}\n.dci-field+.dci-field{border-top:1px solid var(--dsw-alias-border-l2)}\n.dci-head{align-items:center;gap:8px;display:flex}\n.dci-label{min-width:0;color:var(--dsw-alias-label-primary);flex:1 1 0%;font-size:13px;font-weight:500;line-height:1.5}\n.dci-input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font:inherit;font-size:13px;line-height:1.5}\n.dci-input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}\n.dci-input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}\n.dci-check{width:16px;height:16px;flex:0 0 auto;accent-color:var(--dsw-alias-brand-primary)}\n.dci-hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}\n.dci-footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}\n.dci-discard,.dci-save{appearance:none;font:inherit;cursor:pointer;border:1px solid transparent;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}\n.dci-discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}\n.dci-discard:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-dimmed)}\n.dci-save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}\n.dci-discard:disabled,.dci-save:disabled{opacity:.4;cursor:default}\n`\n\nconst CHEVRON_PATH =\n 'M11.8486 5.5L11.4238 5.92383L8.69727 8.65137C8.44157 8.90706 8.21562 9.13382 8.01172 9.29785C7.79912 9.46883 7.55595 9.61756 7.25 9.66602C7.08435 9.69222 6.91565 9.69222 6.75 9.66602C6.44405 9.61756 6.20088 9.46883 5.98828 9.29785C5.78438 9.13382 5.55843 8.90706 5.30273 8.65137L2.57617 5.92383L2.15137 5.5L3 4.65137L3.42383 5.07617L6.15137 7.80273C6.42595 8.07732 6.59876 8.24849 6.74023 8.3623C6.87291 8.46904 6.92272 8.47813 6.9375 8.48047C6.97895 8.48703 7.02105 8.48703 7.0625 8.48047C7.07728 8.47813 7.12709 8.46904 7.25977 8.3623C7.40124 8.24849 7.57405 8.07732 7.84863 7.80273L10.5762 5.07617L11 4.65137L11.8486 5.5Z'\n\nconst SETTINGS_DEFAULTS = { autoInject: true, codeHealth: false, mapTopFiles: 24 }\nconst SETTINGS_FIELDS = ['autoInject', 'codeHealth', 'mapTopFiles'] as const\n\n/** Settings card for `code-index`, laid out like the first-party plugin cards. */\nexport const SETTINGS_EN = {\n collapse: 'Collapse settings', expand: 'Expand settings',\n description: 'Project-aware live structural context: symbol search, repo map, and call graph.',\n autoInject: 'Inject repo map', autoInjectHint: 'Add a compact ranked map of the current project to the system prompt.',\n codeHealth: 'Code health tool', codeHealthHint: 'Register code_health for dependency cycles and orphan modules (restart required).',\n mapFiles: 'Map files', mapFilesHint: 'Maximum number of files shown in each repo map.',\n discard: 'Discard changes', save: 'Save', unavailable: 'Settings service unavailable.',\n}\nexport const SETTINGS_ZH = {\n collapse: '收起设置', expand: '展开设置',\n description: '项目感知的实时结构化上下文:符号搜索、仓库地图与调用图。',\n autoInject: '自动注入仓库地图', autoInjectHint: '把当前项目的精简排名地图注入系统提示词。',\n codeHealth: '代码健康工具', codeHealthHint: '注册 code_health 工具,报告环依赖与孤儿模块(重启后生效)。',\n mapFiles: '地图文件数', mapFilesHint: '仓库地图中最多展示的文件数。',\n discard: '放弃修改', save: '保存', unavailable: '设置服务不可用。',\n}\n\nfunction CodeIndexSettingsCard(props: { scope?: SettingsScopeLike<CodeIndexSettings>; t?: (key: string) => string }): ReactNode {\n const scope = props.scope ?? null\n const t = props.t ?? ((key: string) => SETTINGS_EN[key as keyof typeof SETTINGS_EN] ?? key)\n const [open, setOpen] = useState(false)\n const [snapshot, setSnapshot] = useState<SettingsSnapshot<CodeIndexSettings> | null>(\n scope ? scope.getSnapshot() : null,\n )\n const [draft, setDraft] = useState<CodeIndexSettings | null>(null)\n\n useEffect(() => {\n if (!scope) return\n setSnapshot(scope.getSnapshot())\n return scope.subscribe(() => setSnapshot(scope.getSnapshot()))\n }, [scope])\n\n const resolved = snapshot?.value ?? {}\n const form: CodeIndexSettings = { ...SETTINGS_DEFAULTS, ...resolved, ...draft }\n const writable = snapshot?.writable ?? false\n const changed = (key: (typeof SETTINGS_FIELDS)[number]): boolean =>\n form[key] !== (resolved[key] ?? SETTINGS_DEFAULTS[key])\n const dirty = draft !== null && SETTINGS_FIELDS.some(changed)\n\n const edit = (key: (typeof SETTINGS_FIELDS)[number], value: string | number | boolean): void => {\n setDraft({ ...form, [key]: value })\n }\n const save = (): void => {\n if (!scope) return\n for (const key of SETTINGS_FIELDS) {\n if (changed(key)) {\n scope.set(key, form[key]).catch((error: unknown) => {\n console.error('[dsh-code-index] settings save failed', error)\n })\n }\n }\n setDraft(null)\n }\n\n return (\n <li className={open ? 'dci-card dci-cardOpen' : 'dci-card'}>\n <style>{CARD_CSS}</style>\n <button\n type=\"button\"\n className=\"dci-header\"\n aria-expanded={open}\n aria-label={`${t(open ? 'collapse' : 'expand')}: dsh-code-index`}\n onClick={() => { setOpen(!open) }}\n >\n <span className=\"dci-headText\">\n <span className=\"dci-name\">dsh-code-index</span>\n <span className=\"dci-description\">{t('description')}</span>\n </span>\n <svg className={open ? 'dci-chevron dci-chevronOpen' : 'dci-chevron'} width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d={CHEVRON_PATH} fill=\"currentColor\" />\n </svg>\n </button>\n {open ? (\n <div className=\"dci-body\">\n <div className=\"dci-field\">\n <div className=\"dci-head\">\n <label className=\"dci-label\" htmlFor=\"dci-auto-inject\">{t('autoInject')}</label>\n <input\n id=\"dci-auto-inject\"\n className=\"dci-check\"\n type=\"checkbox\"\n checked={form.autoInject}\n disabled={!writable}\n onChange={(event) => { edit('autoInject', event.target.checked) }}\n />\n </div>\n <p className=\"dci-hint\">{t('autoInjectHint')}</p>\n </div>\n <div className=\"dci-field\">\n <div className=\"dci-head\">\n <label className=\"dci-label\" htmlFor=\"dci-code-health\">{t('codeHealth')}</label>\n <input\n id=\"dci-code-health\"\n className=\"dci-check\"\n type=\"checkbox\"\n checked={form.codeHealth}\n disabled={!writable}\n onChange={(event) => { edit('codeHealth', event.target.checked) }}\n />\n </div>\n <p className=\"dci-hint\">{t('codeHealthHint')}</p>\n </div>\n <div className=\"dci-field\">\n <div className=\"dci-head\">\n <label className=\"dci-label\" htmlFor=\"dci-map-files\">{t('mapFiles')}</label>\n </div>\n <input\n id=\"dci-map-files\"\n className=\"dci-input\"\n type=\"text\"\n inputMode=\"numeric\"\n value={String(form.mapTopFiles)}\n disabled={!writable}\n onChange={(event) => { edit('mapTopFiles', Number(event.target.value)) }}\n />\n <p className=\"dci-hint\">{t('mapFilesHint')}</p>\n </div>\n <div className=\"dci-footer\">\n <button type=\"button\" className=\"dci-discard\" disabled={!dirty || !writable} onClick={() => { setDraft(null) }}>\n {t('discard')}\n </button>\n <button type=\"button\" className=\"dci-save\" disabled={!dirty || !writable} onClick={save}>{t('save')}</button>\n </div>\n </div>\n ) : null}\n {scope ? null : <p className=\"dci-hint\" style={{ padding: '0 16px 12px' }}>{t('unavailable')}</p>}\n </li>\n )\n}\n\nexport const name = 'dsh-code-index'\n\n/** `slots` is required; config and locale services are injected optionally. */\nexport const inject = ['slots']\n\nconst TOOLVIEW_KEYS = [\n 'code_index',\n 'code_symbols',\n 'code_search',\n 'code_map',\n 'code_refs',\n 'code_change_context',\n 'code_context',\n 'code_health',\n]\n\nexport function apply(ctx: ClientContextLike): void {\n const card = CodeToolCard as unknown as (props: never) => ReactNode\n ctx.inject?.(['locale'], (localized) => {\n if (localized.locale) localized.effect(() => localized.locale!.register('settings.codeIndex', { zh: SETTINGS_ZH, en: SETTINGS_EN }))\n })\n ctx.slots.inject('tool.call.toolview', function* () {\n for (const key of TOOLVIEW_KEYS) {\n yield ctx.slots.register({ name: 'tool.call.toolview', key }, card)\n }\n })\n\n // New DSH exposes per-plugin volatile config forms and the plugin settings\n // tab. Keep the prior settingsScope slot for clients that still provide it.\n ctx.inject?.(['configForms'], (configured) => {\n const form = configured.configForms?.get('dsh-code-index') ?? configured.configForms?.get('code-index')\n if (!form) return\n configured.slots.inject('settings.plugins.tab', function* () {\n yield configured.slots.register(\n {\n name: 'settings.plugins.tab',\n id: 'code-index',\n order: 60,\n label: 'Code Index',\n locale: 'settings.codeIndex',\n inject: () => ({ scope: form }),\n },\n CodeIndexSettingsCard as unknown as (props: never) => ReactNode,\n )\n })\n })\n ctx.inject?.(['settingsScope'], (legacy) => {\n const settingsScope = legacy.settingsScope?.bind({ namespace: 'code-index' })\n legacy.slots.inject('settings.plugin.item', function* () {\n yield legacy.slots.register(\n {\n name: 'settings.plugin.item',\n key: 'code-index',\n locale: 'settings.codeIndex',\n inject: () => ({ scope: settingsScope }),\n },\n CodeIndexSettingsCard as unknown as (props: never) => ReactNode,\n )\n })\n })\n}\n"],"mappings":"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","names":[]}