@wascartech/devbot 0.0.0-stage → 2.1.1
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 +150 -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 +438 -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 +158 -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,251 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// ---- Webhook payloads -------------------------------------------------------
|
|
3
|
+
const projectSchema = z.object({
|
|
4
|
+
id: z.number().int(),
|
|
5
|
+
path_with_namespace: z.string(),
|
|
6
|
+
git_http_url: z.string().url().refine((u) => /^https?:\/\//i.test(u), "must be http(s)"),
|
|
7
|
+
default_branch: z.string().nullable(),
|
|
8
|
+
web_url: z.string(),
|
|
9
|
+
});
|
|
10
|
+
const userSchema = z.object({
|
|
11
|
+
id: z.number().int(),
|
|
12
|
+
username: z.string(),
|
|
13
|
+
name: z.string(),
|
|
14
|
+
});
|
|
15
|
+
// Work item reference embedded in Note Hook payloads. The JSON key is `issue`
|
|
16
|
+
// (GitLab's wire name — Note Hook only fires for issue-type work items among
|
|
17
|
+
// the work item family; non-issue work item comments do not arrive via Note
|
|
18
|
+
// Hook). We keep the field name `issue` to match the wire; the TS type is
|
|
19
|
+
// named WorkItemRef.
|
|
20
|
+
export const workItemRefSchema = z.object({
|
|
21
|
+
id: z.number().int(),
|
|
22
|
+
iid: z.number().int(),
|
|
23
|
+
title: z.string(),
|
|
24
|
+
// GitLab sends `null` (not "") for a work item created without a
|
|
25
|
+
// description — the REST API does the same. Typed nullable here and
|
|
26
|
+
// normalized to "" by the ingress, matching the GitHub/Gitea adapters.
|
|
27
|
+
description: z.string().nullish(),
|
|
28
|
+
url: z.string().url(),
|
|
29
|
+
});
|
|
30
|
+
// Note Hook: comment on a work item. GitLab's noteable_type is "Issue" for
|
|
31
|
+
// issue-type work items (the only work item type that triggers Note Hook).
|
|
32
|
+
// ponytail: noteable_type literal "Issue" is GitLab's wire value, not our
|
|
33
|
+
// concept. Note Hook does not fire for non-issue work item types (task,
|
|
34
|
+
// epic, etc.); their comments would arrive through different event shapes
|
|
35
|
+
// GitLab does not currently emit. Revisit when GitLab extends Note Hook.
|
|
36
|
+
export const NoteHookPayloadSchema = z.object({
|
|
37
|
+
object_kind: z.literal("note"),
|
|
38
|
+
event_type: z.literal("note"),
|
|
39
|
+
user: userSchema,
|
|
40
|
+
project: projectSchema,
|
|
41
|
+
object_attributes: z.object({
|
|
42
|
+
id: z.number().int(),
|
|
43
|
+
note: z.string(),
|
|
44
|
+
noteable_type: z.literal("Issue"),
|
|
45
|
+
author_id: z.number().int(),
|
|
46
|
+
action: z.enum(["create", "update"]),
|
|
47
|
+
url: z.string(),
|
|
48
|
+
}),
|
|
49
|
+
issue: workItemRefSchema,
|
|
50
|
+
});
|
|
51
|
+
// Work Item Hook: work item created/opened. object_kind is "issue" for issues,
|
|
52
|
+
// "work_item" for all other work item types (task, test_case, epic, ...).
|
|
53
|
+
// object_attributes.type carries the work item type ("Issue", "Task", ...).
|
|
54
|
+
export const WorkItemHookPayloadSchema = z.object({
|
|
55
|
+
object_kind: z.literal("issue").or(z.literal("work_item")),
|
|
56
|
+
event_type: z.literal("issue").or(z.literal("work_item")),
|
|
57
|
+
user: userSchema,
|
|
58
|
+
project: projectSchema,
|
|
59
|
+
object_attributes: z.object({
|
|
60
|
+
id: z.number().int(),
|
|
61
|
+
iid: z.number().int(),
|
|
62
|
+
title: z.string(),
|
|
63
|
+
// Same wire quirk as workItemRefSchema: `null` for an empty description.
|
|
64
|
+
description: z.string().nullish(),
|
|
65
|
+
action: z.enum(["open", "close", "reopen", "update"]),
|
|
66
|
+
url: z.string().url(),
|
|
67
|
+
type: z.string().optional(),
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
70
|
+
// Pipeline Hook: a CI pipeline changes status. Only a terminal `failed` status
|
|
71
|
+
// is interesting to DevBot. `merge_request` is present when the pipeline ran
|
|
72
|
+
// for an MR (not every pipeline does); its source_branch lets the handler match
|
|
73
|
+
// the DevBot-created MR registry without a branch-name convention.
|
|
74
|
+
export const PipelineHookPayloadSchema = z.object({
|
|
75
|
+
object_kind: z.literal("pipeline"),
|
|
76
|
+
user: userSchema.optional(),
|
|
77
|
+
project: projectSchema,
|
|
78
|
+
object_attributes: z.object({
|
|
79
|
+
id: z.number().int(),
|
|
80
|
+
status: z.string(),
|
|
81
|
+
ref: z.string(),
|
|
82
|
+
sha: z.string().optional(),
|
|
83
|
+
}),
|
|
84
|
+
merge_request: z
|
|
85
|
+
.object({
|
|
86
|
+
iid: z.number().int(),
|
|
87
|
+
source_branch: z.string(),
|
|
88
|
+
})
|
|
89
|
+
.optional(),
|
|
90
|
+
});
|
|
91
|
+
// ---- GitLab REST API responses ---------------------------------------------
|
|
92
|
+
export const NoteSchema = z.object({
|
|
93
|
+
id: z.number().int(),
|
|
94
|
+
body: z.string(),
|
|
95
|
+
});
|
|
96
|
+
// Issue note as returned by GET /projects/:id/issues/:iid/notes. Richer than
|
|
97
|
+
// the NoteSchema above (which is the minimal shape for POST's return value):
|
|
98
|
+
// the list response carries author + system + created_at. Fields optional
|
|
99
|
+
// defensively — GitLab has historically omitted fields in some contexts; the
|
|
100
|
+
// bot's logic needs only id, body, author.id.
|
|
101
|
+
export const IssueNoteSchema = z.object({
|
|
102
|
+
id: z.number().int(),
|
|
103
|
+
body: z.string(),
|
|
104
|
+
system: z.boolean().optional(),
|
|
105
|
+
author: z
|
|
106
|
+
.object({
|
|
107
|
+
id: z.number().int(),
|
|
108
|
+
username: z.string(),
|
|
109
|
+
name: z.string(),
|
|
110
|
+
})
|
|
111
|
+
.optional(),
|
|
112
|
+
created_at: z.string().optional(),
|
|
113
|
+
});
|
|
114
|
+
export const MergeRequestSchema = z.object({
|
|
115
|
+
id: z.number().int(),
|
|
116
|
+
iid: z.number().int(),
|
|
117
|
+
source_branch: z.string(),
|
|
118
|
+
target_branch: z.string(),
|
|
119
|
+
state: z.string(),
|
|
120
|
+
web_url: z.string(),
|
|
121
|
+
});
|
|
122
|
+
// GET /projects/:id/members/all/:user_id — inherited membership (resolves
|
|
123
|
+
// group-level roles). Only the fields the trigger-authorization gate needs:
|
|
124
|
+
// the user's effective access_level in the project (10 Guest, 20 Reporter,
|
|
125
|
+
// 30 Developer, 40 Maintainer, 50 Owner). 404 = not a member at all → deny.
|
|
126
|
+
export const ProjectMemberSchema = z.object({
|
|
127
|
+
id: z.number().int(),
|
|
128
|
+
access_level: z.number().int(),
|
|
129
|
+
});
|
|
130
|
+
// GET /users?username=<login> — used to resolve a access rule's username
|
|
131
|
+
// to its stable numeric id at add time. GitLab returns an array; an exact-match
|
|
132
|
+
// entry is picked by the caller.
|
|
133
|
+
export const UserLookupSchema = z.object({
|
|
134
|
+
id: z.number().int(),
|
|
135
|
+
username: z.string(),
|
|
136
|
+
name: z.string(),
|
|
137
|
+
});
|
|
138
|
+
// GET /projects/:id/issues/:iid/discussions — used by findNoteDiscussionId to
|
|
139
|
+
// map a triggering note id → its discussion id (so a Step-0 error reply can be
|
|
140
|
+
// posted in the same thread as the mention). Only the id of each note in a
|
|
141
|
+
// discussion is needed for the lookup.
|
|
142
|
+
const DiscussionNoteRefSchema = z.object({ id: z.number().int() });
|
|
143
|
+
export const DiscussionSchema = z.object({
|
|
144
|
+
id: z.string(),
|
|
145
|
+
notes: z.array(DiscussionNoteRefSchema),
|
|
146
|
+
});
|
|
147
|
+
// Single issue as returned by GET /projects/:id/issues/:iid. Only the fields
|
|
148
|
+
// the reset authorization check needs (author + assignees). GitLab returns
|
|
149
|
+
// `assignees` as an array (multi-assignee); `assignee` singular is deprecated.
|
|
150
|
+
// Not admin-only — works with the bot's project-scoped token.
|
|
151
|
+
export const IssueDetailSchema = z.object({
|
|
152
|
+
id: z.number().int(),
|
|
153
|
+
iid: z.number().int(),
|
|
154
|
+
author: z.object({ id: z.number().int() }),
|
|
155
|
+
assignees: z.array(z.object({ id: z.number().int() })).optional(),
|
|
156
|
+
});
|
|
157
|
+
// ---- MCP tool response schemas ---------------------------------------------
|
|
158
|
+
// Returned by GET /projects/:id/issues (list) and GET /projects/:id/issues/:iid
|
|
159
|
+
// (single). Carry the fields an agent working on a work item needs to triage
|
|
160
|
+
// and act: identity, state, content, links, labels, assignees. Fields optional
|
|
161
|
+
// defensively because GitLab omits some on higher tiers / older instances; the
|
|
162
|
+
// MCP tools only read what's present, never assume a field is set.
|
|
163
|
+
const gitlabUserBrief = z.object({
|
|
164
|
+
id: z.number().int(),
|
|
165
|
+
username: z.string(),
|
|
166
|
+
name: z.string(),
|
|
167
|
+
web_url: z.string().optional(),
|
|
168
|
+
});
|
|
169
|
+
export const IssueListItemSchema = z.object({
|
|
170
|
+
id: z.number().int(),
|
|
171
|
+
iid: z.number().int(),
|
|
172
|
+
title: z.string(),
|
|
173
|
+
description: z.string().nullish(),
|
|
174
|
+
state: z.string(),
|
|
175
|
+
web_url: z.string(),
|
|
176
|
+
labels: z.array(z.string()).optional(),
|
|
177
|
+
assignees: z.array(gitlabUserBrief).optional(),
|
|
178
|
+
author: gitlabUserBrief.optional(),
|
|
179
|
+
created_at: z.string().optional(),
|
|
180
|
+
updated_at: z.string().optional(),
|
|
181
|
+
closed_at: z.string().nullable().optional(),
|
|
182
|
+
due_date: z.string().nullable().optional(),
|
|
183
|
+
milestone: z
|
|
184
|
+
.object({ id: z.number().int(), title: z.string() })
|
|
185
|
+
.nullable()
|
|
186
|
+
.optional(),
|
|
187
|
+
references: z
|
|
188
|
+
.object({ short: z.string(), relative: z.string(), full: z.string() })
|
|
189
|
+
.optional(),
|
|
190
|
+
user_notes_count: z.number().int().optional(),
|
|
191
|
+
confidential: z.boolean().optional(),
|
|
192
|
+
});
|
|
193
|
+
export const MergeRequestListItemSchema = z.object({
|
|
194
|
+
id: z.number().int(),
|
|
195
|
+
iid: z.number().int(),
|
|
196
|
+
title: z.string(),
|
|
197
|
+
description: z.string().optional(),
|
|
198
|
+
state: z.string(),
|
|
199
|
+
web_url: z.string(),
|
|
200
|
+
source_branch: z.string().optional(),
|
|
201
|
+
target_branch: z.string().optional(),
|
|
202
|
+
labels: z.array(z.string()).optional(),
|
|
203
|
+
author: gitlabUserBrief.optional(),
|
|
204
|
+
assignees: z.array(gitlabUserBrief).optional(),
|
|
205
|
+
created_at: z.string().optional(),
|
|
206
|
+
updated_at: z.string().optional(),
|
|
207
|
+
merged_at: z.string().nullable().optional(),
|
|
208
|
+
draft: z.boolean().optional(),
|
|
209
|
+
references: z
|
|
210
|
+
.object({ short: z.string(), relative: z.string(), full: z.string() })
|
|
211
|
+
.optional(),
|
|
212
|
+
user_notes_count: z.number().int().optional(),
|
|
213
|
+
});
|
|
214
|
+
// GET /projects/:id/merge_requests/:iid/discussions — MR discussions include
|
|
215
|
+
// diff-anchored annotations (DiffNote with position), general threads
|
|
216
|
+
// (DiscussionNote), and system notes. Richer than the issue-only DiscussionSchema
|
|
217
|
+
// above (which is minimal on purpose for the note→discussion lookup): this one
|
|
218
|
+
// carries the fields an agent reviewing an MR needs — resolution state, diff
|
|
219
|
+
// position, code suggestions, author. Fields optional defensively because
|
|
220
|
+
// GitLab omits some on higher tiers / older instances (same convention as the
|
|
221
|
+
// list-item schemas). Reuses gitlabUserBrief for author / resolved_by.
|
|
222
|
+
const MergeRequestNoteSchema = z.object({
|
|
223
|
+
id: z.number().int(),
|
|
224
|
+
type: z.string().nullable().optional(),
|
|
225
|
+
body: z.string(),
|
|
226
|
+
system: z.boolean().optional(),
|
|
227
|
+
author: gitlabUserBrief.optional(),
|
|
228
|
+
created_at: z.string().optional(),
|
|
229
|
+
updated_at: z.string().optional(),
|
|
230
|
+
resolvable: z.boolean().optional(),
|
|
231
|
+
resolved: z.boolean().optional(),
|
|
232
|
+
resolved_by: gitlabUserBrief.nullable().optional(),
|
|
233
|
+
resolved_at: z.string().nullable().optional(),
|
|
234
|
+
position: z.record(z.string(), z.unknown()).optional(),
|
|
235
|
+
suggestions: z.array(z.record(z.string(), z.unknown())).optional(),
|
|
236
|
+
});
|
|
237
|
+
export const MergeRequestDiscussionSchema = z.object({
|
|
238
|
+
id: z.string(),
|
|
239
|
+
individual_note: z.boolean().optional(),
|
|
240
|
+
notes: z.array(MergeRequestNoteSchema),
|
|
241
|
+
});
|
|
242
|
+
// Markdown uploads API response (POST /projects/:id/uploads). `markdown` is the
|
|
243
|
+
// server-rendered reference; `full_path` is the host-absolute path.
|
|
244
|
+
export const UploadSchema = z.object({
|
|
245
|
+
id: z.number().int().optional(),
|
|
246
|
+
alt: z.string().optional(),
|
|
247
|
+
url: z.string(),
|
|
248
|
+
full_path: z.string().optional(),
|
|
249
|
+
markdown: z.string(),
|
|
250
|
+
});
|
|
251
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/platform/gitlab/schemas.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
+
// ponytail: 5-minute replay guard. Standard Webhooks spec recommends a
|
|
3
|
+
// tolerance window; 300s is the spec default. Tighten if a clock-skewed
|
|
4
|
+
// GitLab instance delivers legitimately late, loosen if replay attacks
|
|
5
|
+
// matter more. Upgrade path: store seen webhook-id values for the window.
|
|
6
|
+
const MAX_SKEW_SEC = 300;
|
|
7
|
+
function b64decode(s) {
|
|
8
|
+
return Buffer.from(s, "base64");
|
|
9
|
+
}
|
|
10
|
+
export function b64encode(buf) {
|
|
11
|
+
return buf.toString("base64");
|
|
12
|
+
}
|
|
13
|
+
function headerString(headers, name) {
|
|
14
|
+
const v = headers[name.toLowerCase()];
|
|
15
|
+
if (Array.isArray(v))
|
|
16
|
+
return v[0];
|
|
17
|
+
return v;
|
|
18
|
+
}
|
|
19
|
+
export function verifyWebhookSignature(signingToken, headers, rawBody, nowMs) {
|
|
20
|
+
const sigHeader = headerString(headers, "webhook-signature");
|
|
21
|
+
const id = headerString(headers, "webhook-id");
|
|
22
|
+
const ts = headerString(headers, "webhook-timestamp");
|
|
23
|
+
if (!sigHeader || !id || !ts)
|
|
24
|
+
return false;
|
|
25
|
+
const tsNum = Number(ts);
|
|
26
|
+
if (!Number.isFinite(tsNum))
|
|
27
|
+
return false;
|
|
28
|
+
const skew = Math.abs(Math.floor(nowMs / 1000) - tsNum);
|
|
29
|
+
if (skew > MAX_SKEW_SEC)
|
|
30
|
+
return false;
|
|
31
|
+
if (!signingToken.startsWith("whsec_"))
|
|
32
|
+
return false;
|
|
33
|
+
let key;
|
|
34
|
+
try {
|
|
35
|
+
key = b64decode(signingToken.slice("whsec_".length));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const message = `${id}.${ts}.${rawBody.toString("utf8")}`;
|
|
41
|
+
const digest = createHmac("sha256", key).update(message).digest();
|
|
42
|
+
const expected = Buffer.from(`v1,${b64encode(digest)}`);
|
|
43
|
+
for (const part of sigHeader.split(" ")) {
|
|
44
|
+
const got = Buffer.from(part);
|
|
45
|
+
// ponytail: length-check-before-compare is accepted per Standard Webhooks
|
|
46
|
+
// spec; the length leak is negligible (expected length is fixed per key).
|
|
47
|
+
if (got.length === expected.length && timingSafeEqual(got, expected))
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=signature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signature.js","sourceRoot":"","sources":["../../../src/platform/gitlab/signature.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE1D,uEAAuE;AACvE,0EAA0E;AAC1E,yEAAyE;AACzE,4EAA4E;AAC5E,MAAM,YAAY,GAAG,GAAG,CAAC;AAEzB,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,OAAO,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,YAAY,CAAC,OAAsD,EAAE,IAAY;IACxF,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,YAAoB,EACpB,OAAsD,EACtD,OAAe,EACf,KAAa;IAEb,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IAC7D,MAAM,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC/C,MAAM,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;IACtD,IAAI,CAAC,SAAS,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IAE3C,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IACzB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;IACxD,IAAI,IAAI,GAAG,YAAY;QAAE,OAAO,KAAK,CAAC;IAEtC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IACrD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1D,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;IAClE,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAExD,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,0EAA0E;QAC1E,4EAA4E;QAC5E,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,eAAe,CAAC,GAAG,EAAE,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;IACpF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Platform factory: returns the singleton driver selected by config.PLATFORM.
|
|
2
|
+
// One DevBot process talks to exactly one forge instance.
|
|
3
|
+
import { config } from "../config.js";
|
|
4
|
+
import { gitlabPlatform } from "./gitlab/index.js";
|
|
5
|
+
import { forgejoPlatform } from "./gitealike/forgejo.js";
|
|
6
|
+
import { giteaPlatform } from "./gitealike/gitea.js";
|
|
7
|
+
import { createGithubPlatform } from "./github/index.js";
|
|
8
|
+
let cached;
|
|
9
|
+
export function getPlatform() {
|
|
10
|
+
if (cached)
|
|
11
|
+
return cached;
|
|
12
|
+
switch (config.PLATFORM) {
|
|
13
|
+
case "forgejo":
|
|
14
|
+
cached = forgejoPlatform;
|
|
15
|
+
break;
|
|
16
|
+
case "gitea":
|
|
17
|
+
cached = giteaPlatform;
|
|
18
|
+
break;
|
|
19
|
+
case "github":
|
|
20
|
+
cached = createGithubPlatform();
|
|
21
|
+
break;
|
|
22
|
+
case "gitlab":
|
|
23
|
+
default:
|
|
24
|
+
cached = gitlabPlatform;
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
return cached;
|
|
28
|
+
}
|
|
29
|
+
/** Test hook: reset the memoized driver. */
|
|
30
|
+
export function resetPlatformForTest() {
|
|
31
|
+
cached = undefined;
|
|
32
|
+
}
|
|
33
|
+
/** Test hook: force a specific driver (e.g. exercise a forge's typed gap in a
|
|
34
|
+
* suite whose PLATFORM env selects a different forge). */
|
|
35
|
+
export function setPlatformForTest(platform) {
|
|
36
|
+
cached = platform;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/platform/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,0DAA0D;AAE1D,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,IAAI,MAA4B,CAAC;AAEjC,MAAM,UAAU,WAAW;IACzB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,SAAS;YACZ,MAAM,GAAG,eAAe,CAAC;YACzB,MAAM;QACR,KAAK,OAAO;YACV,MAAM,GAAG,aAAa,CAAC;YACvB,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,GAAG,oBAAoB,EAAE,CAAC;YAChC,MAAM;QACR,KAAK,QAAQ,CAAC;QACd;YACE,MAAM,GAAG,cAAc,CAAC;YACxB,MAAM;IACV,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,oBAAoB;IAClC,MAAM,GAAG,SAAS,CAAC;AACrB,CAAC;AAED;2DAC2D;AAC3D,MAAM,UAAU,kBAAkB,CAAC,QAAkB;IACnD,MAAM,GAAG,QAAQ,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// The Platform port: one aggregate interface assembled from capability
|
|
2
|
+
// sub-interfaces. Callers depend on the port (via `getPlatform()`), never on a
|
|
3
|
+
// specific forge. GitLab, ForgeJo and Gitea each implement it.
|
|
4
|
+
export const CAPABILITY_METHODS = {
|
|
5
|
+
ingress: ["eventName", "projectIdFromBody", "deliveryId", "verifySignature", "parseWebhook", "generateWebhookSecret"],
|
|
6
|
+
workItems: [
|
|
7
|
+
"postComment", "replyInThread", "postErrorReply", "listComments", "getWorkItem",
|
|
8
|
+
"getWorkItemStateOrNull", "getMemberPermission", "resolveUser", "searchUsers", "listWorkItems",
|
|
9
|
+
"getWorkItemSummary", "listCommentsFull", "listLabels", "listMilestones",
|
|
10
|
+
],
|
|
11
|
+
changeRequests: ["list", "create", "update", "get", "listReviewDiscussions", "listNotes"],
|
|
12
|
+
repository: [
|
|
13
|
+
"getRepo", "branchExists", "firstExistingBranch", "listBranches", "listTree", "getFile",
|
|
14
|
+
"listCommits", "getCommit", "compare", "listTags", "listMembers", "listReleases",
|
|
15
|
+
"listWikiPages", "getWikiPage", "searchProject",
|
|
16
|
+
],
|
|
17
|
+
ci: ["listPipelines", "getPipeline", "listPipelineJobs", "getJobLog"],
|
|
18
|
+
gitAuth: ["gitExtraHeader", "cloneUrl"],
|
|
19
|
+
attachments: ["findRefs", "download", "upload"],
|
|
20
|
+
onboarding: [
|
|
21
|
+
"authorizeUrl", "exchangeCode", "currentUser", "listProjects", "addBot", "removeBot",
|
|
22
|
+
"findOrCreateWebhook", "setWebhookSecret", "ensureCiFailureEvents", "deleteWebhook", "testWebhook",
|
|
23
|
+
],
|
|
24
|
+
links: ["workItemUrl"],
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=port.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port.js","sourceRoot":"","sources":["../../src/platform/port.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,+EAA+E;AAC/E,+DAA+D;AAgT/D,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,OAAO,EAAE,CAAC,WAAW,EAAE,mBAAmB,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,uBAAuB,CAAC;IACrH,SAAS,EAAE;QACT,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa;QAC/E,wBAAwB,EAAE,qBAAqB,EAAE,aAAa,EAAE,aAAa,EAAE,eAAe;QAC9F,oBAAoB,EAAE,kBAAkB,EAAE,YAAY,EAAE,gBAAgB;KACzE;IACD,cAAc,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,uBAAuB,EAAE,WAAW,CAAC;IACzF,UAAU,EAAE;QACV,SAAS,EAAE,cAAc,EAAE,qBAAqB,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS;QACvF,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc;QAChF,eAAe,EAAE,aAAa,EAAE,eAAe;KAChD;IACD,EAAE,EAAE,CAAC,eAAe,EAAE,aAAa,EAAE,kBAAkB,EAAE,WAAW,CAAC;IACrE,OAAO,EAAE,CAAC,gBAAgB,EAAE,UAAU,CAAC;IACvC,WAAW,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC;IAC/C,UAAU,EAAE;QACV,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW;QACpF,qBAAqB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,eAAe,EAAE,aAAa;KACnG;IACD,KAAK,EAAE,CAAC,aAAa,CAAC;CACkB,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Platform-neutral domain types for the DevBot forge abstraction.
|
|
2
|
+
//
|
|
3
|
+
// Every driver (GitLab, ForgeJo, Gitea) speaks in these shapes. Callers
|
|
4
|
+
// (webhook, runner, MCP tools) depend on these — never on a forge's wire
|
|
5
|
+
// format. The property that names a project-internal work item number is
|
|
6
|
+
// `number` (GitLab calls it `iid`; Gitea/ForgeJo call it `number`).
|
|
7
|
+
/** Stream-side tail accumulator. Retains only the last `maxBytes` bytes seen
|
|
8
|
+
* while counting the total, so a full-read of an over-cap log stays bounded
|
|
9
|
+
* in memory. Used by the drivers' raw fetchers in `overflow: "tail"` mode. */
|
|
10
|
+
export class TailAccumulator {
|
|
11
|
+
maxBytes;
|
|
12
|
+
chunks = [];
|
|
13
|
+
len = 0;
|
|
14
|
+
total = 0;
|
|
15
|
+
constructor(maxBytes) {
|
|
16
|
+
this.maxBytes = maxBytes;
|
|
17
|
+
}
|
|
18
|
+
push(value) {
|
|
19
|
+
this.total += value.byteLength;
|
|
20
|
+
this.chunks.push(Buffer.from(value));
|
|
21
|
+
this.len += value.byteLength;
|
|
22
|
+
// Compact once we hold ~2× the cap so the chunk list cannot grow without
|
|
23
|
+
// bound on a very large stream; keeps the retained window to the last cap.
|
|
24
|
+
if (this.len > this.maxBytes * 2) {
|
|
25
|
+
const merged = Buffer.concat(this.chunks);
|
|
26
|
+
const keep = merged.subarray(Math.max(0, merged.length - this.maxBytes));
|
|
27
|
+
this.chunks = [Buffer.from(keep)];
|
|
28
|
+
this.len = keep.length;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
result() {
|
|
32
|
+
const merged = Buffer.concat(this.chunks);
|
|
33
|
+
const bytes = merged.subarray(Math.max(0, merged.length - this.maxBytes));
|
|
34
|
+
return { bytes, totalBytes: this.total };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Build a FileContent from the raw end-of-stream slice of a larger source.
|
|
38
|
+
* Job logs keep their tail (the failure is at the end); when the source was
|
|
39
|
+
* larger than the slice we prefix an explicit head-omitted marker so the
|
|
40
|
+
* result is never silently empty. `totalBytes` is the size before truncation. */
|
|
41
|
+
export function tailFileContent(tail, totalBytes, contentType, maxBytes) {
|
|
42
|
+
const truncated = totalBytes > maxBytes;
|
|
43
|
+
if (!truncated) {
|
|
44
|
+
return { content: tail.toString("utf8"), truncated: false, bytes: totalBytes, contentType };
|
|
45
|
+
}
|
|
46
|
+
// Callers may pass an already-sliced tail (streaming fetchers) or the whole
|
|
47
|
+
// buffer (GitHub inflates the ZIP first); slice here so both are correct.
|
|
48
|
+
const slice = tail.byteLength > maxBytes ? tail.subarray(tail.byteLength - maxBytes) : tail;
|
|
49
|
+
// The slice boundary can split a multi-byte UTF-8 char; drop the replacement
|
|
50
|
+
// character it produces so the retained tail starts on a clean boundary.
|
|
51
|
+
const text = slice.toString("utf8").replace(/^\uFFFD/, "");
|
|
52
|
+
return {
|
|
53
|
+
content: `[… ${totalBytes - slice.byteLength} bytes omitted from the start …]\n${text}`,
|
|
54
|
+
truncated: true,
|
|
55
|
+
bytes: totalBytes,
|
|
56
|
+
contentType,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// ---- Errors ----------------------------------------------------------------
|
|
60
|
+
/** HTTP error from a forge, normalized. */
|
|
61
|
+
export class PlatformHttpError extends Error {
|
|
62
|
+
status;
|
|
63
|
+
op;
|
|
64
|
+
body;
|
|
65
|
+
constructor(status, op, body) {
|
|
66
|
+
super(`platform ${status} on ${op}: ${body}`);
|
|
67
|
+
this.name = "PlatformHttpError";
|
|
68
|
+
this.status = status;
|
|
69
|
+
this.op = op;
|
|
70
|
+
this.body = body;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** Operation not available on this platform (e.g. CI model differences). */
|
|
74
|
+
export class UnsupportedError extends Error {
|
|
75
|
+
constructor(op) {
|
|
76
|
+
super(`operation '${op}' is not supported on this platform`);
|
|
77
|
+
this.name = "UnsupportedError";
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/platform/types.ts"],"names":[],"mappings":"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"}
|
package/dist/podman.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { log } from "./logger.js";
|
|
3
|
+
import { killContainerByName } from "./opencode.js";
|
|
4
|
+
import { appendPodmanPhase } from "./run-log-sink.js";
|
|
5
|
+
const defaultClient = {
|
|
6
|
+
run(args, opts = {}) {
|
|
7
|
+
return new Promise((resolve) => {
|
|
8
|
+
const child = spawn("podman", args, { stdio: ["pipe", "pipe", "pipe"] });
|
|
9
|
+
const out = [];
|
|
10
|
+
const err = [];
|
|
11
|
+
child.stdout.on("data", (b) => out.push(b));
|
|
12
|
+
child.stderr.on("data", (b) => err.push(b));
|
|
13
|
+
// Optional stdin (used to stream large payloads into a container without
|
|
14
|
+
// hitting the argv size limit). Absent → close stdin immediately so a
|
|
15
|
+
// container reading stdin sees EOF instead of hanging. A write to a child
|
|
16
|
+
// that exits early raises EPIPE; swallow it (the exit code is the signal).
|
|
17
|
+
child.stdin.on("error", () => { });
|
|
18
|
+
if (opts.input !== undefined)
|
|
19
|
+
child.stdin.end(opts.input);
|
|
20
|
+
else
|
|
21
|
+
child.stdin.end();
|
|
22
|
+
let timer;
|
|
23
|
+
if (opts.timeoutMs) {
|
|
24
|
+
timer = setTimeout(() => {
|
|
25
|
+
try {
|
|
26
|
+
child.kill("SIGKILL");
|
|
27
|
+
}
|
|
28
|
+
catch { /* dead */ }
|
|
29
|
+
const i = args.indexOf("--name");
|
|
30
|
+
const cname = i >= 0 && i + 1 < args.length ? args[i + 1] : undefined;
|
|
31
|
+
if (cname)
|
|
32
|
+
killContainerByName(cname);
|
|
33
|
+
}, opts.timeoutMs);
|
|
34
|
+
}
|
|
35
|
+
child.on("error", () => {
|
|
36
|
+
if (timer)
|
|
37
|
+
clearTimeout(timer);
|
|
38
|
+
// ponytail: don't log podman args — they embed secrets via shq(authJson).
|
|
39
|
+
// Log only the container name (non-secret, useful for debugging).
|
|
40
|
+
const nameIdx = args.indexOf("--name");
|
|
41
|
+
const containerName = nameIdx >= 0 && nameIdx + 1 < args.length ? args[nameIdx + 1] : undefined;
|
|
42
|
+
log.error("podman spawn error", { containerName });
|
|
43
|
+
resolve({ code: -1, stdout: "", stderr: "spawn failed" });
|
|
44
|
+
});
|
|
45
|
+
child.on("close", (code) => {
|
|
46
|
+
if (timer)
|
|
47
|
+
clearTimeout(timer);
|
|
48
|
+
resolve({
|
|
49
|
+
code: code ?? -1,
|
|
50
|
+
stdout: Buffer.concat(out).toString("utf8"),
|
|
51
|
+
stderr: Buffer.concat(err).toString("utf8"),
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
// ponytail: mutable global. ESM live bindings mean consumers read the current
|
|
58
|
+
// value at access time, so setPodmanClient(mock) before a test takes effect.
|
|
59
|
+
// Upgrade path: per-instance injection if concurrency matters.
|
|
60
|
+
let client = defaultClient;
|
|
61
|
+
export function setPodmanClient(c) {
|
|
62
|
+
client = c;
|
|
63
|
+
}
|
|
64
|
+
export function resetPodmanClient() {
|
|
65
|
+
client = defaultClient;
|
|
66
|
+
}
|
|
67
|
+
// OpenCode can issue parallel MCP tool calls. Helper containers reuse fixed
|
|
68
|
+
// per-work-item names (attachdl/attachread/peersync/gitexclude), so a second
|
|
69
|
+
// launch while the first is live fails with "container name ... already in
|
|
70
|
+
// use" (exit 125). Serialize `podman run` calls that share a --name; different
|
|
71
|
+
// names (and non-run commands) stay concurrent.
|
|
72
|
+
const runChains = new Map();
|
|
73
|
+
function namedContainer(args) {
|
|
74
|
+
const i = args.indexOf("--name");
|
|
75
|
+
return i >= 0 && i + 1 < args.length ? args[i + 1] : undefined;
|
|
76
|
+
}
|
|
77
|
+
// The function every caller uses — reads the live binding.
|
|
78
|
+
export async function podman(args, opts) {
|
|
79
|
+
if (args[0] !== "run") {
|
|
80
|
+
const result = await client.run(args, opts);
|
|
81
|
+
captureRunOutput(args, result);
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
const name = namedContainer(args);
|
|
85
|
+
if (!name) {
|
|
86
|
+
const result = await client.run(args, opts);
|
|
87
|
+
captureRunOutput(args, result);
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
const previous = runChains.get(name) ?? Promise.resolve();
|
|
91
|
+
const current = previous.catch(() => { }).then(() => client.run(args, opts));
|
|
92
|
+
runChains.set(name, current);
|
|
93
|
+
try {
|
|
94
|
+
const result = await current;
|
|
95
|
+
captureRunOutput(args, result);
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
if (runChains.get(name) === current)
|
|
100
|
+
runChains.delete(name);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Tee a phase container's output into the active run's log sink (work item #61).
|
|
104
|
+
// Only `podman run` is captured — ps/rm/volume housekeeping is not part of a
|
|
105
|
+
// run's transcript. Best-effort: a capture failure never affects the run.
|
|
106
|
+
function captureRunOutput(args, result) {
|
|
107
|
+
if (args[0] !== "run")
|
|
108
|
+
return;
|
|
109
|
+
const name = namedContainer(args);
|
|
110
|
+
if (!name)
|
|
111
|
+
return;
|
|
112
|
+
try {
|
|
113
|
+
appendPodmanPhase(name, result.code, result.stdout, result.stderr);
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
log.warn("run log capture failed", { err: e });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=podman.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"podman.js","sourceRoot":"","sources":["../src/podman.ts"],"names":[],"mappings":"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"}
|