@wascartech/devbot 0.0.0-stage → 2.1.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/LICENSE +202 -0
- package/README.md +638 -2
- package/dist/access-grant-store.js +99 -0
- package/dist/access-grant-store.js.map +1 -0
- package/dist/access-resolve.js +11 -0
- package/dist/access-resolve.js.map +1 -0
- package/dist/access-rule-store.js +99 -0
- package/dist/access-rule-store.js.map +1 -0
- package/dist/admin/access-routes.js +73 -0
- package/dist/admin/access-routes.js.map +1 -0
- package/dist/admin/access-rule-routes.js +107 -0
- package/dist/admin/access-rule-routes.js.map +1 -0
- package/dist/admin/custom-repos-routes.js +93 -0
- package/dist/admin/custom-repos-routes.js.map +1 -0
- package/dist/admin/env-routes.js +74 -0
- package/dist/admin/env-routes.js.map +1 -0
- package/dist/admin/global-settings-routes.js +254 -0
- package/dist/admin/global-settings-routes.js.map +1 -0
- package/dist/admin/mcp-cleanup.js +12 -0
- package/dist/admin/mcp-cleanup.js.map +1 -0
- package/dist/admin/mcp-routes.js +169 -0
- package/dist/admin/mcp-routes.js.map +1 -0
- package/dist/admin/query-params.js +80 -0
- package/dist/admin/query-params.js.map +1 -0
- package/dist/admin/routes.js +150 -0
- package/dist/admin/routes.js.map +1 -0
- package/dist/admin/run-history-routes.js +44 -0
- package/dist/admin/run-history-routes.js.map +1 -0
- package/dist/admin/run-routes.js +99 -0
- package/dist/admin/run-routes.js.map +1 -0
- package/dist/admin/settings-routes.js +119 -0
- package/dist/admin/settings-routes.js.map +1 -0
- package/dist/admin/stats-routes.js +51 -0
- package/dist/admin/stats-routes.js.map +1 -0
- package/dist/admin/task-routes.js +213 -0
- package/dist/admin/task-routes.js.map +1 -0
- package/dist/admin/test-routes.js +38 -0
- package/dist/admin/test-routes.js.map +1 -0
- package/dist/admin/volume-routes.js +82 -0
- package/dist/admin/volume-routes.js.map +1 -0
- package/dist/admin/webhook-routes.js +174 -0
- package/dist/admin/webhook-routes.js.map +1 -0
- package/dist/agents.js +48 -0
- package/dist/agents.js.map +1 -0
- package/dist/assignee-value.js +6 -0
- package/dist/assignee-value.js.map +1 -0
- package/dist/attachments.js +76 -0
- package/dist/attachments.js.map +1 -0
- package/dist/auto-commands.js +88 -0
- package/dist/auto-commands.js.map +1 -0
- package/dist/auto-features.js +32 -0
- package/dist/auto-features.js.map +1 -0
- package/dist/base-branch-store.js +40 -0
- package/dist/base-branch-store.js.map +1 -0
- package/dist/base-branches.js +9 -0
- package/dist/base-branches.js.map +1 -0
- package/dist/build-workflow.js +116 -0
- package/dist/build-workflow.js.map +1 -0
- package/dist/change-request-lifecycle.js +16 -0
- package/dist/change-request-lifecycle.js.map +1 -0
- package/dist/change-request-store.js +72 -0
- package/dist/change-request-store.js.map +1 -0
- package/dist/ci-failure.js +80 -0
- package/dist/ci-failure.js.map +1 -0
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js +17 -0
- package/dist/config.js.map +1 -0
- package/dist/conflict-fix.js +178 -0
- package/dist/conflict-fix.js.map +1 -0
- package/dist/cookie.js +70 -0
- package/dist/cookie.js.map +1 -0
- package/dist/crypto-util.js +40 -0
- package/dist/crypto-util.js.map +1 -0
- package/dist/custom-repos-store.js +90 -0
- package/dist/custom-repos-store.js.map +1 -0
- package/dist/custom-repos-sync.js +118 -0
- package/dist/custom-repos-sync.js.map +1 -0
- package/dist/db.js +12 -0
- package/dist/db.js.map +1 -0
- package/dist/devbot-scripts.js +18 -0
- package/dist/devbot-scripts.js.map +1 -0
- package/dist/devcontainer.js +141 -0
- package/dist/devcontainer.js.map +1 -0
- package/dist/env-config-store.js +132 -0
- package/dist/env-config-store.js.map +1 -0
- package/dist/error-log-store.js +193 -0
- package/dist/error-log-store.js.map +1 -0
- package/dist/git.js +605 -0
- package/dist/git.js.map +1 -0
- package/dist/global-queue.js +127 -0
- package/dist/global-queue.js.map +1 -0
- package/dist/global-settings-store.js +307 -0
- package/dist/global-settings-store.js.map +1 -0
- package/dist/help.js +41 -0
- package/dist/help.js.map +1 -0
- package/dist/http-csp.js +15 -0
- package/dist/http-csp.js.map +1 -0
- package/dist/http-util.js +40 -0
- package/dist/http-util.js.map +1 -0
- package/dist/idempotency.js +50 -0
- package/dist/idempotency.js.map +1 -0
- package/dist/lifecycle.js +234 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/logger.js +33 -0
- package/dist/logger.js.map +1 -0
- package/dist/lsp-servers.js +81 -0
- package/dist/lsp-servers.js.map +1 -0
- package/dist/mcp/auth.js +62 -0
- package/dist/mcp/auth.js.map +1 -0
- package/dist/mcp/effective-mcp.js +42 -0
- package/dist/mcp/effective-mcp.js.map +1 -0
- package/dist/mcp/oauth-refresh.js +138 -0
- package/dist/mcp/oauth-refresh.js.map +1 -0
- package/dist/mcp/peer-sync.js +109 -0
- package/dist/mcp/peer-sync.js.map +1 -0
- package/dist/mcp/registry.js +54 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/runner-bridge.js +93 -0
- package/dist/mcp/runner-bridge.js.map +1 -0
- package/dist/mcp/server.js +173 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/_helpers.js +88 -0
- package/dist/mcp/tools/_helpers.js.map +1 -0
- package/dist/mcp/tools/attachments.js +117 -0
- package/dist/mcp/tools/attachments.js.map +1 -0
- package/dist/mcp/tools/cicd.js +105 -0
- package/dist/mcp/tools/cicd.js.map +1 -0
- package/dist/mcp/tools/discovery.js +34 -0
- package/dist/mcp/tools/discovery.js.map +1 -0
- package/dist/mcp/tools/issues.js +56 -0
- package/dist/mcp/tools/issues.js.map +1 -0
- package/dist/mcp/tools/merge_requests.js +67 -0
- package/dist/mcp/tools/merge_requests.js.map +1 -0
- package/dist/mcp/tools/metadata.js +127 -0
- package/dist/mcp/tools/metadata.js.map +1 -0
- package/dist/mcp/tools/peer_sync.js +43 -0
- package/dist/mcp/tools/peer_sync.js.map +1 -0
- package/dist/mcp/tools/repository.js +178 -0
- package/dist/mcp/tools/repository.js.map +1 -0
- package/dist/mcp/tools/work_tracking.js +125 -0
- package/dist/mcp/tools/work_tracking.js.map +1 -0
- package/dist/mcp/tools/workitems.js +30 -0
- package/dist/mcp/tools/workitems.js.map +1 -0
- package/dist/mcp/volume-files.js +187 -0
- package/dist/mcp/volume-files.js.map +1 -0
- package/dist/mcp-auth-store.js +134 -0
- package/dist/mcp-auth-store.js.map +1 -0
- package/dist/mcp-config-store.js +83 -0
- package/dist/mcp-config-store.js.map +1 -0
- package/dist/mention.js +512 -0
- package/dist/mention.js.map +1 -0
- package/dist/migrate.js +73 -0
- package/dist/migrate.js.map +1 -0
- package/dist/mr-assignee.js +71 -0
- package/dist/mr-assignee.js.map +1 -0
- package/dist/mr-content.js +90 -0
- package/dist/mr-content.js.map +1 -0
- package/dist/oauth-routes.js +54 -0
- package/dist/oauth-routes.js.map +1 -0
- package/dist/onboarding-allowlist.js +32 -0
- package/dist/onboarding-allowlist.js.map +1 -0
- package/dist/opencode.js +291 -0
- package/dist/opencode.js.map +1 -0
- package/dist/outbound-webhook-store.js +229 -0
- package/dist/outbound-webhook-store.js.map +1 -0
- package/dist/outbound-webhook.js +314 -0
- package/dist/outbound-webhook.js.map +1 -0
- package/dist/path-sandbox.js +200 -0
- package/dist/path-sandbox.js.map +1 -0
- package/dist/platform/git-auth.js +34 -0
- package/dist/platform/git-auth.js.map +1 -0
- package/dist/platform/gitealike/attachments.js +62 -0
- package/dist/platform/gitealike/attachments.js.map +1 -0
- package/dist/platform/gitealike/base.js +935 -0
- package/dist/platform/gitealike/base.js.map +1 -0
- package/dist/platform/gitealike/forgejo.js +16 -0
- package/dist/platform/gitealike/forgejo.js.map +1 -0
- package/dist/platform/gitealike/gitea.js +16 -0
- package/dist/platform/gitealike/gitea.js.map +1 -0
- package/dist/platform/gitealike/http.js +152 -0
- package/dist/platform/gitealike/http.js.map +1 -0
- package/dist/platform/gitealike/schemas.js +284 -0
- package/dist/platform/gitealike/schemas.js.map +1 -0
- package/dist/platform/github/attachments.js +52 -0
- package/dist/platform/github/attachments.js.map +1 -0
- package/dist/platform/github/http.js +153 -0
- package/dist/platform/github/http.js.map +1 -0
- package/dist/platform/github/index.js +936 -0
- package/dist/platform/github/index.js.map +1 -0
- package/dist/platform/github/schemas.js +308 -0
- package/dist/platform/github/schemas.js.map +1 -0
- package/dist/platform/github/zip.js +85 -0
- package/dist/platform/github/zip.js.map +1 -0
- package/dist/platform/gitlab/admin.js +105 -0
- package/dist/platform/gitlab/admin.js.map +1 -0
- package/dist/platform/gitlab/api.js +229 -0
- package/dist/platform/gitlab/api.js.map +1 -0
- package/dist/platform/gitlab/attachments.js +79 -0
- package/dist/platform/gitlab/attachments.js.map +1 -0
- package/dist/platform/gitlab/http.js +165 -0
- package/dist/platform/gitlab/http.js.map +1 -0
- package/dist/platform/gitlab/index.js +630 -0
- package/dist/platform/gitlab/index.js.map +1 -0
- package/dist/platform/gitlab/oauth.js +58 -0
- package/dist/platform/gitlab/oauth.js.map +1 -0
- package/dist/platform/gitlab/read.js +182 -0
- package/dist/platform/gitlab/read.js.map +1 -0
- package/dist/platform/gitlab/schemas-read.js +274 -0
- package/dist/platform/gitlab/schemas-read.js.map +1 -0
- package/dist/platform/gitlab/schemas.js +251 -0
- package/dist/platform/gitlab/schemas.js.map +1 -0
- package/dist/platform/gitlab/signature.js +52 -0
- package/dist/platform/gitlab/signature.js.map +1 -0
- package/dist/platform/index.js +38 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/port.js +26 -0
- package/dist/platform/port.js.map +1 -0
- package/dist/platform/types.js +80 -0
- package/dist/platform/types.js.map +1 -0
- package/dist/podman.js +119 -0
- package/dist/podman.js.map +1 -0
- package/dist/project-sync.js +69 -0
- package/dist/project-sync.js.map +1 -0
- package/dist/prompt.js +47 -0
- package/dist/prompt.js.map +1 -0
- package/dist/queue-store.js +236 -0
- package/dist/queue-store.js.map +1 -0
- package/dist/queue.js +129 -0
- package/dist/queue.js.map +1 -0
- package/dist/redact.js +23 -0
- package/dist/redact.js.map +1 -0
- package/dist/run-files.js +297 -0
- package/dist/run-files.js.map +1 -0
- package/dist/run-filters.js +54 -0
- package/dist/run-filters.js.map +1 -0
- package/dist/run-history-store.js +229 -0
- package/dist/run-history-store.js.map +1 -0
- package/dist/run-log-sink.js +270 -0
- package/dist/run-log-sink.js.map +1 -0
- package/dist/run-log.js +97 -0
- package/dist/run-log.js.map +1 -0
- package/dist/run-usage.js +29 -0
- package/dist/run-usage.js.map +1 -0
- package/dist/run-view.js +112 -0
- package/dist/run-view.js.map +1 -0
- package/dist/runner.js +1094 -0
- package/dist/runner.js.map +1 -0
- package/dist/runtime-apply.js +26 -0
- package/dist/runtime-apply.js.map +1 -0
- package/dist/runtime-settings.js +71 -0
- package/dist/runtime-settings.js.map +1 -0
- package/dist/runtime-state.js +19 -0
- package/dist/runtime-state.js.map +1 -0
- package/dist/server.js +119 -0
- package/dist/server.js.map +1 -0
- package/dist/settings-store.js +320 -0
- package/dist/settings-store.js.map +1 -0
- package/dist/status.js +121 -0
- package/dist/status.js.map +1 -0
- package/dist/stop.js +56 -0
- package/dist/stop.js.map +1 -0
- package/dist/sweeps.js +87 -0
- package/dist/sweeps.js.map +1 -0
- package/dist/task-log.js +279 -0
- package/dist/task-log.js.map +1 -0
- package/dist/task-view.js +62 -0
- package/dist/task-view.js.map +1 -0
- package/dist/token-store.js +68 -0
- package/dist/token-store.js.map +1 -0
- package/dist/types/access.js +74 -0
- package/dist/types/access.js.map +1 -0
- package/dist/types/custom-repos.js +28 -0
- package/dist/types/custom-repos.js.map +1 -0
- package/dist/types/env-config.js +25 -0
- package/dist/types/env-config.js.map +1 -0
- package/dist/types/env.js +190 -0
- package/dist/types/env.js.map +1 -0
- package/dist/types/global-settings.js +178 -0
- package/dist/types/global-settings.js.map +1 -0
- package/dist/types/lsp-servers.js +145 -0
- package/dist/types/lsp-servers.js.map +1 -0
- package/dist/types/mcp-config.js +77 -0
- package/dist/types/mcp-config.js.map +1 -0
- package/dist/types/opencode.js +59 -0
- package/dist/types/opencode.js.map +1 -0
- package/dist/types/outbound-webhook.js +56 -0
- package/dist/types/outbound-webhook.js.map +1 -0
- package/dist/types/project-settings.js +114 -0
- package/dist/types/project-settings.js.map +1 -0
- package/dist/types/provider-registry.js +37 -0
- package/dist/types/provider-registry.js.map +1 -0
- package/dist/types/runtime-settings.js +78 -0
- package/dist/types/runtime-settings.js.map +1 -0
- package/dist/usage-stats.js +159 -0
- package/dist/usage-stats.js.map +1 -0
- package/dist/version.js +19 -0
- package/dist/version.js.map +1 -0
- package/dist/volume-gc.js +193 -0
- package/dist/volume-gc.js.map +1 -0
- package/dist/volume-manage.js +191 -0
- package/dist/volume-manage.js.map +1 -0
- package/dist/volume-store.js +122 -0
- package/dist/volume-store.js.map +1 -0
- package/dist/webhook.js +1106 -0
- package/dist/webhook.js.map +1 -0
- package/dist/work-item-auto-store.js +75 -0
- package/dist/work-item-auto-store.js.map +1 -0
- package/dist/work-item-branch-store.js +37 -0
- package/dist/work-item-branch-store.js.map +1 -0
- package/migrations/0001_initial.sql +59 -0
- package/migrations/0002_queue_status.sql +15 -0
- package/migrations/0003_work_item_base_branch.sql +14 -0
- package/migrations/0004_project_settings.sql +15 -0
- package/migrations/0005_global_settings.sql +34 -0
- package/migrations/0006_model_variants.sql +8 -0
- package/migrations/0007_container_error_logs.sql +21 -0
- package/migrations/0008_project_access_grants.sql +16 -0
- package/migrations/0009_drop_imported_legacy.sql +4 -0
- package/migrations/0010_container_error_log_model.sql +6 -0
- package/migrations/0011_container_error_log_title.sql +5 -0
- package/migrations/0012_pending_task_cancel.sql +6 -0
- package/migrations/0013_builder_image.sql +6 -0
- package/migrations/0014_build_workflow.sql +7 -0
- package/migrations/0015_access_rules.sql +24 -0
- package/migrations/0016_trigger_policy.sql +17 -0
- package/migrations/0017_attachment_upload.sql +8 -0
- package/migrations/0018_work_item_branch.sql +11 -0
- package/migrations/0019_auto_push_mr.sql +18 -0
- package/migrations/0020_outbound_webhooks.sql +47 -0
- package/migrations/0021_runtime_settings.sql +12 -0
- package/migrations/0022_auto_resolve_conflicts.sql +17 -0
- package/migrations/0023_ci_fail_auto_report.sql +27 -0
- package/migrations/0024_work_item_auto_override.sql +22 -0
- package/migrations/0025_run_history.sql +37 -0
- package/migrations/0026_run_history_task_seq.sql +6 -0
- package/migrations/0027_custom_repos.sql +11 -0
- package/migrations/0028_run_usage.sql +14 -0
- package/migrations/0029_drop_ocr_langs.sql +6 -0
- package/migrations/0030_mr_assignee.sql +9 -0
- package/migrations/0031_lsp_servers.sql +14 -0
- package/opencode-config/managed/devbot-agent-policy.md +61 -0
- package/opencode-config/managed/opencode.json +77 -0
- package/opencode-config/opencode.json +211 -0
- package/opencode-config/plugins/devbot-path-guard.js +224 -0
- package/package.json +157 -4
- package/public/assets/DashboardSidebarCollapse-rIuzCmVm.js +1 -0
- package/public/assets/DashboardToolbar-DFCUqZ4Z.js +1 -0
- package/public/assets/ErrorLogModal.vue_vue_type_script_setup_true_lang-BCyNIf1E.js +1 -0
- package/public/assets/ErrorLogsPage-DyYK2Rop.js +1 -0
- package/public/assets/LogSlideover.vue_vue_type_script_setup_true_lang-33xie7TE.js +1 -0
- package/public/assets/OverviewPage-CFfa0uwg.js +1 -0
- package/public/assets/PageGrid-CBROIU87.js +1 -0
- package/public/assets/PeriodRangePicker.vue_vue_type_script_setup_true_lang-DiFUNem7.js +1 -0
- package/public/assets/ProjectDetailPage-CreyvUit.js +1 -0
- package/public/assets/ProjectsPage-CFx8-elJ.js +1 -0
- package/public/assets/RunDetailSlideover.vue_vue_type_script_setup_true_lang-DopYYmCT.js +1 -0
- package/public/assets/RunsPage-CRnnXU4P.js +1 -0
- package/public/assets/Select-Bvx32Diz.js +1 -0
- package/public/assets/SelectMenu-BjMxc4VB.js +1 -0
- package/public/assets/SettingsPage-Bb6LM3wO.js +60 -0
- package/public/assets/TimeCell.vue_vue_type_script_setup_true_lang-DW_UB0Fu.js +1 -0
- package/public/assets/UsagePage-BLMDEsv-.js +332 -0
- package/public/assets/UsagePage-DodEeAjB.css +1 -0
- package/public/assets/VolumesPage-CxcLc3L2.js +1 -0
- package/public/assets/WebhookConfigPanel.vue_vue_type_script_setup_true_lang-B2V2GF6b.js +1 -0
- package/public/assets/WorkItemCell.vue_vue_type_script_setup_true_lang-BQn6vTjd.js +1 -0
- package/public/assets/index-BMbMibyb.js +4 -0
- package/public/assets/index-C5RBBrPj.js +30 -0
- package/public/assets/index-CgX29UgC.css +1 -0
- package/public/assets/usage-format-jsb31_O8.js +1 -0
- package/public/assets/useManagedProjects-8rtjRqVJ.js +1 -0
- package/public/assets/useRouteTab-DfwrcMic.js +1 -0
- package/public/favicon.ico +0 -0
- package/public/favicon.png +0 -0
- package/public/index.html +15 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
// DevBot path guard (work item #46). An opencode plugin, loaded from the
|
|
2
|
+
// per-run config dir, that refuses tool calls which would reach credentials
|
|
3
|
+
// outside the project root or hidden state inside it.
|
|
4
|
+
//
|
|
5
|
+
// Why a plugin: opencode config `permission` rules are evaluated by pattern and
|
|
6
|
+
// can be overridden by a target repo's `opencode.json`, and a repo can also ship
|
|
7
|
+
// its own `.opencode/plugins/`. This plugin is loaded from the DevBot-owned
|
|
8
|
+
// per-run config dir (Global.Path.config -> $XDG_CONFIG_HOME/opencode), so it
|
|
9
|
+
// runs regardless of the repo's config. It cannot be removed by the repo.
|
|
10
|
+
//
|
|
11
|
+
// The policy JSON is injected by the runner as DEVBOT_PATH_POLICY, keeping
|
|
12
|
+
// src/path-sandbox.ts the single source of truth. The matching logic here is the
|
|
13
|
+
// same algorithm; scripts/check-path-sandbox.ts asserts both agree on a shared
|
|
14
|
+
// fixture table.
|
|
15
|
+
//
|
|
16
|
+
// Residual risk (documented in docs/agent-sandbox.md): the `bash` tool is only
|
|
17
|
+
// guarded heuristically here. Arbitrary shell can compute paths, so the real
|
|
18
|
+
// enforcement for bash is the managed-config shell wrapper that masks the xdg
|
|
19
|
+
// volume (see docker/devbot-shell). read/glob/grep/edit/list are in-process and
|
|
20
|
+
// are fully covered by this plugin + the managed permission denies.
|
|
21
|
+
//
|
|
22
|
+
// The path check canonicalizes (realpath) before applying the policy. The
|
|
23
|
+
// lexical rules alone are not enough: the in-process tools run in the opencode
|
|
24
|
+
// process (uid devbot), which CAN read the credential volume, so a symlink under
|
|
25
|
+
// the root pointing at .env/.git/.xdg-*/a masked root would otherwise be followed
|
|
26
|
+
// and read (work item #93).
|
|
27
|
+
|
|
28
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
29
|
+
import { basename, dirname, join } from "node:path";
|
|
30
|
+
|
|
31
|
+
const DEFAULT_POLICY = {
|
|
32
|
+
root: "/workspace",
|
|
33
|
+
denied: [".git", ".ssh"],
|
|
34
|
+
deniedPrefixes: [".xdg"],
|
|
35
|
+
deniedFiles: [".env"],
|
|
36
|
+
allowedFiles: [".env.example"],
|
|
37
|
+
masked: [
|
|
38
|
+
"/home/devbot/.xdg",
|
|
39
|
+
"/home/devbot/.config",
|
|
40
|
+
"$XDG_DATA_HOME",
|
|
41
|
+
"$XDG_CONFIG_HOME",
|
|
42
|
+
"$XDG_STATE_HOME",
|
|
43
|
+
"$XDG_CACHE_HOME",
|
|
44
|
+
"~/.xdg",
|
|
45
|
+
"~/.config",
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
function loadPolicy() {
|
|
50
|
+
const raw = process.env.DEVBOT_PATH_POLICY;
|
|
51
|
+
if (!raw) return DEFAULT_POLICY;
|
|
52
|
+
try {
|
|
53
|
+
const p = JSON.parse(raw);
|
|
54
|
+
return {
|
|
55
|
+
root: typeof p.root === "string" ? p.root : DEFAULT_POLICY.root,
|
|
56
|
+
denied: Array.isArray(p.denied) ? p.denied : DEFAULT_POLICY.denied,
|
|
57
|
+
deniedPrefixes: Array.isArray(p.deniedPrefixes) ? p.deniedPrefixes : DEFAULT_POLICY.deniedPrefixes,
|
|
58
|
+
deniedFiles: Array.isArray(p.deniedFiles) ? p.deniedFiles : DEFAULT_POLICY.deniedFiles,
|
|
59
|
+
allowedFiles: Array.isArray(p.allowedFiles) ? p.allowedFiles : DEFAULT_POLICY.allowedFiles,
|
|
60
|
+
masked: Array.isArray(p.masked) ? p.masked : DEFAULT_POLICY.masked,
|
|
61
|
+
};
|
|
62
|
+
} catch {
|
|
63
|
+
return DEFAULT_POLICY;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function isDeniedSegment(seg, policy) {
|
|
68
|
+
if (seg === "") return false;
|
|
69
|
+
if (policy.allowedFiles.includes(seg)) return false;
|
|
70
|
+
if (policy.denied.includes(seg)) return true;
|
|
71
|
+
if (policy.deniedPrefixes.some((p) => seg === p || seg.startsWith(p + "-"))) return true;
|
|
72
|
+
if (policy.deniedFiles.includes(seg)) return true;
|
|
73
|
+
if (seg.startsWith(".env.") && !policy.allowedFiles.includes(seg)) return true;
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function isDeniedPath(absPath, policy) {
|
|
78
|
+
return absPath.split("/").some((seg) => isDeniedSegment(seg, policy));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Canonicalize a path, tolerating a not-yet-created file (write/edit): walk up
|
|
82
|
+
// to the nearest existing ancestor, realpath that, and re-append the missing
|
|
83
|
+
// tail. Returns null only when even `/` cannot be resolved.
|
|
84
|
+
function canonicalize(abs) {
|
|
85
|
+
let cur = abs;
|
|
86
|
+
const tail = [];
|
|
87
|
+
while (!existsSync(cur)) {
|
|
88
|
+
const parent = dirname(cur);
|
|
89
|
+
if (parent === cur) return null;
|
|
90
|
+
tail.unshift(basename(cur));
|
|
91
|
+
cur = parent;
|
|
92
|
+
}
|
|
93
|
+
let real;
|
|
94
|
+
try {
|
|
95
|
+
real = realpathSync(cur);
|
|
96
|
+
} catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
return tail.length ? join(real, ...tail) : real;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// The masked roots (credential locations) with `~` and `$VAR` expanded from the
|
|
103
|
+
// opencode process environment. Used to reject a canonical path that landed on
|
|
104
|
+
// one even when the lexical segment rules would not (e.g. /home/devbot/.config).
|
|
105
|
+
function maskedRoots(policy) {
|
|
106
|
+
const home = process.env.HOME || "~";
|
|
107
|
+
const out = [];
|
|
108
|
+
for (const m of policy.masked) {
|
|
109
|
+
const s = m
|
|
110
|
+
.replace(/^~(?=\/|$)/, home)
|
|
111
|
+
.replace(/\$(\w+)/g, (_, name) => process.env[name] || "");
|
|
112
|
+
if (s) out.push(s);
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Reject `..` escapes, absolute paths outside the root, and denied segments
|
|
118
|
+
// lexically, then canonicalize to catch symlink escapes. The in-process tools
|
|
119
|
+
// run as uid devbot (which can read the credential volume), so the real target
|
|
120
|
+
// must be re-checked, not just the symlink's own spelling.
|
|
121
|
+
function checkPath(raw, policy) {
|
|
122
|
+
if (typeof raw !== "string" || raw.trim() === "") return null;
|
|
123
|
+
const v = raw.trim();
|
|
124
|
+
if (v.includes("\0")) return "path contains a NUL byte";
|
|
125
|
+
const joined = v.startsWith("/") ? v : policy.root + "/" + v;
|
|
126
|
+
const parts = [];
|
|
127
|
+
for (const seg of joined.split("/")) {
|
|
128
|
+
if (seg === "" || seg === ".") continue;
|
|
129
|
+
if (seg === "..") return "path must stay inside " + policy.root;
|
|
130
|
+
if (isDeniedSegment(seg, policy)) return "path is restricted: " + seg;
|
|
131
|
+
parts.push(seg);
|
|
132
|
+
}
|
|
133
|
+
const abs = "/" + parts.join("/");
|
|
134
|
+
if (abs !== policy.root && !abs.startsWith(policy.root + "/")) {
|
|
135
|
+
return "path must stay inside " + policy.root;
|
|
136
|
+
}
|
|
137
|
+
const real = canonicalize(abs);
|
|
138
|
+
if (real !== null) {
|
|
139
|
+
if (isDeniedPath(real, policy)) {
|
|
140
|
+
return "path resolves to a restricted path: " + real;
|
|
141
|
+
}
|
|
142
|
+
for (const root of maskedRoots(policy)) {
|
|
143
|
+
if (real === root || real.startsWith(root + "/")) {
|
|
144
|
+
return "path resolves to a restricted location: " + real;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
let rootReal = null;
|
|
148
|
+
try {
|
|
149
|
+
rootReal = realpathSync(policy.root);
|
|
150
|
+
} catch {
|
|
151
|
+
rootReal = null;
|
|
152
|
+
}
|
|
153
|
+
if (rootReal !== null && real !== rootReal && !real.startsWith(rootReal + "/")) {
|
|
154
|
+
return "path resolves outside " + policy.root + ": " + real;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function bashGuardReason(command, policy) {
|
|
161
|
+
if (typeof command !== "string") return null;
|
|
162
|
+
for (const m of policy.masked) {
|
|
163
|
+
if (m.startsWith("$")) {
|
|
164
|
+
// Env-var masks only count when used as a path (followed by `/`).
|
|
165
|
+
// A bare mention (`echo $XDG_DATA_HOME`, a grep pattern) is not an access
|
|
166
|
+
// and blocking it makes agents loop on false positives (#96).
|
|
167
|
+
const name = m.slice(1).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
168
|
+
if (new RegExp("\\$\\{?" + name + "\\}?(?=/)").test(command)) {
|
|
169
|
+
return "command references restricted path " + m;
|
|
170
|
+
}
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (command.includes(m)) return "command references restricted path " + m;
|
|
174
|
+
}
|
|
175
|
+
if (/(^|[\s'"=])\.\.(\/|[\s'"]|$)/.test(command)) return "command references a parent path (..)";
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function block(policy, tool, detail) {
|
|
180
|
+
const message =
|
|
181
|
+
"[devbot-path-guard] blocked " + tool + ": " + detail +
|
|
182
|
+
". This location is outside the run sandbox and is permanently unavailable for this session. " +
|
|
183
|
+
"Do not retry this or any command that references the blocked path; continue the task using only files under " +
|
|
184
|
+
policy.root + ".";
|
|
185
|
+
// console.error lands in the run container's logs, giving an audit trail.
|
|
186
|
+
try {
|
|
187
|
+
console.error(message);
|
|
188
|
+
} catch {
|
|
189
|
+
// logging must never change the guard's decision
|
|
190
|
+
}
|
|
191
|
+
throw new Error(message);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// The path-bearing tools and the argument that holds the path.
|
|
195
|
+
const PATH_TOOLS = {
|
|
196
|
+
read: "path",
|
|
197
|
+
edit: "path",
|
|
198
|
+
write: "path",
|
|
199
|
+
glob: "path",
|
|
200
|
+
grep: "path",
|
|
201
|
+
list: "path",
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
export const DevbotPathGuard = async () => {
|
|
205
|
+
const policy = loadPolicy();
|
|
206
|
+
return {
|
|
207
|
+
"tool.execute.before": async (input, output) => {
|
|
208
|
+
const args = output && typeof output.args === "object" && output.args !== null ? output.args : {};
|
|
209
|
+
if (input && input.tool === "bash") {
|
|
210
|
+
const reason = bashGuardReason(args.command, policy);
|
|
211
|
+
if (reason) block(policy, "bash", reason);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const key = PATH_TOOLS[input && input.tool];
|
|
215
|
+
if (key) {
|
|
216
|
+
// Older opencode builds used `filePath` for read; accept both.
|
|
217
|
+
const candidate = args[key] !== undefined ? args[key] : args.filePath;
|
|
218
|
+
const reason = checkPath(candidate, policy);
|
|
219
|
+
if (reason) block(policy, input.tool, reason + " (" + candidate + ")");
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,159 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wascartech/devbot",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": "Adrien Jussak <adrien.jussak@wascar.tech>",
|
|
7
|
+
"license": "Apache-2.0",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=22"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"devbot": "dist/cli.js"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/",
|
|
16
|
+
"migrations/",
|
|
17
|
+
"public/",
|
|
18
|
+
"opencode-config/",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"dev": "NODE_OPTIONS=--experimental-sqlite tsx watch --env-file-if-exists=.env src/server.ts",
|
|
24
|
+
"dev:web": "vite --config web/vite.config.ts",
|
|
25
|
+
"build": "tsc && vite build --config web/vite.config.ts",
|
|
26
|
+
"build:web": "vite build --config web/vite.config.ts",
|
|
27
|
+
"start": "node --experimental-sqlite --env-file-if-exists=.env dist/server.js",
|
|
28
|
+
"typecheck": "tsc --noEmit && vue-tsc --noEmit -p web/tsconfig.json",
|
|
29
|
+
"typecheck:web": "vue-tsc --noEmit -p web/tsconfig.json",
|
|
30
|
+
"test": "node scripts/run-all-tests.mjs",
|
|
31
|
+
"test:web": "vitest run",
|
|
32
|
+
"test:signature": "node --experimental-sqlite --test --import tsx scripts/check-signature.ts",
|
|
33
|
+
"test:mention": "node --experimental-sqlite --test --import tsx scripts/check-mention.ts",
|
|
34
|
+
"test:auto-features": "node --experimental-sqlite --test --import tsx scripts/check-auto-features.ts",
|
|
35
|
+
"test:branch-naming": "node --experimental-sqlite --test --import tsx scripts/check-branch-naming.ts",
|
|
36
|
+
"test:prompt": "node --experimental-sqlite --test --import tsx scripts/check-prompt.ts",
|
|
37
|
+
"test:opencode": "node --experimental-sqlite --test --import tsx scripts/check-opencode.ts",
|
|
38
|
+
"test:opencode-lsp": "node --experimental-sqlite --test --import tsx scripts/check-opencode-lsp.ts",
|
|
39
|
+
"test:redact": "node --experimental-sqlite --test --import tsx scripts/check-redact.ts",
|
|
40
|
+
"test:cookie": "node --experimental-sqlite --test --import tsx scripts/check-cookie.ts",
|
|
41
|
+
"test:oauth": "node --experimental-sqlite --test --import tsx scripts/check-oauth.ts",
|
|
42
|
+
"test:run-usage": "node --experimental-sqlite --test --import tsx scripts/check-run-usage.ts",
|
|
43
|
+
"test:runner": "node --experimental-sqlite --test --import tsx scripts/check-runner-helpers.ts",
|
|
44
|
+
"test:git-sync": "node --experimental-sqlite --test --import tsx scripts/check-git-sync.ts",
|
|
45
|
+
"test:volume-selinux": "node --experimental-sqlite --test --import tsx scripts/check-volume-selinux.ts",
|
|
46
|
+
"test:podman-serialize": "node --experimental-sqlite --test --import tsx scripts/check-podman-serialize.ts",
|
|
47
|
+
"test:run-outcomes": "node --experimental-sqlite --test --import tsx scripts/check-run-outcomes.ts",
|
|
48
|
+
"test:schemas": "node --experimental-sqlite --test --import tsx scripts/check-schemas.ts",
|
|
49
|
+
"test:queue": "node --experimental-sqlite --test --import tsx scripts/check-queue.ts",
|
|
50
|
+
"test:global-queue": "node --experimental-sqlite --test --import tsx scripts/check-global-queue.ts",
|
|
51
|
+
"test:queue-store": "node --experimental-sqlite --test --import tsx scripts/check-queue-store.ts",
|
|
52
|
+
"test:idempotency": "node --experimental-sqlite --test --import tsx scripts/check-idempotency.ts",
|
|
53
|
+
"test:migrate": "node --experimental-sqlite --test --import tsx scripts/check-migrate.ts",
|
|
54
|
+
"test:dispatch": "node --experimental-sqlite --test --import tsx scripts/check-dispatch.ts",
|
|
55
|
+
"test:webhook-e2e": "node --experimental-sqlite --test --import tsx scripts/check-webhook-e2e.ts",
|
|
56
|
+
"test:mr-content": "node --experimental-sqlite --test --import tsx scripts/check-mr-content.ts",
|
|
57
|
+
"test:mr-lifecycle": "node --experimental-sqlite --test --import tsx scripts/check-mr-lifecycle.ts",
|
|
58
|
+
"test:mr-assignee": "node --experimental-sqlite --test --import tsx scripts/check-mr-assignee.ts",
|
|
59
|
+
"test:build-workflow": "node --experimental-sqlite --test --import tsx scripts/check-build-workflow.ts",
|
|
60
|
+
"test:push": "node --experimental-sqlite --test --import tsx scripts/check-push-fallback.ts",
|
|
61
|
+
"test:conflict-fix": "node --experimental-sqlite --test --import tsx scripts/check-conflict-fix.ts",
|
|
62
|
+
"test:mr-discussions": "node --experimental-sqlite --test --import tsx scripts/check-mr-discussions.ts",
|
|
63
|
+
"test:attachments": "node --experimental-sqlite --test --import tsx scripts/check-attachments.ts",
|
|
64
|
+
"test:env": "node --experimental-sqlite --test --import tsx scripts/check-env-config.ts",
|
|
65
|
+
"test:env-schema": "node --experimental-sqlite --test --import tsx scripts/check-env-schema.ts",
|
|
66
|
+
"test:volume-store": "node --experimental-sqlite --test --import tsx scripts/check-volume-store.ts",
|
|
67
|
+
"test:volume-gc": "node --experimental-sqlite --test --import tsx scripts/check-volume-gc.ts",
|
|
68
|
+
"test:volume-manage": "node --experimental-sqlite --test --import tsx scripts/check-volume-manage.ts",
|
|
69
|
+
"test:base-branch": "node --experimental-sqlite --test --import tsx scripts/check-base-branch-store.ts",
|
|
70
|
+
"test:work-item-branch": "node --experimental-sqlite --test --import tsx scripts/check-work-item-branch-store.ts",
|
|
71
|
+
"test:reset-teardown": "node --experimental-sqlite --test --import tsx scripts/check-reset-teardown.ts",
|
|
72
|
+
"test:config": "node --experimental-sqlite --test --import tsx scripts/check-config.ts",
|
|
73
|
+
"test:bootstrap": "node --experimental-sqlite --test --import tsx scripts/check-bootstrap.ts",
|
|
74
|
+
"test:env-injection": "node --experimental-sqlite --test --import tsx scripts/check-env-injection.ts",
|
|
75
|
+
"test:devcontainer": "node --experimental-sqlite --test --import tsx scripts/check-devcontainer.ts",
|
|
76
|
+
"test:devcontainer-wiring": "node --experimental-sqlite --test --import tsx scripts/check-devcontainer-wiring.ts",
|
|
77
|
+
"test:project-settings": "node --experimental-sqlite --test --import tsx scripts/check-project-settings.ts",
|
|
78
|
+
"test:project-sync": "node --experimental-sqlite --test --import tsx scripts/check-project-sync.ts",
|
|
79
|
+
"test:custom-repos": "node --experimental-sqlite --test --import tsx scripts/check-custom-repos.ts",
|
|
80
|
+
"test:package": "node --experimental-sqlite --test --import tsx scripts/check-package.ts",
|
|
81
|
+
"test:global-settings": "node --experimental-sqlite --test --import tsx scripts/check-global-settings.ts",
|
|
82
|
+
"test:global-mcp-run": "node --experimental-sqlite --test --import tsx scripts/check-global-mcp-run.ts",
|
|
83
|
+
"test:runtime-settings": "node --experimental-sqlite --test --import tsx scripts/check-runtime-settings.ts",
|
|
84
|
+
"test:provider-registry": "node --experimental-sqlite --test --import tsx scripts/check-provider-registry.ts",
|
|
85
|
+
"test:config-generation": "node --experimental-sqlite --test --import tsx scripts/check-config-generation.ts",
|
|
86
|
+
"test:csp": "node --experimental-sqlite --test --import tsx scripts/check-csp.ts",
|
|
87
|
+
"test:ui-e2e": "node --experimental-sqlite --test --import tsx scripts/check-ui-e2e.ts",
|
|
88
|
+
"test:task-view": "node --experimental-sqlite --test --import tsx scripts/check-task-view.ts",
|
|
89
|
+
"test:work-item-url": "node --experimental-sqlite --test --import tsx scripts/check-work-item-url.ts",
|
|
90
|
+
"test:task-log": "node --experimental-sqlite --test --import tsx scripts/check-task-log.ts",
|
|
91
|
+
"test:error-logs": "node --experimental-sqlite --test --import tsx scripts/check-error-log-store.ts",
|
|
92
|
+
"test:run-log": "node --experimental-sqlite --test --import tsx scripts/check-run-log.ts",
|
|
93
|
+
"test:run-history": "node --experimental-sqlite --test --import tsx scripts/check-run-history-store.ts",
|
|
94
|
+
"test:run-view": "node --experimental-sqlite --test --import tsx scripts/check-run-view.ts",
|
|
95
|
+
"test:run-filters": "node --experimental-sqlite --test --import tsx scripts/check-run-filters.ts",
|
|
96
|
+
"test:access-grants": "node --experimental-sqlite --test --import tsx scripts/check-access-grants.ts",
|
|
97
|
+
"test:access-rules": "node --experimental-sqlite --test --import tsx scripts/check-access-rules.ts",
|
|
98
|
+
"test:access-gate": "node --experimental-sqlite --test --import tsx scripts/check-access-gate.ts",
|
|
99
|
+
"test:mcp-scope": "node --experimental-sqlite --test --import tsx scripts/check-mcp-scope.ts",
|
|
100
|
+
"test:mcp-auth-refresh": "node --experimental-sqlite --test --import tsx scripts/check-mcp-auth-refresh.ts",
|
|
101
|
+
"test:peer-sync": "node --experimental-sqlite --test --import tsx scripts/check-peer-sync.ts",
|
|
102
|
+
"test:upload-attachments": "node --experimental-sqlite --test --import tsx scripts/check-upload-attachments.ts",
|
|
103
|
+
"test:mcp-upload-tool": "node --experimental-sqlite --test --import tsx scripts/check-mcp-upload-tool.ts",
|
|
104
|
+
"test:mcp-download-tool": "node --experimental-sqlite --test --import tsx scripts/check-mcp-download-tool.ts",
|
|
105
|
+
"test:platform-webhooks": "node --experimental-sqlite --test --import tsx scripts/check-platform-webhooks.ts",
|
|
106
|
+
"test:platform-drivers": "node --experimental-sqlite --test --import tsx scripts/check-platform-drivers.ts",
|
|
107
|
+
"test:platform-parity": "node --experimental-sqlite --test --import tsx scripts/check-platform-parity.ts",
|
|
108
|
+
"test:forgejo-access-gate": "node --experimental-sqlite --test --import tsx scripts/check-forgejo-access-gate.ts",
|
|
109
|
+
"test:ci-adapter": "node --experimental-sqlite --test --import tsx scripts/check-ci-adapter.ts",
|
|
110
|
+
"test:ci-fail-report": "node --experimental-sqlite --test --import tsx scripts/check-ci-fail-report.ts",
|
|
111
|
+
"test:mcp-ci-tools": "node --experimental-sqlite --test --import tsx scripts/check-mcp-ci-tools.ts",
|
|
112
|
+
"test:gitlab-webhooks": "node --experimental-sqlite --test --import tsx scripts/check-gitlab-webhooks.ts",
|
|
113
|
+
"test:github-webhooks": "node --experimental-sqlite --test --import tsx scripts/check-github-webhooks.ts",
|
|
114
|
+
"test:github-driver": "node --experimental-sqlite --test --import tsx scripts/check-github-driver.ts",
|
|
115
|
+
"test:onboarding-allowlist": "node --experimental-sqlite --test --import tsx scripts/check-onboarding-allowlist.ts",
|
|
116
|
+
"test:outbound-webhooks": "node --experimental-sqlite --test --import tsx scripts/check-outbound-webhooks.ts",
|
|
117
|
+
"test:path-sandbox": "node --experimental-sqlite --test --import tsx scripts/check-path-sandbox.ts",
|
|
118
|
+
"test:guard-opencode": "node --experimental-sqlite --test --import tsx scripts/check-guard-opencode.ts",
|
|
119
|
+
"test:podman-volume": "node --experimental-sqlite --test --import tsx scripts/check-podman-volume.ts",
|
|
120
|
+
"test:podman-run": "node --experimental-sqlite --test --import tsx scripts/check-podman-run.ts",
|
|
121
|
+
"test:nested-podman": "node --experimental-sqlite --test --import tsx scripts/check-nested-podman.ts",
|
|
122
|
+
"test:shell-sandbox": "node --experimental-sqlite --test --import tsx scripts/check-shell-sandbox.ts",
|
|
123
|
+
"test:plan-agent": "node --experimental-sqlite --test --import tsx scripts/check-plan-agent.ts",
|
|
124
|
+
"test:stats": "node --experimental-sqlite --test --import tsx scripts/check-stats.ts",
|
|
125
|
+
"test:status": "node --experimental-sqlite --test --import tsx scripts/check-status.ts",
|
|
126
|
+
"test:stop": "node --experimental-sqlite --test --import tsx scripts/check-stop.ts",
|
|
127
|
+
"test:help": "node --experimental-sqlite --test --import tsx scripts/check-help.ts"
|
|
128
|
+
},
|
|
129
|
+
"publishConfig": {
|
|
130
|
+
"access": "public"
|
|
131
|
+
},
|
|
132
|
+
"dependencies": {
|
|
133
|
+
"@internationalized/date": "^3.12.2",
|
|
134
|
+
"@modelcontextprotocol/sdk": "^1.32.0",
|
|
135
|
+
"@nuxt/ui": "^4.0.0",
|
|
136
|
+
"@unovis/ts": "^1.7.0",
|
|
137
|
+
"@unovis/vue": "^1.7.0",
|
|
138
|
+
"@vueuse/core": "^15.0.0",
|
|
139
|
+
"express": "^5.0.0",
|
|
140
|
+
"helmet": "^8.0.0",
|
|
141
|
+
"tailwindcss": "^4.0.0",
|
|
142
|
+
"vue": "^3.5.0",
|
|
143
|
+
"vue-router": "^5.0.0",
|
|
144
|
+
"zod": "^4.0.0"
|
|
145
|
+
},
|
|
146
|
+
"devDependencies": {
|
|
147
|
+
"@iconify-json/lucide": "^1.2.120",
|
|
148
|
+
"@types/express": "^5.0.0",
|
|
149
|
+
"@types/node": "^24.0.0",
|
|
150
|
+
"@vitejs/plugin-vue": "^6.0.0",
|
|
151
|
+
"@vue/test-utils": "^2.5.0",
|
|
152
|
+
"happy-dom": "^20.14.5",
|
|
153
|
+
"tsx": "^4.19.0",
|
|
154
|
+
"typescript": "^5.5.4",
|
|
155
|
+
"vite": "^7.3.1",
|
|
156
|
+
"vitest": "^3.2.7",
|
|
157
|
+
"vue-tsc": "^3.0.0"
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{u as a,q as Q,aH as oe,a6 as re,bs as Y,x as W,S as V,bt as X,W as ae,bu as he,c as J,f as j,D as _,E as L,F as ie,aE as ce,e as C,X as w,h as z,bv as ue,j as k,Z as P,$ as N,w as U,P as ne,R as de,am as fe,a as ee,aA as T,aB as A,bw as me,y as ge,l as pe,t as Se,T as be,ak as ve,ar as ye,r as _e,i as Ee}from"./index-C5RBBrPj.js";function Oe(o,h,e){const t=new Array(o);return new Proxy(t,{get(s,i,l){if(typeof i=="string"){const n=i.charCodeAt(0);if(n>=48&&n<=57){const r=+i;if(Number.isInteger(r)&&r>=0&&r<o){let c=s[r];if(!c){const u=h[r*2];c=s[r]={index:r,key:e(r),start:u,size:h[r*2+1],end:u+h[r*2+1],lane:0}}return c}}if(i==="length")return o}return Reflect.get(s,i,l)}})}function M(o,h,e){let t=e.initialDeps??[],s,i=!0;function l(){const n=o();return(n.length!==t.length||n.some((c,u)=>t[u]!==c))&&(t=n,s=h(...n),e?.onChange&&!(i&&e.skipInitialOnChange)&&e.onChange(s),i=!1),s}return l.updateDeps=n=>{t=n},l}function te(o,h){if(o===void 0)throw new Error("Unexpected undefined");return o}const Ce=(o,h)=>Math.abs(o-h)<1.01,we=(o,h,e)=>{let t;return function(...s){o.clearTimeout(t),t=o.setTimeout(()=>h.apply(this,s),e)}};let q;const H=()=>{if(q!==void 0)return q;if(typeof navigator>"u")return q=!1;if(/iP(hone|od|ad)/.test(navigator.userAgent))return q=!0;const o=navigator.maxTouchPoints;return q=navigator.platform==="MacIntel"&&o!==void 0&&o>0},se=o=>{const{offsetWidth:h,offsetHeight:e}=o;return{width:h,height:e}},xe=o=>o,ze=o=>{const h=Math.max(o.startIndex-o.overscan,0),t=Math.min(o.endIndex+o.overscan,o.count-1)-h+1,s=new Array(t);for(let i=0;i<t;i++)s[i]=h+i;return s},Ie=(o,h)=>{const e=o.scrollElement;if(!e)return;const t=o.targetWindow;if(!t)return;const s=l=>{const{width:n,height:r}=l;h({width:Math.round(n),height:Math.round(r)})};if(s(se(e)),!t.ResizeObserver)return()=>{};const i=new t.ResizeObserver(l=>{const n=()=>{const r=l[0];if(r?.borderBoxSize){const c=r.borderBoxSize[0];if(c){s({width:c.inlineSize,height:c.blockSize});return}}s(se(e))};o.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(n):n()});return i.observe(e,{box:"border-box"}),()=>{i.unobserve(e)}},B={passive:!0},Te=typeof window>"u"?!0:"onscrollend"in window,Ae=(o,h,e)=>{const t=o.scrollElement;if(!t)return;const s=o.targetWindow;if(!s)return;const i=o.options.useScrollendEvent&&Te;let l=0;const n=i?null:we(s,()=>h(l,!1),o.options.isScrollingResetDelay),r=m=>()=>{l=e(t),n?.(),h(l,m)},c=r(!0),u=r(!1);return t.addEventListener("scroll",c,B),i&&t.addEventListener("scrollend",u,B),()=>{t.removeEventListener("scroll",c),i&&t.removeEventListener("scrollend",u)}},Me=(o,h)=>Ae(o,h,e=>{const{horizontal:t,isRtl:s}=o.options;return t?e.scrollLeft*(s&&-1||1):e.scrollTop}),ke=(o,h,e)=>{if(e.options.useCachedMeasurements){const t=e.indexFromElement(o),s=e.options.getItemKey(t);return e.itemSizeCache.get(s)??e.options.estimateSize(t)}if(h?.borderBoxSize){const t=h.borderBoxSize[0];if(t)return Math.round(t[e.options.horizontal?"inlineSize":"blockSize"])}if(!h){const t=e.indexFromElement(o),s=e.options.getItemKey(t),i=e.itemSizeCache.get(s);if(i!==void 0)return i}return o[e.options.horizontal?"offsetWidth":"offsetHeight"]},De=(o,{adjustments:h=0,behavior:e},t)=>{var s,i;(i=(s=t.scrollElement)==null?void 0:s.scrollTo)==null||i.call(s,{[t.options.horizontal?"left":"top"]:o+h,behavior:e})},Fe=De;class Re{constructor(h){this.unsubs=[],this.scrollElement=null,this.targetWindow=null,this.isScrolling=!1,this.scrollState=null,this.measurementsCache=[],this._flatMeasurements=null,this.itemSizeCache=new Map,this.itemSizeCacheVersion=0,this.laneAssignments=new Map,this.pendingMin=null,this.prevLanes=void 0,this.lanesChangedFlag=!1,this.lanesSettling=!1,this.pendingScrollAnchor=null,this.scrollRect=null,this.scrollOffset=null,this.scrollDirection=null,this.scrollAdjustments=0,this._iosDeferredAdjustment=0,this._iosTouching=!1,this._iosJustTouchEnded=!1,this._iosTouchEndTimerId=null,this._intendedScrollOffset=null,this.elementsCache=new Map,this.now=()=>{var e,t,s;return((s=(t=(e=this.targetWindow)==null?void 0:e.performance)==null?void 0:t.now)==null?void 0:s.call(t))??Date.now()},this.observer=(()=>{let e=null;const t=()=>e||(!this.targetWindow||!this.targetWindow.ResizeObserver?null:e=new this.targetWindow.ResizeObserver(s=>{s.forEach(i=>{const l=()=>{const n=i.target,r=this.indexFromElement(n);if(!n.isConnected){this.observer.unobserve(n);for(const[c,u]of this.elementsCache)if(u===n){this.elementsCache.delete(c);break}return}this.shouldMeasureDuringScroll(r)&&this.resizeItem(r,this.options.measureElement(n,i,this))};this.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(l):l()})}));return{disconnect:()=>{var s;(s=t())==null||s.disconnect(),e=null},observe:s=>{var i;return(i=t())==null?void 0:i.observe(s,{box:"border-box"})},unobserve:s=>{var i;return(i=t())==null?void 0:i.unobserve(s)}}})(),this.range=null,this.setOptions=e=>{var t,s;const i={debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:xe,rangeExtractor:ze,onChange:()=>{},measureElement:ke,initialRect:{width:0,height:0},scrollMargin:0,gap:0,indexAttribute:"data-index",initialMeasurementsCache:[],lanes:1,anchorTo:"start",followOnAppend:!1,scrollEndThreshold:1,isScrollingResetDelay:150,enabled:!0,isRtl:!1,useScrollendEvent:!1,useAnimationFrameWithResizeObserver:!1,laneAssignmentMode:"estimate",useCachedMeasurements:!1};for(const d in e){const g=e[d];g!==void 0&&(i[d]=g)}const l=this.options;let n=null,r=null,c=!1;if(l!==void 0&&l.enabled&&i.enabled&&i.anchorTo==="end"&&this.scrollElement!==null){const d=l.count,g=i.count,S=this.getMeasurements(),E=d>0?((t=S[0])==null?void 0:t.key)??l.getItemKey(0):null,O=d>0?((s=S[d-1])==null?void 0:s.key)??l.getItemKey(d-1):null;if(g!==d||d>0&&g>0&&(i.getItemKey(0)!==E||i.getItemKey(g-1)!==O)){c=!0;const y=d>0?this.getVirtualItemForOffset(this.getScrollOffset())??S[0]:null;y&&(n=[y.key,this.getScrollOffset()-y.start]);const v=i.followOnAppend===!0?"auto":i.followOnAppend||null;v&&g>d&&this.isAtEnd(l.scrollEndThreshold)&&(d===0||i.getItemKey(g-1)!==O)&&(r=v)}}this.options=i,c&&(this.pendingMin=0,this.itemSizeCacheVersion++);let u=!1,m=0;if(n&&this.scrollOffset!==null){const[d,g]=n,S=this.getMeasurements(),{count:E,getItemKey:O}=this.options;let f=0;for(;f<E&&O(f)!==d;)f++;if(f<E){const p=S[f];if(p){const y=Math.max(0,p.start+g);y!==this.scrollOffset&&(m=y-this.scrollOffset,this.scrollOffset=y,u=!0)}}}(u||r)&&(this.pendingScrollAnchor=[u?n[0]:null,u?n[1]:0,r,m])},this.notify=e=>{var t,s;(s=(t=this.options).onChange)==null||s.call(t,this,e)},this.maybeNotify=M(()=>(this.calculateRange(),[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]),e=>{this.notify(e)},{key:!1,debug:()=>this.options.debug,initialDeps:[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]}),this.cleanup=()=>{this.unsubs.filter(Boolean).forEach(e=>e()),this.unsubs=[],this.observer.disconnect(),this.rafId!=null&&this.targetWindow&&(this.targetWindow.cancelAnimationFrame(this.rafId),this.rafId=null),this.scrollState=null,this._iosDeferredAdjustment=0,this._iosTouching=!1,this._iosJustTouchEnded=!1,this.scrollElement=null,this.targetWindow=null},this._didMount=()=>()=>{this.cleanup()},this._willUpdate=()=>{var e;const t=this.options.enabled?this.options.getScrollElement():null;if(this.scrollElement!==t){if(this.cleanup(),!t){this.maybeNotify();return}if(this.scrollElement=t,this.scrollElement&&"ownerDocument"in this.scrollElement?this.targetWindow=this.scrollElement.ownerDocument.defaultView:this.targetWindow=((e=this.scrollElement)==null?void 0:e.window)??null,this.elementsCache.forEach(i=>{this.observer.observe(i)}),this.unsubs.push(this.options.observeElementRect(this,i=>{this.scrollRect=i,this.maybeNotify()})),this.unsubs.push(this.options.observeElementOffset(this,(i,l)=>{if(l&&this._intendedScrollOffset===null&&i===this.scrollOffset)return;this._intendedScrollOffset!==null&&Math.abs(i-this._intendedScrollOffset)<1.5&&(i=this._intendedScrollOffset),this._intendedScrollOffset=null,this.scrollAdjustments=0;const n=this.getScrollOffset();this.scrollDirection=l?n===i?this.scrollDirection:n<i?"forward":"backward":null,this.scrollOffset=i,this.isScrolling=l,this._flushIosDeferredIfReady(),this.scrollState&&this.scheduleScrollReconcile(),this.maybeNotify()})),"addEventListener"in this.scrollElement){const i=this.scrollElement,l=()=>{this._iosTouching=!0,this._iosJustTouchEnded=!1,this._iosTouchEndTimerId!==null&&this.targetWindow!=null&&(this.targetWindow.clearTimeout(this._iosTouchEndTimerId),this._iosTouchEndTimerId=null)},n=()=>{this._iosTouching=!1,!(!H()||this.targetWindow==null)&&(this._iosJustTouchEnded=!0,this._iosTouchEndTimerId=this.targetWindow.setTimeout(()=>{this._iosJustTouchEnded=!1,this._iosTouchEndTimerId=null,this._flushIosDeferredIfReady()},150))};i.addEventListener("touchstart",l,B),i.addEventListener("touchend",n,B),this.unsubs.push(()=>{i.removeEventListener("touchstart",l),i.removeEventListener("touchend",n),this._iosTouchEndTimerId!==null&&this.targetWindow!=null&&(this.targetWindow.clearTimeout(this._iosTouchEndTimerId),this._iosTouchEndTimerId=null)})}this._scrollToOffset(this.getScrollOffset(),{adjustments:void 0,behavior:void 0})}const s=this.pendingScrollAnchor;if(this.pendingScrollAnchor=null,s&&this.scrollElement&&this.options.enabled){const[i,l,n,r]=s;i!==null&&!n&&(H()&&(this.isScrolling||this._iosTouching||this._iosJustTouchEnded)?r!==0&&(this._iosDeferredAdjustment+=r):this._scrollToOffset(this.getScrollOffset(),{adjustments:void 0,behavior:void 0})),n&&this.scrollToEnd({behavior:n})}},this._flushIosDeferredIfReady=()=>{if(this._iosDeferredAdjustment===0||this.isScrolling||this._iosTouching||this._iosJustTouchEnded)return;const e=this.getScrollOffset(),t=this.getMaxScrollOffset();if(e<0||e>t)return;if(this._iosDeferredAdjustment<0&&e>=t-1){this._iosDeferredAdjustment=0;return}const s=this._iosDeferredAdjustment;this._iosDeferredAdjustment=0,this._scrollToOffset(e,{adjustments:this.scrollAdjustments+=s,behavior:void 0})},this.rafId=null,this.getSize=()=>this.options.enabled?(this.scrollRect=this.scrollRect??this.options.initialRect,this.scrollRect[this.options.horizontal?"width":"height"]):(this.scrollRect=null,0),this.getScrollOffset=()=>this.options.enabled?(this.scrollOffset=this.scrollOffset??(typeof this.options.initialOffset=="function"?this.options.initialOffset():this.options.initialOffset),this.scrollOffset):(this.scrollOffset=null,0),this.getMeasurementOptions=M(()=>[this.options.count,this.options.paddingStart,this.options.scrollMargin,this.options.getItemKey,this.options.enabled,this.options.lanes,this.options.laneAssignmentMode,this.options.gap],(e,t,s,i,l,n,r,c)=>(this.prevLanes!==void 0&&this.prevLanes!==n&&(this.lanesChangedFlag=!0),this.prevLanes=n,this.pendingMin=null,{count:e,paddingStart:t,scrollMargin:s,getItemKey:i,enabled:l,lanes:n,laneAssignmentMode:r,gap:c}),{key:!1}),this.getMeasurements=M(()=>[this.getMeasurementOptions(),this.itemSizeCacheVersion],({count:e,paddingStart:t,scrollMargin:s,getItemKey:i,enabled:l,lanes:n,laneAssignmentMode:r,gap:c},u)=>{const m=this.itemSizeCache;if(!l)return this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),[];if(this.laneAssignments.size>e)for(const f of this.laneAssignments.keys())f>=e&&this.laneAssignments.delete(f);this.lanesChangedFlag&&(this.lanesChangedFlag=!1,this.lanesSettling=!0,this.measurementsCache=[],this.itemSizeCache.clear(),this.laneAssignments.clear(),this.pendingMin=null),this.measurementsCache.length===0&&!this.lanesSettling&&(this.measurementsCache=this.options.initialMeasurementsCache,this.measurementsCache.forEach(f=>{this.itemSizeCache.set(f.key,f.size)}));const d=this.lanesSettling?0:this.pendingMin??0;if(this.pendingMin=null,this.lanesSettling&&this.measurementsCache.length===e&&(this.lanesSettling=!1),n===1){const f=e*2;let p=this._flatMeasurements;if(!p||p.length<f){const b=new Float64Array(f);p&&d>0&&b.set(p.subarray(0,d*2)),p=b,this._flatMeasurements=p}let y;if(d===0)y=t+s;else{const b=d-1;y=p[b*2]+p[b*2+1]+c}for(let b=d;b<e;b++){const $=i(b),D=m.get($),F=typeof D=="number"?D:this.options.estimateSize(b);p[b*2]=y,p[b*2+1]=F,y+=F+c}const v=Oe(e,p,i);return this.measurementsCache=v,v}const g=this.measurementsCache.slice(0,d),S=new Array(n).fill(void 0),E=new Float64Array(n);let O=0;for(let f=0;f<d;f++){const p=g[f];p&&(S[p.lane]===void 0&&O++,S[p.lane]=f,E[p.lane]=p.end)}for(let f=d;f<e;f++){const p=i(f),y=this.laneAssignments.get(f);let v,b;const $=r==="estimate"||m.has(p);if(y!==void 0&&this.options.lanes>1){v=y;const R=S[v],x=R!==void 0?g[R]:void 0;b=x?x.end+c:t+s}else if(O===n){let R=0,x=E[0],G=S[0];for(let I=1;I<n;I++){const K=E[I];(K<x||K===x&&S[I]<G)&&(R=I,x=K,G=S[I])}v=R,b=x+c,$&&this.laneAssignments.set(f,v)}else v=f%this.options.lanes,b=t+s,$&&this.laneAssignments.set(f,v);const D=m.get(p),F=typeof D=="number"?D:this.options.estimateSize(f),Z=b+F;g[f]={index:f,start:b,size:F,end:Z,key:p,lane:v},S[v]===void 0&&O++,S[v]=f,E[v]=Z}return this.measurementsCache=g,g},{key:!1,debug:()=>this.options.debug}),this.calculateRange=M(()=>[this.getMeasurements(),this.getSize(),this.getScrollOffset(),this.options.lanes],(e,t,s,i)=>e.length===0||t===0?(this.range=null,null):(this.range=je(e,t,s,i,i===1&&this._flatMeasurements!=null?this._flatMeasurements:null),this.range),{key:!1,debug:()=>this.options.debug}),this.getVirtualIndexes=M(()=>{let e=null,t=null;const s=this.calculateRange();return s&&(e=s.startIndex,t=s.endIndex),this.maybeNotify.updateDeps([this.isScrolling,e,t]),[this.options.rangeExtractor,this.options.overscan,this.options.count,e,t]},(e,t,s,i,l)=>i===null||l===null?[]:e({startIndex:i,endIndex:l,overscan:t,count:s}),{key:!1,debug:()=>this.options.debug}),this.indexFromElement=e=>{const t=this.options.indexAttribute,s=e.getAttribute(t);return s?parseInt(s,10):(console.warn(`Missing attribute name '${t}={index}' on measured element.`),-1)},this.shouldMeasureDuringScroll=e=>{var t;if(!this.scrollState||this.scrollState.behavior!=="smooth")return!0;const s=this.scrollState.index??((t=this.getVirtualItemForOffset(this.scrollState.lastTargetOffset))==null?void 0:t.index);if(s!==void 0&&this.range){const i=Math.max(this.options.overscan,Math.ceil((this.range.endIndex-this.range.startIndex)/2)),l=Math.max(0,s-i),n=Math.min(this.options.count-1,s+i);return e>=l&&e<=n}return!0},this.measureElement=e=>{if(!e){this.elementsCache.forEach((l,n)=>{l.isConnected||(this.observer.unobserve(l),this.elementsCache.delete(n))});return}const t=this.indexFromElement(e),s=this.options.getItemKey(t),i=this.elementsCache.get(s);i!==e&&(i&&this.observer.unobserve(i),this.observer.observe(e),this.elementsCache.set(s,e)),(!this.isScrolling||this.scrollState)&&this.shouldMeasureDuringScroll(t)&&this.resizeItem(t,this.options.measureElement(e,void 0,this))},this.resizeItem=(e,t)=>{var s,i;if(e<0||e>=this.options.count)return;let l,n,r;const c=this._flatMeasurements;if(this.options.lanes===1&&c!==null)r=this.options.getItemKey(e),n=c[e*2],l=c[e*2+1];else{const d=this.measurementsCache[e];if(!d)return;r=d.key,n=d.start,l=d.size}const u=this.itemSizeCache.get(r)??l,m=t-u;if(m!==0){const d=this.options.anchorTo==="end"&&((s=this.scrollState)==null?void 0:s.behavior)!=="smooth"&&this.getVirtualDistanceFromEnd()<=this.options.scrollEndThreshold,g=d?this.getTotalSize():0,S=this.getScrollOffset()+this.scrollAdjustments,O=!this.itemSizeCache.has(r)?n<S:n+u<=S&&this.scrollDirection!=="backward",f=((i=this.scrollState)==null?void 0:i.behavior)!=="smooth"&&(this.shouldAdjustScrollPositionOnItemSizeChange!==void 0?this.shouldAdjustScrollPositionOnItemSizeChange(this.measurementsCache[e]??{index:e,key:r,start:n,size:l,end:n+l,lane:0},m,this):O);(this.pendingMin===null||e<this.pendingMin)&&(this.pendingMin=e),this.itemSizeCache.set(r,t),this.itemSizeCacheVersion++,d?this.applyScrollAdjustment(this.getTotalSize()-g):f&&this.applyScrollAdjustment(m),this.notify(!1)}},this.getVirtualItems=M(()=>[this.getVirtualIndexes(),this.getMeasurements()],(e,t)=>{const s=[];for(let i=0,l=e.length;i<l;i++){const n=e[i],r=t[n];s.push(r)}return s},{key:!1,debug:()=>this.options.debug}),this.getVirtualItemForOffset=e=>{const t=this.getMeasurements();if(t.length===0)return;const s=this._flatMeasurements,i=this.options.lanes===1&&s!=null,l=le(0,t.length-1,i?n=>s[n*2]:n=>te(t[n]).start,e);return te(t[l])},this.getMaxScrollOffset=()=>{if(!this.scrollElement)return 0;if("scrollHeight"in this.scrollElement)return this.options.horizontal?this.scrollElement.scrollWidth-this.scrollElement.clientWidth:this.scrollElement.scrollHeight-this.scrollElement.clientHeight;{const e=this.scrollElement.document.documentElement;return this.options.horizontal?e.scrollWidth-this.scrollElement.innerWidth:e.scrollHeight-this.scrollElement.innerHeight}},this.getVirtualDistanceFromEnd=()=>Math.max(this.getTotalSize()-this.getSize()-this.getScrollOffset(),0),this.getDistanceFromEnd=()=>Math.max(this.getMaxScrollOffset()-this.getScrollOffset(),0),this.isAtEnd=(e=this.options.scrollEndThreshold)=>this.getDistanceFromEnd()<=e,this.getOffsetForAlignment=(e,t,s=0)=>{if(!this.scrollElement)return 0;const i=this.getSize(),l=this.getScrollOffset();t==="auto"&&(t=e>=l+i?"end":"start"),t==="center"?e+=(s-i)/2:t==="end"&&(e-=i);const n=this.getMaxScrollOffset();return Math.max(Math.min(n,e),0)},this.getOffsetForIndex=(e,t="auto")=>{e=Math.max(0,Math.min(e,this.options.count-1));const s=this.getSize(),i=this.getScrollOffset(),l=this.measurementsCache[e];if(!l)return;if(t==="auto")if(l.end>=i+s-this.options.scrollPaddingEnd)t="end";else if(l.start<=i+this.options.scrollPaddingStart)t="start";else return[i,t];if(t==="end"&&e===this.options.count-1)return[this.getMaxScrollOffset(),t];const n=t==="end"?l.end+this.options.scrollPaddingEnd:l.start-this.options.scrollPaddingStart;return[this.getOffsetForAlignment(n,t,l.size),t]},this.scrollToOffset=(e,{align:t="start",behavior:s="auto"}={})=>{this._iosDeferredAdjustment=0;const i=this.getOffsetForAlignment(e,t),l=this.now();this.scrollState={index:null,align:t,behavior:s,startedAt:l,lastTargetOffset:i,stableFrames:0},this._scrollToOffset(i,{adjustments:void 0,behavior:s}),this.scheduleScrollReconcile()},this.scrollToIndex=(e,{align:t="auto",behavior:s="auto"}={})=>{this._iosDeferredAdjustment=0,e=Math.max(0,Math.min(e,this.options.count-1));const i=this.getOffsetForIndex(e,t);if(!i)return;const[l,n]=i,r=this.now();this.scrollState={index:e,align:n,behavior:s,startedAt:r,lastTargetOffset:l,stableFrames:0},this._scrollToOffset(l,{adjustments:void 0,behavior:s}),this.scheduleScrollReconcile()},this.scrollBy=(e,{behavior:t="auto"}={})=>{const s=this.getScrollOffset()+e,i=this.now();this.scrollState={index:null,align:"start",behavior:t,startedAt:i,lastTargetOffset:s,stableFrames:0},this._scrollToOffset(s,{adjustments:void 0,behavior:t}),this.scheduleScrollReconcile()},this.scrollToEnd=({behavior:e="auto"}={})=>{if(this.options.count>0){this.scrollToIndex(this.options.count-1,{align:"end",behavior:e});return}this.scrollToOffset(Math.max(this.getTotalSize()-this.getSize(),0),{behavior:e})},this.getTotalSize=()=>{var e;const t=this.getMeasurements();let s;if(t.length===0)s=this.options.paddingStart;else if(this.options.lanes===1){const i=t.length-1,l=this._flatMeasurements;l!=null?s=l[i*2]+l[i*2+1]:s=((e=t[i])==null?void 0:e.end)??0}else{const i=Array(this.options.lanes).fill(null);let l=t.length-1;for(;l>=0&&i.some(n=>n===null);){const n=t[l];i[n.lane]===null&&(i[n.lane]=n.end),l--}s=Math.max(...i.filter(n=>n!==null))}return Math.max(s-this.options.scrollMargin+this.options.paddingEnd,0)},this.takeSnapshot=()=>{const e=[];if(this.itemSizeCache.size===0)return e;const t=this.getMeasurements();for(const s of t)s&&this.itemSizeCache.has(s.key)&&e.push({index:s.index,key:s.key,start:s.start,size:s.size,end:s.end,lane:s.lane});return e},this._scrollToOffset=(e,{adjustments:t,behavior:s})=>{this._intendedScrollOffset=e+(t??0),this.options.scrollToFn(e,{behavior:s,adjustments:t},this)},this.measure=()=>{this.pendingMin=null,this.itemSizeCache.clear(),this.laneAssignments.clear(),this.itemSizeCacheVersion++,this.notify(!1)},this.setOptions(h)}applyScrollAdjustment(h,e){h!==0&&(H()&&(this.isScrolling||this._iosTouching||this._iosJustTouchEnded)?this._iosDeferredAdjustment+=h:(this._scrollToOffset(this.getScrollOffset(),{adjustments:this.scrollAdjustments+=h,behavior:e}),this.scrollOffset!==null&&(this.scrollOffset+=this.scrollAdjustments,this.scrollOffset<0&&(this.scrollOffset=0),this.scrollAdjustments=0)))}scheduleScrollReconcile(){if(!this.targetWindow){this.scrollState=null;return}this.rafId==null&&(this.rafId=this.targetWindow.requestAnimationFrame(()=>{this.rafId=null,this.reconcileScroll()}))}reconcileScroll(){if(!this.scrollState||!this.scrollElement)return;if(this.now()-this.scrollState.startedAt>5e3){this.scrollState=null;return}const t=this.scrollState.index!=null?this.getOffsetForIndex(this.scrollState.index,this.scrollState.align):void 0,s=t?t[0]:this.scrollState.lastTargetOffset,i=1,l=s!==this.scrollState.lastTargetOffset;if(!l&&Ce(s,this.getScrollOffset())){if(this.scrollState.stableFrames++,this.scrollState.stableFrames>=i){this.getScrollOffset()!==s&&this._scrollToOffset(s,{adjustments:void 0,behavior:"auto"}),this.scrollState=null;return}}else if(this.scrollState.stableFrames=0,l){const n=this.getSize()||600,r=Math.abs(s-this.getScrollOffset()),c=this.scrollState.behavior==="smooth"&&r>n;this.scrollState.lastTargetOffset=s,c||(this.scrollState.behavior="auto"),this._scrollToOffset(s,{adjustments:void 0,behavior:c?"smooth":"auto"})}this.scheduleScrollReconcile()}}const le=(o,h,e,t)=>{for(;o<=h;){const s=(o+h)/2|0,i=e(s);if(i<t)o=s+1;else if(i>t)h=s-1;else return s}return o>0?o-1:0};function qe(o,h,e){let t=0;for(;t<=h;){const s=(t+h)/2|0,i=o[s*2];if(i<e)t=s+1;else if(i>e)h=s-1;else return s}return t>0?t-1:0}function je(o,h,e,t,s){const i=o.length-1;if(o.length<=t)return{startIndex:0,endIndex:i};if(t===1&&s!==null){const c=qe(s,i,e);let u=c;const m=e+h;for(;u<i&&s[u*2]+s[u*2+1]<m;)u++;return{startIndex:c,endIndex:u}}let n=le(0,i,c=>o[c].start,e),r=n;if(t===1)for(;r<i&&o[r].end<e+h;)r++;else if(t>1){const c=Array(t).fill(0);for(;r<i&&c.some(m=>m<e+h);){const m=o[r];c[m.lane]=m.end,r++}const u=Array(t).fill(e+h);for(;n>=0&&u.some(m=>m>=e);){const m=o[n];u[m.lane]=m.start,n--}n=Math.max(0,n-n%t),r=Math.min(i,r+(t-1-r%t))}return{startIndex:n,endIndex:r}}function We(o){const h=new Re(a(o)),e=re(h),t=h._didMount();return Q(()=>a(o).getScrollElement(),s=>{s&&h._willUpdate()},{immediate:!0}),Q(()=>a(o),s=>{h.setOptions({...s,onChange:(i,l)=>{var n;Y(e),(n=s.onChange)==null||n.call(s,i,l)}}),h._willUpdate(),Y(e)},{immediate:!0}),oe(t),e}function Ke(o){return We(W(()=>({observeElementRect:Ie,observeElementOffset:Me,scrollToFn:Fe,...a(o)})))}const $e={slots:{root:"relative flex flex-col min-w-0 min-h-svh lg:not-last:border-e lg:not-last:border-default shrink-0",body:"flex flex-col gap-4 sm:gap-6 flex-1 overflow-y-auto p-4 sm:p-6",handle:""},variants:{size:{true:{root:"w-full lg:w-(--width)"},false:{root:"flex-1"}}}},Le=["data-dragging"],He=Object.assign({inheritAttrs:!1},{__name:"DashboardPanel",props:{class:{type:null,required:!1},ui:{type:Object,required:!1},id:{type:String,required:!1},minSize:{type:Number,required:!1,default:15},maxSize:{type:Number,required:!1},defaultSize:{type:Number,required:!1},resizable:{type:Boolean,required:!1,default:!1}},setup(o){const e=V("dashboardPanel",o),t=N(),s=X({storageKey:"dashboard",unit:"%"}),i=`${s.storageKey}-panel-${e.id||ae()}`,{el:l,size:n,isDragging:r,onMouseDown:c,onTouchStart:u,onDoubleClick:m}=he(i,ce(()=>({...s,...e}))),d=W(()=>P({extend:$e,...t.ui?.dashboardPanel||{}})({size:!!n.value}));return(g,S)=>(C(),J(ie,null,[j("div",L({id:i,ref_key:"el",ref:l,"data-slot":"root"},g.$attrs,{"data-dragging":a(r),class:d.value.root({class:[a(e).ui?.root,a(e).class]}),style:[a(n)?{"--width":`${a(n)}${a(s).unit}`}:void 0]}),[_(g.$slots,"default",{},()=>[_(g.$slots,"header"),j("div",{"data-slot":"body",class:w(d.value.body({class:a(e).ui?.body}))},[_(g.$slots,"body")],2),_(g.$slots,"footer")])],16,Le),_(g.$slots,"resize-handle",{onMouseDown:a(c),onTouchStart:a(u),onDoubleClick:a(m)},()=>[a(e).resizable?(C(),z(ue,{key:0,"aria-controls":i,"data-slot":"handle",class:w(d.value.handle({class:a(e).ui?.handle})),onMousedown:a(c),onTouchstart:a(u),onDblclick:a(m)},null,8,["class","onMousedown","onTouchstart","onDblclick"])):k("",!0)])],64))}}),Be={base:"animate-pulse rounded-md bg-elevated"},Je={__name:"Skeleton",props:{as:{type:null,required:!1},class:{type:null,required:!1},ui:{type:Object,required:!1}},setup(o){const e=V("skeleton",o),t=N(),s=W(()=>P({extend:Be,...t.ui?.skeleton||{}}));return(i,l)=>(C(),z(a(ne),{as:a(e).as,"aria-busy":"true","aria-label":"loading","aria-live":"polite",role:"alert",class:w(s.value({class:[a(e).ui?.base,a(e).class]}))},{default:U(()=>[_(i.$slots,"default")]),_:3},8,["as","class"]))}},Ve={slots:{root:"h-(--ui-header-height) shrink-0 flex items-center justify-between border-b border-default px-4 sm:px-6 gap-1.5",left:"flex items-center gap-1.5 min-w-0",icon:"shrink-0 size-5 self-center me-1.5",title:"flex items-center gap-1.5 font-semibold text-highlighted truncate",center:"hidden lg:flex",right:"flex items-center shrink-0 gap-1.5",toggle:""},variants:{toggleSide:{left:{toggle:""},right:{toggle:""}}}},Ue=Object.assign({inheritAttrs:!1},{__name:"DashboardNavbar",props:{as:{type:null,required:!1},icon:{type:null,required:!1},title:{type:String,required:!1},toggle:{type:[Boolean,Object],required:!1,default:!0},toggleSide:{type:String,required:!1,default:"left"},class:{type:null,required:!1},ui:{type:Object,required:!1}},setup(o){const h=o,e=de(),t=V("dashboardNavbar",h),s=N(),i=X({}),[l,n]=fe(),r=W(()=>P({extend:Ve,...s.ui?.dashboardNavbar||{}})());return(c,u)=>(C(),J(ie,null,[ee(a(l),null,{default:U(()=>[_(c.$slots,"toggle",T(A({...a(i),ui:r.value})),()=>[a(t).toggle?(C(),z(me,L({key:0},typeof a(t).toggle=="object"?a(t).toggle:{},{side:a(t).toggleSide,"data-slot":"toggle",class:r.value.toggle({class:a(t).ui?.toggle,toggleSide:a(t).toggleSide})}),null,16,["side","class"])):k("",!0)])]),_:3}),ee(a(ne),L({as:a(t).as,"data-slot":"root"},c.$attrs,{class:r.value.root({class:[a(t).ui?.root,a(t).class]})}),{default:U(()=>[j("div",{"data-slot":"left",class:w(r.value.left({class:a(t).ui?.left}))},[a(t).toggleSide==="left"?(C(),z(a(n),{key:0})):k("",!0),_(c.$slots,"left",T(A(a(i))),()=>[_(c.$slots,"leading",T(A({...a(i),ui:r.value})),()=>[a(t).icon?(C(),z(ge,{key:0,name:a(t).icon,"data-slot":"icon",class:w(r.value.icon({class:a(t).ui?.icon}))},null,8,["name","class"])):k("",!0)]),j("h1",{"data-slot":"title",class:w(r.value.title({class:a(t).ui?.title}))},[_(c.$slots,"title",{},()=>[pe(Se(a(t).title),1)])],2),_(c.$slots,"trailing",T(A({...a(i),ui:r.value})))])],2),e.default?(C(),J("div",{key:0,"data-slot":"center",class:w(r.value.center({class:a(t).ui?.center}))},[_(c.$slots,"default",T(A(a(i))))],2)):k("",!0),j("div",{"data-slot":"right",class:w(r.value.right({class:a(t).ui?.right}))},[_(c.$slots,"right",T(A(a(i)))),a(t).toggleSide==="right"?(C(),z(a(n),{key:0})):k("",!0)],2)]),_:3},16,["as","class"])],64))}}),Pe={base:"hidden lg:flex",variants:{side:{left:"",right:""}}},Xe={__name:"DashboardSidebarCollapse",props:{color:{type:null,required:!1,default:"neutral"},variant:{type:null,required:!1,default:"ghost"},side:{type:String,required:!1,default:"left"},ui:{type:Object,required:!1},label:{type:String,required:!1},activeColor:{type:null,required:!1},activeVariant:{type:null,required:!1},size:{type:null,required:!1},square:{type:Boolean,required:!1},block:{type:Boolean,required:!1},loadingAuto:{type:Boolean,required:!1},onClick:{type:[Function,Array],required:!1},class:{type:null,required:!1},icon:{type:null,required:!1},avatar:{type:Object,required:!1},leading:{type:Boolean,required:!1},leadingIcon:{type:null,required:!1},trailing:{type:Boolean,required:!1},trailingIcon:{type:null,required:!1},loading:{type:Boolean,required:!1},loadingIcon:{type:null,required:!1},as:{type:null,required:!1},type:{type:null,required:!1},disabled:{type:Boolean,required:!1},exactActiveClass:{type:String,required:!1},viewTransition:{type:Boolean,required:!1}},setup(o){const e=V("dashboardSidebarCollapse",o),t=be(ve(e,"icon","side","class")),{t:s}=ye(),i=N(),{sidebarCollapsed:l,collapseSidebar:n}=X({sidebarCollapsed:_e(!1),collapseSidebar:()=>{}}),r=W(()=>P({extend:Pe,...i.ui?.dashboardSidebarCollapse||{}}));return(c,u)=>(C(),z(Ee,L({...a(t),icon:a(e).icon||(a(l)?a(i).ui.icons.panelOpen:a(i).ui.icons.panelClose),"aria-label":a(l)?a(s)("dashboardSidebarCollapse.expand"):a(s)("dashboardSidebarCollapse.collapse"),...c.$attrs},{class:r.value({class:[a(e).ui?.base,a(e).class],side:a(e).side}),onClick:u[0]||(u[0]=m=>a(n)?.(!a(l)))}),null,16,["class"]))}};export{He as _,Je as a,Ue as b,Xe as c,Ke as u};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as h,C as q,e as u,h as f,w as d,D as p,l as z,E as m,u as a,P as y,B as U,A as X,x as v,I as Z,aA as G,aB as H,t as J,R as K,S as j,ar as Q,T as W,U as Y,a as I,X as _,i as R,j as B,c as S,F as V,g as ee,$ as T,Z as A,f as D}from"./index-C5RBBrPj.js";var ae=h({__name:"PaginationEllipsis",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(o){const s=o;return q(),(t,r)=>(u(),f(a(y),m(s,{"data-type":"ellipsis"}),{default:d(()=>[p(t.$slots,"default",{},()=>[r[0]||(r[0]=z("…"))])]),_:3},16))}}),te=ae;const[L,se]=Z("PaginationRoot");var le=h({__name:"PaginationRoot",props:{page:{type:Number,required:!1},defaultPage:{type:Number,required:!1,default:1},itemsPerPage:{type:Number,required:!0},total:{type:Number,required:!1,default:0},siblingCount:{type:Number,required:!1,default:2},disabled:{type:Boolean,required:!1},showEdges:{type:Boolean,required:!1,default:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"nav"}},emits:["update:page"],setup(o,{emit:s}){const t=o,r=s,{siblingCount:l,disabled:e,showEdges:n}=U(t);q();const i=X(t,"page",r,{defaultValue:t.defaultPage,passive:t.page===void 0}),b=v(()=>Math.max(1,Math.ceil(t.total/(t.itemsPerPage||1))));return se({page:i,onPageChange(g){i.value=g},pageCount:b,siblingCount:l,disabled:e,showEdges:n}),(g,$)=>(u(),f(a(y),{as:g.as,"as-child":g.asChild},{default:d(()=>[p(g.$slots,"default",{page:a(i),pageCount:b.value})]),_:3},8,["as","as-child"]))}}),oe=le,re=h({__name:"PaginationFirst",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"}},setup(o){const s=o,t=L();q();const r=v(()=>t.page.value===1||t.disabled.value);return(l,e)=>(u(),f(a(y),m(s,{"aria-label":"First Page",type:l.as==="button"?"button":void 0,disabled:r.value,onClick:e[0]||(e[0]=n=>!r.value&&a(t).onPageChange(1))}),{default:d(()=>[p(l.$slots,"default",{},()=>[e[1]||(e[1]=z("First page"))])]),_:3},16,["type","disabled"]))}}),ie=re,ne=h({__name:"PaginationLast",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"}},setup(o){const s=o,t=L();q();const r=v(()=>t.page.value===t.pageCount.value||t.disabled.value);return(l,e)=>(u(),f(a(y),m(s,{"aria-label":"Last Page",type:l.as==="button"?"button":void 0,disabled:r.value,onClick:e[0]||(e[0]=n=>!r.value&&a(t).onPageChange(a(t).pageCount.value))}),{default:d(()=>[p(l.$slots,"default",{},()=>[e[1]||(e[1]=z("Last page"))])]),_:3},16,["type","disabled"]))}}),ue=ne;function P(o,s){const t=s-o+1;return Array.from({length:t},(r,l)=>l+o)}function de(o){return o.map(s=>typeof s=="number"?{type:"page",value:s}:{type:"ellipsis"})}const k="ellipsis";function pe(o,s,t,r){const e=s,n=Math.max(o-t,1),i=Math.min(o+t,e);if(r){const g=Math.min(2*t+5,s)-2,$=n>3&&Math.abs(e-g-1+1)>2&&Math.abs(n-1)>2,w=i<e-2&&Math.abs(e-g)>2&&Math.abs(e-i)>2;if(!$&&w)return[...P(1,g),k,e];if($&&!w){const c=P(e-g+1,e);return[1,k,...c]}if($&&w){const c=P(n,i);return[1,k,...c,k,e]}return P(1,e)}else{const b=t*2+1;return s<b?P(1,e):o<=t+1?P(1,b):s-o<=t?P(s-b+1,e):P(n,i)}}var fe=h({__name:"PaginationList",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},setup(o){const s=o;q();const t=L(),r=v(()=>de(pe(t.page.value,t.pageCount.value,t.siblingCount.value,t.showEdges.value)));return(l,e)=>(u(),f(a(y),G(H(s)),{default:d(()=>[p(l.$slots,"default",{items:r.value})]),_:3},16))}}),ce=fe,ve=h({__name:"PaginationListItem",props:{value:{type:Number,required:!0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"}},setup(o){const s=o;q();const t=L(),r=v(()=>t.page.value===s.value),l=v(()=>t.disabled.value);return(e,n)=>(u(),f(a(y),m(s,{"data-type":"page","aria-label":`Page ${e.value}`,"aria-current":r.value?"page":void 0,"data-selected":r.value?"true":void 0,disabled:l.value,type:e.as==="button"?"button":void 0,onClick:n[0]||(n[0]=i=>!l.value&&a(t).onPageChange(e.value))}),{default:d(()=>[p(e.$slots,"default",{},()=>[z(J(e.value),1)])]),_:3},16,["aria-label","aria-current","data-selected","disabled","type"]))}}),ge=ve,_e=h({__name:"PaginationNext",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"}},setup(o){const s=o;q();const t=L(),r=v(()=>t.page.value===t.pageCount.value||t.disabled.value);return(l,e)=>(u(),f(a(y),m(s,{"aria-label":"Next Page",type:l.as==="button"?"button":void 0,disabled:r.value,onClick:e[0]||(e[0]=n=>!r.value&&a(t).onPageChange(a(t).page.value+1))}),{default:d(()=>[p(l.$slots,"default",{},()=>[e[1]||(e[1]=z("Next page"))])]),_:3},16,["type","disabled"]))}}),be=_e,ye=h({__name:"PaginationPrev",props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:"button"}},setup(o){const s=o;q();const t=L(),r=v(()=>t.page.value===1||t.disabled.value);return(l,e)=>(u(),f(a(y),m(s,{"aria-label":"Previous Page",type:l.as==="button"?"button":void 0,disabled:r.value,onClick:e[0]||(e[0]=n=>!r.value&&a(t).onPageChange(a(t).page.value-1))}),{default:d(()=>[p(l.$slots,"default",{},()=>[e[1]||(e[1]=z("Prev page"))])]),_:3},16,["type","disabled"]))}}),Pe=ye;const me={slots:{root:"",list:"flex items-center gap-1",ellipsis:"pointer-events-none",label:"min-w-5 text-center",first:"",prev:"",item:"",next:"",last:""}},xe={__name:"Pagination",props:{as:{type:null,required:!1},firstIcon:{type:null,required:!1},prevIcon:{type:null,required:!1},nextIcon:{type:null,required:!1},lastIcon:{type:null,required:!1},ellipsisIcon:{type:null,required:!1},color:{type:null,required:!1,default:"neutral"},variant:{type:null,required:!1,default:"outline"},activeColor:{type:null,required:!1,default:"primary"},activeVariant:{type:null,required:!1,default:"solid"},showControls:{type:Boolean,required:!1,default:!0},size:{type:null,required:!1},to:{type:Function,required:!1},class:{type:null,required:!1},ui:{type:Object,required:!1},defaultPage:{type:Number,required:!1},disabled:{type:Boolean,required:!1},itemsPerPage:{type:Number,required:!1,default:10},page:{type:Number,required:!1},showEdges:{type:Boolean,required:!1,default:!1},siblingCount:{type:Number,required:!1,default:2},total:{type:Number,required:!1,default:0}},emits:["update:page"],setup(o,{emit:s}){const t=o,r=s,l=K(),e=j("pagination",t),{dir:n}=Q(),i=T(),b=W(Y(e,"as","defaultPage","disabled","itemsPerPage","page","showEdges","siblingCount","total"),r),g=v(()=>e.firstIcon||(n.value==="rtl"?i.ui.icons.chevronDoubleRight:i.ui.icons.chevronDoubleLeft)),$=v(()=>e.prevIcon||(n.value==="rtl"?i.ui.icons.chevronRight:i.ui.icons.chevronLeft)),w=v(()=>e.nextIcon||(n.value==="rtl"?i.ui.icons.chevronLeft:i.ui.icons.chevronRight)),F=v(()=>e.lastIcon||(n.value==="rtl"?i.ui.icons.chevronDoubleLeft:i.ui.icons.chevronDoubleRight)),c=v(()=>A({extend:me,...i.ui?.pagination||{}})());return(N,qe)=>(u(),f(a(oe),m(a(b),{"data-slot":"root",class:c.value.root({class:[a(e).ui?.root,a(e).class]})}),{default:d(({page:C,pageCount:E})=>[I(a(ce),{"data-slot":"list",class:_(c.value.list({class:a(e).ui?.list}))},{default:d(({items:O})=>[a(e).showControls||l.first?(u(),f(a(ie),{key:0,"as-child":"","data-slot":"first",class:_(c.value.first({class:a(e).ui?.first}))},{default:d(()=>[p(N.$slots,"first",{},()=>[I(R,{color:a(e).color,variant:a(e).variant,size:a(e).size,icon:g.value,to:a(e).to?.(1)},null,8,["color","variant","size","icon","to"])])]),_:3},8,["class"])):B("",!0),a(e).showControls||l.prev?(u(),f(a(Pe),{key:1,"as-child":"","data-slot":"prev",class:_(c.value.prev({class:a(e).ui?.prev}))},{default:d(()=>[p(N.$slots,"prev",{},()=>[I(R,{color:a(e).color,variant:a(e).variant,size:a(e).size,icon:$.value,to:C>1?a(e).to?.(C-1):void 0},null,8,["color","variant","size","icon","to"])])]),_:2},1032,["class"])):B("",!0),(u(!0),S(V,null,ee(O,(x,M)=>(u(),S(V,{key:M},[x.type==="page"?(u(),f(a(ge),{key:0,"as-child":"",value:x.value,"data-slot":"item",class:_(c.value.item({class:a(e).ui?.item}))},{default:d(()=>[p(N.$slots,"item",m({ref_for:!0},{item:x,index:M,page:C,pageCount:E}),()=>[I(R,{color:C===x.value?a(e).activeColor:a(e).color,variant:C===x.value?a(e).activeVariant:a(e).variant,size:a(e).size,label:String(x.value),ui:{label:c.value.label()},to:a(e).to?.(x.value),square:""},null,8,["color","variant","size","label","ui","to"])])]),_:2},1032,["value","class"])):(u(),f(a(te),{key:1,"as-child":"","data-slot":"ellipsis",class:_(c.value.ellipsis({class:a(e).ui?.ellipsis}))},{default:d(()=>[p(N.$slots,"ellipsis",{ui:c.value},()=>[I(R,{as:"div",color:a(e).color,variant:a(e).variant,size:a(e).size,icon:a(e).ellipsisIcon||a(i).ui.icons.ellipsis},null,8,["color","variant","size","icon"])])]),_:3},8,["class"]))],64))),128)),a(e).showControls||l.next?(u(),f(a(be),{key:2,"as-child":"","data-slot":"next",class:_(c.value.next({class:a(e).ui?.next}))},{default:d(()=>[p(N.$slots,"next",{},()=>[I(R,{color:a(e).color,variant:a(e).variant,size:a(e).size,icon:w.value,to:C<E?a(e).to?.(C+1):void 0},null,8,["color","variant","size","icon","to"])])]),_:2},1032,["class"])):B("",!0),a(e).showControls||l.last?(u(),f(a(ue),{key:3,"as-child":"","data-slot":"last",class:_(c.value.last({class:a(e).ui?.last}))},{default:d(()=>[p(N.$slots,"last",{},()=>[I(R,{color:a(e).color,variant:a(e).variant,size:a(e).size,icon:F.value,to:a(e).to?.(E)},null,8,["color","variant","size","icon","to"])])]),_:2},1032,["class"])):B("",!0)]),_:2},1032,["class"])]),_:3},16,["class"]))}},he={slots:{root:"shrink-0 flex items-center justify-between border-b border-default px-4 sm:px-6 gap-1.5 overflow-x-auto min-h-[49px]",left:"flex items-center gap-1.5",right:"flex items-center gap-1.5"}},Ie={__name:"DashboardToolbar",props:{as:{type:null,required:!1},class:{type:null,required:!1},ui:{type:Object,required:!1}},setup(o){const t=j("dashboardToolbar",o),r=T(),l=v(()=>A({extend:he,...r.ui?.dashboardToolbar||{}})());return(e,n)=>(u(),f(a(y),{as:a(t).as,"data-slot":"root",class:_(l.value.root({class:[a(t).ui?.root,a(t).class]}))},{default:d(()=>[p(e.$slots,"default",{},()=>[D("div",{"data-slot":"left",class:_(l.value.left({class:[a(t).ui?.left]}))},[p(e.$slots,"left")],2),D("div",{"data-slot":"right",class:_(l.value.right({class:[a(t).ui?.right]}))},[p(e.$slots,"right")],2)])]),_:3},8,["as","class"]))}};export{xe as _,Ie as a};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as c,m as x,q as g,h as w,w as b,s as k,r as y,c as d,f as t,l as o,t as n,u as M,j as p,e as u,b as I}from"./index-C5RBBrPj.js";import{a as B,f as C}from"./LogSlideover.vue_vue_type_script_setup_true_lang-33xie7TE.js";const $={key:0,class:"text-sm text-muted space-y-1"},E={key:0},L=c({__name:"ErrorLogModal",props:k({logId:{}},{open:{type:Boolean,default:!1},openModifiers:{}}),emits:["update:open"],setup(r){const s=x(r,"open"),i=r,e=y(null);g(s,async l=>{if(!l||!i.logId)return;e.value=null;const{data:a}=await I(`/api/error-logs/${i.logId}`);e.value=a?.log??null});function m(l){return new Date(l*1e3).toLocaleString()}function v(){return e.value?.logReason==="expired"?"Run logs expired. The run-log file was removed by the retention policy.":"No logs available."}return(l,a)=>(u(),w(B,{open:s.value,"onUpdate:open":a[0]||(a[0]=f=>s.value=f),title:"Error detail",description:e.value?`#${e.value.workItemIid} · ${e.value.phase} · ${e.value.kind}`:"",text:e.value?.logs??"",available:e.value?e.value.logAvailable??!0:!1,truncated:e.value?.truncated??!1,"unavailable-text":v(),"work-item-url":e.value?.workItemUrl??""},{meta:b(()=>[e.value?(u(),d("div",$,[t("p",null,[a[1]||(a[1]=t("span",{class:"text-default font-medium"},"Message:",-1)),o(" "+n(e.value.message),1)]),t("p",null,[a[2]||(a[2]=t("span",{class:"text-default font-medium"},"When:",-1)),o(" "+n(m(e.value.createdAt)),1)]),t("p",null,[a[3]||(a[3]=t("span",{class:"text-default font-medium"},"Model:",-1)),o(" "+n(M(C)(e.value.model,e.value.variant)),1)]),e.value.exitCode!==null?(u(),d("p",E,[a[4]||(a[4]=t("span",{class:"text-default font-medium"},"Exit code:",-1)),o(" "+n(e.value.exitCode),1)])):p("",!0)])):p("",!0)]),_:1},8,["open","description","text","available","truncated","unavailable-text","work-item-url"]))}});export{L as _};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as oe,a as te,b as se,c as ne}from"./DashboardSidebarCollapse-rIuzCmVm.js";import{_ as ie,a as re}from"./DashboardToolbar-DFCUqZ4Z.js";import{d as O,e as v,h as q,w as n,a as l,i as z,f as x,t as A,a1 as ce,n as ue,a4 as de,a5 as me,a6 as ve,q as T,o as pe,c as w,F as M,r as s,b as F,g as _e,_ as ge,y as fe,j as be,x as P}from"./index-C5RBBrPj.js";import{_ as he,a as ke}from"./SelectMenu-BjMxc4VB.js";import{b as $e,_ as ye}from"./PeriodRangePicker.vue_vue_type_script_setup_true_lang-DiFUNem7.js";import{_ as we,w as Ue}from"./index-BMbMibyb.js";import{_ as xe}from"./WorkItemCell.vue_vue_type_script_setup_true_lang-BQn6vTjd.js";import{_ as je}from"./TimeCell.vue_vue_type_script_setup_true_lang-DW_UB0Fu.js";import{_ as Ve}from"./LogSlideover.vue_vue_type_script_setup_true_lang-33xie7TE.js";import{_ as Ie}from"./ErrorLogModal.vue_vue_type_script_setup_true_lang-BCyNIf1E.js";import"./Select-Bvx32Diz.js";const Ce={class:"text-sm text-muted"},Pe=["title"],Se=O({__name:"ErrorLogsTable",props:{logs:{},loading:{type:Boolean}},emits:["view"],setup(S,{emit:c}){const r=c,f=[{accessorKey:"createdAt",header:"When"},{accessorKey:"workItemIid",header:"Work item"},{accessorKey:"mode",header:"Mode"},{accessorKey:"model",header:"Model"},{accessorKey:"phase",header:"Phase"},{accessorKey:"kind",header:"Kind"},{accessorKey:"message",header:"Message"},{id:"actions"}];return(p,B)=>{const b=ce,_=z,u=we;return v(),q(u,{data:S.logs,columns:f,loading:S.loading},{"createdAt-cell":n(({row:e})=>[l(je,{value:e.original.createdAt,unit:"s"},null,8,["value"])]),"workItemIid-cell":n(({row:e})=>[l(xe,{"work-item-iid":e.original.workItemIid,"work-item-title":e.original.workItemTitle,"project-path":e.original.projectPath,"project-id":e.original.projectId,onOpen:d=>r("view",e.original.id)},null,8,["work-item-iid","work-item-title","project-path","project-id","onOpen"])]),"mode-cell":n(({row:e})=>[l(b,{label:e.original.mode,color:"neutral",variant:"subtle"},null,8,["label"])]),"model-cell":n(({row:e})=>[l(Ve,{model:e.original.model,variant:e.original.variant},null,8,["model","variant"])]),"phase-cell":n(({row:e})=>[l(b,{label:e.original.phase,color:"warning",variant:"subtle"},null,8,["label"])]),"kind-cell":n(({row:e})=>[x("span",Ce,A(e.original.kind),1)]),"message-cell":n(({row:e})=>[x("span",{class:"text-sm text-muted truncate max-w-xs inline-block align-bottom",title:e.original.message},A(e.original.message),9,Pe)]),"actions-cell":n(({row:e})=>[l(_,{label:"View",icon:"i-lucide-scroll-text",color:"neutral",variant:"ghost",size:"xs","aria-label":`View error log ${e.original.id}`,onClick:d=>r("view",e.original.id)},null,8,["aria-label","onClick"])]),_:1},8,["data","loading"])}}}),Ee={class:"space-y-4"},Le={key:0,class:"space-y-3"},Me={class:"space-y-3 py-6"},Ae={class:"text-muted"},Be={key:0,class:"flex justify-center pt-2"},U=15,Qe=O({__name:"ErrorLogsPage",setup(S){const c=s([]),r=s(!0),f=ue(),p=s(365),B=de(),b=me(B),_=ve({start:b.subtract({days:29}),end:b}),u=s(null),e=s(null),d=s(null),h=s(""),j=s({projects:[],models:[],modes:[]}),D=s({}),R=P(()=>[{label:"All projects",value:null},...j.value.projects.map(t=>({label:D.value[String(t)]??`#${t}`,value:t}))]),W=P(()=>[{label:"All models",value:null},...j.value.models.map(t=>({label:t||"—",value:t}))]),G=P(()=>[{label:"All modes",value:null},...j.value.modes.map(t=>({label:t||"—",value:t}))]),Q=P(()=>u.value!==null||e.value!==null||d.value!==null||h.value.trim()!==""||p.value!==365),E=s(!1),K=s(null),i=s(1),k=s(0),g=s(!1),L=s(!1);async function Z(){L.value=!0;const{error:t,status:a}=await F("/api/error-logs",{method:"DELETE"});if(L.value=!1,g.value=!1,t){a!==401&&f.add({title:"Failed to clear error logs",description:t,color:"error",icon:"i-lucide-alert-circle"});return}f.add({title:"Error logs cleared",color:"success",icon:"i-lucide-check-circle"}),i.value=1,await $()}async function $(){r.value=!0;const t=(i.value-1)*U,a=new URLSearchParams($e(p.value,_.value,{projectId:u.value,model:e.value,mode:d.value})),V=h.value.trim();V.length>0&&a.set("q",V),a.set("limit",String(U)),a.set("offset",String(t));const{data:m,error:I,status:y}=await F(`/api/error-logs?${a.toString()}`);if(r.value=!1,I){y!==401&&f.add({title:"Failed to load error logs",description:I,color:"error",icon:"i-lucide-alert-circle"});return}c.value=m?.logs??[],k.value=m?.total??c.value.length,j.value=m?.filterOptions??{projects:[],models:[],modes:[]},D.value=m?.projectPaths??{};const C=Math.max(1,Math.ceil(k.value/U));if(i.value>C){i.value=C;return}}function N(){i.value!==1?i.value=1:$()}T([p,_,u,e,d],N,{deep:!0}),Ue(h,N,{debounce:300}),T(i,()=>{$()});function H(t){K.value=t,E.value=!0}return pe($),(t,a)=>{const V=ne,m=z,I=se,y=he,C=ke,J=re,X=te,Y=fe,ee=ge,ae=ie,le=oe;return v(),w(M,null,[l(le,{id:"errors"},{header:n(()=>[l(I,{title:"Error logs",icon:"i-lucide-shield-alert"},{leading:n(()=>[l(V)]),right:n(()=>[l(m,{label:g.value?"Confirm clear":"Clear",icon:g.value?"i-lucide-check":"i-lucide-trash-2",color:g.value?"error":"neutral",variant:"soft",loading:L.value,disabled:k.value===0,onClick:a[0]||(a[0]=o=>g.value?Z():g.value=!0)},null,8,["label","icon","color","loading","disabled"]),l(m,{label:"Reload",icon:"i-lucide-refresh-cw",color:"neutral",variant:"soft",loading:r.value,onClick:$},null,8,["loading"])]),_:1}),l(J,null,{left:n(()=>[l(ye,{period:p.value,"onUpdate:period":a[1]||(a[1]=o=>p.value=o),range:_.value,"onUpdate:range":a[2]||(a[2]=o=>_.value=o)},null,8,["period","range"]),l(y,{modelValue:u.value,"onUpdate:modelValue":a[3]||(a[3]=o=>u.value=o),items:R.value,"value-key":"value",class:"w-48","aria-label":"Project filter"},null,8,["modelValue","items"]),l(y,{modelValue:e.value,"onUpdate:modelValue":a[4]||(a[4]=o=>e.value=o),items:W.value,"value-key":"value",class:"w-56","aria-label":"Model filter"},null,8,["modelValue","items"]),l(y,{modelValue:d.value,"onUpdate:modelValue":a[5]||(a[5]=o=>d.value=o),items:G.value,"value-key":"value",class:"w-40","aria-label":"Mode filter"},null,8,["modelValue","items"]),l(C,{modelValue:h.value,"onUpdate:modelValue":a[6]||(a[6]=o=>h.value=o),icon:"i-lucide-search",placeholder:"Search work item title","aria-label":"Search work item title",class:"w-64"},null,8,["modelValue"])]),_:1})]),body:n(()=>[x("div",Ee,[r.value&&c.value.length===0?(v(),w("div",Le,[(v(),w(M,null,_e(3,o=>l(X,{key:o,class:"h-10 w-full"})),64))])):c.value.length===0?(v(),q(ee,{key:1,class:"text-center"},{default:n(()=>[x("div",Me,[l(Y,{name:"i-lucide-shield-check",class:"size-10 text-dimmed mx-auto"}),x("p",Ae,A(Q.value?"No error logs match your filters.":"No error logs."),1)])]),_:1})):(v(),w(M,{key:2},[l(Se,{logs:c.value,loading:r.value,onView:H},null,8,["logs","loading"]),k.value>U?(v(),w("div",Be,[l(ae,{page:i.value,"onUpdate:page":a[7]||(a[7]=o=>i.value=o),total:k.value,"items-per-page":U},null,8,["page","total"])])):be("",!0)],64))])]),_:1}),l(Ie,{open:E.value,"onUpdate:open":a[8]||(a[8]=o=>E.value=o),"log-id":K.value},null,8,["open","log-id"])],64)}}});export{Qe as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as v,e as l,c as o,t as c,u as g,r as m,q as x,o as B,a as f,a1 as w,j as d,f as p,x as L,ab as b,m as $,h as T,ai as M,aj as S,w as h,s as U,D as _,i as H}from"./index-C5RBBrPj.js";function N(e,a){return e?a?`${e} (${a})`:e:"—"}const C={class:"text-sm text-muted font-mono"},X=v({__name:"ModelCell",props:{model:{},variant:{}},setup(e){return(a,r)=>(l(),o("span",C,c(g(N)(e.model,e.variant)),1))}}),E={class:"relative"},O={key:0,class:"absolute right-2 top-2 z-10"},V={key:0,class:"text-xs text-muted mb-2","data-testid":"log-phase"},j={key:1,class:"text-sm text-muted py-6 text-center"},D={key:2,class:"text-sm text-muted py-6 text-center"},I={key:3,class:"text-xs whitespace-pre-wrap break-words font-mono text-default"},P={key:4,class:"text-xs text-warning mt-2"},q=8,z=v({__name:"LogViewer",props:{text:{},available:{type:Boolean},truncated:{type:Boolean},live:{type:Boolean,default:!1},phaseLabel:{default:""},unavailableText:{default:""}},setup(e){const a=e,r=L(()=>a.unavailableText||"No logs available. The task has not started a container yet, or has already finished."),n=m(null),s=m(a.live===!0);function u(t){return t.scrollHeight-t.scrollTop-t.clientHeight<=q}function i(){const t=n.value;t&&(t.scrollTop=t.scrollHeight)}function y(){const t=n.value;!t||!a.live||(s.value=u(t))}return x(()=>a.live,t=>{s.value=t===!0,t&&b(i)}),x(()=>a.text,()=>{s.value&&b(i)},{flush:"post"}),B(()=>{a.live&&i()}),(t,R)=>{const k=w;return l(),o("div",E,[e.live?(l(),o("div",O,[f(k,{label:"Live",color:"primary",variant:"subtle",icon:"i-lucide-radio"})])):d("",!0),p("div",{ref_key:"scrollEl",ref:n,"data-testid":"log-scroll",class:"max-h-[60vh] overflow-auto rounded-md bg-elevated border border-default p-3",onScroll:y},[e.available&&e.phaseLabel?(l(),o("p",V," Phase: "+c(e.phaseLabel),1)):d("",!0),e.available?e.text?(l(),o("pre",I,c(e.text),1)):(l(),o("p",D," No output yet"+c(e.phaseLabel?` during “${e.phaseLabel}”`:"")+". ",1)):(l(),o("p",j,c(r.value),1)),e.available&&e.truncated?(l(),o("p",P,"…output truncated.")):d("",!0)],544)])}}}),F={class:"space-y-3"},A=v({__name:"LogSlideover",props:U({title:{},description:{default:""},text:{},available:{type:Boolean},truncated:{type:Boolean},live:{type:Boolean,default:!1},phaseLabel:{default:""},unavailableText:{default:""},workItemUrl:{default:""}},{open:{type:Boolean,default:!1},openModifiers:{}}),emits:["update:open"],setup(e){const a=$(e,"open");return(r,n)=>{const s=H,u=M;return l(),T(u,{open:a.value,"onUpdate:open":n[0]||(n[0]=i=>a.value=i),title:e.title,description:e.description??"",ui:{content:"max-w-4xl",footer:"justify-end"}},S({body:h(()=>[p("div",F,[_(r.$slots,"meta"),f(z,{text:e.text,available:e.available,truncated:e.truncated,live:e.live,"phase-label":e.phaseLabel,"unavailable-text":e.unavailableText},null,8,["text","available","truncated","live","phase-label","unavailable-text"])])]),_:2},[e.workItemUrl?{name:"footer",fn:h(()=>[f(s,{label:"Open in forge",icon:"i-lucide-external-link",color:"neutral",variant:"soft",to:e.workItemUrl,target:"_blank",rel:"noopener"},null,8,["to"])]),key:"0"}:void 0]),1032,["open","title","description"])}}});export{X as _,A as a,N as f};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as I,a as O,b as S,c as R}from"./DashboardSidebarCollapse-rIuzCmVm.js";import{_ as q,a as F}from"./PageGrid-CBROIU87.js";import{d as M,o as z,c as i,a as e,w as s,F as h,r as o,b as P,e as n,f as r,_ as A,u as V,g as j,h as G,i as Q,t as b,j as H}from"./index-C5RBBrPj.js";import{r as J,m as K,a as W}from"./useManagedProjects-8rtjRqVJ.js";import{_ as X,a as Y}from"./RunDetailSlideover.vue_vue_type_script_setup_true_lang-DopYYmCT.js";import{_ as Z}from"./ErrorLogModal.vue_vue_type_script_setup_true_lang-BCyNIf1E.js";import"./index-BMbMibyb.js";import"./usage-format-jsb31_O8.js";import"./WorkItemCell.vue_vue_type_script_setup_true_lang-BQn6vTjd.js";import"./TimeCell.vue_vue_type_script_setup_true_lang-DW_UB0Fu.js";import"./LogSlideover.vue_vue_type_script_setup_true_lang-33xie7TE.js";const ee={class:"space-y-6"},te={class:"flex items-center justify-between"},ae={key:0,class:"space-y-3"},oe={key:1,class:"text-sm text-muted py-2"},se={class:"flex items-center justify-between"},ne={key:0,class:"divide-y divide-default"},le={class:"min-w-0"},ie=["onClick"],re={class:"text-sm text-dimmed truncate"},ce={key:1,class:"text-sm text-muted py-2"},ye=M({__name:"OverviewPage",setup(ue){const u=o({active:0,max:0,waiting:0}),_=o(0),d=o([]),w=o(0),v=o([]),c=o(!0),g=o(!1),k=o(null),f=o(!1),y=o(null);function x(l){k.value=l,g.value=!0}function $(l){y.value=l,f.value=!0}async function C(){c.value=!0;const[l,a]=await Promise.all([P("/api/runs?status=active&limit=5&offset=0"),P("/api/error-logs?limit=5&offset=0")]);_.value=l.data?.total??0,d.value=l.data?.runs??[],u.value=l.data?.quota??{active:0,max:0,waiting:0},w.value=a.data?.total??0,v.value=a.data?.logs??[],c.value=!1}return z(async()=>{await Promise.all([C(),J()])}),(l,a)=>{const N=R,m=Q,B=S,p=A,D=q,E=O,U=F,L=I;return n(),i(h,null,[e(L,{id:"overview"},{header:s(()=>[e(B,{title:"Overview",icon:"i-lucide-layout-dashboard"},{leading:s(()=>[e(N)]),right:s(()=>[e(m,{label:"Refresh",icon:"i-lucide-refresh-cw",color:"neutral",variant:"soft",loading:c.value,onClick:C},null,8,["loading"])]),_:1})]),body:s(()=>[r("div",ee,[e(D,{class:"lg:grid-cols-4 gap-4"},{default:s(()=>[e(p,{title:"Running",icon:"i-lucide-activity",description:`${u.value.active} / ${u.value.max} active · ${u.value.waiting} waiting`,to:"/runs"},null,8,["description"]),e(p,{title:"Queued / total",icon:"i-lucide-list-checks",description:`${_.value} task${_.value===1?"":"s"} in flight`,to:"/runs"},null,8,["description"]),e(p,{title:"Projects",icon:"i-lucide-folder-git-2",description:V(K)?"Loading…":`${V(W).length} onboarded`,to:"/projects"},null,8,["description"]),e(p,{title:"Error logs",icon:"i-lucide-shield-alert",description:`${w.value} retained`,to:"/errors"},null,8,["description"])]),_:1}),e(U,null,{header:s(()=>[r("div",te,[a[2]||(a[2]=r("h2",{class:"text-lg font-semibold text-highlighted"},"Active runs",-1)),e(m,{label:"View all",icon:"i-lucide-arrow-right",color:"neutral",variant:"ghost",to:"/runs"})])]),default:s(()=>[c.value&&d.value.length===0?(n(),i("div",ae,[(n(),i(h,null,j(3,t=>e(E,{key:t,class:"h-10 w-full"})),64))])):d.value.length===0?(n(),i("p",oe,"No running tasks.")):(n(),G(Y,{key:2,runs:d.value,loading:!1,compact:"",onLogs:x,onDetails:x,onStop:()=>{}},null,8,["runs"]))]),_:1}),e(U,null,{header:s(()=>[r("div",se,[a[3]||(a[3]=r("h2",{class:"text-lg font-semibold text-highlighted"},"Recent errors",-1)),e(m,{label:"View all",icon:"i-lucide-arrow-right",color:"neutral",variant:"ghost",to:"/errors"})])]),default:s(()=>[v.value.length>0?(n(),i("ul",ne,[(n(!0),i(h,null,j(v.value,t=>(n(),i("li",{key:t.id,class:"py-2 flex items-start justify-between gap-3"},[r("div",le,[r("button",{type:"button",class:"font-medium text-primary hover:underline text-left bg-transparent border-0 p-0 cursor-pointer",onClick:T=>$(t.id)}," #"+b(t.workItemIid)+" "+b(t.workItemTitle),9,ie),r("p",re,b(t.message),1)]),e(m,{label:"View",icon:"i-lucide-scroll-text",color:"neutral",variant:"ghost",size:"xs","aria-label":`View error log ${t.id}`,onClick:T=>$(t.id)},null,8,["aria-label","onClick"])]))),128))])):c.value?H("",!0):(n(),i("p",ce,"No error logs."))]),_:1})])]),_:1}),e(X,{open:g.value,"onUpdate:open":a[0]||(a[0]=t=>g.value=t),run:k.value},null,8,["open","run"]),e(Z,{open:f.value,"onUpdate:open":a[1]||(a[1]=t=>f.value=t),"log-id":y.value},null,8,["open","log-id"])],64)}}});export{ye as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{R as q,S as g,e as i,h as m,w as y,u as e,c as d,X as r,D as l,l as f,t as v,j as n,P as h,x as b,Z as _,$ as x}from"./index-C5RBBrPj.js";const $={slots:{root:"rounded-lg overflow-hidden",header:"p-4 sm:px-6",title:"text-highlighted font-semibold",description:"mt-1 text-muted text-sm",body:"p-4 sm:p-6",footer:"p-4 sm:px-6"},variants:{variant:{solid:{root:"bg-inverted text-inverted",title:"text-inverted",description:"text-dimmed"},outline:{root:"bg-default ring ring-default divide-y divide-default"},soft:{root:"bg-elevated/50 divide-y divide-default"},subtle:{root:"bg-elevated/50 ring ring-default divide-y divide-default"}}},defaultVariants:{variant:"outline"}},P={__name:"Card",props:{as:{type:null,required:!1},title:{type:String,required:!1},description:{type:String,required:!1},variant:{type:null,required:!1},class:{type:null,required:!1},ui:{type:Object,required:!1}},setup(u){const p=u,s=q(),t=g("card",p),c=x(),a=b(()=>_({extend:$,...c.ui?.card||{}})({variant:t.variant}));return(o,C)=>(i(),m(e(h),{as:e(t).as,"data-slot":"root",class:r(a.value.root({class:[e(t).ui?.root,e(t).class]}))},{default:y(()=>[s.header||e(t).title||s.title||e(t).description||s.description?(i(),d("div",{key:0,"data-slot":"header",class:r(a.value.header({class:e(t).ui?.header}))},[l(o.$slots,"header",{},()=>[e(t).title||s.title?(i(),d("div",{key:0,"data-slot":"title",class:r(a.value.title({class:e(t).ui?.title}))},[l(o.$slots,"title",{},()=>[f(v(e(t).title),1)])],2)):n("",!0),e(t).description||s.description?(i(),d("div",{key:1,"data-slot":"description",class:r(a.value.description({class:e(t).ui?.description}))},[l(o.$slots,"description",{},()=>[f(v(e(t).description),1)])],2)):n("",!0)])],2)):n("",!0),s.default?(i(),d("div",{key:1,"data-slot":"body",class:r(a.value.body({class:e(t).ui?.body}))},[l(o.$slots,"default")],2)):n("",!0),s.footer?(i(),d("div",{key:2,"data-slot":"footer",class:r(a.value.footer({class:e(t).ui?.footer}))},[l(o.$slots,"footer")],2)):n("",!0)]),_:3},8,["as","class"]))}},k={base:"relative grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8"},j={__name:"PageGrid",props:{as:{type:null,required:!1},class:{type:null,required:!1},ui:{type:Object,required:!1}},setup(u){const s=g("pageGrid",u),t=x(),c=b(()=>_({extend:k,...t.ui?.pageGrid||{}}));return(a,o)=>(i(),m(e(h),{as:e(s).as,class:r(c.value({class:[e(s).ui?.base,e(s).class]}))},{default:y(()=>[l(a.$slots,"default")]),_:3},8,["as","class"]))}};export{j as _,P as a};
|