@winspan/claude-forge 9.2.0 → 9.12.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/DEVELOPMENT.md +80 -19
- package/README.md +13 -6
- package/dist/catalogs/agents.json +19 -24
- package/dist/catalogs/skills.json +139 -27
- package/dist/claudemd/templates/swarm-protocol.md +1 -1
- package/dist/cli/commands/agent.d.ts +169 -0
- package/dist/cli/commands/agent.d.ts.map +1 -0
- package/dist/cli/commands/agent.js +690 -0
- package/dist/cli/commands/agent.js.map +1 -0
- package/dist/cli/commands/codegraph.d.ts +17 -0
- package/dist/cli/commands/codegraph.d.ts.map +1 -0
- package/dist/cli/commands/codegraph.js +263 -0
- package/dist/cli/commands/codegraph.js.map +1 -0
- package/dist/cli/commands/decisions.d.ts.map +1 -1
- package/dist/cli/commands/decisions.js +46 -9
- package/dist/cli/commands/decisions.js.map +1 -1
- package/dist/cli/commands/executions.d.ts.map +1 -1
- package/dist/cli/commands/executions.js +2 -1
- package/dist/cli/commands/executions.js.map +1 -1
- package/dist/cli/commands/insights-goal-check.d.ts +5 -1
- package/dist/cli/commands/insights-goal-check.d.ts.map +1 -1
- package/dist/cli/commands/insights-goal-check.js +15 -15
- package/dist/cli/commands/insights-goal-check.js.map +1 -1
- package/dist/cli/commands/knowledge.d.ts +51 -0
- package/dist/cli/commands/knowledge.d.ts.map +1 -1
- package/dist/cli/commands/knowledge.js +202 -29
- package/dist/cli/commands/knowledge.js.map +1 -1
- package/dist/cli/commands/loop.d.ts +95 -0
- package/dist/cli/commands/loop.d.ts.map +1 -0
- package/dist/cli/commands/loop.js +408 -0
- package/dist/cli/commands/loop.js.map +1 -0
- package/dist/cli/commands/maintenance.d.ts +33 -0
- package/dist/cli/commands/maintenance.d.ts.map +1 -0
- package/dist/cli/commands/maintenance.js +75 -0
- package/dist/cli/commands/maintenance.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +23 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +82 -0
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/skills.d.ts +131 -0
- package/dist/cli/commands/skills.d.ts.map +1 -1
- package/dist/cli/commands/skills.js +409 -9
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/commands/stats.d.ts.map +1 -1
- package/dist/cli/commands/stats.js +9 -2
- package/dist/cli/commands/stats.js.map +1 -1
- package/dist/cli/index.js +8 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/constants.d.ts +37 -0
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +43 -0
- package/dist/core/constants.js.map +1 -1
- package/dist/core/diagnostics/checks.d.ts.map +1 -1
- package/dist/core/diagnostics/checks.js +2 -1
- package/dist/core/diagnostics/checks.js.map +1 -1
- package/dist/core/diagnostics/daemon-status.d.ts +1 -1
- package/dist/core/diagnostics/daemon-status.d.ts.map +1 -1
- package/dist/core/diagnostics/daemon-status.js +1 -1
- package/dist/core/diagnostics/daemon-status.js.map +1 -1
- package/dist/core/diagnostics/entropy-checks.d.ts +3 -2
- package/dist/core/diagnostics/entropy-checks.d.ts.map +1 -1
- package/dist/core/diagnostics/entropy-checks.js +10 -5
- package/dist/core/diagnostics/entropy-checks.js.map +1 -1
- package/dist/core/diagnostics/heartbeat-reader.d.ts +28 -0
- package/dist/core/diagnostics/heartbeat-reader.d.ts.map +1 -0
- package/dist/core/diagnostics/heartbeat-reader.js +50 -0
- package/dist/core/diagnostics/heartbeat-reader.js.map +1 -0
- package/dist/core/event-fields.d.ts +27 -0
- package/dist/core/event-fields.d.ts.map +1 -1
- package/dist/core/event-fields.js +43 -0
- package/dist/core/event-fields.js.map +1 -1
- package/dist/core/governance/global-inject.d.ts +34 -4
- package/dist/core/governance/global-inject.d.ts.map +1 -1
- package/dist/core/governance/global-inject.js +80 -25
- package/dist/core/governance/global-inject.js.map +1 -1
- package/dist/core/insights/agent-anchor-guard.d.ts +77 -0
- package/dist/core/insights/agent-anchor-guard.d.ts.map +1 -0
- package/dist/core/insights/agent-anchor-guard.js +119 -0
- package/dist/core/insights/agent-anchor-guard.js.map +1 -0
- package/dist/core/insights/agent-distill-context.d.ts +55 -0
- package/dist/core/insights/agent-distill-context.d.ts.map +1 -0
- package/dist/core/insights/agent-distill-context.js +146 -0
- package/dist/core/insights/agent-distill-context.js.map +1 -0
- package/dist/core/insights/agent-distill-spawn.d.ts +56 -0
- package/dist/core/insights/agent-distill-spawn.d.ts.map +1 -0
- package/dist/core/insights/agent-distill-spawn.js +179 -0
- package/dist/core/insights/agent-distill-spawn.js.map +1 -0
- package/dist/core/insights/agent-drift.d.ts +66 -0
- package/dist/core/insights/agent-drift.d.ts.map +1 -0
- package/dist/core/insights/agent-drift.js +109 -0
- package/dist/core/insights/agent-drift.js.map +1 -0
- package/dist/core/insights/agent-evolution-sources.d.ts +21 -0
- package/dist/core/insights/agent-evolution-sources.d.ts.map +1 -0
- package/dist/core/insights/agent-evolution-sources.js +36 -0
- package/dist/core/insights/agent-evolution-sources.js.map +1 -0
- package/dist/core/insights/agent-health.d.ts +142 -0
- package/dist/core/insights/agent-health.d.ts.map +1 -0
- package/dist/core/insights/agent-health.js +296 -0
- package/dist/core/insights/agent-health.js.map +1 -0
- package/dist/core/insights/agent-patch-apply.d.ts +45 -0
- package/dist/core/insights/agent-patch-apply.d.ts.map +1 -0
- package/dist/core/insights/agent-patch-apply.js +165 -0
- package/dist/core/insights/agent-patch-apply.js.map +1 -0
- package/dist/core/insights/agent-suggest.d.ts +128 -0
- package/dist/core/insights/agent-suggest.d.ts.map +1 -0
- package/dist/core/insights/agent-suggest.js +284 -0
- package/dist/core/insights/agent-suggest.js.map +1 -0
- package/dist/core/insights/coverage-tiers.d.ts +46 -0
- package/dist/core/insights/coverage-tiers.d.ts.map +1 -0
- package/dist/core/insights/coverage-tiers.js +95 -0
- package/dist/core/insights/coverage-tiers.js.map +1 -0
- package/dist/{daemon/services → core/insights}/experience-extractor.d.ts +0 -7
- package/dist/core/insights/experience-extractor.d.ts.map +1 -0
- package/dist/{daemon/services → core/insights}/experience-extractor.js +5 -9
- package/dist/core/insights/experience-extractor.js.map +1 -0
- package/dist/{daemon/services → core/insights}/violation-reporter.d.ts +20 -1
- package/dist/core/insights/violation-reporter.d.ts.map +1 -0
- package/dist/{daemon/services → core/insights}/violation-reporter.js +56 -4
- package/dist/core/insights/violation-reporter.js.map +1 -0
- package/dist/core/loop/loop-engine.d.ts +140 -0
- package/dist/core/loop/loop-engine.d.ts.map +1 -0
- package/dist/core/loop/loop-engine.js +266 -0
- package/dist/core/loop/loop-engine.js.map +1 -0
- package/dist/core/queue/index.d.ts.map +1 -1
- package/dist/core/queue/index.js +2 -1
- package/dist/core/queue/index.js.map +1 -1
- package/dist/core/storage/base.d.ts +159 -0
- package/dist/core/storage/base.d.ts.map +1 -1
- package/dist/core/storage/base.js +523 -0
- package/dist/core/storage/base.js.map +1 -1
- package/dist/core/storage/codegraph-types.d.ts +79 -0
- package/dist/core/storage/codegraph-types.d.ts.map +1 -0
- package/dist/core/storage/codegraph-types.js +14 -0
- package/dist/core/storage/codegraph-types.js.map +1 -0
- package/dist/core/storage/codegraph.d.ts +186 -0
- package/dist/core/storage/codegraph.d.ts.map +1 -0
- package/dist/core/storage/codegraph.js +452 -0
- package/dist/core/storage/codegraph.js.map +1 -0
- package/dist/core/storage/decisions.d.ts +30 -5
- package/dist/core/storage/decisions.d.ts.map +1 -1
- package/dist/core/storage/decisions.js +45 -13
- package/dist/core/storage/decisions.js.map +1 -1
- package/dist/core/storage/events.d.ts +127 -0
- package/dist/core/storage/events.d.ts.map +1 -1
- package/dist/core/storage/events.js +318 -3
- package/dist/core/storage/events.js.map +1 -1
- package/dist/core/storage/feedback.d.ts +3 -23
- package/dist/core/storage/feedback.d.ts.map +1 -1
- package/dist/core/storage/feedback.js +37 -38
- package/dist/core/storage/feedback.js.map +1 -1
- package/dist/core/storage/injections.d.ts +40 -0
- package/dist/core/storage/injections.d.ts.map +1 -1
- package/dist/core/storage/injections.js +69 -0
- package/dist/core/storage/injections.js.map +1 -1
- package/dist/core/storage/knowledge.d.ts +226 -0
- package/dist/core/storage/knowledge.d.ts.map +1 -1
- package/dist/core/storage/knowledge.js +391 -4
- package/dist/core/storage/knowledge.js.map +1 -1
- package/dist/core/storage/pipeline-rollup.d.ts +1 -7
- package/dist/core/storage/pipeline-rollup.d.ts.map +1 -1
- package/dist/core/storage/pipeline-rollup.js +18 -57
- package/dist/core/storage/pipeline-rollup.js.map +1 -1
- package/dist/core/storage/routing.d.ts +34 -0
- package/dist/core/storage/routing.d.ts.map +1 -1
- package/dist/core/storage/routing.js +92 -2
- package/dist/core/storage/routing.js.map +1 -1
- package/dist/core/storage/rows.d.ts +5 -25
- package/dist/core/storage/rows.d.ts.map +1 -1
- package/dist/core/storage/schema.sql +92 -27
- package/dist/core/storage/sessions.d.ts.map +1 -1
- package/dist/core/storage/sessions.js +2 -1
- package/dist/core/storage/sessions.js.map +1 -1
- package/dist/core/storage/skills.d.ts +159 -0
- package/dist/core/storage/skills.d.ts.map +1 -1
- package/dist/core/storage/skills.js +350 -4
- package/dist/core/storage/skills.js.map +1 -1
- package/dist/core/storage/sqlite.d.ts +81 -25
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +143 -45
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/core/storage/tasks.d.ts +270 -0
- package/dist/core/storage/tasks.d.ts.map +1 -1
- package/dist/core/storage/tasks.js +495 -16
- package/dist/core/storage/tasks.js.map +1 -1
- package/dist/core/storage/tool-intercepts.d.ts +1 -1
- package/dist/core/storage/tool-intercepts.js +1 -1
- package/dist/core/types.d.ts +26 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +1 -3
- package/dist/core/types.js.map +1 -1
- package/dist/core/utils/binary-paths.d.ts +32 -0
- package/dist/core/utils/binary-paths.d.ts.map +1 -1
- package/dist/core/utils/binary-paths.js +52 -0
- package/dist/core/utils/binary-paths.js.map +1 -1
- package/dist/core/utils/claude-cli-resolver.d.ts.map +1 -0
- package/dist/{skills/distill → core/utils}/claude-cli-resolver.js +1 -1
- package/dist/core/utils/claude-cli-resolver.js.map +1 -0
- package/dist/core/utils/claude-cli-spawn.d.ts +1 -1
- package/dist/core/utils/claude-cli-spawn.js +2 -2
- package/dist/core/utils/claude-cli-spawn.js.map +1 -1
- package/dist/core/utils/noise-prompt.d.ts +1 -1
- package/dist/core/utils/noise-prompt.js +1 -1
- package/dist/core/utils/time.d.ts +26 -0
- package/dist/core/utils/time.d.ts.map +1 -1
- package/dist/core/utils/time.js +33 -0
- package/dist/core/utils/time.js.map +1 -1
- package/dist/daemon/config-store.d.ts.map +1 -1
- package/dist/daemon/config-store.js +14 -5
- package/dist/daemon/config-store.js.map +1 -1
- package/dist/daemon/event-parser.d.ts.map +1 -1
- package/dist/daemon/event-parser.js +5 -0
- package/dist/daemon/event-parser.js.map +1 -1
- package/dist/daemon/handlers/post-tool-use.d.ts +24 -16
- package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
- package/dist/daemon/handlers/post-tool-use.js +76 -116
- package/dist/daemon/handlers/post-tool-use.js.map +1 -1
- package/dist/daemon/handlers/pre-tool-use.d.ts +35 -10
- package/dist/daemon/handlers/pre-tool-use.d.ts.map +1 -1
- package/dist/daemon/handlers/pre-tool-use.js +71 -38
- package/dist/daemon/handlers/pre-tool-use.js.map +1 -1
- package/dist/daemon/handlers/stop.d.ts +20 -0
- package/dist/daemon/handlers/stop.d.ts.map +1 -1
- package/dist/daemon/handlers/stop.js +96 -8
- package/dist/daemon/handlers/stop.js.map +1 -1
- package/dist/daemon/handlers/user-prompt.d.ts +16 -1
- package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
- package/dist/daemon/handlers/user-prompt.js +97 -56
- package/dist/daemon/handlers/user-prompt.js.map +1 -1
- package/dist/daemon/handlers/violation-content-backfill.d.ts +76 -0
- package/dist/daemon/handlers/violation-content-backfill.d.ts.map +1 -0
- package/dist/daemon/handlers/violation-content-backfill.js +167 -0
- package/dist/daemon/handlers/violation-content-backfill.js.map +1 -0
- package/dist/daemon/index.d.ts +19 -0
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +125 -200
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/rules/defaults.d.ts.map +1 -1
- package/dist/daemon/rules/defaults.js +151 -64
- package/dist/daemon/rules/defaults.js.map +1 -1
- package/dist/daemon/rules/types.d.ts +28 -22
- package/dist/daemon/rules/types.d.ts.map +1 -1
- package/dist/daemon/rules/workflow-defaults.js +9 -9
- package/dist/daemon/rules/workflow-defaults.js.map +1 -1
- package/dist/daemon/services/codegraph-sync.d.ts +94 -0
- package/dist/daemon/services/codegraph-sync.d.ts.map +1 -0
- package/dist/daemon/services/codegraph-sync.js +159 -0
- package/dist/daemon/services/codegraph-sync.js.map +1 -0
- package/dist/daemon/services/decision-hint.d.ts +47 -10
- package/dist/daemon/services/decision-hint.d.ts.map +1 -1
- package/dist/daemon/services/decision-hint.js +99 -24
- package/dist/daemon/services/decision-hint.js.map +1 -1
- package/dist/daemon/services/event-ttl-sweep.d.ts.map +1 -1
- package/dist/daemon/services/event-ttl-sweep.js +3 -2
- package/dist/daemon/services/event-ttl-sweep.js.map +1 -1
- package/dist/daemon/services/feedback-aggregator.d.ts +14 -26
- package/dist/daemon/services/feedback-aggregator.d.ts.map +1 -1
- package/dist/daemon/services/feedback-aggregator.js +23 -63
- package/dist/daemon/services/feedback-aggregator.js.map +1 -1
- package/dist/daemon/services/heartbeat-writer.d.ts +6 -15
- package/dist/daemon/services/heartbeat-writer.d.ts.map +1 -1
- package/dist/daemon/services/heartbeat-writer.js +7 -36
- package/dist/daemon/services/heartbeat-writer.js.map +1 -1
- package/dist/daemon/services/kb-injector.d.ts +1 -1
- package/dist/daemon/services/kb-injector.d.ts.map +1 -1
- package/dist/daemon/services/kb-injector.js +10 -2
- package/dist/daemon/services/kb-injector.js.map +1 -1
- package/dist/daemon/services/kb-rebuild-scheduler.d.ts +95 -0
- package/dist/daemon/services/kb-rebuild-scheduler.d.ts.map +1 -0
- package/dist/daemon/services/kb-rebuild-scheduler.js +149 -0
- package/dist/daemon/services/kb-rebuild-scheduler.js.map +1 -0
- package/dist/daemon/services/loop-hint.d.ts +139 -0
- package/dist/daemon/services/loop-hint.d.ts.map +1 -0
- package/dist/daemon/services/loop-hint.js +272 -0
- package/dist/daemon/services/loop-hint.js.map +1 -0
- package/dist/daemon/services/outcome-classification-service.js +1 -1
- package/dist/daemon/services/outcome-classification-service.js.map +1 -1
- package/dist/daemon/services/task-segmenter.d.ts +11 -0
- package/dist/daemon/services/task-segmenter.d.ts.map +1 -1
- package/dist/daemon/services/task-segmenter.js +48 -2
- package/dist/daemon/services/task-segmenter.js.map +1 -1
- package/dist/daemon/startup/maintenance-schedulers.d.ts +68 -0
- package/dist/daemon/startup/maintenance-schedulers.d.ts.map +1 -0
- package/dist/daemon/startup/maintenance-schedulers.js +294 -0
- package/dist/daemon/startup/maintenance-schedulers.js.map +1 -0
- package/dist/daemon/templates/agents/agent-retro-distiller.md +106 -0
- package/dist/daemon/templates/agents/claudemd-writer.md +1 -0
- package/dist/daemon/templates/agents/coder.md +165 -8
- package/dist/daemon/templates/agents/decision-maker.md +107 -21
- package/dist/daemon/templates/agents/doc-reviewer.md +4 -1
- package/dist/daemon/templates/agents/harness-debug-full.md +85 -3
- package/dist/daemon/templates/agents/knowledge-builder.md +1 -0
- package/dist/daemon/templates/agents/patch-applier.md +1 -0
- package/dist/daemon/templates/agents/planner.md +55 -3
- package/dist/daemon/templates/agents/safety-net-implementer.md +278 -0
- package/dist/daemon/templates/agents/skill-distiller.md +1 -0
- package/dist/daemon/templates/agents/task-boundary-classifier.md +1 -0
- package/dist/daemon/templates/agents/verify-agent.md +128 -5
- package/dist/hooks/stop.sh +7 -1
- package/dist/knowledge/builder.js +36 -7
- package/dist/knowledge/builder.js.map +1 -1
- package/dist/knowledge/constants.d.ts +10 -5
- package/dist/knowledge/constants.d.ts.map +1 -1
- package/dist/knowledge/constants.js +10 -5
- package/dist/knowledge/constants.js.map +1 -1
- package/dist/knowledge/graph/edge-extractor.d.ts +45 -0
- package/dist/knowledge/graph/edge-extractor.d.ts.map +1 -0
- package/dist/knowledge/graph/edge-extractor.js +242 -0
- package/dist/knowledge/graph/edge-extractor.js.map +1 -0
- package/dist/knowledge/graph/impact.d.ts +73 -0
- package/dist/knowledge/graph/impact.d.ts.map +1 -0
- package/dist/knowledge/graph/impact.js +94 -0
- package/dist/knowledge/graph/impact.js.map +1 -0
- package/dist/knowledge/graph/types.d.ts +22 -0
- package/dist/knowledge/graph/types.d.ts.map +1 -0
- package/dist/knowledge/graph/types.js +13 -0
- package/dist/knowledge/graph/types.js.map +1 -0
- package/dist/knowledge/prompt.d.ts +9 -0
- package/dist/knowledge/prompt.d.ts.map +1 -1
- package/dist/knowledge/prompt.js +17 -5
- package/dist/knowledge/prompt.js.map +1 -1
- package/dist/knowledge/query.d.ts +13 -0
- package/dist/knowledge/query.d.ts.map +1 -1
- package/dist/knowledge/query.js +107 -10
- package/dist/knowledge/query.js.map +1 -1
- package/dist/knowledge/repo-map.d.ts +11 -5
- package/dist/knowledge/repo-map.d.ts.map +1 -1
- package/dist/knowledge/repo-map.js +42 -3
- package/dist/knowledge/repo-map.js.map +1 -1
- package/dist/knowledge/validator.d.ts.map +1 -1
- package/dist/knowledge/validator.js +69 -2
- package/dist/knowledge/validator.js.map +1 -1
- package/dist/mcp/server.d.ts +64 -8
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +233 -18
- package/dist/mcp/server.js.map +1 -1
- package/dist/skills/distill/distiller.js +1 -1
- package/dist/skills/distill/distiller.js.map +1 -1
- package/dist/skills/distilled/distilled-api-design.md +4 -0
- package/dist/skills/distilled/distilled-brainstorming.md +79 -0
- package/dist/skills/distilled/distilled-brand-guidelines.md +86 -0
- package/dist/skills/distilled/distilled-canvas-design.md +128 -0
- package/dist/skills/distilled/distilled-claude-api.md +185 -0
- package/dist/skills/distilled/distilled-creator.md +5 -2
- package/dist/skills/distilled/distilled-dispatching-parallel-agents.md +136 -0
- package/dist/skills/distilled/distilled-doc-coauthoring.md +144 -0
- package/dist/skills/distilled/distilled-docx.md +231 -0
- package/dist/skills/distilled/distilled-executing-plans.md +85 -50
- package/dist/skills/distilled/distilled-finishing-a-development-branch.md +213 -0
- package/dist/skills/distilled/distilled-frontend-design.md +118 -0
- package/dist/skills/distilled/distilled-harness-engineering.md +1 -1
- package/dist/skills/distilled/distilled-receiving-code-review.md +185 -0
- package/dist/skills/distilled/distilled-subagent-driven-development.md +124 -0
- package/dist/skills/distilled/distilled-systematic-debugging.md +108 -260
- package/dist/skills/distilled/distilled-test-driven-development.md +432 -0
- package/dist/skills/distilled/distilled-using-superpowers.md +134 -0
- package/dist/skills/distilled/distilled-verification-before-completion.md +88 -78
- package/dist/skills/distilled/distilled-writing-skills.md +175 -0
- package/dist/skills/registry.d.ts +10 -50
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +7 -118
- package/dist/skills/registry.js.map +1 -1
- package/dist/skills/tools/pipeline-suggest.js +2 -2
- package/dist/skills/tools/pipeline-suggest.js.map +1 -1
- package/dist/skills/tools/skill-invoke.d.ts +2 -1
- package/dist/skills/tools/skill-invoke.d.ts.map +1 -1
- package/dist/skills/tools/skill-invoke.js +3 -1
- package/dist/skills/tools/skill-invoke.js.map +1 -1
- package/dist/web/analytics/anti-pattern-detector.d.ts.map +1 -1
- package/dist/web/analytics/anti-pattern-detector.js +6 -1
- package/dist/web/analytics/anti-pattern-detector.js.map +1 -1
- package/dist/web/analytics/drift-detector.d.ts +6 -0
- package/dist/web/analytics/drift-detector.d.ts.map +1 -1
- package/dist/web/analytics/drift-detector.js +15 -8
- package/dist/web/analytics/drift-detector.js.map +1 -1
- package/dist/web/analytics/weekly-report.d.ts +13 -0
- package/dist/web/analytics/weekly-report.d.ts.map +1 -1
- package/dist/web/analytics/weekly-report.js +17 -3
- package/dist/web/analytics/weekly-report.js.map +1 -1
- package/dist/web/routes/_helpers.d.ts +31 -0
- package/dist/web/routes/_helpers.d.ts.map +1 -1
- package/dist/web/routes/_helpers.js +33 -0
- package/dist/web/routes/_helpers.js.map +1 -1
- package/dist/web/routes/agent-distill.d.ts +49 -0
- package/dist/web/routes/agent-distill.d.ts.map +1 -0
- package/dist/web/routes/agent-distill.js +526 -0
- package/dist/web/routes/agent-distill.js.map +1 -0
- package/dist/web/routes/config.d.ts +56 -0
- package/dist/web/routes/config.d.ts.map +1 -0
- package/dist/web/routes/config.js +243 -0
- package/dist/web/routes/config.js.map +1 -0
- package/dist/web/routes/decisions.js +1 -1
- package/dist/web/routes/decisions.js.map +1 -1
- package/dist/web/routes/error-handler.d.ts +0 -4
- package/dist/web/routes/error-handler.d.ts.map +1 -1
- package/dist/web/routes/error-handler.js +0 -8
- package/dist/web/routes/error-handler.js.map +1 -1
- package/dist/web/routes/events.d.ts.map +1 -1
- package/dist/web/routes/events.js +2 -1
- package/dist/web/routes/events.js.map +1 -1
- package/dist/web/routes/insights.d.ts.map +1 -1
- package/dist/web/routes/insights.js +0 -0
- package/dist/web/routes/insights.js.map +1 -1
- package/dist/web/routes/knowledge.d.ts +43 -2
- package/dist/web/routes/knowledge.d.ts.map +1 -1
- package/dist/web/routes/knowledge.js +117 -6
- package/dist/web/routes/knowledge.js.map +1 -1
- package/dist/web/routes/pipeline.d.ts +0 -9
- package/dist/web/routes/pipeline.d.ts.map +1 -1
- package/dist/web/routes/pipeline.js +0 -4
- package/dist/web/routes/pipeline.js.map +1 -1
- package/dist/web/routes/rules.d.ts.map +1 -1
- package/dist/web/routes/rules.js +20 -6
- package/dist/web/routes/rules.js.map +1 -1
- package/dist/web/routes/sessions.d.ts.map +1 -1
- package/dist/web/routes/sessions.js +8 -7
- package/dist/web/routes/sessions.js.map +1 -1
- package/dist/web/routes/skill-stats.d.ts.map +1 -1
- package/dist/web/routes/skill-stats.js +153 -16
- package/dist/web/routes/skill-stats.js.map +1 -1
- package/dist/web/routes/skills-distill.js +1 -1
- package/dist/web/routes/skills-distill.js.map +1 -1
- package/dist/web/routes/stats.d.ts.map +1 -1
- package/dist/web/routes/stats.js +2 -1
- package/dist/web/routes/stats.js.map +1 -1
- package/dist/web/routes/task-timeline.d.ts +95 -19
- package/dist/web/routes/task-timeline.d.ts.map +1 -1
- package/dist/web/routes/task-timeline.js +344 -88
- package/dist/web/routes/task-timeline.js.map +1 -1
- package/dist/web/routes/tasks.d.ts.map +1 -1
- package/dist/web/routes/tasks.js +52 -30
- package/dist/web/routes/tasks.js.map +1 -1
- package/dist/web/routes/violations.d.ts +1 -1
- package/dist/web/routes/violations.d.ts.map +1 -1
- package/dist/web/routes/violations.js +3 -2
- package/dist/web/routes/violations.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +20 -0
- package/dist/web/server.js.map +1 -1
- package/dist/web/services/agent-distill-manager.d.ts +122 -0
- package/dist/web/services/agent-distill-manager.d.ts.map +1 -0
- package/dist/web/services/agent-distill-manager.js +397 -0
- package/dist/web/services/agent-distill-manager.js.map +1 -0
- package/dist/web/services/distill-manager.d.ts +47 -0
- package/dist/web/services/distill-manager.d.ts.map +1 -1
- package/dist/web/services/distill-manager.js +103 -0
- package/dist/web/services/distill-manager.js.map +1 -1
- package/dist/web/static/assets/AgentDetailPage-DlUeA1sX.js +2 -0
- package/dist/web/static/assets/AgentDetailPage-DlUeA1sX.js.map +1 -0
- package/dist/web/static/assets/AgentDistillRunPage-Cybo4bii.js +3 -0
- package/dist/web/static/assets/AgentDistillRunPage-Cybo4bii.js.map +1 -0
- package/dist/web/static/assets/AgentsPage-Qd9FExLG.js +2 -0
- package/dist/web/static/assets/AgentsPage-Qd9FExLG.js.map +1 -0
- package/dist/web/static/assets/DaemonHealthPage-DTSVqtrI.js +2 -0
- package/dist/web/static/assets/DaemonHealthPage-DTSVqtrI.js.map +1 -0
- package/dist/web/static/assets/DecisionDetailPage-b4BA8dhc.js +2 -0
- package/dist/web/static/assets/DecisionDetailPage-b4BA8dhc.js.map +1 -0
- package/dist/web/static/assets/DecisionsPage-a3NRo_T7.js +2 -0
- package/dist/web/static/assets/DecisionsPage-a3NRo_T7.js.map +1 -0
- package/dist/web/static/assets/DiagnosticsPage-DIVdiIQG.js +2 -0
- package/dist/web/static/assets/DiagnosticsPage-DIVdiIQG.js.map +1 -0
- package/dist/web/static/assets/DistillDetailPage-U6a3l2iP.js +4 -0
- package/dist/web/static/assets/DistillDetailPage-U6a3l2iP.js.map +1 -0
- package/dist/web/static/assets/DistillPage-O7BHtRN8.js +2 -0
- package/dist/web/static/assets/DistillPage-O7BHtRN8.js.map +1 -0
- package/dist/web/static/assets/DistillRunPage-D1JuRWWr.js +2 -0
- package/dist/web/static/assets/DistillRunPage-D1JuRWWr.js.map +1 -0
- package/dist/web/static/assets/GlobalScopeHint-Q3wTJx3F.js +2 -0
- package/dist/web/static/assets/GlobalScopeHint-Q3wTJx3F.js.map +1 -0
- package/dist/web/static/assets/IssueDetailPage-BDfrtk2C.js +2 -0
- package/dist/web/static/assets/IssueDetailPage-BDfrtk2C.js.map +1 -0
- package/dist/web/static/assets/IssuesPage-SKmhlCrw.js +2 -0
- package/dist/web/static/assets/IssuesPage-SKmhlCrw.js.map +1 -0
- package/dist/web/static/assets/KbDetailPage-Yna86Na8.js +2 -0
- package/dist/web/static/assets/KbDetailPage-Yna86Na8.js.map +1 -0
- package/dist/web/static/assets/KbHitsPage-Cljl7H9p.js +2 -0
- package/dist/web/static/assets/KbHitsPage-Cljl7H9p.js.map +1 -0
- package/dist/web/static/assets/{MarkdownRenderer-DZmTl-8J.js → MarkdownRenderer-DlDQNihj.js} +2 -2
- package/dist/web/static/assets/{MarkdownRenderer-DZmTl-8J.js.map → MarkdownRenderer-DlDQNihj.js.map} +1 -1
- package/dist/web/static/assets/NotFound-LMzbP51V.js +2 -0
- package/dist/web/static/assets/{NotFound-BQPh0vaF.js.map → NotFound-LMzbP51V.js.map} +1 -1
- package/dist/web/static/assets/SettingsPage-DzoK4PKg.js +2 -0
- package/dist/web/static/assets/SettingsPage-DzoK4PKg.js.map +1 -0
- package/dist/web/static/assets/SkillDetailPage-BuBJJ_NX.js +2 -0
- package/dist/web/static/assets/SkillDetailPage-BuBJJ_NX.js.map +1 -0
- package/dist/web/static/assets/SkillsPage-aojkJpBc.js +2 -0
- package/dist/web/static/assets/SkillsPage-aojkJpBc.js.map +1 -0
- package/dist/web/static/assets/TaskDetailPage-1ckxnGhw.js +4 -0
- package/dist/web/static/assets/TaskDetailPage-1ckxnGhw.js.map +1 -0
- package/dist/web/static/assets/TasksHubPage-C2PLh3eg.js +6 -0
- package/dist/web/static/assets/TasksHubPage-C2PLh3eg.js.map +1 -0
- package/dist/web/static/assets/WorkplacePage-DHrp5VxS.js +2 -0
- package/dist/web/static/assets/WorkplacePage-DHrp5VxS.js.map +1 -0
- package/dist/web/static/assets/arco-DV6xCLhr.js +14 -0
- package/dist/web/static/assets/arco-DV6xCLhr.js.map +1 -0
- package/dist/web/static/assets/charts-BSV4cyC4.js +37 -0
- package/dist/web/static/assets/charts-BSV4cyC4.js.map +1 -0
- package/dist/web/static/assets/{index-7bl3kbcx.css → index-B_v_MKlb.css} +1 -1
- package/dist/web/static/assets/index-DileOOE4.js +4 -0
- package/dist/web/static/assets/index-DileOOE4.js.map +1 -0
- package/dist/web/static/assets/markdown-CA7ePUts.js +30 -0
- package/dist/web/static/assets/markdown-CA7ePUts.js.map +1 -0
- package/dist/web/static/assets/{outcome-DUn1NjlC.js → outcome-BKGy9azt.js} +2 -2
- package/dist/web/static/assets/{outcome-DUn1NjlC.js.map → outcome-BKGy9azt.js.map} +1 -1
- package/dist/web/static/assets/{query-S6X1S7K9.js → query-CgCOpYWf.js} +2 -2
- package/dist/web/static/assets/{query-S6X1S7K9.js.map → query-CgCOpYWf.js.map} +1 -1
- package/dist/web/static/assets/{react-router-JVUrkhdd.js → react-router-Cxmg8RuL.js} +3 -3
- package/dist/web/static/assets/{react-router-JVUrkhdd.js.map → react-router-Cxmg8RuL.js.map} +1 -1
- package/dist/web/static/assets/{syntax-highlighter-BkZfCDsz.js → syntax-highlighter-BDYycNja.js} +3 -3
- package/dist/web/static/assets/{syntax-highlighter-BkZfCDsz.js.map → syntax-highlighter-BDYycNja.js.map} +1 -1
- package/dist/web/static/assets/task-title-BhOcemuR.js +2 -0
- package/dist/web/static/assets/task-title-BhOcemuR.js.map +1 -0
- package/dist/web/static/assets/useAgentStats-B-uTgqBd.js +2 -0
- package/dist/web/static/assets/useAgentStats-B-uTgqBd.js.map +1 -0
- package/dist/web/static/assets/useDecisions-D-G2Ft5T.js +2 -0
- package/dist/web/static/assets/useDecisions-D-G2Ft5T.js.map +1 -0
- package/dist/web/static/assets/useDistill-21dZkXlT.js +3 -0
- package/dist/web/static/assets/useDistill-21dZkXlT.js.map +1 -0
- package/dist/web/static/assets/useEffectiveProject-DQiyX54y.js +2 -0
- package/dist/web/static/assets/useEffectiveProject-DQiyX54y.js.map +1 -0
- package/dist/web/static/assets/useIssuesFeed-CFiyQkAL.js +2 -0
- package/dist/web/static/assets/useIssuesFeed-CFiyQkAL.js.map +1 -0
- package/dist/web/static/assets/useKbHits-xKXWgqh9.js +2 -0
- package/dist/web/static/assets/useKbHits-xKXWgqh9.js.map +1 -0
- package/dist/web/static/assets/useSkillStats-B5hbIwdf.js +2 -0
- package/dist/web/static/assets/useSkillStats-B5hbIwdf.js.map +1 -0
- package/dist/web/static/assets/vendor-DS-q4Eyc.js +36 -0
- package/dist/web/static/assets/vendor-DS-q4Eyc.js.map +1 -0
- package/dist/web/static/index.html +6 -6
- package/package.json +5 -3
- package/dist/core/storage/workflow-recommendations.d.ts +0 -124
- package/dist/core/storage/workflow-recommendations.d.ts.map +0 -1
- package/dist/core/storage/workflow-recommendations.js +0 -274
- package/dist/core/storage/workflow-recommendations.js.map +0 -1
- package/dist/daemon/services/experience-extractor.d.ts.map +0 -1
- package/dist/daemon/services/experience-extractor.js.map +0 -1
- package/dist/daemon/services/violation-reporter.d.ts.map +0 -1
- package/dist/daemon/services/violation-reporter.js.map +0 -1
- package/dist/daemon/templates/agents/harness-hotfix.md +0 -99
- package/dist/daemon/templates/agents/hybrid-feature-with-safety.md +0 -104
- package/dist/daemon/templates/agents/refactor-specialist.md +0 -98
- package/dist/skills/distill/claude-cli-resolver.d.ts.map +0 -1
- package/dist/skills/distill/claude-cli-resolver.js.map +0 -1
- package/dist/skills/distilled/distilled-defi-amm-security.md +0 -293
- package/dist/skills/keyword-score.d.ts +0 -29
- package/dist/skills/keyword-score.d.ts.map +0 -1
- package/dist/skills/keyword-score.js +0 -54
- package/dist/skills/keyword-score.js.map +0 -1
- package/dist/web/static/assets/AgentContentPage-DkeRNxok.js +0 -2
- package/dist/web/static/assets/AgentContentPage-DkeRNxok.js.map +0 -1
- package/dist/web/static/assets/AgentDelegationTable-ByBa0x1l.js +0 -2
- package/dist/web/static/assets/AgentDelegationTable-ByBa0x1l.js.map +0 -1
- package/dist/web/static/assets/ContextInsightsPage-oUk7_I8u.js +0 -3
- package/dist/web/static/assets/ContextInsightsPage-oUk7_I8u.js.map +0 -1
- package/dist/web/static/assets/DaemonHealthPage-DG2fyOP7.js +0 -2
- package/dist/web/static/assets/DaemonHealthPage-DG2fyOP7.js.map +0 -1
- package/dist/web/static/assets/DecisionsPage-CMAPEnKb.js +0 -2
- package/dist/web/static/assets/DecisionsPage-CMAPEnKb.js.map +0 -1
- package/dist/web/static/assets/DiagnosticsPage-DQd-Zm4r.js +0 -2
- package/dist/web/static/assets/DiagnosticsPage-DQd-Zm4r.js.map +0 -1
- package/dist/web/static/assets/DriftTab-DqpepOhI.js +0 -2
- package/dist/web/static/assets/DriftTab-DqpepOhI.js.map +0 -1
- package/dist/web/static/assets/HealthHomePage-CN6zNIie.js +0 -3
- package/dist/web/static/assets/HealthHomePage-CN6zNIie.js.map +0 -1
- package/dist/web/static/assets/KbHitRateTable-ByEIWujF.js +0 -2
- package/dist/web/static/assets/KbHitRateTable-ByEIWujF.js.map +0 -1
- package/dist/web/static/assets/NotFound-BQPh0vaF.js +0 -2
- package/dist/web/static/assets/ProjectSwitcher-D3lZMFd3.js +0 -2
- package/dist/web/static/assets/ProjectSwitcher-D3lZMFd3.js.map +0 -1
- package/dist/web/static/assets/SettingsPage-oLJBNzQj.js +0 -2
- package/dist/web/static/assets/SettingsPage-oLJBNzQj.js.map +0 -1
- package/dist/web/static/assets/SkillContentPage-DK5rgfgw.js +0 -2
- package/dist/web/static/assets/SkillContentPage-DK5rgfgw.js.map +0 -1
- package/dist/web/static/assets/SkillStatsTable-DYMzjEUV.js +0 -2
- package/dist/web/static/assets/SkillStatsTable-DYMzjEUV.js.map +0 -1
- package/dist/web/static/assets/SkillsDistillTab-C7qaG8q3.js +0 -2
- package/dist/web/static/assets/SkillsDistillTab-C7qaG8q3.js.map +0 -1
- package/dist/web/static/assets/TasksHubPage-03wsRRsJ.js +0 -6
- package/dist/web/static/assets/TasksHubPage-03wsRRsJ.js.map +0 -1
- package/dist/web/static/assets/ViolationsPage-DSiLr-9O.js +0 -3
- package/dist/web/static/assets/ViolationsPage-DSiLr-9O.js.map +0 -1
- package/dist/web/static/assets/arco-Bhi3a6Qp.js +0 -14
- package/dist/web/static/assets/arco-Bhi3a6Qp.js.map +0 -1
- package/dist/web/static/assets/charts-BuHQWDbQ.js +0 -37
- package/dist/web/static/assets/charts-BuHQWDbQ.js.map +0 -1
- package/dist/web/static/assets/index-BIYnq1Dx.js +0 -4
- package/dist/web/static/assets/index-BIYnq1Dx.js.map +0 -1
- package/dist/web/static/assets/useTabsParam-k8qte_0C.js +0 -2
- package/dist/web/static/assets/useTabsParam-k8qte_0C.js.map +0 -1
- package/dist/web/static/assets/vendor-DWgdB1eY.js +0 -65
- package/dist/web/static/assets/vendor-DWgdB1eY.js.map +0 -1
- /package/dist/{skills/distill → core/utils}/claude-cli-resolver.d.ts +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IssueDetailPage-BDfrtk2C.js","sources":["../../src/pages/IssueDetailPage.tsx"],"sourcesContent":["/**\n * IssueDetailPage — 治理 · 问题(治理)详情整页 (Phase 3b, decision 29688066).\n *\n * 替换 `/issues/:id` 的占位组件。整页(非抽屉)布局,翻译原型「问题详情」成\n * 真 Arco 组件(**严禁直搬原型 Tailwind CSS**):\n * A. 页头横条:返回 + 标题 + 类型/严重度 Tag + 元信息(规则 / 动作 / session / 时间 /\n * 关联任务)。\n * B. 横向统计条(类型 / 触发动作 / 严重度 / 近 7 天同类)。\n * C. 左主栏:①发生了什么(被拦命令原文 / 失败摘要 / 漂移 actual)②为什么拦(规则说明\n * + 命中阈值)③建议怎么做(hint)。\n * D. 右 360 栏:概要 Descriptions + 同类近 7 天计数(同规则/同类型计数)+ 关联任务链\n * `/tasks/:id`。\n *\n * 数据:复用 useIssuesFeed 的 merge 列表按稳定 id 定位(零新后端,不额外请求单条端点)。\n * 降级口径(端点真实缺字段,勿伪造):\n * - /api/violations 不返回被拦命令原文 / hint / session → ① 用 summary 兜底(标注摘要)、\n * ② / ③ 用规则启发文案、概要 session 显「端点未返回」。\n * - drift 详情主要展示 actual vs expected;失败任务详情链到 /tasks/:id。\n */\nimport { useMemo } from 'react'\nimport { useParams, useNavigate } from 'react-router-dom'\n\nimport Card from '@arco-design/web-react/es/Card'\nimport Grid from '@arco-design/web-react/es/Grid'\nimport Tag from '@arco-design/web-react/es/Tag'\nimport Typography from '@arco-design/web-react/es/Typography'\nimport Descriptions from '@arco-design/web-react/es/Descriptions'\nimport Button from '@arco-design/web-react/es/Button'\nimport Skeleton from '@arco-design/web-react/es/Skeleton'\nimport Result from '@arco-design/web-react/es/Result'\nimport Message from '@arco-design/web-react/es/Message'\nimport {\n IconLeft,\n IconExclamationCircle,\n IconCopy,\n IconCodeBlock,\n IconInfoCircle,\n IconBulb,\n IconRight,\n} from '@arco-design/web-react/icon'\n\nimport { useIssuesFeed } from '../hooks/useIssuesFeed'\nimport {\n findIssueById,\n countSimilar,\n typeLabel,\n typeColor,\n severityLabel,\n severityColor,\n fmtTime,\n type Issue,\n} from '../hooks/issues-derive'\n\nconst Row = Grid.Row\nconst Col = Grid.Col\n\nfunction typeTag(t: Issue['type']) {\n return <Tag color={typeColor(t)} size=\"small\">{typeLabel(t)}</Tag>\n}\nfunction sevTag(s: Issue['severity']) {\n return <Tag color={severityColor(s)} size=\"small\">{severityLabel(s)}</Tag>\n}\n\n/** 左栏分节卡(标题 + 图标 + 正文块)。 */\nfunction SectionCard({\n icon,\n title,\n children,\n}: {\n icon: React.ReactNode\n title: string\n children: React.ReactNode\n}) {\n return (\n <Card bordered>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>\n {icon}\n <Typography.Text style={{ fontSize: 15, fontWeight: 600 }}>{title}</Typography.Text>\n </div>\n {children}\n </Card>\n )\n}\n\nexport default function IssueDetailPage() {\n const { id } = useParams<{ id: string }>()\n const navigate = useNavigate()\n const { issues, loading, isError, error } = useIssuesFeed()\n\n const issue = useMemo(() => findIssueById(issues, id), [issues, id])\n const count7d = useMemo(() => (issue ? countSimilar(issues, issue) : 0), [issues, issue])\n\n if (loading) {\n return (\n <div style={{ padding: 16 }}>\n <Card bordered>\n <Skeleton animation text={{ rows: 10 }} />\n </Card>\n </div>\n )\n }\n\n if (isError || !issue) {\n return (\n <div style={{ padding: 16 }}>\n <Result\n status=\"error\"\n title=\"加载问题详情失败\"\n subTitle={error?.message || '问题不存在(id 可能已不在当前时间窗内)或端点不可用'}\n extra={\n <Button type=\"primary\" onClick={() => navigate('/issues')}>\n 返回问题\n </Button>\n }\n />\n </div>\n )\n }\n\n const copyRule = () => {\n try {\n void navigator.clipboard?.writeText(issue.rule)\n Message.success(`已复制规则 ${issue.rule}`)\n } catch {\n /* clipboard unavailable */\n }\n }\n\n const isFailure = issue.type === 'failure'\n const isDrift = issue.type === 'drift'\n\n // ① 发生了什么:命令原文用 code 块(深底等宽),失败/漂移用文本块。\n const whatBlock =\n !isFailure && !isDrift ? (\n <pre\n style={{\n margin: 0,\n padding: '12px 14px',\n background: '#1D2129',\n color: '#E5E6EB',\n borderRadius: 6,\n fontSize: 12,\n lineHeight: 1.6,\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n overflowX: 'auto',\n }}\n >\n {issue.what}\n </pre>\n ) : (\n <div\n style={{\n borderLeft: `3px solid ${isFailure ? 'rgb(var(--red-5))' : 'rgb(var(--gold-5))'}`,\n background: 'var(--color-fill-1)',\n borderRadius: '0 6px 6px 0',\n padding: '12px 14px',\n fontSize: 13,\n lineHeight: 1.6,\n }}\n >\n {issue.what}\n </div>\n )\n\n const whatLabel = isFailure\n ? 'verify-agent verdict / 失败摘要'\n : isDrift\n ? '漂移实测 vs 期望'\n : `被 ${issue.rule} 拦下的${issue.action === 'Bash' ? '命令' : '动作'}(端点未返回原文,下为摘要兜底)`\n\n return (\n <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 16 }}>\n {/* ── A. 页头横条 ─────────────────────────────────────────────── */}\n <Card bordered>\n <Button\n type=\"text\"\n size=\"small\"\n icon={<IconLeft />}\n style={{ marginBottom: 8, paddingLeft: 0 }}\n onClick={() => navigate('/issues')}\n >\n 返回问题\n </Button>\n <div\n style={{\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n gap: 16,\n flexWrap: 'wrap',\n }}\n >\n <div style={{ minWidth: 0, flex: 1 }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>\n <IconExclamationCircle style={{ color: 'rgb(var(--red-6))' }} />\n <Typography.Title heading={5} style={{ margin: 0 }}>\n {issue.title}\n </Typography.Title>\n {typeTag(issue.type)}\n {sevTag(issue.severity)}\n </div>\n <div\n style={{\n display: 'flex',\n gap: 12,\n flexWrap: 'wrap',\n marginTop: 8,\n alignItems: 'center',\n }}\n >\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 规则 <Typography.Text style={{ fontFamily: 'monospace' }}>{issue.rule}</Typography.Text>\n </Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 动作 <Typography.Text style={{ fontWeight: 600 }}>{issue.action}</Typography.Text>\n </Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12, fontFamily: 'monospace' }}>\n {issue.session ? `${issue.session.slice(0, 12)}…` : 'session 未返回'}\n </Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n {fmtTime(issue.time)}\n </Typography.Text>\n {issue.relatedTaskId ? (\n <Button\n type=\"text\"\n size=\"mini\"\n style={{ paddingLeft: 0, fontFamily: 'monospace', fontSize: 12 }}\n onClick={() => navigate(`/tasks/${encodeURIComponent(issue.relatedTaskId!)}`)}\n >\n 关联任务 {issue.relatedTaskId.slice(0, 8)}… <IconRight />\n </Button>\n ) : (\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 无关联任务\n </Typography.Text>\n )}\n </div>\n </div>\n <div style={{ display: 'flex', gap: 8, flexShrink: 0 }}>\n <Button size=\"small\" icon={<IconCopy />} onClick={copyRule}>\n 复制规则名\n </Button>\n </div>\n </div>\n </Card>\n\n {/* ── B. 横向统计条 ───────────────────────────────────────────── */}\n <Card bordered>\n <Row>\n <Col span={6}>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>类型</Typography.Text>\n <div style={{ fontSize: 13, fontWeight: 500, marginTop: 4 }}>{typeLabel(issue.type)}</div>\n </Col>\n <Col span={6}>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>触发动作</Typography.Text>\n <div style={{ fontSize: 13, fontWeight: 500, marginTop: 4 }}>{issue.action}</div>\n </Col>\n <Col span={6}>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>严重度</Typography.Text>\n <div style={{ fontSize: 13, fontWeight: 500, marginTop: 4 }}>{severityLabel(issue.severity)}</div>\n </Col>\n <Col span={6}>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>近 7 天同类</Typography.Text>\n <div style={{ fontSize: 13, fontWeight: 500, marginTop: 4 }}>{count7d} 次</div>\n </Col>\n </Row>\n </Card>\n\n <Row gutter={16}>\n {/* ── C. 左主栏 ─────────────────────────────────────────────── */}\n <Col xs={24} lg={16}>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n <SectionCard\n icon={<IconCodeBlock style={{ color: 'var(--color-text-3)' }} />}\n title={`① ${isFailure ? '发生了什么(失败)' : isDrift ? '发生了什么(漂移)' : '发生了什么'}`}\n >\n <Typography.Text type=\"secondary\" style={{ fontSize: 12, display: 'block', marginBottom: 6 }}>\n {whatLabel}\n </Typography.Text>\n {whatBlock}\n </SectionCard>\n\n <SectionCard\n icon={<IconInfoCircle style={{ color: 'rgb(var(--orange-6))' }} />}\n title={`② 为什么${isFailure ? '失败' : isDrift ? '判定漂移' : '拦'}`}\n >\n <div\n style={{\n background: 'var(--color-warning-light-1)',\n border: '1px solid var(--color-warning-light-3)',\n borderRadius: 6,\n padding: 14,\n fontSize: 13,\n lineHeight: 1.7,\n }}\n >\n {issue.why}\n </div>\n </SectionCard>\n\n <SectionCard\n icon={<IconBulb style={{ color: 'rgb(var(--arcoblue-6))' }} />}\n title=\"③ 建议怎么做\"\n >\n <div\n style={{\n background: 'var(--color-primary-light-1)',\n border: '1px solid var(--color-primary-light-3)',\n borderRadius: 6,\n padding: 14,\n fontSize: 13,\n lineHeight: 1.7,\n }}\n >\n {issue.hint}\n </div>\n </SectionCard>\n </div>\n </Col>\n\n {/* ── D. 右 360 栏 ──────────────────────────────────────────── */}\n <Col xs={24} lg={8}>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n <Card bordered title=\"概要\">\n <Descriptions\n column={1}\n size=\"small\"\n colon=\" \"\n data={[\n { label: 'ID', value: <span style={{ fontFamily: 'monospace', fontSize: 12 }}>{issue.id}</span> },\n { label: '规则', value: <span style={{ fontFamily: 'monospace', fontSize: 12 }}>{issue.rule}</span> },\n { label: '类型', value: typeTag(issue.type) },\n { label: '严重度', value: sevTag(issue.severity) },\n { label: '触发动作', value: issue.action },\n { label: 'session', value: <span style={{ fontFamily: 'monospace', fontSize: 12 }}>{issue.session ?? '端点未返回'}</span> },\n { label: '来源', value: issue.source },\n { label: '时间', value: fmtTime(issue.time) },\n ]}\n />\n </Card>\n\n <Card bordered title=\"同类问题计数\">\n <div style={{ display: 'flex', alignItems: 'flex-end', gap: 8 }}>\n <Typography.Text style={{ fontSize: 28, fontWeight: 600, lineHeight: 1, color: 'rgb(var(--red-6))' }}>\n {count7d}\n </Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 13, paddingBottom: 2 }}>\n 次 / 当前时间窗\n </Typography.Text>\n </div>\n <Typography.Paragraph type=\"secondary\" style={{ fontSize: 12, marginTop: 8, marginBottom: 0 }}>\n {issue.type === 'intercept' || issue.type === 'violation' ? (\n <>\n 规则 <span style={{ fontFamily: 'monospace' }}>{issue.rule}</span> 命中{' '}\n <Typography.Text style={{ fontWeight: 600 }}>{count7d}</Typography.Text> 次\n {count7d >= 4 ? ',已成高频信号,建议从命令写法 / 委托流程规避。' : ',偶发,注意复盘。'}\n </>\n ) : (\n <>同类「{typeLabel(issue.type)}」共 <Typography.Text style={{ fontWeight: 600 }}>{count7d}</Typography.Text> 条(当前时间窗内)。</>\n )}\n </Typography.Paragraph>\n </Card>\n\n <Card bordered title=\"关联任务\">\n {issue.relatedTaskId ? (\n <Button\n type=\"outline\"\n long\n onClick={() => navigate(`/tasks/${encodeURIComponent(issue.relatedTaskId!)}`)}\n >\n 查看任务 {issue.relatedTaskId.slice(0, 8)}… <IconRight />\n </Button>\n ) : (\n <Typography.Text type=\"secondary\" style={{ fontSize: 13 }}>\n {issue.source === 'violations'\n ? '违规拦截源端点未返回关联任务(降级)'\n : '该问题类型无关联任务'}\n </Typography.Text>\n )}\n </Card>\n </div>\n </Col>\n </Row>\n </div>\n )\n}\n"],"names":["Row","Grid","Col","typeTag","t","jsx","Tag","typeColor","typeLabel","sevTag","s","severityColor","severityLabel","SectionCard","icon","title","children","jsxs","Card","Typography","IssueDetailPage","id","useParams","navigate","useNavigate","issues","loading","isError","error","useIssuesFeed","issue","useMemo","findIssueById","count7d","countSimilar","Skeleton","Result","Button","copyRule","_a","Message","isFailure","isDrift","whatBlock","whatLabel","IconLeft","IconExclamationCircle","fmtTime","IconRight","IconCopy","IconCodeBlock","IconInfoCircle","IconBulb","Descriptions","Fragment"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as h,j as e}from"./react-vendor-tkvCrao7.js";import{D as W,J as a,T as i,ac as j,c as T,a1 as P,E as _,K as v,F as m,N as b,t as F,b as z}from"./arco-DV6xCLhr.js";import{u as D,s as $,b as L,f as K,t as M,a as N,c as U,d as A}from"./useIssuesFeed-CFiyQkAL.js";import{u as B}from"./react-router-Cxmg8RuL.js";import"./vendor-DS-q4Eyc.js";import"./query-CgCOpYWf.js";import"./index-DileOOE4.js";import"./lucide-CnlPQoG8.js";const u=T.TabPane,G=v.Row,J=v.Col;function q(r){return e.jsx(z,{color:N(r),size:"small",children:M(r)})}function C(r){return e.jsx(z,{color:A(r),size:"small",children:U(r)})}function H({issue:r}){return e.jsxs(a,{bordered:!0,style:{height:"100%"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap"},children:[e.jsx(F,{style:{color:"rgb(var(--gold-6))"}}),e.jsx(i.Text,{style:{fontSize:14,fontWeight:600},children:r.rule}),C(r.severity)]}),e.jsx(i.Paragraph,{style:{margin:"8px 0 0",fontSize:13},children:r.what}),e.jsx("div",{style:{marginTop:10,paddingTop:8,borderTop:"1px solid var(--color-border-1)",display:"flex",justifyContent:"flex-end"},children:e.jsxs(m,{type:"text",size:"mini",children:["查看详情 ",e.jsx(b,{})]})})]})}function se(){const r=B(),{issues:n,loading:I,isError:S,error:l,violationsError:f,tasksError:g,driftError:d,tasksTruncated:w}=D(),[k,E]=h.useState("primary"),{primary:c,drift:p}=h.useMemo(()=>$(n),[n]),o=h.useMemo(()=>L(n),[n]);if(S)return e.jsx("div",{style:{padding:16},children:e.jsx(W,{status:"error",title:"加载问题失败",subTitle:(l==null?void 0:l.message)||"三源端点均不可用"})});const x=s=>r(`/issues/${encodeURIComponent(s)}`),R=[{title:"类型",dataIndex:"type",width:84,render:(s,t)=>q(t.type)},{title:"严重度",dataIndex:"severity",width:76,render:(s,t)=>C(t.severity)},{title:"问题 · 规则",dataIndex:"title",render:(s,t)=>e.jsxs("div",{style:{minWidth:0},children:[e.jsx(i.Paragraph,{style:{margin:0,fontSize:13},ellipsis:{rows:1,showTooltip:!0},children:t.title}),e.jsx(i.Text,{type:"secondary",style:{fontSize:12,fontFamily:"monospace"},children:t.rule})]})},{title:"动作 / 来源",dataIndex:"action",width:110,render:(s,t)=>e.jsx(i.Text,{type:"secondary",style:{fontSize:12},children:t.action})},{title:"session / 任务",dataIndex:"session",width:130,render:(s,t)=>t.relatedTaskId?e.jsxs(m,{type:"text",size:"mini",style:{paddingLeft:0,fontFamily:"monospace",fontSize:12},onClick:y=>{y.stopPropagation(),r(`/tasks/${encodeURIComponent(t.relatedTaskId)}`)},children:[t.relatedTaskId.slice(0,8),"…"]}):t.session?e.jsxs(i.Text,{type:"secondary",style:{fontSize:12,fontFamily:"monospace"},children:[t.session.slice(0,8),"…"]}):e.jsx(i.Text,{type:"secondary",style:{fontSize:12},children:"—"})},{title:"时间",dataIndex:"time",width:120,sorter:(s,t)=>s.time<t.time?-1:s.time>t.time?1:0,render:(s,t)=>e.jsx(i.Text,{type:"secondary",style:{fontSize:12},children:K(t.time)})},{title:"操作",dataIndex:"op",width:72,align:"right",render:(s,t)=>e.jsxs(m,{type:"text",size:"mini",onClick:y=>{y.stopPropagation(),x(t.id)},children:["详情 ",e.jsx(b,{})]})}];return e.jsxs("div",{style:{padding:16,display:"flex",flexDirection:"column",gap:16},children:[e.jsxs(a,{bordered:!0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,flexWrap:"wrap"},children:[e.jsx(i.Title,{heading:6,style:{margin:0},children:"问题"}),e.jsx(i.Text,{type:"secondary",style:{fontSize:12},children:"前端 merge 三源 · 拦截 / 违规 / 失败任务 / 漂移(零新后端)"}),e.jsx("div",{style:{flex:1}}),e.jsxs(i.Text,{type:"secondary",style:{fontSize:12},children:["拦截 ",e.jsx(i.Text,{style:{fontWeight:600,color:"rgb(var(--red-6))"},children:o.intercept})]}),e.jsxs(i.Text,{type:"secondary",style:{fontSize:12},children:["违规 ",e.jsx(i.Text,{style:{fontWeight:600,color:"rgb(var(--orange-6))"},children:o.violation})]}),e.jsxs(i.Text,{type:"secondary",style:{fontSize:12},children:["失败 ",e.jsx(i.Text,{style:{fontWeight:600,color:"rgb(var(--red-6))"},children:o.failure})]}),e.jsxs(i.Text,{type:"secondary",style:{fontSize:12},children:["漂移 ",e.jsx(i.Text,{style:{fontWeight:600,color:"rgb(var(--gold-6))"},children:o.drift})]})]}),(f||g||d)&&e.jsx(j,{type:"warning",style:{marginTop:12},content:e.jsxs("span",{style:{fontSize:12},children:["部分源降级:",f&&"违规拦截源不可用;",g&&"失败任务源不可用;",d&&"漂移源不可用(/api/drift/report 报错,已降级跳过漂移项);","其余源照常合并。"]})}),w&&e.jsx(j,{type:"warning",style:{marginTop:12},content:e.jsx("span",{style:{fontSize:12},children:"失败任务可能因超出扫描上限少报:当前时间窗任务数超过分页扫描安全上限, 未扫描到的部分失败任务不在列表内。可缩短时间窗以覆盖更近期的任务。"})})]}),e.jsxs(T,{activeTab:k,onChange:s=>E(s),children:[e.jsx(u,{title:`拦截 / 违规 / 失败 ${c.length}`,children:e.jsx(a,{bordered:!0,style:{padding:0},children:e.jsx(P,{rowKey:"id",loading:I,data:c,columns:R,pagination:c.length>20?{pageSize:20,showTotal:!0}:!1,border:{wrapper:!1,cell:!1},onRow:s=>({onClick:()=>x(s.id),style:{cursor:"pointer"}})})})},"primary"),e.jsx(u,{title:`漂移 ${p.length}`,children:p.length===0?e.jsx(a,{bordered:!0,children:e.jsx(_,{description:d?"漂移源不可用(/api/drift/report 报错,已降级)":"近窗口内无合规漂移(所有 drift check 通过)"})}):e.jsx(G,{gutter:[16,16],children:p.map(s=>e.jsx(J,{xs:24,md:12,xl:8,children:e.jsx("div",{style:{cursor:"pointer"},onClick:()=>x(s.id),children:e.jsx(H,{issue:s})})},s.id))})},"drift")]})]})}export{se as default};
|
|
2
|
+
//# sourceMappingURL=IssuesPage-SKmhlCrw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IssuesPage-SKmhlCrw.js","sources":["../../src/pages/IssuesPage.tsx"],"sourcesContent":["/**\n * IssuesPage — 治理 · 问题(治理)列表 (Phase 3b, decision 29688066).\n *\n * 替换 `/issues` 的占位组件(接管旧 ViolationsPage 的语义,改名「问题」+ 前端\n * merge 三源)。把原型「问题」列表翻译成真 Arco 组件(**严禁直搬原型 Tailwind CSS**):\n * - 两 Tab:①拦截/违规/失败(一表,Arco Table,按时间倒序)②漂移(Arco Card 卡片)。\n * - 列:类型 Tag / 严重度 Tag / 标题(规则名 or 任务标题)/ 动作 or 来源 / session/任务 / 时间。\n * - 点行进整页详情 `/issues/:id`(稳定 id 带源前缀)。\n *\n * 三源前端 merge(零新后端):/api/violations + /api/tasks(failed) + /api/drift/report。\n * 受全局时间窗驱动(各源按 days/window)。取数 + merge 在 useIssuesFeed / issues-derive,\n * 本组件只渲染派生结果。drift 源缺失(端点报错)→ 漂移 Tab 显空态降级,不阻塞前两源。\n */\nimport { useMemo, useState } from 'react'\nimport { useNavigate } from 'react-router-dom'\n\nimport Card from '@arco-design/web-react/es/Card'\nimport Table from '@arco-design/web-react/es/Table'\nimport Tabs from '@arco-design/web-react/es/Tabs'\nimport Tag from '@arco-design/web-react/es/Tag'\nimport Grid from '@arco-design/web-react/es/Grid'\nimport Typography from '@arco-design/web-react/es/Typography'\nimport Button from '@arco-design/web-react/es/Button'\nimport Empty from '@arco-design/web-react/es/Empty'\nimport Result from '@arco-design/web-react/es/Result'\nimport Alert from '@arco-design/web-react/es/Alert'\nimport { IconRight, IconExclamationCircle } from '@arco-design/web-react/icon'\n\nimport { useIssuesFeed } from '../hooks/useIssuesFeed'\nimport {\n splitIssues,\n buildIssueCounts,\n typeLabel,\n typeColor,\n severityLabel,\n severityColor,\n fmtTime,\n type Issue,\n} from '../hooks/issues-derive'\n\nconst TabPane = Tabs.TabPane\nconst Row = Grid.Row\nconst Col = Grid.Col\n\nfunction typeTag(t: Issue['type']) {\n return (\n <Tag color={typeColor(t)} size=\"small\">\n {typeLabel(t)}\n </Tag>\n )\n}\n\nfunction sevTag(s: Issue['severity']) {\n return (\n <Tag color={severityColor(s)} size=\"small\">\n {severityLabel(s)}\n </Tag>\n )\n}\n\n/** 漂移卡片(端点 fail check → 卡片,与原型漂移网格对齐成 Arco Card)。 */\nfunction DriftCard({ issue }: { issue: Issue }) {\n return (\n <Card bordered style={{ height: '100%' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>\n <IconExclamationCircle style={{ color: 'rgb(var(--gold-6))' }} />\n <Typography.Text style={{ fontSize: 14, fontWeight: 600 }}>{issue.rule}</Typography.Text>\n {sevTag(issue.severity)}\n </div>\n <Typography.Paragraph style={{ margin: '8px 0 0', fontSize: 13 }}>\n {issue.what}\n </Typography.Paragraph>\n <div\n style={{\n marginTop: 10,\n paddingTop: 8,\n borderTop: '1px solid var(--color-border-1)',\n display: 'flex',\n justifyContent: 'flex-end',\n }}\n >\n <Button type=\"text\" size=\"mini\">\n 查看详情 <IconRight />\n </Button>\n </div>\n </Card>\n )\n}\n\nexport default function IssuesPage() {\n const navigate = useNavigate()\n const { issues, loading, isError, error, violationsError, tasksError, driftError, tasksTruncated } =\n useIssuesFeed()\n const [tab, setTab] = useState<'primary' | 'drift'>('primary')\n\n const { primary, drift } = useMemo(() => splitIssues(issues), [issues])\n const counts = useMemo(() => buildIssueCounts(issues), [issues])\n\n if (isError) {\n return (\n <div style={{ padding: 16 }}>\n <Result\n status=\"error\"\n title=\"加载问题失败\"\n subTitle={error?.message || '三源端点均不可用'}\n />\n </div>\n )\n }\n\n const goDetail = (id: string) => navigate(`/issues/${encodeURIComponent(id)}`)\n\n const columns = [\n {\n title: '类型',\n dataIndex: 'type',\n width: 84,\n render: (_: unknown, row: Issue) => typeTag(row.type),\n },\n {\n title: '严重度',\n dataIndex: 'severity',\n width: 76,\n render: (_: unknown, row: Issue) => sevTag(row.severity),\n },\n {\n title: '问题 · 规则',\n dataIndex: 'title',\n render: (_: unknown, row: Issue) => (\n <div style={{ minWidth: 0 }}>\n <Typography.Paragraph\n style={{ margin: 0, fontSize: 13 }}\n ellipsis={{ rows: 1, showTooltip: true }}\n >\n {row.title}\n </Typography.Paragraph>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12, fontFamily: 'monospace' }}>\n {row.rule}\n </Typography.Text>\n </div>\n ),\n },\n {\n title: '动作 / 来源',\n dataIndex: 'action',\n width: 110,\n render: (_: unknown, row: Issue) => (\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n {row.action}\n </Typography.Text>\n ),\n },\n {\n title: 'session / 任务',\n dataIndex: 'session',\n width: 130,\n render: (_: unknown, row: Issue) =>\n row.relatedTaskId ? (\n <Button\n type=\"text\"\n size=\"mini\"\n style={{ paddingLeft: 0, fontFamily: 'monospace', fontSize: 12 }}\n onClick={(e) => {\n e.stopPropagation()\n navigate(`/tasks/${encodeURIComponent(row.relatedTaskId!)}`)\n }}\n >\n {row.relatedTaskId.slice(0, 8)}…\n </Button>\n ) : row.session ? (\n <Typography.Text type=\"secondary\" style={{ fontSize: 12, fontFamily: 'monospace' }}>\n {row.session.slice(0, 8)}…\n </Typography.Text>\n ) : (\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n —\n </Typography.Text>\n ),\n },\n {\n title: '时间',\n dataIndex: 'time',\n width: 120,\n sorter: (a: Issue, b: Issue) => (a.time < b.time ? -1 : a.time > b.time ? 1 : 0),\n render: (_: unknown, row: Issue) => (\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n {fmtTime(row.time)}\n </Typography.Text>\n ),\n },\n {\n title: '操作',\n dataIndex: 'op',\n width: 72,\n align: 'right' as const,\n render: (_: unknown, row: Issue) => (\n <Button\n type=\"text\"\n size=\"mini\"\n onClick={(e) => {\n e.stopPropagation()\n goDetail(row.id)\n }}\n >\n 详情 <IconRight />\n </Button>\n ),\n },\n ]\n\n return (\n <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 16 }}>\n <Card bordered>\n <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>\n <Typography.Title heading={6} style={{ margin: 0 }}>\n 问题\n </Typography.Title>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 前端 merge 三源 · 拦截 / 违规 / 失败任务 / 漂移(零新后端)\n </Typography.Text>\n <div style={{ flex: 1 }} />\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 拦截 <Typography.Text style={{ fontWeight: 600, color: 'rgb(var(--red-6))' }}>{counts.intercept}</Typography.Text>\n </Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 违规 <Typography.Text style={{ fontWeight: 600, color: 'rgb(var(--orange-6))' }}>{counts.violation}</Typography.Text>\n </Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 失败 <Typography.Text style={{ fontWeight: 600, color: 'rgb(var(--red-6))' }}>{counts.failure}</Typography.Text>\n </Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 漂移 <Typography.Text style={{ fontWeight: 600, color: 'rgb(var(--gold-6))' }}>{counts.drift}</Typography.Text>\n </Typography.Text>\n </div>\n {(violationsError || tasksError || driftError) && (\n <Alert\n type=\"warning\"\n style={{ marginTop: 12 }}\n content={\n <span style={{ fontSize: 12 }}>\n 部分源降级:\n {violationsError && '违规拦截源不可用;'}\n {tasksError && '失败任务源不可用;'}\n {driftError && '漂移源不可用(/api/drift/report 报错,已降级跳过漂移项);'}\n 其余源照常合并。\n </span>\n }\n />\n )}\n {tasksTruncated && (\n <Alert\n type=\"warning\"\n style={{ marginTop: 12 }}\n content={\n <span style={{ fontSize: 12 }}>\n 失败任务可能因超出扫描上限少报:当前时间窗任务数超过分页扫描安全上限,\n 未扫描到的部分失败任务不在列表内。可缩短时间窗以覆盖更近期的任务。\n </span>\n }\n />\n )}\n </Card>\n\n <Tabs activeTab={tab} onChange={(k) => setTab(k as 'primary' | 'drift')}>\n <TabPane key=\"primary\" title={`拦截 / 违规 / 失败 ${primary.length}`}>\n <Card bordered style={{ padding: 0 }}>\n <Table<Issue>\n rowKey=\"id\"\n loading={loading}\n data={primary}\n columns={columns}\n pagination={primary.length > 20 ? { pageSize: 20, showTotal: true } : false}\n border={{ wrapper: false, cell: false }}\n onRow={(row) => ({\n onClick: () => goDetail(row.id),\n style: { cursor: 'pointer' },\n })}\n />\n </Card>\n </TabPane>\n <TabPane key=\"drift\" title={`漂移 ${drift.length}`}>\n {drift.length === 0 ? (\n <Card bordered>\n <Empty\n description={\n driftError\n ? '漂移源不可用(/api/drift/report 报错,已降级)'\n : '近窗口内无合规漂移(所有 drift check 通过)'\n }\n />\n </Card>\n ) : (\n <Row gutter={[16, 16]}>\n {drift.map((d) => (\n <Col key={d.id} xs={24} md={12} xl={8}>\n <div style={{ cursor: 'pointer' }} onClick={() => goDetail(d.id)}>\n <DriftCard issue={d} />\n </div>\n </Col>\n ))}\n </Row>\n )}\n </TabPane>\n </Tabs>\n </div>\n )\n}\n"],"names":["TabPane","Tabs","Row","Grid","Col","typeTag","t","jsx","Tag","typeColor","typeLabel","sevTag","s","severityColor","severityLabel","DriftCard","issue","jsxs","Card","IconExclamationCircle","Typography","Button","IconRight","IssuesPage","navigate","useNavigate","issues","loading","isError","error","violationsError","tasksError","driftError","tasksTruncated","useIssuesFeed","tab","setTab","useState","primary","drift","useMemo","splitIssues","counts","buildIssueCounts","Result","goDetail","id","columns","_","row","e","a","b","fmtTime","Alert","k","Table","Empty","d"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as e}from"./react-vendor-tkvCrao7.js";import{J as r,d as b,D as v,F as c,X as S,x as z,T as n,Y as T,a2 as k,K as g,E as x,y as C,$ as w,O as I,b as a,a3 as B}from"./arco-DV6xCLhr.js";import{M as D}from"./MarkdownRenderer-DlDQNihj.js";import{a as R,k as p,f as u,s as W}from"./useKbHits-xKXWgqh9.js";import{d as $,u as K}from"./react-router-Cxmg8RuL.js";import"./vendor-DS-q4Eyc.js";import"./syntax-highlighter-BDYycNja.js";import"./markdown-CA7ePUts.js";import"./query-CgCOpYWf.js";import"./index-DileOOE4.js";import"./lucide-CnlPQoG8.js";import"./useEffectiveProject-DQiyX54y.js";const M=g.Row,y=g.Col;function m(l){const i={"agent-pull":"arcoblue",injection:"cyan",mixed:"purple",none:"gray"};return e.jsx(a,{color:i[l],size:"small",children:W(l)})}function E(l){return l==="agent-pull"?e.jsx(a,{color:"arcoblue",size:"small",children:"agent-pull"}):l==="injection"?e.jsx(a,{color:"cyan",size:"small",children:"injection"}):e.jsx(a,{size:"small",children:l})}function F(l){if(!l||!Number.isFinite(l))return"—";try{const i=new Date(l),t=o=>String(o).padStart(2,"0");return`${t(i.getMonth()+1)}-${t(i.getDate())} ${t(i.getHours())}:${t(i.getMinutes())}`}catch{return"—"}}function U(){const{name:l}=$(),i=K(),{view:t,loading:o,isError:h,error:d}=R(l);if(o)return e.jsx("div",{style:{padding:16},children:e.jsx(r,{bordered:!0,children:e.jsx(b,{animation:!0,text:{rows:8}})})});if(h||!t)return e.jsx("div",{style:{padding:16},children:e.jsx(v,{status:"error",title:"加载 KB 详情失败",subTitle:(d==null?void 0:d.message)||"KB 页不存在或端点不可用",extra:e.jsx(c,{type:"primary",onClick:()=>i("/ai/kb"),children:"返回 KB 命中"})})});const f=()=>{var s;try{(s=navigator.clipboard)==null||s.writeText(t.name),B.success(`已复制 ${t.name}`)}catch{}};return e.jsxs("div",{style:{padding:16,display:"flex",flexDirection:"column",gap:16},children:[e.jsxs(r,{bordered:!0,children:[e.jsx(c,{type:"text",size:"small",icon:e.jsx(S,{}),style:{marginBottom:8,paddingLeft:0},onClick:()=>i("/ai/kb"),children:"返回 KB 命中"}),e.jsxs("div",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:16,flexWrap:"wrap"},children:[e.jsxs("div",{style:{minWidth:0,flex:1},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsx(z,{style:{color:"rgb(var(--arcoblue-6))"}}),e.jsx(n.Title,{heading:5,style:{margin:0,fontFamily:"monospace"},children:t.name}),m(t.dominantSource)]}),e.jsxs("div",{style:{display:"flex",gap:12,flexWrap:"wrap",marginTop:8,alignItems:"center"},children:[e.jsx(n.Text,{type:"secondary",style:{fontSize:12},children:p(t.kind)}),e.jsxs(n.Text,{type:"secondary",style:{fontSize:12},children:["命中 ",e.jsx("b",{children:t.hits})]}),e.jsxs(n.Text,{type:"secondary",style:{fontSize:12},children:["采纳率 ",e.jsx("b",{children:u(t.adoptionRate)})]}),t.generatedAt&&e.jsxs(n.Text,{type:"secondary",style:{fontSize:12,display:"inline-flex",alignItems:"center",gap:4},children:[e.jsx(T,{})," ",t.generatedAt.slice(0,16).replace("T"," ")]})]})]}),e.jsx(c,{size:"small",icon:e.jsx(k,{}),onClick:f,children:"复制路径"})]})]}),e.jsxs(M,{gutter:16,align:"start",children:[e.jsx(y,{xs:24,xl:16,style:{marginBottom:16},children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16},children:[e.jsx(r,{bordered:!0,title:e.jsx("span",{style:{fontSize:14,fontWeight:600},children:"📄 正文预览"}),extra:e.jsxs(n.Text,{type:"secondary",style:{fontSize:12},children:[t.wordCount," 字"]}),children:t.content?e.jsx("div",{style:{border:"1px solid var(--color-border-2)",borderRadius:4,background:"var(--color-fill-1)",padding:"12px 16px",maxHeight:520,overflow:"auto"},children:e.jsx(D,{content:t.content})}):e.jsx(x,{description:"无正文内容"})}),e.jsx(r,{bordered:!0,title:e.jsx("span",{style:{fontSize:14,fontWeight:600},children:"🔗 谁 pull 了它"}),extra:e.jsxs(n.Text,{type:"secondary",style:{fontSize:12},children:["窗口内 agent 主动 pull · ",t.pulls.length," 条"]}),children:t.pulls.length>0?e.jsx("div",{style:{display:"flex",flexDirection:"column"},children:t.pulls.map((s,j)=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,padding:"8px 0",borderBottom:"1px solid var(--color-border-1)"},children:[e.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:6,width:180,flexShrink:0,fontSize:13},children:[e.jsx(C,{style:{color:"var(--color-text-3)"}}),s.agent]}),e.jsx(n.Text,{style:{fontFamily:"monospace",fontSize:12,flex:1,minWidth:0},ellipsis:!0,title:s.reason,children:s.reason}),E(s.source),e.jsx(n.Text,{type:"secondary",style:{fontSize:12,width:96,textAlign:"right"},children:F(s.ts)})]},`${s.agent}-${s.ts}-${j}`))}):e.jsx(x,{description:"窗口内无 agent 主动 pull 记录(仅注入命中)"})})]})}),e.jsx(y,{xs:24,xl:8,style:{marginBottom:16},children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16},children:[e.jsx(r,{bordered:!0,title:e.jsx("span",{style:{fontSize:14,fontWeight:600},children:"概要"}),children:e.jsx(w,{colon:" :",size:"small",column:1,labelStyle:{width:88,color:"var(--color-text-3)"},data:[{label:"路径",value:e.jsx(n.Text,{code:!0,style:{fontSize:11},children:t.name})},{label:"类型",value:p(t.kind)},{label:"字数",value:t.wordCount},{label:"引用",value:t.refs},{label:"命中",value:e.jsx(n.Text,{style:{fontWeight:600,color:"rgb(var(--arcoblue-6))"},children:t.hits})},{label:"采纳率",value:u(t.adoptionRate)},{label:"主要来源",value:m(t.dominantSource)},{label:"审计",value:t.auditStatus==="ok"?e.jsxs(n.Text,{style:{fontSize:12,color:"rgb(var(--green-6))",display:"inline-flex",alignItems:"center",gap:4},children:[e.jsx(I,{})," ok"]}):e.jsx(a,{color:t.auditStatus==="error"?"red":"orange",size:"small",children:t.auditStatus})}]})}),e.jsx(r,{bordered:!0,title:e.jsx("span",{style:{fontSize:14,fontWeight:600},children:"关联任务"}),children:e.jsx(x,{description:"暂无关联任务(端点未提供 per-page 关联)"})})]})})]})]})}export{U as default};
|
|
2
|
+
//# sourceMappingURL=KbDetailPage-Yna86Na8.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KbDetailPage-Yna86Na8.js","sources":["../../src/pages/ai/KbDetailPage.tsx"],"sourcesContent":["/**\n * KbDetailPage — AI 资源 · KB 命中详情整页 (Phase 2b, decision 29688066).\n *\n * 替换 `/ai/kb/:name` 的占位组件。整页(非抽屉)布局,翻译原型「命中详情」\n * 成真 Arco 组件(**严禁直搬原型 Tailwind CSS**):\n * A. 页头横条:路径标题 + 来源 Tag + 元信息(类型/命中/采纳率/最近生成)+ 复制路径\n * B. 左右双栏:\n * 左 = 正文预览(MarkdownRenderer)+「谁 pull 了它」(agent / reason\n * workflow/phase / source / 时间)\n * 右 360 = 概要 Descriptions + 关联任务(可链 /tasks/:id;当前端点未提供\n * per-page 关联任务,降级为空态提示)\n *\n * 数据接真实端点(GET /api/knowledge/page/:name + 同窗 cited/pulls/list),取数 +\n * 派生在 useKbDetail / kb-derive,本组件只渲染。\n */\nimport { useParams, useNavigate } from 'react-router-dom'\n\nimport Card from '@arco-design/web-react/es/Card'\nimport Grid from '@arco-design/web-react/es/Grid'\nimport Tag from '@arco-design/web-react/es/Tag'\nimport Typography from '@arco-design/web-react/es/Typography'\nimport Descriptions from '@arco-design/web-react/es/Descriptions'\nimport Button from '@arco-design/web-react/es/Button'\nimport Empty from '@arco-design/web-react/es/Empty'\nimport Skeleton from '@arco-design/web-react/es/Skeleton'\nimport Result from '@arco-design/web-react/es/Result'\nimport Message from '@arco-design/web-react/es/Message'\nimport {\n IconLeft,\n IconBook,\n IconClockCircle,\n IconCheckCircle,\n IconCopy,\n IconRobot,\n} from '@arco-design/web-react/icon'\n\nimport MarkdownRenderer from '../../components/MarkdownRenderer'\nimport { useKbDetail } from '../../hooks/useKbHits'\nimport {\n formatPct,\n kindLabel,\n sourceLabel,\n type KbSource,\n type KbPullRow,\n} from '../../hooks/kb-derive'\n\nconst Row = Grid.Row\nconst Col = Grid.Col\n\nfunction sourceTag(source: KbSource) {\n const map: Record<KbSource, string> = {\n 'agent-pull': 'arcoblue',\n injection: 'cyan',\n mixed: 'purple',\n none: 'gray',\n }\n return <Tag color={map[source]} size=\"small\">{sourceLabel(source)}</Tag>\n}\n\nfunction pullSourceTag(source: KbPullRow['source']) {\n if (source === 'agent-pull') return <Tag color=\"arcoblue\" size=\"small\">agent-pull</Tag>\n if (source === 'injection') return <Tag color=\"cyan\" size=\"small\">injection</Tag>\n return <Tag size=\"small\">{source}</Tag>\n}\n\nfunction fmtTs(ts: number): string {\n if (!ts || !Number.isFinite(ts)) return '—'\n try {\n const d = new Date(ts)\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`\n } catch {\n return '—'\n }\n}\n\nexport default function KbDetailPage() {\n const { name } = useParams<{ name: string }>()\n const navigate = useNavigate()\n const { view, loading, isError, error } = useKbDetail(name)\n\n if (loading) {\n return (\n <div style={{ padding: 16 }}>\n <Card bordered>\n <Skeleton animation text={{ rows: 8 }} />\n </Card>\n </div>\n )\n }\n\n if (isError || !view) {\n return (\n <div style={{ padding: 16 }}>\n <Result\n status=\"error\"\n title=\"加载 KB 详情失败\"\n subTitle={error?.message || 'KB 页不存在或端点不可用'}\n extra={\n <Button type=\"primary\" onClick={() => navigate('/ai/kb')}>\n 返回 KB 命中\n </Button>\n }\n />\n </div>\n )\n }\n\n const copyPath = () => {\n try {\n void navigator.clipboard?.writeText(view.name)\n Message.success(`已复制 ${view.name}`)\n } catch {\n /* clipboard unavailable — ignore */\n }\n }\n\n return (\n <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 16 }}>\n {/* ── A. 页头横条 ─────────────────────────────────────────────── */}\n <Card bordered>\n <Button\n type=\"text\"\n size=\"small\"\n icon={<IconLeft />}\n style={{ marginBottom: 8, paddingLeft: 0 }}\n onClick={() => navigate('/ai/kb')}\n >\n 返回 KB 命中\n </Button>\n <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16, flexWrap: 'wrap' }}>\n <div style={{ minWidth: 0, flex: 1 }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>\n <IconBook style={{ color: 'rgb(var(--arcoblue-6))' }} />\n <Typography.Title heading={5} style={{ margin: 0, fontFamily: 'monospace' }}>\n {view.name}\n </Typography.Title>\n {sourceTag(view.dominantSource)}\n </div>\n <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginTop: 8, alignItems: 'center' }}>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>{kindLabel(view.kind)}</Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>命中 <b>{view.hits}</b></Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>采纳率 <b>{formatPct(view.adoptionRate)}</b></Typography.Text>\n {view.generatedAt && (\n <Typography.Text type=\"secondary\" style={{ fontSize: 12, display: 'inline-flex', alignItems: 'center', gap: 4 }}>\n <IconClockCircle /> {view.generatedAt.slice(0, 16).replace('T', ' ')}\n </Typography.Text>\n )}\n </div>\n </div>\n <Button size=\"small\" icon={<IconCopy />} onClick={copyPath}>复制路径</Button>\n </div>\n </Card>\n\n {/* ── B. 左右双栏 ─────────────────────────────────────────────── */}\n <Row gutter={16} align=\"start\">\n {/* 左主栏:正文预览 + 谁 pull 了它 */}\n <Col xs={24} xl={16} style={{ marginBottom: 16 }}>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n <Card\n bordered\n title={<span style={{ fontSize: 14, fontWeight: 600 }}>📄 正文预览</span>}\n extra={<Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>{view.wordCount} 字</Typography.Text>}\n >\n {view.content ? (\n <div\n style={{\n border: '1px solid var(--color-border-2)',\n borderRadius: 4,\n background: 'var(--color-fill-1)',\n padding: '12px 16px',\n maxHeight: 520,\n overflow: 'auto',\n }}\n >\n <MarkdownRenderer content={view.content} />\n </div>\n ) : (\n <Empty description=\"无正文内容\" />\n )}\n </Card>\n\n <Card\n bordered\n title={<span style={{ fontSize: 14, fontWeight: 600 }}>🔗 谁 pull 了它</span>}\n extra={<Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>窗口内 agent 主动 pull · {view.pulls.length} 条</Typography.Text>}\n >\n {view.pulls.length > 0 ? (\n <div style={{ display: 'flex', flexDirection: 'column' }}>\n {view.pulls.map((p, i) => (\n <div\n key={`${p.agent}-${p.ts}-${i}`}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 12,\n padding: '8px 0',\n borderBottom: '1px solid var(--color-border-1)',\n }}\n >\n <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, width: 180, flexShrink: 0, fontSize: 13 }}>\n <IconRobot style={{ color: 'var(--color-text-3)' }} />\n {p.agent}\n </span>\n <Typography.Text style={{ fontFamily: 'monospace', fontSize: 12, flex: 1, minWidth: 0 }} ellipsis title={p.reason}>\n {p.reason}\n </Typography.Text>\n {pullSourceTag(p.source)}\n <Typography.Text type=\"secondary\" style={{ fontSize: 12, width: 96, textAlign: 'right' }}>\n {fmtTs(p.ts)}\n </Typography.Text>\n </div>\n ))}\n </div>\n ) : (\n <Empty description=\"窗口内无 agent 主动 pull 记录(仅注入命中)\" />\n )}\n </Card>\n </div>\n </Col>\n\n {/* 右侧栏:概要 + 关联任务 */}\n <Col xs={24} xl={8} style={{ marginBottom: 16 }}>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n <Card bordered title={<span style={{ fontSize: 14, fontWeight: 600 }}>概要</span>}>\n <Descriptions\n colon=\" :\"\n size=\"small\"\n column={1}\n labelStyle={{ width: 88, color: 'var(--color-text-3)' }}\n data={[\n { label: '路径', value: <Typography.Text code style={{ fontSize: 11 }}>{view.name}</Typography.Text> },\n { label: '类型', value: kindLabel(view.kind) },\n { label: '字数', value: view.wordCount },\n { label: '引用', value: view.refs },\n { label: '命中', value: <Typography.Text style={{ fontWeight: 600, color: 'rgb(var(--arcoblue-6))' }}>{view.hits}</Typography.Text> },\n { label: '采纳率', value: formatPct(view.adoptionRate) },\n { label: '主要来源', value: sourceTag(view.dominantSource) },\n {\n label: '审计',\n value:\n view.auditStatus === 'ok'\n ? <Typography.Text style={{ fontSize: 12, color: 'rgb(var(--green-6))', display: 'inline-flex', alignItems: 'center', gap: 4 }}><IconCheckCircle /> ok</Typography.Text>\n : <Tag color={view.auditStatus === 'error' ? 'red' : 'orange'} size=\"small\">{view.auditStatus}</Tag>,\n },\n ]}\n />\n </Card>\n\n <Card bordered title={<span style={{ fontSize: 14, fontWeight: 600 }}>关联任务</span>}>\n {/*\n 端点未提供 per-page 关联任务(kb-cited-pages 只回计数,\n agent-kb-pulls.recent 无 page_name 可 join)。按 spec「缺字段降级」\n 先空态提示,关联任务可在 Phase 3+ 端点补齐后挂 /tasks/:id 链接。\n */}\n <Empty description=\"暂无关联任务(端点未提供 per-page 关联)\" />\n </Card>\n </div>\n </Col>\n </Row>\n </div>\n )\n}\n"],"names":["Row","Grid","Col","sourceTag","source","map","jsx","Tag","sourceLabel","pullSourceTag","fmtTs","ts","d","pad","n","KbDetailPage","name","useParams","navigate","useNavigate","view","loading","isError","error","useKbDetail","Card","Skeleton","Result","Button","copyPath","_a","Message","jsxs","IconLeft","IconBook","Typography","kindLabel","formatPct","IconClockCircle","IconCopy","MarkdownRenderer","Empty","p","i","IconRobot","Descriptions","IconCheckCircle"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as e}from"./react-vendor-tkvCrao7.js";import{D as d,J as c,T as n,a1 as h,F as u,N as m,b as l}from"./arco-DV6xCLhr.js";import{u as f,k as j,f as T,s as b}from"./useKbHits-xKXWgqh9.js";import{u as z}from"./react-router-Cxmg8RuL.js";import"./vendor-DS-q4Eyc.js";import"./query-CgCOpYWf.js";import"./index-DileOOE4.js";import"./lucide-CnlPQoG8.js";import"./useEffectiveProject-DQiyX54y.js";function p(s){const i={"agent-pull":"arcoblue",injection:"cyan",mixed:"purple",none:"gray"};return e.jsx(l,{color:i[s],size:"small",children:b(s)})}function w(s){return s==="stale"?e.jsx(l,{color:"orange",size:"small",children:"stale"}):s==="error"?e.jsx(l,{color:"red",size:"small",children:"error"}):null}function W(){const s=z(),{view:i,loading:o,isError:x,error:a}=f();if(x)return e.jsx("div",{style:{padding:16},children:e.jsx(d,{status:"error",title:"加载 KB 命中失败",subTitle:(a==null?void 0:a.message)||"/api/knowledge/list 端点不可用"})});if(!o&&!i.built)return e.jsx("div",{style:{padding:16},children:e.jsx(d,{status:"warning",title:"知识库尚未构建",subTitle:"运行 cf knowledge build --apply 后再查看 KB 命中。"})});const y=[{title:"KB 页路径",dataIndex:"name",render:(r,t)=>e.jsxs("div",{style:{minWidth:0},children:[e.jsx(n.Text,{code:!0,style:{fontSize:13},children:t.name}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginTop:2},children:[e.jsxs(n.Text,{type:"secondary",style:{fontSize:12},children:[j(t.kind)," · ",t.refs," 引用"]}),w(t.audit_status)]})]})},{title:"命中次数",dataIndex:"hits",width:100,sorter:(r,t)=>r.hits-t.hits,render:(r,t)=>e.jsx(n.Text,{style:{fontWeight:600},children:t.hits})},{title:"采纳率",dataIndex:"adopt",width:92,render:()=>e.jsx(n.Text,{type:"secondary",style:{fontSize:13},children:T(i.adoptionRate)})},{title:"主要来源",dataIndex:"source",width:120,render:(r,t)=>p(t.source)},{title:"最近生成",dataIndex:"generated_at",width:150,render:(r,t)=>e.jsx(n.Text,{type:"secondary",style:{fontSize:12},children:t.generated_at?t.generated_at.slice(0,16).replace("T"," "):"—"})},{title:"操作",dataIndex:"op",width:76,align:"right",render:(r,t)=>e.jsxs(u,{type:"text",size:"mini",onClick:g=>{g.stopPropagation(),s(`/ai/kb/${encodeURIComponent(t.name)}`)},children:["详情 ",e.jsx(m,{})]})}];return e.jsxs("div",{style:{padding:16,display:"flex",flexDirection:"column",gap:16},children:[e.jsx(c,{bordered:!0,children:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,flexWrap:"wrap"},children:[e.jsx(n.Title,{heading:6,style:{margin:0},children:"KB 命中"}),e.jsx(n.Text,{type:"secondary",style:{fontSize:12},children:"知识库注入命中分析 · kb_query_log / injections(按命中数排序)"}),e.jsx("div",{style:{flex:1}}),e.jsxs(n.Text,{type:"secondary",style:{fontSize:12},children:["页数 ",e.jsx(n.Text,{style:{fontWeight:600},children:i.totalPages})]}),e.jsxs(n.Text,{type:"secondary",style:{fontSize:12},children:["总命中 ",e.jsx(n.Text,{style:{fontWeight:600,color:"rgb(var(--arcoblue-6))"},children:i.totalHits})]}),e.jsxs(n.Text,{type:"secondary",style:{fontSize:12},children:["主要来源 ",p(i.dominantSource)]})]})}),e.jsx(c,{bordered:!0,style:{padding:0},children:e.jsx(h,{rowKey:"name",loading:o,data:i.rows,columns:y,pagination:i.rows.length>20?{pageSize:20,showTotal:!0}:!1,border:{wrapper:!1,cell:!1},onRow:r=>({onClick:()=>s(`/ai/kb/${encodeURIComponent(r.name)}`),style:{cursor:"pointer"}})})})]})}export{W as default};
|
|
2
|
+
//# sourceMappingURL=KbHitsPage-Cljl7H9p.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KbHitsPage-Cljl7H9p.js","sources":["../../src/pages/ai/KbHitsPage.tsx"],"sourcesContent":["/**\n * KbHitsPage — AI 资源 · KB 命中列表 (Phase 2b, decision 29688066).\n *\n * 替换 `/ai/kb` 的占位组件。把原型「KB 命中」列表翻译成真 Arco 组件\n * (**严禁直搬原型 Tailwind CSS**):Card 页头汇总 + Arco Table(按命中数排序),\n * 列:KB 页路径 / 命中次数 / 采纳率 / 主要来源 / 最近生成 / 操作。点行进整页详情\n * `/ai/kb/:name`。数据接真实端点(见 useKbHits),受全局时间窗驱动。\n *\n * 命中口径见 kb-derive.ts:命中=注入 cited 计数;采纳率=列表聚合 effective 命中率;\n * 来源为窗口级降级(per-page 来源拆分不可得)。\n */\nimport { useNavigate } from 'react-router-dom'\n\nimport Card from '@arco-design/web-react/es/Card'\nimport Table from '@arco-design/web-react/es/Table'\nimport Tag from '@arco-design/web-react/es/Tag'\nimport Typography from '@arco-design/web-react/es/Typography'\nimport Button from '@arco-design/web-react/es/Button'\nimport Result from '@arco-design/web-react/es/Result'\nimport { IconRight } from '@arco-design/web-react/icon'\n\nimport { useKbHits } from '../../hooks/useKbHits'\nimport {\n formatPct,\n kindLabel,\n sourceLabel,\n type KbHitRow,\n type KbSource,\n} from '../../hooks/kb-derive'\n\nfunction sourceTag(source: KbSource) {\n const map: Record<KbSource, string> = {\n 'agent-pull': 'arcoblue',\n injection: 'cyan',\n mixed: 'purple',\n none: 'gray',\n }\n return (\n <Tag color={map[source]} size=\"small\">\n {sourceLabel(source)}\n </Tag>\n )\n}\n\nfunction auditTag(status: string) {\n if (status === 'stale') return <Tag color=\"orange\" size=\"small\">stale</Tag>\n if (status === 'error') return <Tag color=\"red\" size=\"small\">error</Tag>\n return null\n}\n\nexport default function KbHitsPage() {\n const navigate = useNavigate()\n const { view, loading, isError, error } = useKbHits()\n\n if (isError) {\n return (\n <div style={{ padding: 16 }}>\n <Result\n status=\"error\"\n title=\"加载 KB 命中失败\"\n subTitle={error?.message || '/api/knowledge/list 端点不可用'}\n />\n </div>\n )\n }\n\n if (!loading && !view.built) {\n return (\n <div style={{ padding: 16 }}>\n <Result\n status=\"warning\"\n title=\"知识库尚未构建\"\n subTitle=\"运行 cf knowledge build --apply 后再查看 KB 命中。\"\n />\n </div>\n )\n }\n\n const columns = [\n {\n title: 'KB 页路径',\n dataIndex: 'name',\n render: (_: unknown, row: KbHitRow) => (\n <div style={{ minWidth: 0 }}>\n <Typography.Text code style={{ fontSize: 13 }}>{row.name}</Typography.Text>\n <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 2 }}>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n {kindLabel(row.kind)} · {row.refs} 引用\n </Typography.Text>\n {auditTag(row.audit_status)}\n </div>\n </div>\n ),\n },\n {\n title: '命中次数',\n dataIndex: 'hits',\n width: 100,\n sorter: (a: KbHitRow, b: KbHitRow) => a.hits - b.hits,\n render: (_: unknown, row: KbHitRow) => (\n <Typography.Text style={{ fontWeight: 600 }}>{row.hits}</Typography.Text>\n ),\n },\n {\n title: '采纳率',\n dataIndex: 'adopt',\n width: 92,\n render: () => (\n <Typography.Text type=\"secondary\" style={{ fontSize: 13 }}>\n {formatPct(view.adoptionRate)}\n </Typography.Text>\n ),\n },\n {\n title: '主要来源',\n dataIndex: 'source',\n width: 120,\n render: (_: unknown, row: KbHitRow) => sourceTag(row.source),\n },\n {\n title: '最近生成',\n dataIndex: 'generated_at',\n width: 150,\n render: (_: unknown, row: KbHitRow) => (\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n {row.generated_at ? row.generated_at.slice(0, 16).replace('T', ' ') : '—'}\n </Typography.Text>\n ),\n },\n {\n title: '操作',\n dataIndex: 'op',\n width: 76,\n align: 'right' as const,\n render: (_: unknown, row: KbHitRow) => (\n <Button\n type=\"text\"\n size=\"mini\"\n onClick={(e) => {\n e.stopPropagation()\n navigate(`/ai/kb/${encodeURIComponent(row.name)}`)\n }}\n >\n 详情 <IconRight />\n </Button>\n ),\n },\n ]\n\n return (\n <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 16 }}>\n <Card bordered>\n <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>\n <Typography.Title heading={6} style={{ margin: 0 }}>KB 命中</Typography.Title>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 知识库注入命中分析 · kb_query_log / injections(按命中数排序)\n </Typography.Text>\n <div style={{ flex: 1 }} />\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 页数 <Typography.Text style={{ fontWeight: 600 }}>{view.totalPages}</Typography.Text>\n </Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 总命中 <Typography.Text style={{ fontWeight: 600, color: 'rgb(var(--arcoblue-6))' }}>{view.totalHits}</Typography.Text>\n </Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 主要来源 {sourceTag(view.dominantSource)}\n </Typography.Text>\n </div>\n </Card>\n\n <Card bordered style={{ padding: 0 }}>\n <Table<KbHitRow>\n rowKey=\"name\"\n loading={loading}\n data={view.rows}\n columns={columns}\n pagination={view.rows.length > 20 ? { pageSize: 20, showTotal: true } : false}\n border={{ wrapper: false, cell: false }}\n onRow={(row) => ({\n onClick: () => navigate(`/ai/kb/${encodeURIComponent(row.name)}`),\n style: { cursor: 'pointer' },\n })}\n />\n </Card>\n </div>\n )\n}\n"],"names":["sourceTag","source","map","jsx","Tag","sourceLabel","auditTag","status","KbHitsPage","navigate","useNavigate","view","loading","isError","error","useKbHits","Result","columns","_","row","jsxs","Typography","kindLabel","a","b","formatPct","Button","e","IconRight","Card","Table"],"mappings":"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"}
|
package/dist/web/static/assets/{MarkdownRenderer-DZmTl-8J.js → MarkdownRenderer-DlDQNihj.js}
RENAMED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{j as a}from"./react-vendor-tkvCrao7.js";import{S as r,o as j,t as n,a as f,j as N,b as d,m as c,s as w,p}from"./syntax-highlighter-
|
|
1
|
+
import{j as a}from"./react-vendor-tkvCrao7.js";import{S as r,o as j,t as n,a as f,j as N,b as d,m as c,s as w,p}from"./syntax-highlighter-BDYycNja.js";import{M as k,r as v}from"./markdown-CA7ePUts.js";r.registerLanguage("typescript",n);r.registerLanguage("ts",n);r.registerLanguage("tsx",f);r.registerLanguage("javascript",n);r.registerLanguage("js",n);r.registerLanguage("json",N);r.registerLanguage("bash",d);r.registerLanguage("shell",d);r.registerLanguage("sh",d);r.registerLanguage("markdown",c);r.registerLanguage("md",c);r.registerLanguage("sql",w);r.registerLanguage("python",p);r.registerLanguage("py",p);const L=new Set(["mermaid","flowchart","sequence","gantt","classDiagram","stateDiagram"]);function I({content:b,className:y=""}){return a.jsx("div",{className:`kb-markdown ${y}`,children:a.jsx(k,{remarkPlugins:[v],components:{code({inline:e,className:o,children:i,node:t,...l}){var m;const g=/language-(\w+)/.exec(o||""),s=g==null?void 0:g[1],x=String(i??""),u=x.includes(`
|
|
2
2
|
`),h=(t==null?void 0:t.position)&&((m=t==null?void 0:t.parent)==null?void 0:m.tagName)==="pre";return e===!0||e===void 0&&!s&&!u&&!h?a.jsx("code",{className:"bg-gray-100 text-gray-800 px-1.5 py-0.5 rounded text-[13px] font-mono border border-gray-200",...l,children:i}):s&&L.has(s)?a.jsxs("div",{className:"my-4 rounded-lg border border-gray-200 bg-gray-50 px-4 py-3",children:[a.jsxs("div",{className:"flex items-center gap-2 text-xs text-gray-500 mb-2",children:[a.jsx("svg",{className:"w-3.5 h-3.5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:a.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7"})}),s==="mermaid"?"Mermaid 流程图":`${s} 图表`,"(暂不支持在线渲染)"]}),a.jsx("pre",{className:"text-xs text-gray-600 font-mono whitespace-pre-wrap leading-relaxed",children:x.replace(/\n$/,"")})]}):s?a.jsxs("div",{className:"my-4 rounded-lg overflow-hidden border border-slate-700",children:[a.jsx("div",{className:"flex items-center justify-between bg-slate-800 px-4 py-1.5",children:a.jsx("span",{className:"text-xs text-slate-300 font-mono",children:s})}),a.jsx(r,{style:j,language:s,PreTag:"div",customStyle:{margin:0,borderRadius:0,fontSize:"12.5px",padding:"16px",lineHeight:"1.6",background:"#1e293b"},...l,children:x.replace(/\n$/,"")})]}):a.jsx("code",{className:"block bg-slate-800 text-slate-100 rounded-lg p-4 overflow-x-auto text-xs font-mono leading-relaxed whitespace-pre",...l,children:i})},pre:({children:e})=>a.jsx(a.Fragment,{children:e}),h1:({children:e})=>a.jsx("h1",{className:"text-xl font-bold text-gray-900 mt-8 mb-3 pb-2 border-b border-gray-200 first:mt-0",children:e}),h2:({children:e})=>a.jsx("h2",{className:"text-lg font-bold text-gray-900 mt-7 mb-3 pb-1.5 border-b border-gray-100 first:mt-0",children:e}),h3:({children:e})=>a.jsx("h3",{className:"text-base font-semibold text-gray-800 mt-5 mb-2",children:e}),h4:({children:e})=>a.jsx("h4",{className:"text-sm font-semibold text-gray-800 mt-4 mb-1.5",children:e}),p:({children:e})=>a.jsx("p",{className:"text-sm text-gray-700 my-3 leading-relaxed",children:e}),ul:({children:e})=>a.jsx("ul",{className:"list-disc pl-5 text-sm text-gray-700 my-3 space-y-1.5",children:e}),ol:({children:e})=>a.jsx("ol",{className:"list-decimal pl-5 text-sm text-gray-700 my-3 space-y-1.5",children:e}),li:({children:e})=>a.jsx("li",{className:"text-sm leading-relaxed pl-1",children:e}),a:({children:e,href:o})=>a.jsx("a",{href:o,target:"_blank",rel:"noopener noreferrer",className:"text-indigo-600 hover:text-indigo-800 underline decoration-indigo-300 hover:decoration-indigo-500 transition-colors",children:e}),blockquote:({children:e})=>a.jsx("blockquote",{className:"border-l-4 border-indigo-200 bg-indigo-50/50 pl-4 pr-3 py-2 my-4 rounded-r-lg text-sm text-gray-700 italic",children:e}),table:({children:e})=>a.jsx("div",{className:"overflow-x-auto my-4 rounded-lg border border-gray-200",children:a.jsx("table",{className:"min-w-full text-sm divide-y divide-gray-200",children:e})}),thead:({children:e})=>a.jsx("thead",{className:"bg-gray-50",children:e}),th:({children:e})=>a.jsx("th",{className:"px-3 py-2 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider",children:e}),td:({children:e})=>a.jsx("td",{className:"px-3 py-2 text-sm text-gray-700 border-t border-gray-100",children:e}),hr:()=>a.jsx("hr",{className:"my-6 border-gray-200"}),strong:({children:e})=>a.jsx("strong",{className:"font-semibold text-gray-900",children:e})},children:b})})}export{I as M};
|
|
3
|
-
//# sourceMappingURL=MarkdownRenderer-
|
|
3
|
+
//# sourceMappingURL=MarkdownRenderer-DlDQNihj.js.map
|
package/dist/web/static/assets/{MarkdownRenderer-DZmTl-8J.js.map → MarkdownRenderer-DlDQNihj.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownRenderer-DZmTl-8J.js","sources":["../../src/components/MarkdownRenderer.tsx"],"sourcesContent":["import ReactMarkdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n// Import PrismLight from its subpath instead of the barrel ('react-syntax-highlighter')\n// to bypass the package's index re-exports of `Prism` (which transitively imports\n// `refractor/all` and bloats the chunk to ~620KB even with tree-shaking).\nimport SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light'\nimport { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism'\nimport typescript from 'react-syntax-highlighter/dist/esm/languages/prism/typescript'\nimport tsx from 'react-syntax-highlighter/dist/esm/languages/prism/tsx'\nimport json from 'react-syntax-highlighter/dist/esm/languages/prism/json'\nimport bash from 'react-syntax-highlighter/dist/esm/languages/prism/bash'\nimport markdown from 'react-syntax-highlighter/dist/esm/languages/prism/markdown'\nimport sql from 'react-syntax-highlighter/dist/esm/languages/prism/sql'\nimport python from 'react-syntax-highlighter/dist/esm/languages/prism/python'\n\n// Register only common languages used in our KB / docs.\n// Unregistered languages fall back to plain text (no crash).\nSyntaxHighlighter.registerLanguage('typescript', typescript)\nSyntaxHighlighter.registerLanguage('ts', typescript)\nSyntaxHighlighter.registerLanguage('tsx', tsx)\nSyntaxHighlighter.registerLanguage('javascript', typescript)\nSyntaxHighlighter.registerLanguage('js', typescript)\nSyntaxHighlighter.registerLanguage('json', json)\nSyntaxHighlighter.registerLanguage('bash', bash)\nSyntaxHighlighter.registerLanguage('shell', bash)\nSyntaxHighlighter.registerLanguage('sh', bash)\nSyntaxHighlighter.registerLanguage('markdown', markdown)\nSyntaxHighlighter.registerLanguage('md', markdown)\nSyntaxHighlighter.registerLanguage('sql', sql)\nSyntaxHighlighter.registerLanguage('python', python)\nSyntaxHighlighter.registerLanguage('py', python)\n\ninterface Props {\n content: string\n className?: string\n}\n\n// Languages that represent diagrams (not real code)\nconst DIAGRAM_LANGS = new Set(['mermaid', 'flowchart', 'sequence', 'gantt', 'classDiagram', 'stateDiagram'])\n\nexport default function MarkdownRenderer({ content, className = '' }: Props) {\n return (\n <div className={`kb-markdown ${className}`}>\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n code({ inline, className, children, node, ...props }: any) {\n const match = /language-(\\w+)/.exec(className || '')\n const lang = match?.[1]\n\n // Detect inline code:\n // - react-markdown v8 passes `inline` prop\n // - react-markdown v9+ does NOT pass `inline`; detect by:\n // 1) no language-* className AND\n // 2) content has no newline AND\n // 3) parent is not `pre`\n const text = String(children ?? '')\n const hasNewline = text.includes('\\n')\n const parentIsPre = node?.position && (node as any)?.parent?.tagName === 'pre'\n const isInline =\n inline === true ||\n (inline === undefined && !lang && !hasNewline && !parentIsPre)\n\n if (isInline) {\n return (\n <code\n className=\"bg-gray-100 text-gray-800 px-1.5 py-0.5 rounded text-[13px] font-mono border border-gray-200\"\n {...props}\n >\n {children}\n </code>\n )\n }\n\n // Handle diagram code blocks gracefully\n if (lang && DIAGRAM_LANGS.has(lang)) {\n return (\n <div className=\"my-4 rounded-lg border border-gray-200 bg-gray-50 px-4 py-3\">\n <div className=\"flex items-center gap-2 text-xs text-gray-500 mb-2\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7\" />\n </svg>\n {lang === 'mermaid' ? 'Mermaid 流程图' : `${lang} 图表`}(暂不支持在线渲染)\n </div>\n <pre className=\"text-xs text-gray-600 font-mono whitespace-pre-wrap leading-relaxed\">\n {text.replace(/\\n$/, '')}\n </pre>\n </div>\n )\n }\n\n // Regular code blocks with syntax highlighting\n if (lang) {\n return (\n <div className=\"my-4 rounded-lg overflow-hidden border border-slate-700\">\n <div className=\"flex items-center justify-between bg-slate-800 px-4 py-1.5\">\n <span className=\"text-xs text-slate-300 font-mono\">{lang}</span>\n </div>\n <SyntaxHighlighter\n style={oneDark}\n language={lang}\n PreTag=\"div\"\n customStyle={{\n margin: 0,\n borderRadius: 0,\n fontSize: '12.5px',\n padding: '16px',\n lineHeight: '1.6',\n background: '#1e293b',\n }}\n {...props}\n >\n {text.replace(/\\n$/, '')}\n </SyntaxHighlighter>\n </div>\n )\n }\n\n // Code blocks without language\n return (\n <code\n className=\"block bg-slate-800 text-slate-100 rounded-lg p-4 overflow-x-auto text-xs font-mono leading-relaxed whitespace-pre\"\n {...props}\n >\n {children}\n </code>\n )\n },\n pre: ({ children }) => <>{children}</>,\n h1: ({ children }) => (\n <h1 className=\"text-xl font-bold text-gray-900 mt-8 mb-3 pb-2 border-b border-gray-200 first:mt-0\">\n {children}\n </h1>\n ),\n h2: ({ children }) => (\n <h2 className=\"text-lg font-bold text-gray-900 mt-7 mb-3 pb-1.5 border-b border-gray-100 first:mt-0\">\n {children}\n </h2>\n ),\n h3: ({ children }) => (\n <h3 className=\"text-base font-semibold text-gray-800 mt-5 mb-2\">{children}</h3>\n ),\n h4: ({ children }) => (\n <h4 className=\"text-sm font-semibold text-gray-800 mt-4 mb-1.5\">{children}</h4>\n ),\n p: ({ children }) => (\n <p className=\"text-sm text-gray-700 my-3 leading-relaxed\">{children}</p>\n ),\n ul: ({ children }) => (\n <ul className=\"list-disc pl-5 text-sm text-gray-700 my-3 space-y-1.5\">{children}</ul>\n ),\n ol: ({ children }) => (\n <ol className=\"list-decimal pl-5 text-sm text-gray-700 my-3 space-y-1.5\">{children}</ol>\n ),\n li: ({ children }) => (\n <li className=\"text-sm leading-relaxed pl-1\">{children}</li>\n ),\n a: ({ children, href }) => (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" className=\"text-indigo-600 hover:text-indigo-800 underline decoration-indigo-300 hover:decoration-indigo-500 transition-colors\">\n {children}\n </a>\n ),\n blockquote: ({ children }) => (\n <blockquote className=\"border-l-4 border-indigo-200 bg-indigo-50/50 pl-4 pr-3 py-2 my-4 rounded-r-lg text-sm text-gray-700 italic\">\n {children}\n </blockquote>\n ),\n table: ({ children }) => (\n <div className=\"overflow-x-auto my-4 rounded-lg border border-gray-200\">\n <table className=\"min-w-full text-sm divide-y divide-gray-200\">{children}</table>\n </div>\n ),\n thead: ({ children }) => (\n <thead className=\"bg-gray-50\">{children}</thead>\n ),\n th: ({ children }) => (\n <th className=\"px-3 py-2 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider\">{children}</th>\n ),\n td: ({ children }) => (\n <td className=\"px-3 py-2 text-sm text-gray-700 border-t border-gray-100\">{children}</td>\n ),\n hr: () => <hr className=\"my-6 border-gray-200\" />,\n strong: ({ children }) => (\n <strong className=\"font-semibold text-gray-900\">{children}</strong>\n ),\n }}\n >\n {content}\n </ReactMarkdown>\n </div>\n )\n}\n"],"names":["SyntaxHighlighter","typescript","tsx","json","bash","markdown","sql","python","DIAGRAM_LANGS","MarkdownRenderer","content","className","jsx","ReactMarkdown","remarkGfm","inline","children","node","props","match","lang","text","hasNewline","parentIsPre","_a","jsxs","oneDark","href"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MarkdownRenderer-DlDQNihj.js","sources":["../../src/components/MarkdownRenderer.tsx"],"sourcesContent":["import ReactMarkdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n// Import PrismLight from its subpath instead of the barrel ('react-syntax-highlighter')\n// to bypass the package's index re-exports of `Prism` (which transitively imports\n// `refractor/all` and bloats the chunk to ~620KB even with tree-shaking).\nimport SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light'\nimport { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism'\nimport typescript from 'react-syntax-highlighter/dist/esm/languages/prism/typescript'\nimport tsx from 'react-syntax-highlighter/dist/esm/languages/prism/tsx'\nimport json from 'react-syntax-highlighter/dist/esm/languages/prism/json'\nimport bash from 'react-syntax-highlighter/dist/esm/languages/prism/bash'\nimport markdown from 'react-syntax-highlighter/dist/esm/languages/prism/markdown'\nimport sql from 'react-syntax-highlighter/dist/esm/languages/prism/sql'\nimport python from 'react-syntax-highlighter/dist/esm/languages/prism/python'\n\n// Register only common languages used in our KB / docs.\n// Unregistered languages fall back to plain text (no crash).\nSyntaxHighlighter.registerLanguage('typescript', typescript)\nSyntaxHighlighter.registerLanguage('ts', typescript)\nSyntaxHighlighter.registerLanguage('tsx', tsx)\nSyntaxHighlighter.registerLanguage('javascript', typescript)\nSyntaxHighlighter.registerLanguage('js', typescript)\nSyntaxHighlighter.registerLanguage('json', json)\nSyntaxHighlighter.registerLanguage('bash', bash)\nSyntaxHighlighter.registerLanguage('shell', bash)\nSyntaxHighlighter.registerLanguage('sh', bash)\nSyntaxHighlighter.registerLanguage('markdown', markdown)\nSyntaxHighlighter.registerLanguage('md', markdown)\nSyntaxHighlighter.registerLanguage('sql', sql)\nSyntaxHighlighter.registerLanguage('python', python)\nSyntaxHighlighter.registerLanguage('py', python)\n\ninterface Props {\n content: string\n className?: string\n}\n\n// Languages that represent diagrams (not real code)\nconst DIAGRAM_LANGS = new Set(['mermaid', 'flowchart', 'sequence', 'gantt', 'classDiagram', 'stateDiagram'])\n\nexport default function MarkdownRenderer({ content, className = '' }: Props) {\n return (\n <div className={`kb-markdown ${className}`}>\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n code({ inline, className, children, node, ...props }: any) {\n const match = /language-(\\w+)/.exec(className || '')\n const lang = match?.[1]\n\n // Detect inline code:\n // - react-markdown v8 passes `inline` prop\n // - react-markdown v9+ does NOT pass `inline`; detect by:\n // 1) no language-* className AND\n // 2) content has no newline AND\n // 3) parent is not `pre`\n const text = String(children ?? '')\n const hasNewline = text.includes('\\n')\n const parentIsPre = node?.position && (node as any)?.parent?.tagName === 'pre'\n const isInline =\n inline === true ||\n (inline === undefined && !lang && !hasNewline && !parentIsPre)\n\n if (isInline) {\n return (\n <code\n className=\"bg-gray-100 text-gray-800 px-1.5 py-0.5 rounded text-[13px] font-mono border border-gray-200\"\n {...props}\n >\n {children}\n </code>\n )\n }\n\n // Handle diagram code blocks gracefully\n if (lang && DIAGRAM_LANGS.has(lang)) {\n return (\n <div className=\"my-4 rounded-lg border border-gray-200 bg-gray-50 px-4 py-3\">\n <div className=\"flex items-center gap-2 text-xs text-gray-500 mb-2\">\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7\" />\n </svg>\n {lang === 'mermaid' ? 'Mermaid 流程图' : `${lang} 图表`}(暂不支持在线渲染)\n </div>\n <pre className=\"text-xs text-gray-600 font-mono whitespace-pre-wrap leading-relaxed\">\n {text.replace(/\\n$/, '')}\n </pre>\n </div>\n )\n }\n\n // Regular code blocks with syntax highlighting\n if (lang) {\n return (\n <div className=\"my-4 rounded-lg overflow-hidden border border-slate-700\">\n <div className=\"flex items-center justify-between bg-slate-800 px-4 py-1.5\">\n <span className=\"text-xs text-slate-300 font-mono\">{lang}</span>\n </div>\n <SyntaxHighlighter\n style={oneDark}\n language={lang}\n PreTag=\"div\"\n customStyle={{\n margin: 0,\n borderRadius: 0,\n fontSize: '12.5px',\n padding: '16px',\n lineHeight: '1.6',\n background: '#1e293b',\n }}\n {...props}\n >\n {text.replace(/\\n$/, '')}\n </SyntaxHighlighter>\n </div>\n )\n }\n\n // Code blocks without language\n return (\n <code\n className=\"block bg-slate-800 text-slate-100 rounded-lg p-4 overflow-x-auto text-xs font-mono leading-relaxed whitespace-pre\"\n {...props}\n >\n {children}\n </code>\n )\n },\n pre: ({ children }) => <>{children}</>,\n h1: ({ children }) => (\n <h1 className=\"text-xl font-bold text-gray-900 mt-8 mb-3 pb-2 border-b border-gray-200 first:mt-0\">\n {children}\n </h1>\n ),\n h2: ({ children }) => (\n <h2 className=\"text-lg font-bold text-gray-900 mt-7 mb-3 pb-1.5 border-b border-gray-100 first:mt-0\">\n {children}\n </h2>\n ),\n h3: ({ children }) => (\n <h3 className=\"text-base font-semibold text-gray-800 mt-5 mb-2\">{children}</h3>\n ),\n h4: ({ children }) => (\n <h4 className=\"text-sm font-semibold text-gray-800 mt-4 mb-1.5\">{children}</h4>\n ),\n p: ({ children }) => (\n <p className=\"text-sm text-gray-700 my-3 leading-relaxed\">{children}</p>\n ),\n ul: ({ children }) => (\n <ul className=\"list-disc pl-5 text-sm text-gray-700 my-3 space-y-1.5\">{children}</ul>\n ),\n ol: ({ children }) => (\n <ol className=\"list-decimal pl-5 text-sm text-gray-700 my-3 space-y-1.5\">{children}</ol>\n ),\n li: ({ children }) => (\n <li className=\"text-sm leading-relaxed pl-1\">{children}</li>\n ),\n a: ({ children, href }) => (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" className=\"text-indigo-600 hover:text-indigo-800 underline decoration-indigo-300 hover:decoration-indigo-500 transition-colors\">\n {children}\n </a>\n ),\n blockquote: ({ children }) => (\n <blockquote className=\"border-l-4 border-indigo-200 bg-indigo-50/50 pl-4 pr-3 py-2 my-4 rounded-r-lg text-sm text-gray-700 italic\">\n {children}\n </blockquote>\n ),\n table: ({ children }) => (\n <div className=\"overflow-x-auto my-4 rounded-lg border border-gray-200\">\n <table className=\"min-w-full text-sm divide-y divide-gray-200\">{children}</table>\n </div>\n ),\n thead: ({ children }) => (\n <thead className=\"bg-gray-50\">{children}</thead>\n ),\n th: ({ children }) => (\n <th className=\"px-3 py-2 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider\">{children}</th>\n ),\n td: ({ children }) => (\n <td className=\"px-3 py-2 text-sm text-gray-700 border-t border-gray-100\">{children}</td>\n ),\n hr: () => <hr className=\"my-6 border-gray-200\" />,\n strong: ({ children }) => (\n <strong className=\"font-semibold text-gray-900\">{children}</strong>\n ),\n }}\n >\n {content}\n </ReactMarkdown>\n </div>\n )\n}\n"],"names":["SyntaxHighlighter","typescript","tsx","json","bash","markdown","sql","python","DIAGRAM_LANGS","MarkdownRenderer","content","className","jsx","ReactMarkdown","remarkGfm","inline","children","node","props","match","lang","text","hasNewline","parentIsPre","_a","jsxs","oneDark","href"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as t}from"./react-vendor-tkvCrao7.js";import{b as a,L as i}from"./react-router-Cxmg8RuL.js";import{T as n,F as r}from"./arco-DV6xCLhr.js";import"./vendor-DS-q4Eyc.js";function c(){const e=a(),o=`${e.pathname}${e.search}`;return t.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"64px 16px",gap:12},"data-testid":"not-found-page",children:[t.jsx(n.Title,{heading:2,style:{marginBottom:0},children:"404"}),t.jsx(n.Text,{type:"secondary",style:{fontSize:14},children:"找不到这个页面"}),t.jsx("code",{style:{fontSize:12,padding:"4px 8px",background:"var(--color-fill-2)",borderRadius:4,maxWidth:600,overflow:"auto",whiteSpace:"nowrap"},title:o,children:o}),t.jsx(i,{to:"/health",replace:!0,children:t.jsx(r,{type:"primary",style:{marginTop:12},children:"返回 Health 主页"})})]})}export{c as default};
|
|
2
|
+
//# sourceMappingURL=NotFound-LMzbP51V.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotFound-
|
|
1
|
+
{"version":3,"file":"NotFound-LMzbP51V.js","sources":["../../src/components/NotFound.tsx"],"sourcesContent":["/**\n * NotFound — v4 catch-all 404 page (C-3).\n *\n * Renders inside the standard Layout so the topbar/sidebar stay visible. We\n * surface the offending path so debugging stale links is straightforward,\n * and offer a one-click back to /health.\n */\nimport { useLocation, Link } from 'react-router-dom'\nimport Typography from '@arco-design/web-react/es/Typography'\nimport Button from '@arco-design/web-react/es/Button'\n\nexport default function NotFound() {\n const location = useLocation()\n const fullPath = `${location.pathname}${location.search}`\n\n return (\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '64px 16px',\n gap: 12,\n }}\n data-testid=\"not-found-page\"\n >\n <Typography.Title heading={2} style={{ marginBottom: 0 }}>\n 404\n </Typography.Title>\n <Typography.Text type=\"secondary\" style={{ fontSize: 14 }}>\n 找不到这个页面\n </Typography.Text>\n <code\n style={{\n fontSize: 12,\n padding: '4px 8px',\n background: 'var(--color-fill-2)',\n borderRadius: 4,\n maxWidth: 600,\n overflow: 'auto',\n whiteSpace: 'nowrap',\n }}\n title={fullPath}\n >\n {fullPath}\n </code>\n <Link to=\"/health\" replace>\n <Button type=\"primary\" style={{ marginTop: 12 }}>\n 返回 Health 主页\n </Button>\n </Link>\n </div>\n )\n}\n"],"names":["NotFound","location","useLocation","fullPath","jsxs","jsx","Typography","Link","Button"],"mappings":"gLAWA,SAAwBA,GAAW,CACjC,MAAMC,EAAWC,EAAA,EACXC,EAAW,GAAGF,EAAS,QAAQ,GAAGA,EAAS,MAAM,GAEvD,OACEG,EAAAA,KAAC,MAAA,CACC,MAAO,CACL,QAAS,OACT,cAAe,SACf,WAAY,SACZ,eAAgB,SAChB,QAAS,YACT,IAAK,EAAA,EAEP,cAAY,iBAEZ,SAAA,CAAAC,EAAAA,IAACC,EAAW,MAAX,CAAiB,QAAS,EAAG,MAAO,CAAE,aAAc,CAAA,EAAK,SAAA,KAAA,CAE1D,EACAD,EAAAA,IAACC,EAAW,KAAX,CAAgB,KAAK,YAAY,MAAO,CAAE,SAAU,EAAA,EAAM,SAAA,SAAA,CAE3D,EACAD,EAAAA,IAAC,OAAA,CACC,MAAO,CACL,SAAU,GACV,QAAS,UACT,WAAY,sBACZ,aAAc,EACd,SAAU,IACV,SAAU,OACV,WAAY,QAAA,EAEd,MAAOF,EAEN,SAAAA,CAAA,CAAA,QAEFI,EAAA,CAAK,GAAG,UAAU,QAAO,GACxB,SAAAF,MAACG,EAAA,CAAO,KAAK,UAAU,MAAO,CAAE,UAAW,IAAM,wBAEjD,CAAA,CACF,CAAA,CAAA,CAAA,CAGN"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as y,j as e}from"./react-vendor-tkvCrao7.js";import{e as I}from"./index-DileOOE4.js";import{a as R}from"./react-router-Cxmg8RuL.js";import{a as E,u as G,c as $}from"./query-CgCOpYWf.js";import{a as L}from"./auth-Bnf8ZcqN.js";import{c as T,q as M,T as f,R as O,n as F,y as q,a8 as A,S as D,ac as v,F as x,J as C,aA as S,b as w,ag as _,ae as N,az as j}from"./arco-DV6xCLhr.js";import"./vendor-DS-q4Eyc.js";import"./lucide-CnlPQoG8.js";function Q(n,s,t){return n&&s.includes(n)?n:t}function B(n,s,t="tab"){const[o,a]=R(),r=o.get(t),c=y.useMemo(()=>Q(r,n,s),[r,n,s]),d=y.useCallback(u=>{const p=new URLSearchParams(o);u===s?p.delete(t):p.set(t,u),a(p,{replace:!1})},[o,a,s,t]);return{tab:c,setTab:d}}const U={threshold:"阈值配置",governance:"治理开关",retention:"数据保留"},J=["threshold","governance","retention"];function V(n){return n==="true"}function W(n,s){if(n!==void 0&&/^-?\d+$/.test(n)){const t=Number(n);if(Number.isInteger(t))return t}return s.min??0}function H(n){if(!n||!n.writable)return{groups:[],hasGovernance:!1,empty:!0};const s=new Map;for(const r of n.items??[])s.set(r.key,r);const t=new Map;let o=!1;for(const[r,c]of Object.entries(n.writable)){const d=s.get(r),u=d==null?void 0:d.value,p=c.type==="bool"?V(u):W(u,c);c.governance&&(o=!0);const g={key:r,spec:c,value:p,rawValue:u??null,updated_at:(d==null?void 0:d.updated_at)??null},m=t.get(c.group)??[];m.push(g),t.set(c.group,m)}const a=[];for(const r of J){const c=t.get(r);!c||c.length===0||(c.sort((d,u)=>d.spec.label.localeCompare(u.spec.label)),a.push({group:r,title:U[r],fields:c}))}return{groups:a,hasGovernance:o,empty:a.length===0}}function K(n,s){const t=[];for(const o of n.groups)for(const a of o.fields){if(!(a.key in s))continue;const r=s[a.key],c=typeof r=="boolean"?String(r):String(r).trim(),d=String(a.value);c!==d&&t.push({key:a.key,value:c})}return t}async function X(){const n=await fetch("/api/config");if(!n.ok)throw new Error(`/api/config → ${n.status}`);return n.json()}async function Y(n){const s=await L("/api/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n.length===1?n[0]:{items:n})});if(!s.ok){const t=await s.json().catch(()=>null);throw new Error((t==null?void 0:t.message)??(t==null?void 0:t.error)??`HTTP ${s.status}`)}return s.json()}function Z(){const n=E(),s=G({queryKey:["config"],queryFn:X,staleTime:3e4}),t=$({mutationFn:Y,onSuccess:()=>{n.invalidateQueries({queryKey:["config"]})}});return{view:y.useMemo(()=>H(s.data),[s.data]),loading:s.isLoading,isError:s.isError,error:s.error??null,refetch:()=>{s.refetch()},save:a=>t.mutateAsync(a),saving:t.isPending}}const b=T.TabPane,ee=O.Group,ne=["config","theme","about"];function te({field:n,value:s,onChange:t}){return n.spec.type==="bool"?e.jsx(_,{checked:s,onChange:o=>t(o),"data-testid":`cfg-switch-${n.key}`}):e.jsx(N,{value:s,min:n.spec.min,max:n.spec.max,step:1,style:{width:160},onChange:o=>t(typeof o=="number"?o:n.spec.min??0),"data-testid":`cfg-input-${n.key}`})}function se(){const{view:n,loading:s,isError:t,error:o,save:a,saving:r,refetch:c}=Z(),[d,u]=y.useState({}),p=y.useMemo(()=>{const l={};for(const i of n.groups)for(const h of i.fields)l[h.key]=h.value;return l},[n]);y.useEffect(()=>{u(p)},[p]);const g=K(n,d),m=g.length>0,k=y.useMemo(()=>{const l=new Set;for(const i of n.groups)for(const h of i.fields)h.spec.governance&&l.add(h.key);return g.some(i=>l.has(i.key))},[g,n]);async function P(){if(g.length!==0)try{const l=await a(g);j.success({content:`已保存 ${l.applied.length} 项配置`}),l.needsRestart&&j.warning({content:"治理类配置已写入,需 restart daemon 生效:cf daemon restart",duration:6e3})}catch(l){j.error({content:`保存失败:${String((l==null?void 0:l.message)??l)}`})}}return s?e.jsx("div",{style:{display:"flex",justifyContent:"center",padding:48},children:e.jsx(D,{tip:"加载配置..."})}):t?e.jsx(v,{type:"error",title:"读取配置失败",content:String((o==null?void 0:o.message)??o),action:e.jsx(x,{size:"small",onClick:c,children:"重试"})}):e.jsxs("div",{"data-testid":"config-panel",style:{display:"flex",flexDirection:"column",gap:16},children:[k&&e.jsx(v,{type:"warning",showIcon:!0,content:"检测到治理类配置改动 —— 保存后需 restart daemon 才会生效(cf daemon restart)。"}),n.groups.map(l=>e.jsx(C,{title:l.title,bordered:!0,headerStyle:{fontSize:15},children:e.jsx(S,{layout:"horizontal",labelCol:{span:10},wrapperCol:{span:14},children:l.fields.map(i=>e.jsx(S.Item,{label:e.jsxs("span",{children:[i.spec.label,i.spec.governance&&e.jsx(w,{size:"small",color:"orange",style:{marginLeft:8},children:"治理"})]}),extra:e.jsxs(f.Text,{type:"secondary",style:{fontSize:12},children:[i.spec.description,i.spec.type==="int"&&i.spec.min!==void 0&&e.jsxs("span",{style:{marginLeft:6},children:["(区间 ",i.spec.min,"–",i.spec.max,")"]}),i.rawValue===null&&e.jsx(w,{size:"small",style:{marginLeft:6},children:"未设置 · 用默认"})]}),children:e.jsx(te,{field:i,value:d[i.key]??i.value,onChange:h=>u(z=>({...z,[i.key]:h}))})},i.key))})},l.group)),e.jsx(C,{title:"Agent 同步",bordered:!0,headerStyle:{fontSize:15},children:e.jsxs(f.Paragraph,{type:"secondary",style:{fontSize:13,margin:0},children:["本地 ",e.jsx("code",{children:".claude/agents"})," 与全局 ",e.jsx("code",{children:"~/.claude/agents"})," 的同步由 CLI ",e.jsx("code",{children:"cf agents sync"})," 管理。Web 设置页不直接触发同步(避免误操作), 请在终端运行该命令。"]})}),e.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:12},children:[e.jsx(x,{onClick:()=>u(p),disabled:!m||r,children:"重置"}),e.jsxs(x,{type:"primary",onClick:P,loading:r,disabled:!m,"data-testid":"cfg-save",children:["保存",m?` (${g.length})`:""]})]})]})}function pe(){const{tab:n,setTab:s}=B(ne,"config","section"),[t,o]=I();return e.jsx("div",{"data-testid":"settings-page","data-section":n,style:{padding:24},children:e.jsxs(T,{activeTab:n,onChange:a=>s(a),type:"line",children:[e.jsx(b,{title:e.jsxs("span",{children:[e.jsx(M,{})," 配置"]}),children:e.jsx("div",{style:{paddingTop:16},children:e.jsx(se,{})})},"config"),e.jsx(b,{title:e.jsxs("span",{children:[e.jsx(F,{})," 主题"]}),children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12,padding:16},children:[e.jsx(f.Title,{heading:6,children:"外观"}),e.jsx(ee,{type:"button",value:t,onChange:a=>o(a),options:[{value:"light",label:"浅色"},{value:"dark",label:"深色"}]}),e.jsxs(f.Paragraph,{type:"secondary",style:{fontSize:12},children:["主题偏好保存在 localStorage ",e.jsx("code",{children:"claude-forge:theme"}),",刷新页面后保留。"]})]})},"theme"),e.jsx(b,{title:e.jsxs("span",{children:[e.jsx(A,{})," 关于"]}),children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:8,padding:16},children:[e.jsx(f.Title,{heading:6,children:"claude-forge"}),e.jsxs(f.Paragraph,{style:{fontSize:13},children:["版本: ",e.jsxs("code",{children:["v","9.12.0"]})]}),e.jsxs(f.Paragraph,{style:{fontSize:13},children:[e.jsx(q,{})," 配置写入 ",e.jsx("code",{children:"forge_config"})," 表(",e.jsx("code",{children:"~/.claude-forge/data.db"}),")。 治理类开关改后需 ",e.jsx("code",{children:"cf daemon restart"}),";schema 相关 key 无自动 migration, 故设置页只暴露后端白名单内的安全 key。"]}),e.jsx(f.Paragraph,{type:"secondary",style:{fontSize:12},children:"Arco 管理后台重设计(2026-06)— 分组 11 视图 · 设置页可写(Phase 4a,decision 29688066)。"})]})},"about")]})})}export{pe as default};
|
|
2
|
+
//# sourceMappingURL=SettingsPage-DzoK4PKg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsPage-DzoK4PKg.js","sources":["../../src/hooks/useTabsParam.ts","../../src/hooks/config-derive.ts","../../src/hooks/useConfig.ts","../../src/pages/SettingsPage.tsx"],"sourcesContent":["/**\n * useTabsParam — generic ?tab=<key> URL-param state hook.\n *\n * Three v4 IA pages (Context / Violations / Settings) all reimplemented the\n * same scaffold: a `KNOWN[]` array, a `parseTab` clamp, and a `handleChange`\n * that wrote/deleted the URL param. This hook consolidates that logic so the\n * pages keep their own `<Tabs>` JSX but share the URL-state plumbing.\n *\n * Design notes:\n * - We DO NOT wrap Arco `<Tabs>` — that's over-abstraction. Each page still\n * owns its tab JSX (tab titles, lazy-loading, icons differ per page).\n * - When `tab === defaultKey`, the URL param is DELETED (clean URLs) — this\n * matches existing behavior in all 3 call sites pre-refactor.\n * - The `paramName` arg defaults to `'tab'`. SettingsPage passes `'section'`.\n *\n * Pure logic (`clampTab`) is exported separately so unit tests can cover it\n * without mounting React / react-router.\n */\n\nimport { useCallback, useMemo } from 'react'\nimport { useSearchParams } from 'react-router-dom'\n\n/**\n * Clamp an arbitrary string (or null) to the known tab set.\n * Returns `defaultKey` if `raw` is null, empty, or not in `known`.\n */\nexport function clampTab<K extends string>(\n raw: string | null,\n known: readonly K[],\n defaultKey: K,\n): K {\n if (!raw) return defaultKey\n if ((known as readonly string[]).includes(raw)) return raw as K\n return defaultKey\n}\n\nexport interface UseTabsParamResult<K extends string> {\n tab: K\n setTab: (key: K) => void\n}\n\nexport function useTabsParam<K extends string>(\n known: readonly K[],\n defaultKey: K,\n paramName: string = 'tab',\n): UseTabsParamResult<K> {\n const [searchParams, setSearchParams] = useSearchParams()\n const raw = searchParams.get(paramName)\n const tab = useMemo(() => clampTab(raw, known, defaultKey), [raw, known, defaultKey])\n\n const setTab = useCallback(\n (key: K) => {\n const next = new URLSearchParams(searchParams)\n if (key === defaultKey) next.delete(paramName)\n else next.set(paramName, key)\n setSearchParams(next, { replace: false })\n },\n // searchParams identity is stable per render from react-router; setSearchParams is also stable.\n [searchParams, setSearchParams, defaultKey, paramName],\n )\n\n return { tab, setTab }\n}\n","/**\n * config-derive — /api/config 响应 → 设置页视图模型(纯函数,可单测)。\n *\n * Arco Phase 4a (decision 29688066)。把后端 { items[], writable{} } 装配成\n * 按 group 分组的可编辑字段列表:每个字段携带白名单 schema(type/range/\n * governance/label)+ 当前值(来自 items,缺则用 type 默认)。页面组件按 group\n * 渲染 Form 分组卡,治理类字段渲染 Switch、int 字段渲染 InputNumber。\n *\n * 与 agent-derive / issues-derive 同一模式:取数 hook 调本模块装配,页面只渲染。\n */\n\nexport type ConfigType = 'bool' | 'int'\nexport type ConfigGroup = 'threshold' | 'governance' | 'retention'\n\n/** 后端白名单 schema 的前端镜像(CONFIG_WRITE_WHITELIST 的值形状)。 */\nexport interface ConfigSpec {\n type: ConfigType\n min?: number\n max?: number\n governance: boolean\n label: string\n description: string\n group: ConfigGroup\n}\n\nexport interface ConfigItem {\n key: string\n value: string\n updated_at: string\n}\n\nexport interface ConfigApiResponse {\n generated_at: string\n items: ConfigItem[]\n writable: Record<string, ConfigSpec>\n}\n\n/** 一个可编辑字段(合并 schema + 当前值)。 */\nexport interface ConfigField {\n key: string\n spec: ConfigSpec\n /** 当前持久值。bool → boolean;int → number;缺失用 type 默认。 */\n value: boolean | number\n /** 原始字符串值(缺失为 null,UI 可标「未设置(用默认)」)。 */\n rawValue: string | null\n updated_at: string | null\n}\n\nexport interface ConfigGroupView {\n group: ConfigGroup\n title: string\n fields: ConfigField[]\n}\n\nexport interface ConfigView {\n groups: ConfigGroupView[]\n /** 任一 governance 字段 → 设置页提示「治理类改动需 restart daemon」。 */\n hasGovernance: boolean\n empty: boolean\n}\n\nconst GROUP_TITLES: Record<ConfigGroup, string> = {\n threshold: '阈值配置',\n governance: '治理开关',\n retention: '数据保留',\n}\n\nconst GROUP_ORDER: ConfigGroup[] = ['threshold', 'governance', 'retention']\n\n/** bool 字符串 → boolean(仅 'true' 为真;与后端 ConfigStore.isEnabled 同口径)。 */\nfunction coerceBool(raw: string | undefined): boolean {\n return raw === 'true'\n}\n\n/** int 字符串 → number(无效/缺失退回区间下界或 0)。 */\nfunction coerceInt(raw: string | undefined, spec: ConfigSpec): number {\n if (raw !== undefined && /^-?\\d+$/.test(raw)) {\n const n = Number(raw)\n if (Number.isInteger(n)) return n\n }\n return spec.min ?? 0\n}\n\n/**\n * 装配设置页视图。resp 为空(loading / error)时返回空视图(页面渲染骨架/错误)。\n */\nexport function buildConfigView(resp: ConfigApiResponse | undefined): ConfigView {\n if (!resp || !resp.writable) {\n return { groups: [], hasGovernance: false, empty: true }\n }\n\n const valueByKey = new Map<string, ConfigItem>()\n for (const it of resp.items ?? []) valueByKey.set(it.key, it)\n\n const byGroup = new Map<ConfigGroup, ConfigField[]>()\n let hasGovernance = false\n\n for (const [key, spec] of Object.entries(resp.writable)) {\n const item = valueByKey.get(key)\n const raw = item?.value\n const value: boolean | number =\n spec.type === 'bool' ? coerceBool(raw) : coerceInt(raw, spec)\n if (spec.governance) hasGovernance = true\n\n const field: ConfigField = {\n key,\n spec,\n value,\n rawValue: raw ?? null,\n updated_at: item?.updated_at ?? null,\n }\n const list = byGroup.get(spec.group) ?? []\n list.push(field)\n byGroup.set(spec.group, list)\n }\n\n const groups: ConfigGroupView[] = []\n for (const g of GROUP_ORDER) {\n const fields = byGroup.get(g)\n if (!fields || fields.length === 0) continue\n // 组内按 label 稳定排序,渲染顺序确定。\n fields.sort((a, b) => a.spec.label.localeCompare(b.spec.label))\n groups.push({ group: g, title: GROUP_TITLES[g], fields })\n }\n\n return { groups, hasGovernance, empty: groups.length === 0 }\n}\n\n/**\n * 把页面表单值(key → boolean|number|string)归一成 POST body 的字符串对。\n * 仅产出与 baseline 不同的项(最小写集;空 → 调用方可跳过提交)。\n */\nexport function diffConfigChanges(\n view: ConfigView,\n formValues: Record<string, boolean | number | string>,\n): Array<{ key: string; value: string }> {\n const out: Array<{ key: string; value: string }> = []\n for (const g of view.groups) {\n for (const f of g.fields) {\n if (!(f.key in formValues)) continue\n const next = formValues[f.key]\n const nextStr =\n typeof next === 'boolean' ? String(next) : String(next).trim()\n const curStr = String(f.value)\n if (nextStr !== curStr) out.push({ key: f.key, value: nextStr })\n }\n }\n return out\n}\n","/**\n * useConfig — 设置页取数 + 写配置 hook(Arco Phase 4a, decision 29688066)。\n *\n * 接真实 GET/POST /api/config(唯一硬后端缺口,本轮新补):\n * GET /api/config → { items[], writable{} } 读全量回显 + 白名单 schema\n * POST /api/config → 写单/批量(白名单 + 范围/类型校验,治理类返回 needsRestart)\n *\n * 写操作走 authFetch(带 Bearer,server.ts 对 /api 非 GET 挂 requireAuth)。\n * 成功后 invalidate 重拉以回显 daemon 写入的 canonical updated_at。\n *\n * 纯装配(按 group/type 分组、合并当前值与白名单 schema)放在 config-derive.ts,\n * 页面组件只渲染派生结果(与 agent-derive / issues-derive 同一模式)。\n */\nimport { useMemo } from 'react'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\n\nimport { authFetch } from '../utils/auth'\nimport {\n buildConfigView,\n type ConfigApiResponse,\n type ConfigView,\n} from './config-derive'\n\nasync function fetchConfig(): Promise<ConfigApiResponse> {\n const r = await fetch('/api/config')\n if (!r.ok) throw new Error(`/api/config → ${r.status}`)\n return r.json() as Promise<ConfigApiResponse>\n}\n\nexport interface ConfigWriteItem {\n key: string\n value: string\n}\n\nexport interface ConfigWriteResult {\n ok: boolean\n applied: Array<{ key: string; value: string; updated_at: string; governance: boolean }>\n needsRestart: boolean\n restart_hint: string | null\n}\n\nasync function writeConfig(items: ConfigWriteItem[]): Promise<ConfigWriteResult> {\n const res = await authFetch('/api/config', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(items.length === 1 ? items[0] : { items }),\n })\n if (!res.ok) {\n const body = (await res.json().catch(() => null)) as { message?: string; error?: string } | null\n throw new Error(body?.message ?? body?.error ?? `HTTP ${res.status}`)\n }\n return res.json() as Promise<ConfigWriteResult>\n}\n\nexport interface UseConfigResult {\n view: ConfigView\n loading: boolean\n isError: boolean\n error: Error | null\n refetch: () => void\n /** 写单/批量配置(mutation)。 */\n save: (items: ConfigWriteItem[]) => Promise<ConfigWriteResult>\n saving: boolean\n}\n\nexport function useConfig(): UseConfigResult {\n const qc = useQueryClient()\n\n const cfgQ = useQuery({\n queryKey: ['config'],\n queryFn: fetchConfig,\n staleTime: 30_000,\n })\n\n const mutation = useMutation<ConfigWriteResult, Error, ConfigWriteItem[]>({\n mutationFn: writeConfig,\n onSuccess: () => {\n // 重拉以回显 daemon 写入的 canonical value / updated_at。\n void qc.invalidateQueries({ queryKey: ['config'] })\n },\n })\n\n const view = useMemo(() => buildConfigView(cfgQ.data), [cfgQ.data])\n\n return {\n view,\n loading: cfgQ.isLoading,\n isError: cfgQ.isError,\n error: (cfgQ.error as Error) ?? null,\n refetch: () => {\n void cfgQ.refetch()\n },\n save: (items) => mutation.mutateAsync(items),\n saving: mutation.isPending,\n }\n}\n","/**\n * /system/settings — 系统 · 设置(可写)。Arco Phase 4a, decision 29688066。\n *\n * 替换 Phase 0 的占位组件为真实可写设置页。读 GET /api/config 回显当前\n * 值,改值后 POST /api/config(authFetch 带 Bearer)。治理类 key 改动后显示\n * 「需 restart daemon 生效」Alert(Q2,用户拍板)。\n *\n * 真 Arco 组件(Form / Switch / InputNumber / Card / Button / Alert),严禁直搬\n * 原型 Tailwind CSS。分组卡:阈值配置 / 治理开关 / 数据保留 + Agent 同步(只读状态)+\n * 主题 / 关于(保留原 theme/about)。\n *\n * 危险/不可写的 key 不暴露为可编辑——后端白名单 CONFIG_WRITE_WHITELIST 是唯一\n * 真源,前端只渲染 writable schema 返回的字段(KB 注入 threshold / TASK_SWITCH /\n * MAX_BUFFER 等运行时常量类 key 后端故意未列入,前端自然不显示为可写)。\n */\nimport { useEffect, useMemo, useState } from 'react'\nimport {\n Alert,\n Button,\n Card,\n Form,\n InputNumber,\n Notification,\n Radio,\n Spin,\n Switch,\n Tabs,\n Tag,\n Typography,\n} from '@arco-design/web-react'\nimport { IconSettings, IconSun, IconInfoCircle, IconRobot } from '@arco-design/web-react/icon'\n\nimport { useTheme } from '../lib/theme'\nimport { useTabsParam } from '../hooks/useTabsParam'\nimport { useConfig } from '../hooks/useConfig'\nimport { diffConfigChanges, type ConfigField, type ConfigView } from '../hooks/config-derive'\n\nconst TabPane = Tabs.TabPane\nconst RadioGroup = Radio.Group\n\ntype SettingsSection = 'config' | 'theme' | 'about'\nconst KNOWN: readonly SettingsSection[] = ['config', 'theme', 'about'] as const\n\n/** 单个可编辑字段的控件(bool → Switch,int → InputNumber)。 */\nfunction FieldControl({\n field,\n value,\n onChange,\n}: {\n field: ConfigField\n value: boolean | number\n onChange: (v: boolean | number) => void\n}) {\n if (field.spec.type === 'bool') {\n return (\n <Switch\n checked={value as boolean}\n onChange={(v) => onChange(v)}\n data-testid={`cfg-switch-${field.key}`}\n />\n )\n }\n return (\n <InputNumber\n value={value as number}\n min={field.spec.min}\n max={field.spec.max}\n step={1}\n style={{ width: 160 }}\n onChange={(v) => onChange(typeof v === 'number' ? v : (field.spec.min ?? 0))}\n data-testid={`cfg-input-${field.key}`}\n />\n )\n}\n\n/** 配置可写面(阈值 / 治理 / 保留分组卡 + 保存)。 */\nfunction ConfigPanel() {\n const { view, loading, isError, error, save, saving, refetch } = useConfig()\n // 本地编辑态:key → 值。初值由 view 派生,view 变化(重拉)时重置。\n const [draft, setDraft] = useState<Record<string, boolean | number>>({})\n\n const baseline = useMemo(() => {\n const m: Record<string, boolean | number> = {}\n for (const g of view.groups) for (const f of g.fields) m[f.key] = f.value\n return m\n }, [view])\n\n useEffect(() => {\n setDraft(baseline)\n }, [baseline])\n\n const changes = diffConfigChanges(view as ConfigView, draft)\n const dirty = changes.length > 0\n // 改动是否含治理类 key(决定是否提示 restart)。\n const touchesGovernance = useMemo(() => {\n const govKeys = new Set<string>()\n for (const g of view.groups) for (const f of g.fields) if (f.spec.governance) govKeys.add(f.key)\n return changes.some((c) => govKeys.has(c.key))\n }, [changes, view])\n\n async function handleSave() {\n if (changes.length === 0) return\n try {\n const result = await save(changes)\n Notification.success({ content: `已保存 ${result.applied.length} 项配置` })\n if (result.needsRestart) {\n Notification.warning({\n content: '治理类配置已写入,需 restart daemon 生效:cf daemon restart',\n duration: 6000,\n })\n }\n } catch (err) {\n Notification.error({ content: `保存失败:${String((err as Error)?.message ?? err)}` })\n }\n }\n\n if (loading) {\n return (\n <div style={{ display: 'flex', justifyContent: 'center', padding: 48 }}>\n <Spin tip=\"加载配置...\" />\n </div>\n )\n }\n if (isError) {\n return (\n <Alert\n type=\"error\"\n title=\"读取配置失败\"\n content={String(error?.message ?? error)}\n action={<Button size=\"small\" onClick={refetch}>重试</Button>}\n />\n )\n }\n\n return (\n <div data-testid=\"config-panel\" style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n {touchesGovernance && (\n <Alert\n type=\"warning\"\n showIcon\n content=\"检测到治理类配置改动 —— 保存后需 restart daemon 才会生效(cf daemon restart)。\"\n />\n )}\n\n {view.groups.map((grp) => (\n <Card key={grp.group} title={grp.title} bordered headerStyle={{ fontSize: 15 }}>\n <Form layout=\"horizontal\" labelCol={{ span: 10 }} wrapperCol={{ span: 14 }}>\n {grp.fields.map((f) => (\n <Form.Item\n key={f.key}\n label={\n <span>\n {f.spec.label}\n {f.spec.governance && (\n <Tag size=\"small\" color=\"orange\" style={{ marginLeft: 8 }}>治理</Tag>\n )}\n </span>\n }\n extra={\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n {f.spec.description}\n {f.spec.type === 'int' && f.spec.min !== undefined && (\n <span style={{ marginLeft: 6 }}>\n (区间 {f.spec.min}–{f.spec.max})\n </span>\n )}\n {f.rawValue === null && (\n <Tag size=\"small\" style={{ marginLeft: 6 }}>未设置 · 用默认</Tag>\n )}\n </Typography.Text>\n }\n >\n <FieldControl\n field={f}\n value={draft[f.key] ?? f.value}\n onChange={(v) => setDraft((d) => ({ ...d, [f.key]: v }))}\n />\n </Form.Item>\n ))}\n </Form>\n </Card>\n ))}\n\n {/* Agent 同步(只读状态卡;原型 cfg sync 为 toast mock,本轮不接真实 sync 后端)。 */}\n <Card title=\"Agent 同步\" bordered headerStyle={{ fontSize: 15 }}>\n <Typography.Paragraph type=\"secondary\" style={{ fontSize: 13, margin: 0 }}>\n 本地 <code>.claude/agents</code> 与全局 <code>~/.claude/agents</code> 的同步由\n CLI <code>cf agents sync</code> 管理。Web 设置页不直接触发同步(避免误操作),\n 请在终端运行该命令。\n </Typography.Paragraph>\n </Card>\n\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 12 }}>\n <Button onClick={() => setDraft(baseline)} disabled={!dirty || saving}>\n 重置\n </Button>\n <Button\n type=\"primary\"\n onClick={handleSave}\n loading={saving}\n disabled={!dirty}\n data-testid=\"cfg-save\"\n >\n 保存{dirty ? ` (${changes.length})` : ''}\n </Button>\n </div>\n </div>\n )\n}\n\nexport default function SettingsPage() {\n const { tab: section, setTab } = useTabsParam<SettingsSection>(KNOWN, 'config', 'section')\n const [theme, setTheme] = useTheme()\n\n return (\n <div data-testid=\"settings-page\" data-section={section} style={{ padding: 24 }}>\n <Tabs activeTab={section} onChange={(k) => setTab(k as SettingsSection)} type=\"line\">\n <TabPane key=\"config\" title={<span><IconSettings /> 配置</span>}>\n <div style={{ paddingTop: 16 }}>\n <ConfigPanel />\n </div>\n </TabPane>\n\n <TabPane key=\"theme\" title={<span><IconSun /> 主题</span>}>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 12, padding: 16 }}>\n <Typography.Title heading={6}>外观</Typography.Title>\n <RadioGroup\n type=\"button\"\n value={theme}\n onChange={(v: 'light' | 'dark') => setTheme(v)}\n options={[\n { value: 'light', label: '浅色' },\n { value: 'dark', label: '深色' },\n ]}\n />\n <Typography.Paragraph type=\"secondary\" style={{ fontSize: 12 }}>\n 主题偏好保存在 localStorage <code>claude-forge:theme</code>,刷新页面后保留。\n </Typography.Paragraph>\n </div>\n </TabPane>\n\n <TabPane key=\"about\" title={<span><IconInfoCircle /> 关于</span>}>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 8, padding: 16 }}>\n <Typography.Title heading={6}>claude-forge</Typography.Title>\n <Typography.Paragraph style={{ fontSize: 13 }}>\n 版本: <code>v{__APP_VERSION__}</code>\n </Typography.Paragraph>\n <Typography.Paragraph style={{ fontSize: 13 }}>\n <IconRobot /> 配置写入 <code>forge_config</code> 表(<code>~/.claude-forge/data.db</code>)。\n 治理类开关改后需 <code>cf daemon restart</code>;schema 相关 key 无自动 migration,\n 故设置页只暴露后端白名单内的安全 key。\n </Typography.Paragraph>\n <Typography.Paragraph type=\"secondary\" style={{ fontSize: 12 }}>\n Arco 管理后台重设计(2026-06)— 分组 11 视图 · 设置页可写(Phase 4a,decision 29688066)。\n </Typography.Paragraph>\n </div>\n </TabPane>\n </Tabs>\n </div>\n )\n}\n"],"names":["clampTab","raw","known","defaultKey","useTabsParam","paramName","searchParams","setSearchParams","useSearchParams","tab","useMemo","setTab","useCallback","key","next","GROUP_TITLES","GROUP_ORDER","coerceBool","coerceInt","spec","n","buildConfigView","resp","valueByKey","it","byGroup","hasGovernance","item","value","field","list","groups","g","fields","a","b","diffConfigChanges","view","formValues","out","f","nextStr","curStr","fetchConfig","r","writeConfig","items","res","authFetch","body","useConfig","qc","useQueryClient","cfgQ","useQuery","mutation","useMutation","TabPane","Tabs","RadioGroup","Radio","KNOWN","FieldControl","onChange","jsx","Switch","v","InputNumber","ConfigPanel","loading","isError","error","save","saving","refetch","draft","setDraft","useState","baseline","m","useEffect","changes","dirty","touchesGovernance","govKeys","c","handleSave","result","Notification","err","Spin","Alert","Button","jsxs","grp","Card","Form","Tag","Typography","d","SettingsPage","section","theme","setTheme","useTheme","k","IconSettings","IconSun","IconInfoCircle","IconRobot"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{j as e}from"./react-vendor-tkvCrao7.js";import{J as a,d as u,D as b,F as p,X as v,w as T,T as s,Y as S,K as f,E as o,$ as k,b as c,a4 as z,y as w,a5 as R}from"./arco-DV6xCLhr.js";import{M as C}from"./MarkdownRenderer-DlDQNihj.js";import{c as I,a as x,b as j,r as W,d as D,i as B}from"./useSkillStats-B5hbIwdf.js";import{G as E}from"./GlobalScopeHint-Q3wTJx3F.js";import{d as L,u as M}from"./react-router-Cxmg8RuL.js";import"./vendor-DS-q4Eyc.js";import"./syntax-highlighter-BDYycNja.js";import"./markdown-CA7ePUts.js";import"./query-CgCOpYWf.js";import"./index-DileOOE4.js";import"./lucide-CnlPQoG8.js";import"./useEffectiveProject-DQiyX54y.js";const P=f.Row,y=f.Col;function A(l,i){return i===0?e.jsx(c,{size:"small",color:"gray",children:"未评分"}):e.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:6},children:[e.jsx(z,{readonly:!0,allowHalf:!0,value:W(l),style:{fontSize:14}}),e.jsx(s.Text,{style:{fontWeight:600},children:j(l)})]})}function G(l){const i=[{label:"helped",n:l.helped,color:"rgb(var(--green-6))"},{label:"partial",n:l.partial,color:"rgb(var(--orange-6))"},{label:"not-actionable",n:l.notActionable,color:"rgb(var(--red-6))"}],t=l.totalRated||1;return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:10},children:[i.map(n=>e.jsxs("div",{children:[e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",marginBottom:4},children:[e.jsx(s.Text,{style:{fontSize:12},children:n.label}),e.jsxs(s.Text,{type:"secondary",style:{fontSize:12},children:[n.n," · ",l.totalRated>0?Math.round(n.n/t*100):0,"%"]})]}),e.jsx(R,{percent:l.totalRated>0?Math.round(n.n/t*100):0,showText:!1,color:n.color,size:"small"})]},n.label)),l.pending>0&&e.jsxs(s.Text,{type:"secondary",style:{fontSize:11},children:["另有 ",l.pending," 次调用未评分(不计入有用率分母)"]})]})}function H(l){const i=D(l.usefulness);return e.jsxs("div",{style:{padding:"10px 0",borderBottom:"1px solid var(--color-border-1)"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:6,fontSize:13},children:[e.jsx(w,{style:{color:"var(--color-text-3)"}}),l.agent]}),e.jsx(c,{size:"small",children:B(l.invocationType)}),e.jsx(s.Text,{code:!0,style:{fontSize:11},title:l.reason,children:l.reason}),e.jsx("div",{style:{flex:1}}),e.jsx(c,{size:"small",color:i.color,children:i.label}),e.jsx(s.Text,{type:"secondary",style:{fontSize:12,width:96,textAlign:"right"},children:x(l.ts)})]}),l.usefulnessNote&&e.jsxs(s.Text,{type:"secondary",style:{fontSize:12,display:"block",marginTop:4,paddingLeft:22},children:["“",l.usefulnessNote,"”"]})]},l.id)}function _(){const{id:l}=L(),i=M(),{view:t,loading:n,isError:h,error:d,project:g,isAllProjects:m}=I(l);if(n)return e.jsx("div",{style:{padding:16},children:e.jsx(a,{bordered:!0,children:e.jsx(u,{animation:!0,text:{rows:8}})})});if(h||!t)return e.jsx("div",{style:{padding:16},children:e.jsx(b,{status:"error",title:"加载 Skill 详情失败",subTitle:(d==null?void 0:d.message)||"skill 不存在或端点不可用",extra:e.jsx(p,{type:"primary",onClick:()=>i("/ai/skills"),children:"返回 Skill 调用"})})});const r=t.breakdown;return e.jsxs("div",{style:{padding:16,display:"flex",flexDirection:"column",gap:16},children:[e.jsxs(a,{bordered:!0,children:[e.jsx(p,{type:"text",size:"small",icon:e.jsx(v,{}),style:{marginBottom:8,paddingLeft:0},onClick:()=>i("/ai/skills"),children:"返回 Skill 调用"}),e.jsx("div",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:16,flexWrap:"wrap"},children:e.jsxs("div",{style:{minWidth:0,flex:1},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsx(T,{style:{color:"rgb(var(--arcoblue-6))"}}),e.jsx(s.Title,{heading:5,style:{margin:0,fontFamily:"monospace"},children:t.id}),A(r.actionableRate,r.totalRated),e.jsx(E,{project:g,isAllProjects:m,usageLabel:"调用统计"})]}),t.description&&e.jsx(s.Text,{type:"secondary",style:{fontSize:12,display:"block",marginTop:6},children:t.description}),e.jsxs("div",{style:{display:"flex",gap:12,flexWrap:"wrap",marginTop:8,alignItems:"center"},children:[e.jsxs(s.Text,{type:"secondary",style:{fontSize:12},children:["调用 ",e.jsx("b",{children:t.calls}),"(真调 ",t.invoked,")"]}),e.jsxs(s.Text,{type:"secondary",style:{fontSize:12},children:["已评 ",e.jsx("b",{children:r.totalRated})]}),t.caller&&e.jsxs(s.Text,{type:"secondary",style:{fontSize:12},children:["主要调用方 ",e.jsx("b",{children:t.caller})]}),t.lastTs>0&&e.jsxs(s.Text,{type:"secondary",style:{fontSize:12,display:"inline-flex",alignItems:"center",gap:4},children:[e.jsx(S,{})," ",x(t.lastTs)]})]})]})})]}),e.jsxs(P,{gutter:16,align:"start",children:[e.jsx(y,{xs:24,xl:16,style:{marginBottom:16},children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16},children:[e.jsx(a,{bordered:!0,title:e.jsx("span",{style:{fontSize:14,fontWeight:600},children:"📖 方法论正文"}),children:t.contentExists&&t.content?e.jsx("div",{style:{border:"1px solid var(--color-border-2)",borderRadius:4,background:"var(--color-fill-1)",padding:"12px 16px",maxHeight:520,overflow:"auto"},children:e.jsx(C,{content:t.content})}):e.jsx(o,{description:"该 skill 无可读正文(非 distilled 文件或 content endpoint 不可用)"})}),e.jsx(a,{bordered:!0,title:e.jsx("span",{style:{fontSize:14,fontWeight:600},children:"🧾 调用记录"}),extra:e.jsxs(s.Text,{type:"secondary",style:{fontSize:12},children:["窗口内 ",t.records.length," 条"]}),children:t.records.length>0?e.jsx("div",{style:{display:"flex",flexDirection:"column"},children:t.records.map(H)}):e.jsx(o,{description:"窗口内无调用记录"})})]})}),e.jsx(y,{xs:24,xl:8,style:{marginBottom:16},children:e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16},children:[e.jsx(a,{bordered:!0,title:e.jsx("span",{style:{fontSize:14,fontWeight:600},children:"概要"}),children:e.jsx(k,{colon:" :",size:"small",column:1,labelStyle:{width:88,color:"var(--color-text-3)"},data:[{label:"Skill",value:e.jsx(s.Text,{code:!0,style:{fontSize:11},children:t.id})},{label:"调用数",value:e.jsx(s.Text,{style:{fontWeight:600},children:t.calls})},{label:"真调用",value:t.invoked},{label:"注入",value:t.injected},{label:"已评分",value:r.totalRated},{label:"有用率",value:j(r.actionableRate)},{label:"主要调用方",value:t.caller||"—"},{label:"最近",value:x(t.lastTs)}]})}),e.jsx(a,{bordered:!0,title:e.jsx("span",{style:{fontSize:14,fontWeight:600},children:"有用性分布"}),children:r.totalRated>0?G(r):e.jsx(o,{description:"尚无有用性自评(agent 用完 skill 后 cf skill feedback 写入)"})}),e.jsx(a,{bordered:!0,title:e.jsx("span",{style:{fontSize:14,fontWeight:600},children:"关联任务"}),children:e.jsx(o,{description:"暂无关联任务(端点未提供 per-skill 关联)"})})]})})]})]})}export{_ as default};
|
|
2
|
+
//# sourceMappingURL=SkillDetailPage-BuBJJ_NX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SkillDetailPage-BuBJJ_NX.js","sources":["../../src/pages/ai/SkillDetailPage.tsx"],"sourcesContent":["/**\n * SkillDetailPage — AI 资源 · Skill 调用详情整页 (Phase 2c, decision 29688066).\n *\n * 替换 `/ai/skills/:id` 的占位组件。整页(非抽屉)布局,翻译原型「Skill 调用\n * 详情」成真 Arco 组件(**严禁直搬原型 Tailwind CSS**):\n * A. 页头横条:skill id + ★平均有用性 Tag + 调用数/最近 + 返回\n * B. 左右双栏:\n * 左 = 方法论正文预览(MarkdownRenderer;content endpoint 不提供则降级)+\n * 调用记录列表(agent + reason workflow/phase + invocation_type +\n * rating + note + 时间)\n * 右 360 = 概要 Descriptions + helped/partial/not-actionable 分布条 +\n * 关联任务(端点未提供 per-skill 关联,降级空态)\n *\n * 数据接真实端点(GET /api/skill-stats/invocations/:id + /api/skills/:id/content +\n * 同窗 list stat),取数 + 派生在 useSkillDetail / skill-derive,本组件只渲染。\n */\nimport { useParams, useNavigate } from 'react-router-dom'\n\nimport Card from '@arco-design/web-react/es/Card'\nimport Grid from '@arco-design/web-react/es/Grid'\nimport Tag from '@arco-design/web-react/es/Tag'\nimport Typography from '@arco-design/web-react/es/Typography'\nimport Descriptions from '@arco-design/web-react/es/Descriptions'\nimport Button from '@arco-design/web-react/es/Button'\nimport Rate from '@arco-design/web-react/es/Rate'\nimport Empty from '@arco-design/web-react/es/Empty'\nimport Skeleton from '@arco-design/web-react/es/Skeleton'\nimport Result from '@arco-design/web-react/es/Result'\nimport Progress from '@arco-design/web-react/es/Progress'\nimport {\n IconLeft,\n IconThunderbolt,\n IconClockCircle,\n IconRobot,\n} from '@arco-design/web-react/icon'\n\nimport MarkdownRenderer from '../../components/MarkdownRenderer'\nimport { useSkillDetail } from '../../hooks/useSkillStats'\nimport GlobalScopeHint from '../../components/ai/GlobalScopeHint'\nimport {\n formatPct,\n formatTs,\n ratingStars,\n invocationTypeLabel,\n usefulnessMeta,\n type SkillRecordRow,\n type UsefulnessBreakdown,\n} from '../../hooks/skill-derive'\n\nconst Row = Grid.Row\nconst Col = Grid.Col\n\nfunction ratingTag(rate: number | null, totalRated: number) {\n if (totalRated === 0) {\n return <Tag size=\"small\" color=\"gray\">未评分</Tag>\n }\n return (\n <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>\n <Rate readonly allowHalf value={ratingStars(rate)} style={{ fontSize: 14 }} />\n <Typography.Text style={{ fontWeight: 600 }}>{formatPct(rate)}</Typography.Text>\n </span>\n )\n}\n\n/** helped/partial/not-actionable 三段分布条(Arco Progress steps 风格手搓段条)。 */\nfunction breakdownBars(b: UsefulnessBreakdown) {\n const segs: Array<{ label: string; n: number; color: string }> = [\n { label: 'helped', n: b.helped, color: 'rgb(var(--green-6))' },\n { label: 'partial', n: b.partial, color: 'rgb(var(--orange-6))' },\n { label: 'not-actionable', n: b.notActionable, color: 'rgb(var(--red-6))' },\n ]\n const denom = b.totalRated || 1\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>\n {segs.map((s) => (\n <div key={s.label}>\n <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>\n <Typography.Text style={{ fontSize: 12 }}>{s.label}</Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n {s.n} · {b.totalRated > 0 ? Math.round((s.n / denom) * 100) : 0}%\n </Typography.Text>\n </div>\n <Progress\n percent={b.totalRated > 0 ? Math.round((s.n / denom) * 100) : 0}\n showText={false}\n color={s.color}\n size=\"small\"\n />\n </div>\n ))}\n {b.pending > 0 && (\n <Typography.Text type=\"secondary\" style={{ fontSize: 11 }}>\n 另有 {b.pending} 次调用未评分(不计入有用率分母)\n </Typography.Text>\n )}\n </div>\n )\n}\n\nfunction recordItem(r: SkillRecordRow) {\n const meta = usefulnessMeta(r.usefulness)\n return (\n <div\n key={r.id}\n style={{\n padding: '10px 0',\n borderBottom: '1px solid var(--color-border-1)',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>\n <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 13 }}>\n <IconRobot style={{ color: 'var(--color-text-3)' }} />\n {r.agent}\n </span>\n <Tag size=\"small\">{invocationTypeLabel(r.invocationType)}</Tag>\n <Typography.Text code style={{ fontSize: 11 }} title={r.reason}>\n {r.reason}\n </Typography.Text>\n <div style={{ flex: 1 }} />\n <Tag size=\"small\" color={meta.color}>\n {meta.label}\n </Tag>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12, width: 96, textAlign: 'right' }}>\n {formatTs(r.ts)}\n </Typography.Text>\n </div>\n {r.usefulnessNote && (\n <Typography.Text\n type=\"secondary\"\n style={{ fontSize: 12, display: 'block', marginTop: 4, paddingLeft: 22 }}\n >\n “{r.usefulnessNote}”\n </Typography.Text>\n )}\n </div>\n )\n}\n\nexport default function SkillDetailPage() {\n const { id } = useParams<{ id: string }>()\n const navigate = useNavigate()\n const { view, loading, isError, error, project, isAllProjects } = useSkillDetail(id)\n\n if (loading) {\n return (\n <div style={{ padding: 16 }}>\n <Card bordered>\n <Skeleton animation text={{ rows: 8 }} />\n </Card>\n </div>\n )\n }\n\n if (isError || !view) {\n return (\n <div style={{ padding: 16 }}>\n <Result\n status=\"error\"\n title=\"加载 Skill 详情失败\"\n subTitle={error?.message || 'skill 不存在或端点不可用'}\n extra={\n <Button type=\"primary\" onClick={() => navigate('/ai/skills')}>\n 返回 Skill 调用\n </Button>\n }\n />\n </div>\n )\n }\n\n const b = view.breakdown\n\n return (\n <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 16 }}>\n {/* ── A. 页头横条 ─────────────────────────────────────────────── */}\n <Card bordered>\n <Button\n type=\"text\"\n size=\"small\"\n icon={<IconLeft />}\n style={{ marginBottom: 8, paddingLeft: 0 }}\n onClick={() => navigate('/ai/skills')}\n >\n 返回 Skill 调用\n </Button>\n <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16, flexWrap: 'wrap' }}>\n <div style={{ minWidth: 0, flex: 1 }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>\n <IconThunderbolt style={{ color: 'rgb(var(--arcoblue-6))' }} />\n <Typography.Title heading={5} style={{ margin: 0, fontFamily: 'monospace' }}>\n {view.id}\n </Typography.Title>\n {ratingTag(b.actionableRate, b.totalRated)}\n <GlobalScopeHint project={project} isAllProjects={isAllProjects} usageLabel=\"调用统计\" />\n </div>\n {view.description && (\n <Typography.Text type=\"secondary\" style={{ fontSize: 12, display: 'block', marginTop: 6 }}>\n {view.description}\n </Typography.Text>\n )}\n <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginTop: 8, alignItems: 'center' }}>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 调用 <b>{view.calls}</b>(真调 {view.invoked})\n </Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 已评 <b>{b.totalRated}</b>\n </Typography.Text>\n {view.caller && (\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 主要调用方 <b>{view.caller}</b>\n </Typography.Text>\n )}\n {view.lastTs > 0 && (\n <Typography.Text type=\"secondary\" style={{ fontSize: 12, display: 'inline-flex', alignItems: 'center', gap: 4 }}>\n <IconClockCircle /> {formatTs(view.lastTs)}\n </Typography.Text>\n )}\n </div>\n </div>\n </div>\n </Card>\n\n {/* ── B. 左右双栏 ─────────────────────────────────────────────── */}\n <Row gutter={16} align=\"start\">\n {/* 左主栏:方法论正文 + 调用记录 */}\n <Col xs={24} xl={16} style={{ marginBottom: 16 }}>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n <Card\n bordered\n title={<span style={{ fontSize: 14, fontWeight: 600 }}>📖 方法论正文</span>}\n >\n {view.contentExists && view.content ? (\n <div\n style={{\n border: '1px solid var(--color-border-2)',\n borderRadius: 4,\n background: 'var(--color-fill-1)',\n padding: '12px 16px',\n maxHeight: 520,\n overflow: 'auto',\n }}\n >\n <MarkdownRenderer content={view.content} />\n </div>\n ) : (\n <Empty description=\"该 skill 无可读正文(非 distilled 文件或 content endpoint 不可用)\" />\n )}\n </Card>\n\n <Card\n bordered\n title={<span style={{ fontSize: 14, fontWeight: 600 }}>🧾 调用记录</span>}\n extra={\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 窗口内 {view.records.length} 条\n </Typography.Text>\n }\n >\n {view.records.length > 0 ? (\n <div style={{ display: 'flex', flexDirection: 'column' }}>\n {view.records.map(recordItem)}\n </div>\n ) : (\n <Empty description=\"窗口内无调用记录\" />\n )}\n </Card>\n </div>\n </Col>\n\n {/* 右侧栏:概要 + 分布条 + 关联任务 */}\n <Col xs={24} xl={8} style={{ marginBottom: 16 }}>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>\n <Card bordered title={<span style={{ fontSize: 14, fontWeight: 600 }}>概要</span>}>\n <Descriptions\n colon=\" :\"\n size=\"small\"\n column={1}\n labelStyle={{ width: 88, color: 'var(--color-text-3)' }}\n data={[\n { label: 'Skill', value: <Typography.Text code style={{ fontSize: 11 }}>{view.id}</Typography.Text> },\n { label: '调用数', value: <Typography.Text style={{ fontWeight: 600 }}>{view.calls}</Typography.Text> },\n { label: '真调用', value: view.invoked },\n { label: '注入', value: view.injected },\n { label: '已评分', value: b.totalRated },\n { label: '有用率', value: formatPct(b.actionableRate) },\n { label: '主要调用方', value: view.caller || '—' },\n { label: '最近', value: formatTs(view.lastTs) },\n ]}\n />\n </Card>\n\n <Card bordered title={<span style={{ fontSize: 14, fontWeight: 600 }}>有用性分布</span>}>\n {b.totalRated > 0 ? (\n breakdownBars(b)\n ) : (\n <Empty description=\"尚无有用性自评(agent 用完 skill 后 cf skill feedback 写入)\" />\n )}\n </Card>\n\n <Card bordered title={<span style={{ fontSize: 14, fontWeight: 600 }}>关联任务</span>}>\n {/*\n records 端点回 session_id 但无 task_id;per-skill→task 关联端点未提供,\n 按 spec「缺字段降级」先空态。可在端点补 task 关联后挂 /tasks/:id 链接。\n */}\n <Empty description=\"暂无关联任务(端点未提供 per-skill 关联)\" />\n </Card>\n </div>\n </Col>\n </Row>\n </div>\n )\n}\n"],"names":["Row","Grid","Col","ratingTag","rate","totalRated","Tag","jsxs","jsx","Rate","ratingStars","Typography","formatPct","breakdownBars","b","segs","denom","s","Progress","recordItem","r","meta","usefulnessMeta","IconRobot","invocationTypeLabel","formatTs","SkillDetailPage","id","useParams","navigate","useNavigate","view","loading","isError","error","project","isAllProjects","useSkillDetail","Card","Skeleton","Result","Button","IconLeft","IconThunderbolt","GlobalScopeHint","IconClockCircle","MarkdownRenderer","Empty","Descriptions"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as m,j as e}from"./react-vendor-tkvCrao7.js";import{D as T,J as c,T as s,R as r,a1 as S,b as x,y as v,F as k,N as b,a4 as z}from"./arco-DV6xCLhr.js";import{u as R,f as C,a as I,r as W,b as _}from"./useSkillStats-B5hbIwdf.js";import{G as w}from"./GlobalScopeHint-Q3wTJx3F.js";import{u as L}from"./react-router-Cxmg8RuL.js";import"./vendor-DS-q4Eyc.js";import"./query-CgCOpYWf.js";import"./index-DileOOE4.js";import"./lucide-CnlPQoG8.js";import"./useEffectiveProject-DQiyX54y.js";function D(i){return i.totalRated===0?e.jsx(s.Text,{type:"secondary",style:{fontSize:12},children:"未评分"}):e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:2},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6},children:[e.jsx(z,{readonly:!0,allowHalf:!0,value:W(i.actionableRate),style:{fontSize:13}}),e.jsx(s.Text,{style:{fontWeight:600,fontSize:13},children:_(i.actionableRate)})]}),e.jsxs(s.Text,{type:"secondary",style:{fontSize:11},children:[i.helped," helped · ",i.partial," partial · ",i.notActionable," 无效",i.pending>0?` · ${i.pending} 待评`:""]})]})}function J(){const i=L(),{view:n,loading:p,isError:y,error:o,project:h,isAllProjects:f}=R(),[a,j]=m.useState("all");if(y)return e.jsx("div",{style:{padding:16},children:e.jsx(T,{status:"error",title:"加载 Skill 调用失败",subTitle:(o==null?void 0:o.message)||"/api/skill-stats/invocations 端点不可用"})});const d=C(n.rows,a),u=[{title:"Skill",dataIndex:"id",render:(l,t)=>e.jsxs("div",{style:{minWidth:0},children:[e.jsx(s.Text,{code:!0,style:{fontSize:13},children:t.id}),t.isUnused&&e.jsx(x,{color:"gray",size:"small",style:{marginLeft:6},children:"未使用"}),t.description&&e.jsx("div",{style:{marginTop:2},children:e.jsx(s.Text,{type:"secondary",style:{fontSize:12},ellipsis:{rows:1,showTooltip:!0},children:t.description})})]})},{title:"调用次数",dataIndex:"calls",width:116,sorter:(l,t)=>l.calls-t.calls,render:(l,t)=>e.jsxs("div",{children:[e.jsx(s.Text,{style:{fontWeight:600},children:t.calls}),e.jsxs(s.Text,{type:"secondary",style:{fontSize:11,marginLeft:6},children:["真调 ",t.invoked]})]})},{title:"有用性",dataIndex:"actionableRate",width:200,sorter:(l,t)=>(l.actionableRate??-1)-(t.actionableRate??-1),render:(l,t)=>D(t)},{title:"主要调用方",dataIndex:"caller",width:140,render:(l,t)=>t.caller?e.jsx(x,{color:"arcoblue",size:"small",icon:e.jsx(v,{}),children:t.caller}):e.jsx(s.Text,{type:"secondary",style:{fontSize:12},children:"—"})},{title:"最近调用",dataIndex:"lastTs",width:124,sorter:(l,t)=>l.lastTs-t.lastTs,render:(l,t)=>e.jsx(s.Text,{type:"secondary",style:{fontSize:12},children:I(t.lastTs)})},{title:"操作",dataIndex:"op",width:76,align:"right",render:(l,t)=>e.jsxs(k,{type:"text",size:"mini",onClick:g=>{g.stopPropagation(),i(`/ai/skills/${encodeURIComponent(t.id)}`)},children:["详情 ",e.jsx(b,{})]})}];return e.jsxs("div",{style:{padding:16,display:"flex",flexDirection:"column",gap:16},children:[e.jsxs(c,{bordered:!0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,flexWrap:"wrap"},children:[e.jsx(s.Title,{heading:6,style:{margin:0},children:"Skill 调用"}),e.jsx(s.Text,{type:"secondary",style:{fontSize:12},children:"方法论 skill 调用与有用性自评 · skill_invocations(按调用数排序)"}),e.jsx(w,{project:h,isAllProjects:f,usageLabel:"调用统计"}),e.jsx("div",{style:{flex:1}}),e.jsxs(s.Text,{type:"secondary",style:{fontSize:12},children:["Skill 数"," ",e.jsx(s.Text,{style:{fontWeight:600},children:n.totalSkills}),n.unusedSkills>0&&e.jsxs(s.Text,{type:"secondary",style:{fontSize:11,marginLeft:6},children:["· 未使用"," ",e.jsx(s.Text,{style:{fontWeight:600},children:n.unusedSkills})]})]}),e.jsxs(s.Text,{type:"secondary",style:{fontSize:12},children:["真实调用"," ",e.jsx(s.Text,{style:{fontWeight:600,color:"rgb(var(--arcoblue-6))"},children:n.totalInvoked}),e.jsxs(s.Text,{type:"secondary",style:{fontSize:11,marginLeft:6},children:["· 总行 ",n.totalCalls,"(含注入/历史匹配)"]})]}),e.jsxs(s.Text,{type:"secondary",style:{fontSize:12},children:["已评分"," ",e.jsxs(s.Text,{style:{fontWeight:600},children:[n.totalHelped,"/",n.totalRated," helped"]})]})]}),e.jsx("div",{style:{marginTop:12},children:e.jsxs(r.Group,{type:"button",size:"small",value:a,onChange:l=>j(l),children:[e.jsx(r,{value:"all",children:"全部"}),e.jsx(r,{value:"invoked",children:"仅调用过"}),e.jsx(r,{value:"unused",children:"仅未使用"})]})})]}),e.jsx(c,{bordered:!0,style:{padding:0},children:e.jsx(S,{rowKey:"id",loading:p,data:d,columns:u,pagination:d.length>20?{pageSize:20,showTotal:!0}:!1,border:{wrapper:!1,cell:!1},noDataElement:e.jsx(s.Text,{type:"secondary",children:a==="unused"?"没有未使用的 skill":a==="invoked"?"窗口内暂无 skill 调用记录":"暂无 skill"}),onRow:l=>({onClick:()=>i(`/ai/skills/${encodeURIComponent(l.id)}`),style:{cursor:"pointer"}})})})]})}export{J as default};
|
|
2
|
+
//# sourceMappingURL=SkillsPage-aojkJpBc.js.map
|