@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,141 @@
|
|
|
1
|
+
// Pure helpers for nested rootless Podman inside the per-work-item builder
|
|
2
|
+
// container (work item #17). Kept free of config/db imports so the flag and
|
|
3
|
+
// storage shapes can be unit-tested without podman, env, or a DB.
|
|
4
|
+
//
|
|
5
|
+
// Security envelope: enabling dev containers broadens the builder container's
|
|
6
|
+
// privileges (nested user namespaces + mount + mknod) versus the default
|
|
7
|
+
// unprivileged launch. It never mounts the host podman socket or host
|
|
8
|
+
// filesystem. The capability set is deliberately minimal and pinned by the host
|
|
9
|
+
// smoke test in docs/dev-containers.md; --privileged is a documented last
|
|
10
|
+
// resort, never a default.
|
|
11
|
+
import { accessSync, constants } from "node:fs";
|
|
12
|
+
// Dev containers are build-mode only and globally gated. Plan mode is read-only
|
|
13
|
+
// and never gets a container runtime. Pure: the caller passes the resolved
|
|
14
|
+
// runtime flag so this module stays config-free.
|
|
15
|
+
export function devcontainerEnabled(enabled, mode) {
|
|
16
|
+
return enabled && mode === "build";
|
|
17
|
+
}
|
|
18
|
+
// Probe for the FUSE device. Used only when the configured driver is "auto".
|
|
19
|
+
// A missing /dev/fuse is not an error — it just selects the portable vfs driver.
|
|
20
|
+
export function hasFuseDevice(path = "/dev/fuse") {
|
|
21
|
+
try {
|
|
22
|
+
accessSync(path, constants.R_OK | constants.W_OK);
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Inner rootless store lives on the dedicated per-work-item podman volume
|
|
30
|
+
// (mounted at /home/devbot/.local/share/containers). Never under /workspace, so
|
|
31
|
+
// container artifacts cannot leak into the git diff. graphroot/runroot are
|
|
32
|
+
// separate subdirs so a runroot cleanup can never touch the image store.
|
|
33
|
+
export const PODMAN_STORE_DIR = "/home/devbot/.local/share/containers";
|
|
34
|
+
// Resolve the effective storage driver. "auto" probes for /dev/fuse at startup:
|
|
35
|
+
// fuse-overlayfs when present (layered, disk-efficient), else vfs (portable but
|
|
36
|
+
// full-copy). An explicit choice is honored as-is.
|
|
37
|
+
export function resolveStorageDriver(configured, hasFuse) {
|
|
38
|
+
if (configured === "auto")
|
|
39
|
+
return hasFuse ? "fuse-overlayfs" : "vfs";
|
|
40
|
+
return configured;
|
|
41
|
+
}
|
|
42
|
+
// Base `podman run` args every mode needs. The sandbox shell runs commands as
|
|
43
|
+
// the unprivileged `agent` UID (uid 1001), so the container process needs
|
|
44
|
+
// CAP_SETUID/CAP_SETGID for `setpriv` to drop to it. Nested-podman build runs add
|
|
45
|
+
// the rest (SYS_ADMIN/MKNOD/SYS_CHROOT) via nestedPodmanArgs; the duplicate
|
|
46
|
+
// SETUID/SETGID there is harmless. The agent UID itself never keeps
|
|
47
|
+
// DAC_OVERRIDE, so /home/devbot/.xdg stays readable only by opencode.
|
|
48
|
+
export function sandboxBaseArgs() {
|
|
49
|
+
return ["--cap-add", "SETUID", "--cap-add", "SETGID"];
|
|
50
|
+
}
|
|
51
|
+
// Extra `podman run` args appended to the outer builder launch when dev
|
|
52
|
+
// containers are enabled for a build-mode run. Ordering is not load-bearing but
|
|
53
|
+
// the exact membership is tested. --device /dev/fuse is added only for
|
|
54
|
+
// fuse-overlayfs.
|
|
55
|
+
export function nestedPodmanArgs(driver) {
|
|
56
|
+
const args = [
|
|
57
|
+
// Predictable host↔container uid mapping; the inner subuid range (1001:64535
|
|
58
|
+
// in the image) is derived from this mapping.
|
|
59
|
+
"--userns=keep-id",
|
|
60
|
+
// No systemd inside the builder; the inner runtime uses cgroupfs and shares
|
|
61
|
+
// the outer cgroup namespace.
|
|
62
|
+
"--cgroupns=host",
|
|
63
|
+
// The nested store manages its own SELinux labels.
|
|
64
|
+
"--security-opt", "label=disable",
|
|
65
|
+
// The default seccomp profile blocks the clone/unshare flags crun needs.
|
|
66
|
+
"--security-opt", "seccomp=unconfined",
|
|
67
|
+
// The inner crun must write /proc/sys/net/ipv4/ping_group_range when it
|
|
68
|
+
// builds the container's new network namespace; the outer run mounts /proc
|
|
69
|
+
// read-only by default, so a path-scoped unmask is not enough (it still
|
|
70
|
+
// reports "Read-only file system"). unmask=ALL remounts /proc writable —
|
|
71
|
+
// far less than --privileged, and pinned by the host smoke test.
|
|
72
|
+
"--security-opt", "unmask=ALL",
|
|
73
|
+
// Minimal escalation: create nested namespaces, map uid/gid, mknod, chroot.
|
|
74
|
+
"--cap-add", "SYS_ADMIN",
|
|
75
|
+
"--cap-add", "SETUID",
|
|
76
|
+
"--cap-add", "SETGID",
|
|
77
|
+
"--cap-add", "MKNOD",
|
|
78
|
+
"--cap-add", "SYS_CHROOT",
|
|
79
|
+
// pasta (the rootless network backend passt ships) opens /dev/net/tun to
|
|
80
|
+
// build the container tap device. The default rootless launch does not pass
|
|
81
|
+
// it, so inner networking fails with "Failed to open() /dev/net/tun".
|
|
82
|
+
"--device", "/dev/net/tun",
|
|
83
|
+
];
|
|
84
|
+
if (driver === "fuse-overlayfs") {
|
|
85
|
+
args.push("--device", "/dev/fuse");
|
|
86
|
+
}
|
|
87
|
+
return args;
|
|
88
|
+
}
|
|
89
|
+
// Inner containers/storage.conf written into the podman volume's storage
|
|
90
|
+
// directory. Podman's valid drivers are overlay/vfs/...; fuse-overlayfs is a
|
|
91
|
+
// mount_program under [storage.options.overlay], so selecting fuse-overlayfs
|
|
92
|
+
// means driver=overlay + mount_program=fuse-overlayfs.
|
|
93
|
+
export function storageConf(driver) {
|
|
94
|
+
const lines = [
|
|
95
|
+
"[storage]",
|
|
96
|
+
driver === "fuse-overlayfs" ? `driver = "overlay"` : `driver = "vfs"`,
|
|
97
|
+
`graphroot = "${PODMAN_STORE_DIR}/storage"`,
|
|
98
|
+
`runroot = "${PODMAN_STORE_DIR}/runroot"`,
|
|
99
|
+
];
|
|
100
|
+
if (driver === "fuse-overlayfs") {
|
|
101
|
+
lines.push("", "[storage.options.overlay]", `mount_program = "/usr/bin/fuse-overlayfs"`);
|
|
102
|
+
}
|
|
103
|
+
lines.push("");
|
|
104
|
+
return lines.join("\n");
|
|
105
|
+
}
|
|
106
|
+
// The `-v <volume>:<store>:Z` mount for the private inner runtime store. It is
|
|
107
|
+
// deliberately NOT /workspace, so artifacts can never enter the git diff.
|
|
108
|
+
export function devcontainerVolumeArgs(podmanVolume) {
|
|
109
|
+
return ["-v", `${podmanVolume}:${PODMAN_STORE_DIR}:Z`];
|
|
110
|
+
}
|
|
111
|
+
// Point the inner podman at the storage.conf written into the podman volume
|
|
112
|
+
// (CONTAINERS_STORAGE_CONF). Without this, rootless podman would look in
|
|
113
|
+
// $XDG_CONFIG_HOME/containers (now the out-of-tree xdg volume — still worth
|
|
114
|
+
// overriding so the inner runtime's config never mixes with opencode's). The
|
|
115
|
+
// referenced file is created by ensurePodmanStore.
|
|
116
|
+
export function devcontainerEnvArgs() {
|
|
117
|
+
return [
|
|
118
|
+
"--env", `CONTAINERS_STORAGE_CONF=${PODMAN_STORE_DIR}/storage.conf`,
|
|
119
|
+
// Tells docker/devbot-shell to route container-runtime commands through the
|
|
120
|
+
// non-bwrap, cap-preserving path (nested rootless podman cannot run under
|
|
121
|
+
// bwrap's PR_SET_NO_NEW_PRIVS). Set by the runner, never the agent.
|
|
122
|
+
"--env", "DEVBOT_NESTED_PODMAN=1",
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
// Prompt block appended to build-mode runs when dev containers are enabled.
|
|
126
|
+
// Tells the agent the capability exists, that its runtime is private to the
|
|
127
|
+
// work item, and that the store lives outside /workspace so it can never be
|
|
128
|
+
// committed.
|
|
129
|
+
export function devcontainerPromptSection() {
|
|
130
|
+
return [
|
|
131
|
+
"## Local container runtime (Podman)",
|
|
132
|
+
"",
|
|
133
|
+
"`podman` is available inside this container for integration tests. Its runtime is **private to this work item**: containers, images, and networks you create here are invisible to every other task, and no other task can affect yours.",
|
|
134
|
+
"",
|
|
135
|
+
"- Build and run the project's own images, or pull service images (postgres, redis, etc.), then `podman network create` a private network so containers resolve each other by name.",
|
|
136
|
+
"- Prefer a repo `compose.yaml`/`docker-compose.yml` via `podman compose` when one exists; otherwise use raw `podman`.",
|
|
137
|
+
"- The container store lives in a separate volume outside `/workspace`, so container artifacts are never part of the git diff and must not be committed.",
|
|
138
|
+
"- Stop long-running containers when you're done (`podman rm -f <name>`); they are reaped when this run exits.",
|
|
139
|
+
].join("\n");
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=devcontainer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devcontainer.js","sourceRoot":"","sources":["../src/devcontainer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { db } from "./db.js";
|
|
2
|
+
import { log } from "./logger.js";
|
|
3
|
+
import { encrypt, decryptOrPlaintext } from "./crypto-util.js";
|
|
4
|
+
import { EnvVarSchema, } from "./types/env-config.js";
|
|
5
|
+
// Per-project environment variables. Same DB file as project_tokens and
|
|
6
|
+
// project_mcp_servers (devbot.db, 0600). Keyed by (project_id, name); the
|
|
7
|
+
// value is encrypted at rest via crypto-util.ts (AES-256-GCM, SESSION_KEY).
|
|
8
|
+
// The runner is the trust boundary for what the container actually receives
|
|
9
|
+
// — values are re-validated on read; a corrupt row is skipped (logged at
|
|
10
|
+
// warn), never crashes a run.
|
|
11
|
+
export function initEnvVarsTables() {
|
|
12
|
+
db.exec(`
|
|
13
|
+
CREATE TABLE IF NOT EXISTS project_env_vars (
|
|
14
|
+
project_id INTEGER NOT NULL,
|
|
15
|
+
name TEXT NOT NULL,
|
|
16
|
+
value TEXT NOT NULL,
|
|
17
|
+
enabled INTEGER NOT NULL,
|
|
18
|
+
created_at INTEGER NOT NULL,
|
|
19
|
+
updated_at INTEGER NOT NULL,
|
|
20
|
+
PRIMARY KEY (project_id, name)
|
|
21
|
+
)
|
|
22
|
+
`);
|
|
23
|
+
}
|
|
24
|
+
function rowToEnvVar(projectId, row) {
|
|
25
|
+
let plaintext;
|
|
26
|
+
try {
|
|
27
|
+
plaintext = decryptOrPlaintext(row.value);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
log.warn("env var row decrypt failed, skipping", { projectId, name: row.name });
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const v = EnvVarSchema.safeParse({
|
|
34
|
+
name: row.name,
|
|
35
|
+
value: plaintext,
|
|
36
|
+
enabled: row.enabled === 1,
|
|
37
|
+
});
|
|
38
|
+
if (!v.success) {
|
|
39
|
+
log.warn("env var row failed schema, skipping", { projectId, name: row.name });
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return v.data;
|
|
43
|
+
}
|
|
44
|
+
export function listEnvVars(projectId) {
|
|
45
|
+
const rows = db
|
|
46
|
+
.prepare("SELECT name, value, enabled FROM project_env_vars WHERE project_id = ? ORDER BY name")
|
|
47
|
+
.all(projectId);
|
|
48
|
+
const out = [];
|
|
49
|
+
for (const r of rows) {
|
|
50
|
+
const v = rowToEnvVar(projectId, r);
|
|
51
|
+
if (v)
|
|
52
|
+
out.push(v);
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
// Stripped shape for the browser — never exposes the value.
|
|
57
|
+
export function listEnvVarSummaries(projectId) {
|
|
58
|
+
const rows = db
|
|
59
|
+
.prepare("SELECT name, value, enabled FROM project_env_vars WHERE project_id = ? ORDER BY name")
|
|
60
|
+
.all(projectId);
|
|
61
|
+
const out = [];
|
|
62
|
+
for (const r of rows) {
|
|
63
|
+
// Re-validate the name (value decrypt is cheap; skip to keep summary fast).
|
|
64
|
+
const plaintext = decryptOrPlaintext(r.value);
|
|
65
|
+
const v = EnvVarSchema.safeParse({
|
|
66
|
+
name: r.name,
|
|
67
|
+
value: plaintext,
|
|
68
|
+
enabled: r.enabled === 1,
|
|
69
|
+
});
|
|
70
|
+
if (!v.success) {
|
|
71
|
+
log.warn("env var row failed schema, skipping", { projectId, name: r.name });
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
out.push({ name: v.data.name, enabled: v.data.enabled, hasValue: true });
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
// Upsert a var. If value is empty and a row already exists, keep the existing
|
|
79
|
+
// encrypted value (the "leave unchanged" semantics from the panel edit flow).
|
|
80
|
+
export function upsertEnvVar(projectId, name, value, enabled) {
|
|
81
|
+
const now = Math.floor(Date.now() / 1000);
|
|
82
|
+
if (value === "") {
|
|
83
|
+
// Keep existing value, only update enabled + updated_at.
|
|
84
|
+
const existing = db
|
|
85
|
+
.prepare("SELECT value FROM project_env_vars WHERE project_id = ? AND name = ?")
|
|
86
|
+
.get(projectId, name);
|
|
87
|
+
if (existing) {
|
|
88
|
+
db.prepare(`INSERT OR REPLACE INTO project_env_vars
|
|
89
|
+
(project_id, name, value, enabled, created_at, updated_at)
|
|
90
|
+
VALUES (?, ?, ?, ?,
|
|
91
|
+
COALESCE((SELECT created_at FROM project_env_vars WHERE project_id = ? AND name = ?), ?),
|
|
92
|
+
?)`).run(projectId, name, existing.value, enabled ? 1 : 0, projectId, name, now, now);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// No existing row + empty value → store empty string (hasValue will be false
|
|
96
|
+
// after a re-read since empty value validates fine but is meaningless).
|
|
97
|
+
// We allow it so the admin can create a placeholder and fill the value
|
|
98
|
+
// later via another PUT.
|
|
99
|
+
}
|
|
100
|
+
const v = EnvVarSchema.safeParse({ name, value, enabled });
|
|
101
|
+
if (!v.success) {
|
|
102
|
+
throw new Error("invalid env var");
|
|
103
|
+
}
|
|
104
|
+
db.prepare(`INSERT OR REPLACE INTO project_env_vars
|
|
105
|
+
(project_id, name, value, enabled, created_at, updated_at)
|
|
106
|
+
VALUES (?, ?, ?, ?, COALESCE((SELECT created_at FROM project_env_vars WHERE project_id = ? AND name = ?), ?), ?)`).run(projectId, name, encrypt(v.data.value), v.data.enabled ? 1 : 0, projectId, name, now, now);
|
|
107
|
+
}
|
|
108
|
+
export function deleteEnvVar(projectId, name) {
|
|
109
|
+
const r = db
|
|
110
|
+
.prepare("DELETE FROM project_env_vars WHERE project_id = ? AND name = ?")
|
|
111
|
+
.run(projectId, name);
|
|
112
|
+
return r.changes > 0;
|
|
113
|
+
}
|
|
114
|
+
export function deleteAllEnvVars(projectId) {
|
|
115
|
+
db.prepare("DELETE FROM project_env_vars WHERE project_id = ?").run(projectId);
|
|
116
|
+
}
|
|
117
|
+
// Build the array of enabled env vars the runner injects into container runs.
|
|
118
|
+
// Decrypts + validates each row; disabled or corrupt rows are skipped (never
|
|
119
|
+
// crash a run over one hand-edited DB row).
|
|
120
|
+
export function buildEnvArray(projectId) {
|
|
121
|
+
const rows = db
|
|
122
|
+
.prepare("SELECT name, value, enabled FROM project_env_vars WHERE project_id = ? AND enabled = 1 ORDER BY name")
|
|
123
|
+
.all(projectId);
|
|
124
|
+
const out = [];
|
|
125
|
+
for (const r of rows) {
|
|
126
|
+
const v = rowToEnvVar(projectId, r);
|
|
127
|
+
if (v && v.enabled)
|
|
128
|
+
out.push({ name: v.name, value: v.value });
|
|
129
|
+
}
|
|
130
|
+
return out;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=env-config-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-config-store.js","sourceRoot":"","sources":["../src/env-config-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { db } from "./db.js";
|
|
2
|
+
import { log } from "./logger.js";
|
|
3
|
+
// Persisted record of final run failures across all phases. One row per final
|
|
4
|
+
// failure (retries collapse to the last attempt — the caller records once on a
|
|
5
|
+
// terminal/transient-exhausted return). Retention is age-based: purged at
|
|
6
|
+
// startup and by a daily sweep for ERROR_LOG_RETENTION_DAYS (see lifecycle.ts).
|
|
7
|
+
// Log bodies are redacted by callers and additionally capped here so a runaway
|
|
8
|
+
// container can't bloat the DB. Same DB file as the other stores (devbot.db).
|
|
9
|
+
// Max stored body, in chars. Matches the live-log cap; anything larger is
|
|
10
|
+
// truncated and flagged so the UI can say so.
|
|
11
|
+
export const ERROR_LOG_MAX_CHARS = 200_000;
|
|
12
|
+
export function initErrorLogTables() {
|
|
13
|
+
// Belt-and-braces: migrations 0007/0010/0011/0025 are authoritative; keep the
|
|
14
|
+
// idempotent CREATE so a test DB opened without migrate() still works.
|
|
15
|
+
db.exec(`
|
|
16
|
+
CREATE TABLE IF NOT EXISTS container_error_logs (
|
|
17
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
18
|
+
task_seq INTEGER,
|
|
19
|
+
work_item_id INTEGER NOT NULL,
|
|
20
|
+
work_item_iid INTEGER NOT NULL,
|
|
21
|
+
project_id INTEGER NOT NULL,
|
|
22
|
+
mode TEXT NOT NULL,
|
|
23
|
+
phase TEXT NOT NULL,
|
|
24
|
+
kind TEXT NOT NULL,
|
|
25
|
+
exit_code INTEGER,
|
|
26
|
+
message TEXT NOT NULL,
|
|
27
|
+
logs TEXT NOT NULL DEFAULT '',
|
|
28
|
+
truncated INTEGER NOT NULL DEFAULT 0,
|
|
29
|
+
created_at INTEGER NOT NULL,
|
|
30
|
+
model TEXT NOT NULL DEFAULT '',
|
|
31
|
+
variant TEXT NOT NULL DEFAULT '',
|
|
32
|
+
work_item_title TEXT NOT NULL DEFAULT '',
|
|
33
|
+
log_file TEXT NOT NULL DEFAULT '',
|
|
34
|
+
run_history_id INTEGER
|
|
35
|
+
)
|
|
36
|
+
`);
|
|
37
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_container_error_logs_created ON container_error_logs(created_at)");
|
|
38
|
+
// A pre-0010 DB lacks model/variant. ADD COLUMN errors if present.
|
|
39
|
+
try {
|
|
40
|
+
db.exec("ALTER TABLE container_error_logs ADD COLUMN model TEXT NOT NULL DEFAULT ''");
|
|
41
|
+
}
|
|
42
|
+
catch { /* exists */ }
|
|
43
|
+
try {
|
|
44
|
+
db.exec("ALTER TABLE container_error_logs ADD COLUMN variant TEXT NOT NULL DEFAULT ''");
|
|
45
|
+
}
|
|
46
|
+
catch { /* exists */ }
|
|
47
|
+
// A pre-0011 DB lacks work_item_title. ADD COLUMN errors if present.
|
|
48
|
+
try {
|
|
49
|
+
db.exec("ALTER TABLE container_error_logs ADD COLUMN work_item_title TEXT NOT NULL DEFAULT ''");
|
|
50
|
+
}
|
|
51
|
+
catch { /* exists */ }
|
|
52
|
+
// A pre-0025 DB lacks the run-log file reference. ADD COLUMN errors if present.
|
|
53
|
+
try {
|
|
54
|
+
db.exec("ALTER TABLE container_error_logs ADD COLUMN log_file TEXT NOT NULL DEFAULT ''");
|
|
55
|
+
}
|
|
56
|
+
catch { /* exists */ }
|
|
57
|
+
try {
|
|
58
|
+
db.exec("ALTER TABLE container_error_logs ADD COLUMN run_history_id INTEGER");
|
|
59
|
+
}
|
|
60
|
+
catch { /* exists */ }
|
|
61
|
+
}
|
|
62
|
+
function escLike(term) {
|
|
63
|
+
return term.replace(/[\\%_]/g, (ch) => `\\${ch}`);
|
|
64
|
+
}
|
|
65
|
+
function buildErrorWhere(filter) {
|
|
66
|
+
if (!filter)
|
|
67
|
+
return { sql: "", params: [] };
|
|
68
|
+
const clauses = [];
|
|
69
|
+
const params = [];
|
|
70
|
+
if (filter.projectId !== undefined) {
|
|
71
|
+
clauses.push("project_id = ?");
|
|
72
|
+
params.push(filter.projectId);
|
|
73
|
+
}
|
|
74
|
+
if (filter.model !== undefined) {
|
|
75
|
+
clauses.push("model = ?");
|
|
76
|
+
params.push(filter.model);
|
|
77
|
+
}
|
|
78
|
+
if (filter.mode !== undefined) {
|
|
79
|
+
clauses.push("mode = ?");
|
|
80
|
+
params.push(filter.mode);
|
|
81
|
+
}
|
|
82
|
+
if (filter.title !== undefined) {
|
|
83
|
+
clauses.push("work_item_title LIKE ? ESCAPE '\\'");
|
|
84
|
+
params.push(`%${escLike(filter.title)}%`);
|
|
85
|
+
}
|
|
86
|
+
if (filter.sinceSec !== undefined) {
|
|
87
|
+
clauses.push("created_at >= ?");
|
|
88
|
+
params.push(filter.sinceSec);
|
|
89
|
+
}
|
|
90
|
+
if (filter.untilSec !== undefined) {
|
|
91
|
+
clauses.push("created_at < ?");
|
|
92
|
+
params.push(filter.untilSec);
|
|
93
|
+
}
|
|
94
|
+
return { sql: clauses.length > 0 ? ` WHERE ${clauses.join(" AND ")}` : "", params };
|
|
95
|
+
}
|
|
96
|
+
function capLogs(logs) {
|
|
97
|
+
if (logs.length <= ERROR_LOG_MAX_CHARS)
|
|
98
|
+
return { logs, truncated: false };
|
|
99
|
+
return { logs: logs.slice(0, ERROR_LOG_MAX_CHARS) + "\n…[truncated]", truncated: true };
|
|
100
|
+
}
|
|
101
|
+
export function recordErrorLog(input) {
|
|
102
|
+
const capped = capLogs(input.logs);
|
|
103
|
+
const truncated = input.truncated || capped.truncated;
|
|
104
|
+
const now = Math.floor(Date.now() / 1000);
|
|
105
|
+
const r = db
|
|
106
|
+
.prepare(`INSERT INTO container_error_logs
|
|
107
|
+
(task_seq, work_item_id, work_item_iid, project_id, mode, phase, kind, exit_code, message, logs, truncated, created_at, model, variant, work_item_title, log_file, run_history_id)
|
|
108
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
109
|
+
.run(input.taskSeq, input.workItemId, input.workItemNumber, input.projectId, input.mode, input.phase, input.kind, input.exitCode, input.message, capped.logs, truncated ? 1 : 0, now, input.model ?? "", input.variant ?? "", input.workItemTitle ?? "", input.logFile ?? "", input.runHistoryId ?? null);
|
|
110
|
+
return Number(r.lastInsertRowid);
|
|
111
|
+
}
|
|
112
|
+
function toSummary(r) {
|
|
113
|
+
return {
|
|
114
|
+
id: r.id,
|
|
115
|
+
taskSeq: r.task_seq,
|
|
116
|
+
workItemId: r.work_item_id,
|
|
117
|
+
workItemIid: r.work_item_iid,
|
|
118
|
+
projectId: r.project_id,
|
|
119
|
+
mode: r.mode,
|
|
120
|
+
phase: r.phase,
|
|
121
|
+
kind: r.kind,
|
|
122
|
+
exitCode: r.exit_code,
|
|
123
|
+
message: r.message,
|
|
124
|
+
truncated: r.truncated === 1,
|
|
125
|
+
createdAt: r.created_at,
|
|
126
|
+
model: r.model,
|
|
127
|
+
variant: r.variant,
|
|
128
|
+
workItemTitle: r.work_item_title,
|
|
129
|
+
logFile: r.log_file,
|
|
130
|
+
runHistoryId: r.run_history_id,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
// Newest first. Omits `logs` so the list payload stays small. Optional
|
|
134
|
+
// limit/offset for the WebUI pager, plus optional server-side filters.
|
|
135
|
+
export function listErrorLogs(limit, offset, filter) {
|
|
136
|
+
const { sql: where, params } = buildErrorWhere(filter);
|
|
137
|
+
const sql = `SELECT id, task_seq, work_item_id, work_item_iid, project_id, mode, phase, kind, exit_code, message, truncated, created_at, model, variant, work_item_title, log_file, run_history_id
|
|
138
|
+
FROM container_error_logs${where} ORDER BY id DESC` +
|
|
139
|
+
(limit === undefined ? "" : " LIMIT ? OFFSET ?");
|
|
140
|
+
const args = limit === undefined ? params : [...params, limit, offset ?? 0];
|
|
141
|
+
const rows = db.prepare(sql).all(...args);
|
|
142
|
+
return rows.map(toSummary);
|
|
143
|
+
}
|
|
144
|
+
export function countErrorLogs(filter) {
|
|
145
|
+
const { sql: where, params } = buildErrorWhere(filter);
|
|
146
|
+
const row = db.prepare(`SELECT COUNT(*) AS c FROM container_error_logs${where}`).get(...params);
|
|
147
|
+
return row.c;
|
|
148
|
+
}
|
|
149
|
+
// Distinct filter values across all rows, ignoring any active filter, so a
|
|
150
|
+
// selected value can always be cleared again.
|
|
151
|
+
export function listErrorLogFilterOptions() {
|
|
152
|
+
const rows = db
|
|
153
|
+
.prepare("SELECT DISTINCT project_id, model, mode FROM container_error_logs")
|
|
154
|
+
.all();
|
|
155
|
+
const projects = new Set();
|
|
156
|
+
const models = new Set();
|
|
157
|
+
const modes = new Set();
|
|
158
|
+
for (const r of rows) {
|
|
159
|
+
projects.add(r.project_id);
|
|
160
|
+
models.add(r.model);
|
|
161
|
+
modes.add(r.mode);
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
projects: [...projects].sort((a, b) => a - b),
|
|
165
|
+
models: [...models].sort(),
|
|
166
|
+
modes: [...modes].sort(),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
export function getErrorLog(id) {
|
|
170
|
+
const row = db
|
|
171
|
+
.prepare(`SELECT id, task_seq, work_item_id, work_item_iid, project_id, mode, phase, kind, exit_code, message, truncated, created_at, model, variant, work_item_title, log_file, run_history_id, logs
|
|
172
|
+
FROM container_error_logs WHERE id = ?`)
|
|
173
|
+
.get(id);
|
|
174
|
+
if (!row)
|
|
175
|
+
return null;
|
|
176
|
+
return { ...toSummary(row), logs: row.logs };
|
|
177
|
+
}
|
|
178
|
+
// Delete every error log. Returns the number of rows removed. Manual "Clear"
|
|
179
|
+
// from the WebUI; the age-based retention purge is separate.
|
|
180
|
+
export function clearErrorLogs() {
|
|
181
|
+
const r = db.prepare("DELETE FROM container_error_logs").run();
|
|
182
|
+
if (r.changes > 0)
|
|
183
|
+
log.info("error logs cleared", { cleared: r.changes });
|
|
184
|
+
return Number(r.changes);
|
|
185
|
+
}
|
|
186
|
+
export function purgeErrorLogsOlderThan(days) {
|
|
187
|
+
const cutoff = Math.floor(Date.now() / 1000) - days * 24 * 3600;
|
|
188
|
+
const r = db.prepare("DELETE FROM container_error_logs WHERE created_at < ?").run(cutoff);
|
|
189
|
+
if (r.changes > 0)
|
|
190
|
+
log.debug("error log purge", { purged: r.changes, days });
|
|
191
|
+
return Number(r.changes);
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=error-log-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-log-store.js","sourceRoot":"","sources":["../src/error-log-store.ts"],"names":[],"mappings":"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"}
|