@ddtcorex/dsh-maestro-review 0.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.
Files changed (110) hide show
  1. package/README.md +53 -0
  2. package/client/settings-card.tsx +4 -0
  3. package/lib/config-store.d.ts +53 -0
  4. package/lib/config-store.d.ts.map +1 -0
  5. package/lib/config-store.js +60 -0
  6. package/lib/config-store.js.map +1 -0
  7. package/lib/events.d.ts +27 -0
  8. package/lib/events.d.ts.map +1 -0
  9. package/lib/events.js +2 -0
  10. package/lib/events.js.map +1 -0
  11. package/lib/gitlab-client.d.ts +14 -0
  12. package/lib/gitlab-client.d.ts.map +1 -0
  13. package/lib/gitlab-client.js +146 -0
  14. package/lib/gitlab-client.js.map +1 -0
  15. package/lib/gitlab-webhook.d.ts +17 -0
  16. package/lib/gitlab-webhook.d.ts.map +1 -0
  17. package/lib/gitlab-webhook.js +144 -0
  18. package/lib/gitlab-webhook.js.map +1 -0
  19. package/lib/govard-tool.d.ts +11 -0
  20. package/lib/govard-tool.d.ts.map +1 -0
  21. package/lib/govard-tool.js +95 -0
  22. package/lib/govard-tool.js.map +1 -0
  23. package/lib/index.d.ts +4 -0
  24. package/lib/index.d.ts.map +1 -0
  25. package/lib/index.js +15 -0
  26. package/lib/index.js.map +1 -0
  27. package/lib/notify.d.ts +23 -0
  28. package/lib/notify.d.ts.map +1 -0
  29. package/lib/notify.js +10 -0
  30. package/lib/notify.js.map +1 -0
  31. package/lib/orchestrator.d.ts +144 -0
  32. package/lib/orchestrator.d.ts.map +1 -0
  33. package/lib/orchestrator.js +655 -0
  34. package/lib/orchestrator.js.map +1 -0
  35. package/lib/pin-store.d.ts +5 -0
  36. package/lib/pin-store.d.ts.map +1 -0
  37. package/lib/pin-store.js +5 -0
  38. package/lib/pin-store.js.map +1 -0
  39. package/lib/providers/github.stub.d.ts +3 -0
  40. package/lib/providers/github.stub.d.ts.map +1 -0
  41. package/lib/providers/github.stub.js +10 -0
  42. package/lib/providers/github.stub.js.map +1 -0
  43. package/lib/providers/gitlab.d.ts +13 -0
  44. package/lib/providers/gitlab.d.ts.map +1 -0
  45. package/lib/providers/gitlab.js +173 -0
  46. package/lib/providers/gitlab.js.map +1 -0
  47. package/lib/providers/interface.d.ts +12 -0
  48. package/lib/providers/interface.d.ts.map +1 -0
  49. package/lib/providers/interface.js +2 -0
  50. package/lib/providers/interface.js.map +1 -0
  51. package/lib/review-findings-tool.d.ts +15 -0
  52. package/lib/review-findings-tool.d.ts.map +1 -0
  53. package/lib/review-findings-tool.js +37 -0
  54. package/lib/review-findings-tool.js.map +1 -0
  55. package/lib/review-history.d.ts +35 -0
  56. package/lib/review-history.d.ts.map +1 -0
  57. package/lib/review-history.js +87 -0
  58. package/lib/review-history.js.map +1 -0
  59. package/lib/review-intake.d.ts +7 -0
  60. package/lib/review-intake.d.ts.map +1 -0
  61. package/lib/review-intake.js +80 -0
  62. package/lib/review-intake.js.map +1 -0
  63. package/lib/review-signals.d.ts +17 -0
  64. package/lib/review-signals.d.ts.map +1 -0
  65. package/lib/review-signals.js +49 -0
  66. package/lib/review-signals.js.map +1 -0
  67. package/lib/secure-compare.d.ts +7 -0
  68. package/lib/secure-compare.d.ts.map +1 -0
  69. package/lib/secure-compare.js +14 -0
  70. package/lib/secure-compare.js.map +1 -0
  71. package/lib/settings-rpc.d.ts +22 -0
  72. package/lib/settings-rpc.d.ts.map +1 -0
  73. package/lib/settings-rpc.js +252 -0
  74. package/lib/settings-rpc.js.map +1 -0
  75. package/lib/skills-tool.d.ts +29 -0
  76. package/lib/skills-tool.d.ts.map +1 -0
  77. package/lib/skills-tool.js +160 -0
  78. package/lib/skills-tool.js.map +1 -0
  79. package/lib/workspace-tool.d.ts +10 -0
  80. package/lib/workspace-tool.d.ts.map +1 -0
  81. package/lib/workspace-tool.js +86 -0
  82. package/lib/workspace-tool.js.map +1 -0
  83. package/package.json +53 -0
  84. package/presets/maestro-auditor/agent.cordis.yml +10 -0
  85. package/presets/maestro-auditor/preset.yml +2 -0
  86. package/presets/maestro-coder/agent.cordis.yml +223 -0
  87. package/presets/maestro-coder/preset.yml +2 -0
  88. package/presets/maestro-reviewer/agent.cordis.yml +14 -0
  89. package/presets/maestro-reviewer/preset.yml +2 -0
  90. package/src/augment.d.ts +47 -0
  91. package/src/config-store.ts +109 -0
  92. package/src/events.ts +25 -0
  93. package/src/gitlab-client.ts +186 -0
  94. package/src/gitlab-webhook.ts +166 -0
  95. package/src/govard-tool.ts +114 -0
  96. package/src/index.ts +15 -0
  97. package/src/notify.ts +30 -0
  98. package/src/orchestrator.ts +740 -0
  99. package/src/pin-store.ts +4 -0
  100. package/src/providers/github.stub.ts +11 -0
  101. package/src/providers/gitlab.ts +190 -0
  102. package/src/providers/interface.ts +2 -0
  103. package/src/review-findings-tool.ts +51 -0
  104. package/src/review-history.ts +112 -0
  105. package/src/review-intake.ts +86 -0
  106. package/src/review-signals.ts +52 -0
  107. package/src/secure-compare.ts +13 -0
  108. package/src/settings-rpc.ts +249 -0
  109. package/src/skills-tool.ts +193 -0
  110. package/src/workspace-tool.ts +90 -0
package/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # @ddtcorex/dsh-maestro-review
2
+
3
+ Automated merge-request review for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness):
4
+ pluggable **ReviewProvider** (GitLab first), an orchestrator that spins up reviewer/auditor
5
+ child agents on fresh worktrees, webhook intake for GitLab events, and a settings/tunnel
6
+ client UI injected into the DSH Web slots.
7
+
8
+ Part of the Maestro Harness suite (`dsh-maestro-*`). Cordis patch rows:
9
+ `maestro-review-webhook` (intake), `maestro-review-orchestrator` (pipeline),
10
+ `maestro-review-settings-rpc` (settings UI) — all served by this npm package.
11
+
12
+ ## What it provides
13
+
14
+ - **ReviewProvider abstraction** — GitLab client today; other forges plug in behind the same
15
+ interface.
16
+ - **Orchestrator** — reviewer + auditor agent runs against a disposable worktree of the MR,
17
+ model selection overridable globally (`reviewModel`) and per project mapping.
18
+ - **Webhook intake** — receives GitLab MR events, enqueues reviews (dedup + retention).
19
+ - **Review findings/history/signals** — findings written through the `review-findings`
20
+ tool by tool-only review subagents (never free text); history + signals tracked per MR.
21
+ - **Govard/workspace tooling** available inside review runs.
22
+ - **Client half** — settings section rendered into DSH Web slots; notification copy stays
23
+ here, delivery goes through the optional `maestroNotifier` service.
24
+
25
+ ## Settings
26
+
27
+ Reads its configuration through the **shared namespaced settings store**
28
+ (`~/.dsh/maestro/settings.json`, owned by `@ddtcorex/dsh-maestro-config-lib`) via the flat
29
+ adapter in `src/config-store.ts`; machine runtime state stays in a package-local sidecar.
30
+
31
+ ## Install
32
+
33
+ ```sh
34
+ dsh plugin --profile web add @ddtcorex/dsh-maestro-review
35
+ # or everything at once:
36
+ dsh plugin --profile web add @ddtcorex/dsh-maestro-meta
37
+ ```
38
+
39
+ ## Development
40
+
41
+ ```sh
42
+ pnpm install
43
+ pnpm verify # tsc --noEmit
44
+ pnpm test # vitest run
45
+ pnpm build # tsc -> lib/
46
+ pnpm run build:client # browser bundle -> lib/client.js (required after client changes)
47
+ ```
48
+
49
+ See AGENTS.md for conventions (host/client split, secrets handling, live-validation rules).
50
+
51
+ ## License
52
+
53
+ MIT
@@ -0,0 +1,4 @@
1
+ // Maestro Review — Settings card stub (Client)
2
+ export default function ReviewSettingsCard() {
3
+ return null
4
+ }
@@ -0,0 +1,53 @@
1
+ import type { ReviewSkillProfile } from './skills-tool.js';
2
+ export interface ReviewModelSelection {
3
+ provider: string;
4
+ model: string;
5
+ reasoningEffort?: string;
6
+ }
7
+ export interface MaestroUserConfig {
8
+ gitlabBaseUrl?: string;
9
+ gitlabToken?: string;
10
+ botUsername?: string;
11
+ webhookSecret?: string;
12
+ webhookPort?: number;
13
+ projectMappings?: Array<{
14
+ projectPath: string;
15
+ localRepoPath: string;
16
+ reviewProfile?: ReviewSkillProfile;
17
+ reviewModel?: ReviewModelSelection;
18
+ }>;
19
+ /** Override the DSH default model for automated reviews. When absent the global DSH default is used. */
20
+ reviewModel?: ReviewModelSelection;
21
+ /** Re-run a quick review whenever new commits land on a previously reviewed MR. */
22
+ autoRereviewOnPush?: boolean;
23
+ /** Bound one automated review agent's turn. */
24
+ agentTimeoutMs?: number;
25
+ /** Prune Maestro's own review records older than this many days (0 = keep forever). */
26
+ reviewSessionRetentionDays?: number;
27
+ tunnelMode?: 'quick' | 'named';
28
+ quickTarget?: 'dsh-web' | 'webhook';
29
+ tunnelId?: string;
30
+ tunnelCredentialsFile?: string;
31
+ tunnelHostname?: string;
32
+ proxyPort?: number;
33
+ proxyHost?: string;
34
+ lastTunnelRunning?: boolean;
35
+ /** Gate LAN access behind a second PIN. Default false — LAN stays open. */
36
+ lanPinEnabled?: boolean;
37
+ /** Telegram Bot API credentials for one-way notifications. */
38
+ telegramBotToken?: string;
39
+ telegramChatId?: string;
40
+ /** Also notify this chat when a review finishes. Default false. */
41
+ telegramReviewNotifications?: boolean;
42
+ }
43
+ /**
44
+ * Settings live in the SHARED namespaced store (`~/.dsh/maestro/settings.json`,
45
+ * owned by @ddtcorex/dsh-maestro-config-lib); this store is a thin adapter that
46
+ * keeps the package's flat `MaestroUserConfig` API while delegating persistence.
47
+ * Machine runtime state (RUNTIME_KEYS) never enters settings — it stays in this
48
+ * package's own sidecar so a settings edit can never silently flip tunnel state.
49
+ */
50
+ export declare function configStorePath(dshHome?: string): string;
51
+ export declare function loadUserConfig(dshHome?: string): Promise<MaestroUserConfig>;
52
+ export declare function saveUserConfig(patch: MaestroUserConfig, dshHome?: string): Promise<MaestroUserConfig>;
53
+ //# sourceMappingURL=config-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../src/config-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAO1D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,kBAAkB,CAAC;QAAC,WAAW,CAAC,EAAE,oBAAoB,CAAA;KAAE,CAAC,CAAA;IAC/I,wGAAwG;IACxG,WAAW,CAAC,EAAE,oBAAoB,CAAA;IAClC,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,uFAAuF;IACvF,0BAA0B,CAAC,EAAE,MAAM,CAAA;IACnC,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IAC9B,WAAW,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,2EAA2E;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,mEAAmE;IACnE,2BAA2B,CAAC,EAAE,OAAO,CAAA;CACtC;AAMD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAExD;AAyBD,wBAAsB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAMjF;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAc3G"}
@@ -0,0 +1,60 @@
1
+ import { chmod, mkdir, readFile, writeFile } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { dirname, join } from 'node:path';
4
+ import { RUNTIME_KEYS, readFlat, writeLegacyPatch, } from '@ddtcorex/dsh-maestro-config-lib';
5
+ function resolveDshHome(dshHome) {
6
+ return dshHome ?? process.env.DSH_HOME ?? join(homedir(), '.dsh');
7
+ }
8
+ /**
9
+ * Settings live in the SHARED namespaced store (`~/.dsh/maestro/settings.json`,
10
+ * owned by @ddtcorex/dsh-maestro-config-lib); this store is a thin adapter that
11
+ * keeps the package's flat `MaestroUserConfig` API while delegating persistence.
12
+ * Machine runtime state (RUNTIME_KEYS) never enters settings — it stays in this
13
+ * package's own sidecar so a settings edit can never silently flip tunnel state.
14
+ */
15
+ export function configStorePath(dshHome) {
16
+ return join(resolveDshHome(dshHome), 'maestro', 'settings.json');
17
+ }
18
+ function runtimeStatePath(dshHome) {
19
+ return join(resolveDshHome(dshHome), 'dsh-maestro-review', 'runtime.json');
20
+ }
21
+ async function readRuntimeState(dshHome) {
22
+ try {
23
+ return JSON.parse(await readFile(runtimeStatePath(dshHome), 'utf8'));
24
+ }
25
+ catch {
26
+ return {};
27
+ }
28
+ }
29
+ async function mergeRuntimeState(patch, dshHome) {
30
+ const path = runtimeStatePath(dshHome);
31
+ const merged = { ...(await readRuntimeState(dshHome)), ...patch };
32
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
33
+ await writeFile(path, JSON.stringify(merged, null, 2), { encoding: 'utf-8', mode: 0o600 });
34
+ await chmod(path, 0o600);
35
+ }
36
+ export async function loadUserConfig(dshHome) {
37
+ const [flat, runtime] = await Promise.all([
38
+ readFlat({ dshHome }),
39
+ readRuntimeState(dshHome),
40
+ ]);
41
+ return { ...flat, ...runtime };
42
+ }
43
+ export async function saveUserConfig(patch, dshHome) {
44
+ const settingsPatch = {};
45
+ const runtimePatch = {};
46
+ for (const [key, value] of Object.entries(patch)) {
47
+ if (RUNTIME_KEYS.includes(key))
48
+ runtimePatch[key] = value;
49
+ else
50
+ settingsPatch[key] = value;
51
+ }
52
+ if (Object.keys(settingsPatch).length > 0) {
53
+ await writeLegacyPatch(settingsPatch, { dshHome });
54
+ }
55
+ if (Object.keys(runtimePatch).length > 0) {
56
+ await mergeRuntimeState(runtimePatch, dshHome);
57
+ }
58
+ return loadUserConfig(dshHome);
59
+ }
60
+ //# sourceMappingURL=config-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-store.js","sourceRoot":"","sources":["../src/config-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export interface MrOpenedPayload {
2
+ projectPath: string;
3
+ projectId: number;
4
+ mrIid: number;
5
+ sourceBranch: string;
6
+ }
7
+ export type ReviewMode = 'quick' | 'deep';
8
+ export type ReviewScope = {
9
+ kind: 'mr';
10
+ } | {
11
+ kind: 'discussion';
12
+ discussionId: string;
13
+ path: string;
14
+ line: number;
15
+ };
16
+ export interface ReviewRequest extends MrOpenedPayload {
17
+ /** `push` arrives only when auto re-review on push is enabled and passes the completed-history gate. */
18
+ trigger: 'reviewer-assignment' | 'mention' | 'push';
19
+ mode: ReviewMode;
20
+ scope: ReviewScope;
21
+ }
22
+ declare module '@deepseek-ai/cordis' {
23
+ interface Events {
24
+ 'maestro/review-request': (payload: ReviewRequest) => void;
25
+ }
26
+ }
27
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,CAAA;AAEzC,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GACd;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5E,MAAM,WAAW,aAAc,SAAQ,eAAe;IACpD,wGAAwG;IACxG,OAAO,EAAE,qBAAqB,GAAG,SAAS,GAAG,MAAM,CAAA;IACnD,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,EAAE,WAAW,CAAA;CACnB;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,MAAM;QACd,wBAAwB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAA;KAC3D;CACF"}
package/lib/events.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import z from '@deepseek-ai/schemastery';
3
+ export declare const name = "maestro-gitlab-client";
4
+ export declare const inject: string[];
5
+ export interface Config {
6
+ baseUrl: string;
7
+ projectId: string | number;
8
+ mrIid: number;
9
+ token: string;
10
+ botUsername: string;
11
+ }
12
+ export declare const Config: z<Config>;
13
+ export declare function apply(ctx: Context, config: Config): void;
14
+ //# sourceMappingURL=gitlab-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitlab-client.d.ts","sourceRoot":"","sources":["../src/gitlab-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAGxC,eAAO,MAAM,IAAI,0BAA0B,CAAA;AAC3C,eAAO,MAAM,MAAM,UAAY,CAAA;AAE/B,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAM3B,CAAA;AA0BF,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CA0IxD"}
@@ -0,0 +1,146 @@
1
+ import z from '@deepseek-ai/schemastery';
2
+ import { defineTool } from '@deepseek-ai/dsh-tools';
3
+ export const name = 'maestro-gitlab-client';
4
+ export const inject = ['tools'];
5
+ export const Config = z.object({
6
+ baseUrl: z.string().required(),
7
+ projectId: z.union([z.string(), z.number()]).required(),
8
+ mrIid: z.number().required(),
9
+ token: z.string().role('secret').required(),
10
+ botUsername: z.string().required(),
11
+ });
12
+ export function apply(ctx, config) {
13
+ const apiBase = `${config.baseUrl}/api/v4/projects/${config.projectId}/merge_requests/${config.mrIid}`;
14
+ const headers = { 'PRIVATE-TOKEN': config.token };
15
+ let cachedDiffRefs;
16
+ async function getDiffRefs() {
17
+ if (cachedDiffRefs !== undefined)
18
+ return cachedDiffRefs;
19
+ const response = await fetch(apiBase, { headers });
20
+ if (!response.ok) {
21
+ throw new Error(`GitLab API error ${response.status}: ${await response.text()}`);
22
+ }
23
+ cachedDiffRefs = (await response.json()).diff_refs;
24
+ return cachedDiffRefs;
25
+ }
26
+ ctx.tools.register(defineTool({
27
+ name: 'gitlab_get_mr_diff',
28
+ description: 'Fetch the current unified diff for this merge request.',
29
+ parameters: {},
30
+ output: {
31
+ schema: { type: 'object', additionalProperties: false, properties: { text: { type: 'string', required: true } } },
32
+ render: (_args, value) => [{ type: 'text', text: value.text }],
33
+ },
34
+ async execute() {
35
+ const response = await fetch(`${apiBase}/diffs`, { headers });
36
+ if (!response.ok) {
37
+ throw new Error(`GitLab API error ${response.status}: ${await response.text()}`);
38
+ }
39
+ const diffs = await response.json();
40
+ const text = diffs.map(d => `--- ${d.old_path}\n+++ ${d.new_path}\n${d.diff}`).join('\n\n');
41
+ return { text };
42
+ },
43
+ }));
44
+ ctx.tools.register(defineTool({
45
+ name: 'gitlab_post_mr_comment',
46
+ description: 'Post a Markdown comment (discussion note) on this merge request.',
47
+ parameters: {
48
+ body: { type: 'string', required: true, description: 'Markdown comment body.' },
49
+ },
50
+ output: {
51
+ schema: { type: 'object', additionalProperties: false, properties: { posted: { type: 'boolean', required: true } } },
52
+ render: () => [{ type: 'text', text: 'Comment posted.' }],
53
+ },
54
+ async execute(args) {
55
+ const response = await fetch(`${apiBase}/notes`, {
56
+ method: 'POST',
57
+ headers: { ...headers, 'Content-Type': 'application/json' },
58
+ body: JSON.stringify({ body: args.body }),
59
+ });
60
+ if (!response.ok) {
61
+ throw new Error(`GitLab API error ${response.status}: ${await response.text()}`);
62
+ }
63
+ return { posted: true };
64
+ },
65
+ }));
66
+ ctx.tools.register(defineTool({
67
+ name: 'gitlab_list_own_review_threads',
68
+ description: 'List this merge request\'s unresolved inline discussion threads previously created by this bot account, so you can reply instead of duplicating.',
69
+ parameters: {},
70
+ output: {
71
+ schema: { type: 'object', additionalProperties: false, properties: { text: { type: 'string', required: true } } },
72
+ render: (_args, value) => [{ type: 'text', text: value.text }],
73
+ },
74
+ async execute() {
75
+ const response = await fetch(`${apiBase}/discussions`, { headers });
76
+ if (!response.ok) {
77
+ throw new Error(`GitLab API error ${response.status}: ${await response.text()}`);
78
+ }
79
+ const discussions = await response.json();
80
+ const ownThreads = discussions
81
+ .filter(d => d.notes.length > 0 && d.notes[0].author.username === config.botUsername && !d.notes[0].resolved && d.notes[0].position !== undefined)
82
+ .map(d => ({ discussionId: d.id, path: d.notes[0].position.new_path, line: d.notes[0].position.new_line, lastCommentBody: d.notes[d.notes.length - 1].body }));
83
+ return { text: JSON.stringify(ownThreads) };
84
+ },
85
+ }));
86
+ ctx.tools.register(defineTool({
87
+ name: 'gitlab_post_inline_comment',
88
+ description: 'Create a new inline discussion at a specific file and line in this merge request\'s current diff.',
89
+ parameters: {
90
+ path: { type: 'string', required: true, description: 'File path on the new (target) side of the diff.' },
91
+ line: { type: 'number', required: true, description: 'Line number on the new (target) side of the diff.' },
92
+ body: { type: 'string', required: true, description: 'Markdown comment body.' },
93
+ },
94
+ output: {
95
+ schema: { type: 'object', additionalProperties: false, properties: { posted: { type: 'boolean', required: true } } },
96
+ render: () => [{ type: 'text', text: 'Inline comment posted.' }],
97
+ },
98
+ async execute(args) {
99
+ const diffRefs = await getDiffRefs();
100
+ const response = await fetch(`${apiBase}/discussions`, {
101
+ method: 'POST',
102
+ headers: { ...headers, 'Content-Type': 'application/json' },
103
+ body: JSON.stringify({
104
+ body: args.body,
105
+ position: {
106
+ position_type: 'text',
107
+ base_sha: diffRefs.base_sha,
108
+ start_sha: diffRefs.start_sha,
109
+ head_sha: diffRefs.head_sha,
110
+ old_path: args.path,
111
+ new_path: args.path,
112
+ new_line: args.line,
113
+ },
114
+ }),
115
+ });
116
+ if (!response.ok) {
117
+ throw new Error(`GitLab API error ${response.status}: ${await response.text()}`);
118
+ }
119
+ return { posted: true };
120
+ },
121
+ }));
122
+ ctx.tools.register(defineTool({
123
+ name: 'gitlab_reply_to_thread',
124
+ description: 'Reply to an existing inline discussion thread (discussionId from gitlab_list_own_review_threads) without resolving it.',
125
+ parameters: {
126
+ discussionId: { type: 'string', required: true },
127
+ body: { type: 'string', required: true, description: 'Markdown reply body.' },
128
+ },
129
+ output: {
130
+ schema: { type: 'object', additionalProperties: false, properties: { posted: { type: 'boolean', required: true } } },
131
+ render: () => [{ type: 'text', text: 'Reply posted.' }],
132
+ },
133
+ async execute(args) {
134
+ const response = await fetch(`${apiBase}/discussions/${args.discussionId}/notes`, {
135
+ method: 'POST',
136
+ headers: { ...headers, 'Content-Type': 'application/json' },
137
+ body: JSON.stringify({ body: args.body }),
138
+ });
139
+ if (!response.ok) {
140
+ throw new Error(`GitLab API error ${response.status}: ${await response.text()}`);
141
+ }
142
+ return { posted: true };
143
+ },
144
+ }));
145
+ }
146
+ //# sourceMappingURL=gitlab-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitlab-client.js","sourceRoot":"","sources":["../src/gitlab-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import z from '@deepseek-ai/schemastery';
3
+ export declare const name = "maestro-gitlab-webhook";
4
+ export interface Config {
5
+ port: number;
6
+ /** Username of the GitLab service account used for reviewer assignments. */
7
+ botUsername?: string;
8
+ /**
9
+ * Fallback when Maestro Settings has no webhook secret; optional so a
10
+ * deployment that configures everything through Settings boots without env
11
+ * vars. With neither source set, every request is rejected (fail closed).
12
+ */
13
+ secret?: string;
14
+ }
15
+ export declare const Config: z<Config>;
16
+ export declare function apply(ctx: Context, config: Config): void;
17
+ //# sourceMappingURL=gitlab-webhook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitlab-webhook.d.ts","sourceRoot":"","sources":["../src/gitlab-webhook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAMxC,eAAO,MAAM,IAAI,2BAA2B,CAAA;AAE5C,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAI3B,CAAA;AAkDF,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAyFxD"}
@@ -0,0 +1,144 @@
1
+ import { createServer } from 'node:http';
2
+ import z from '@deepseek-ai/schemastery';
3
+ import { loadUserConfig } from './config-store.js';
4
+ import { secretsMatch } from './secure-compare.js';
5
+ import { routeGitlabReviewRequest } from './review-intake.js';
6
+ export const name = 'maestro-gitlab-webhook';
7
+ export const Config = z.object({
8
+ port: z.natural().max(65535).required(),
9
+ botUsername: z.string(),
10
+ secret: z.string().role('secret'),
11
+ });
12
+ /** GitLab payloads are small; 5 MB is generous and stops unbounded buffering. */
13
+ const MAX_WEBHOOK_BODY_BYTES = 5 * 1024 * 1024;
14
+ function readBody(req, limit = MAX_WEBHOOK_BODY_BYTES) {
15
+ return new Promise((resolvePromise) => {
16
+ let raw = '';
17
+ let settled = false;
18
+ req.on('data', (chunk) => {
19
+ if (settled)
20
+ return;
21
+ if (raw.length + chunk.length > limit) {
22
+ settled = true;
23
+ req.resume();
24
+ resolvePromise(undefined);
25
+ return;
26
+ }
27
+ raw += chunk.toString();
28
+ });
29
+ req.on('end', () => { if (!settled) {
30
+ settled = true;
31
+ resolvePromise(raw);
32
+ } });
33
+ req.on('error', () => { if (!settled) {
34
+ settled = true;
35
+ resolvePromise(undefined);
36
+ } });
37
+ });
38
+ }
39
+ function isValidMrOpenedPayload(value) {
40
+ if (typeof value !== 'object' || value === null)
41
+ return false;
42
+ const v = value;
43
+ return typeof v.projectPath === 'string'
44
+ && typeof v.projectId === 'number'
45
+ && typeof v.mrIid === 'number'
46
+ && typeof v.sourceBranch === 'string';
47
+ }
48
+ function hasValidGitlabMrIdentity(value) {
49
+ if (typeof value !== 'object' || value === null)
50
+ return false;
51
+ const body = value;
52
+ const project = body.project;
53
+ const attributes = body.object_attributes;
54
+ const mergeRequest = body.merge_request;
55
+ const source = body.object_kind === 'note' ? mergeRequest : attributes;
56
+ return typeof project?.id === 'number' && typeof project.path_with_namespace === 'string'
57
+ && typeof source?.iid === 'number' && typeof source.source_branch === 'string';
58
+ }
59
+ export function apply(ctx, config) {
60
+ // Settings wins over the boot secret, re-read per request so a change in the
61
+ // UI takes effect without a restart. With neither source set, every token
62
+ // fails the comparison (a header string never equals `undefined`), so the
63
+ // server stays closed until a secret is configured.
64
+ let warnedUnconfigured = false;
65
+ async function requestAuthorized(headerValue) {
66
+ const userConfig = await loadUserConfig();
67
+ const expected = userConfig.webhookSecret ?? config.secret;
68
+ if (expected === undefined) {
69
+ if (!warnedUnconfigured) {
70
+ warnedUnconfigured = true;
71
+ console.error('maestro-gitlab-webhook: no webhook secret configured — set one in Maestro Settings or MAESTRO_GITLAB_WEBHOOK_SECRET; rejecting all requests until then');
72
+ }
73
+ return false;
74
+ }
75
+ return secretsMatch(headerValue, expected);
76
+ }
77
+ const server = createServer((req, res) => {
78
+ if (req.method !== 'POST') {
79
+ res.writeHead(404).end();
80
+ return;
81
+ }
82
+ void requestAuthorized(req.headers['x-gitlab-token']).then(async (authorized) => {
83
+ if (!authorized) {
84
+ res.writeHead(401).end();
85
+ return;
86
+ }
87
+ readBody(req).then(async (raw) => {
88
+ if (raw === undefined) {
89
+ res.writeHead(413).end();
90
+ return;
91
+ }
92
+ if (req.url === '/hooks/gitlab-mr/trigger') {
93
+ let parsed;
94
+ try {
95
+ parsed = JSON.parse(raw);
96
+ }
97
+ catch {
98
+ res.writeHead(400).end();
99
+ return;
100
+ }
101
+ if (!isValidMrOpenedPayload(parsed)) {
102
+ res.writeHead(400).end();
103
+ return;
104
+ }
105
+ const request = {
106
+ ...parsed,
107
+ trigger: 'mention',
108
+ mode: 'quick',
109
+ scope: { kind: 'mr' },
110
+ };
111
+ ctx.emit('maestro/review-request', request);
112
+ res.writeHead(200).end();
113
+ return;
114
+ }
115
+ if (req.url !== '/hooks/gitlab-mr') {
116
+ res.writeHead(404).end();
117
+ return;
118
+ }
119
+ let body;
120
+ try {
121
+ body = JSON.parse(raw);
122
+ }
123
+ catch {
124
+ res.writeHead(400).end();
125
+ return;
126
+ }
127
+ const userConfig = await loadUserConfig();
128
+ if ((body.object_kind === 'merge_request' || body.object_kind === 'note') && !hasValidGitlabMrIdentity(body)) {
129
+ res.writeHead(400).end();
130
+ return;
131
+ }
132
+ const request = routeGitlabReviewRequest(body, userConfig.botUsername ?? config.botUsername ?? 'maestro', { pushEnabled: userConfig.autoRereviewOnPush === true });
133
+ if (request !== undefined)
134
+ ctx.emit('maestro/review-request', request);
135
+ res.writeHead(200).end();
136
+ });
137
+ });
138
+ });
139
+ server.listen(config.port);
140
+ ctx.effect(() => async () => {
141
+ await new Promise((resolve) => { server.close(() => resolve()); });
142
+ }, 'gitlab-webhook teardown');
143
+ }
144
+ //# sourceMappingURL=gitlab-webhook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitlab-webhook.js","sourceRoot":"","sources":["../src/gitlab-webhook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import z from '@deepseek-ai/schemastery';
3
+ export declare const name = "maestro-govard-tool";
4
+ export declare const inject: string[];
5
+ export interface Config {
6
+ rootPath?: string;
7
+ timeoutMs?: number;
8
+ }
9
+ export declare const Config: z<Config>;
10
+ export declare function apply(ctx: Context, config: Config): void;
11
+ //# sourceMappingURL=govard-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"govard-tool.d.ts","sourceRoot":"","sources":["../src/govard-tool.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAGxC,eAAO,MAAM,IAAI,wBAAwB,CAAA;AACzC,eAAO,MAAM,MAAM,UAAY,CAAA;AAE/B,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAG3B,CAAA;AAqCF,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CA0DxD"}