opencode-gitlab-dap 1.9.0 → 1.10.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/README.md +13 -8
- package/dist/index.cjs +166 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +166 -58
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1913,18 +1913,6 @@ var FLOW_DISPATCH_GUIDELINES = [
|
|
|
1913
1913
|
`resources yourself using GitLab API tools, then dispatch ONE general subagent whose prompt`,
|
|
1914
1914
|
`includes all flow executions (N flows x M resources) to run in parallel.`
|
|
1915
1915
|
].join("\n");
|
|
1916
|
-
var AGENT_CREATION_GUIDELINES = `## Creating Custom GitLab Agents
|
|
1917
|
-
|
|
1918
|
-
Before calling gitlab_create_agent, you MUST:
|
|
1919
|
-
1. Call gitlab_list_builtin_tools and gitlab_list_project_mcp_servers.
|
|
1920
|
-
2. Ask the user 4 questions using the question tool (one call, all 4 questions):
|
|
1921
|
-
- Agent name (suggest one, allow custom)
|
|
1922
|
-
- Visibility: Public or Private
|
|
1923
|
-
- Tools: show tools grouped by category as multi-select (Search, Issues, MRs, Epics, Files, Git, CI/CD, Security, Audit, Planning, Wiki, API)
|
|
1924
|
-
- MCP servers: multi-select from available servers
|
|
1925
|
-
3. Show the generated system prompt and ask for confirmation.
|
|
1926
|
-
4. Only then call gitlab_create_agent. Use full tool GIDs like "gid://gitlab/Ai::Catalog::BuiltInTool/1".
|
|
1927
|
-
5. Ask if the user wants to enable it on the current project.`;
|
|
1928
1916
|
var FLOW_SCHEMA_REFERENCE = `## Flow YAML Schema Reference
|
|
1929
1917
|
|
|
1930
1918
|
### Top-level structure (all required unless noted):
|
|
@@ -2085,35 +2073,6 @@ prompts:
|
|
|
2085
2073
|
user: "Fix this vulnerability: {{vuln_data}}"
|
|
2086
2074
|
placeholder: history
|
|
2087
2075
|
\`\`\``;
|
|
2088
|
-
var PROJECT_KNOWLEDGE_HINT = `## Project Knowledge
|
|
2089
|
-
This project may have persistent memory and skills available via knowledge tools.
|
|
2090
|
-
Use gitlab_memory_load to check for existing project context (facts, decisions, patterns).
|
|
2091
|
-
Use gitlab_skill_list to discover available task-specific skills.
|
|
2092
|
-
When you learn something new about the project, use gitlab_memory_record to preserve it.
|
|
2093
|
-
When you complete a significant task, consider using gitlab_memory_log_session to log learnings.
|
|
2094
|
-
|
|
2095
|
-
### Bootstrap Project Memory
|
|
2096
|
-
When the user says "bootstrap project memory", "initialize memory", or "build project knowledge":
|
|
2097
|
-
1. FIRST: Determine the project path by running \`run_git_command("remote", ["-v"])\` and extracting the path from the git remote URL (e.g., "git@gitlab.com:my-group/my-project.git" \u2192 "my-group/my-project"). NEVER guess the project path.
|
|
2098
|
-
2. Call gitlab_memory_load with the extracted project path to check if memory already exists.
|
|
2099
|
-
3. If memory exists, show a summary and ask if the user wants to refresh it.
|
|
2100
|
-
4. If memory is empty (or user wants refresh), gather project knowledge by:
|
|
2101
|
-
a. Read the project README, key config files, and codebase structure (use file/repo tools).
|
|
2102
|
-
b. Fetch project details via gitlab_get_project.
|
|
2103
|
-
c. List open issues (gitlab_list_issues, state=opened, limit=20).
|
|
2104
|
-
d. List open merge requests (gitlab_list_merge_requests, state=opened, limit=10).
|
|
2105
|
-
e. Check recent pipelines (gitlab_list_pipelines, limit=5).
|
|
2106
|
-
f. List project members (gitlab_list_project_members).
|
|
2107
|
-
5. Record each category as separate memory entries using gitlab_memory_record:
|
|
2108
|
-
- fact: project overview (name, purpose, tech stack, language, dependencies)
|
|
2109
|
-
- fact: architecture and codebase structure (key files, modules, patterns)
|
|
2110
|
-
- fact: CI/CD pipeline configuration (stages, jobs, deployment targets)
|
|
2111
|
-
- fact: open issues summary (count, key issues, labels)
|
|
2112
|
-
- fact: open MRs summary (count, key MRs, review status)
|
|
2113
|
-
- fact: team and contributors
|
|
2114
|
-
- pattern: development workflow observations (branching, review process, release cycle)
|
|
2115
|
-
6. Log a session with gitlab_memory_log_session summarizing the bootstrap.
|
|
2116
|
-
IMPORTANT: Always extract the project path from git remote \u2014 never guess it. Fire multiple gitlab_memory_record calls in parallel \u2014 each creates its own page, so parallel writes are safe.`;
|
|
2117
2076
|
|
|
2118
2077
|
// src/hooks.ts
|
|
2119
2078
|
function buildFlowSubagentPrompt(flow, projectPath, projectUrl) {
|
|
@@ -2272,8 +2231,10 @@ function makeSystemTransformHook(flowAgents, getAuthCache) {
|
|
|
2272
2231
|
output.system.push(FLOW_DISPATCH_GUIDELINES);
|
|
2273
2232
|
}
|
|
2274
2233
|
if (getAuthCache()) {
|
|
2275
|
-
output.system.push(
|
|
2276
|
-
|
|
2234
|
+
output.system.push(
|
|
2235
|
+
`## Project Knowledge
|
|
2236
|
+
Project memory tools are available (gitlab_memory_load, gitlab_memory_record, gitlab_memory_recall). Say "bootstrap project memory" to initialize or refresh project knowledge.`
|
|
2237
|
+
);
|
|
2277
2238
|
}
|
|
2278
2239
|
};
|
|
2279
2240
|
}
|
|
@@ -3466,17 +3427,20 @@ async function searchWikiPages(instanceUrl, token, scope, id, query) {
|
|
|
3466
3427
|
// src/tools/memory-tools.ts
|
|
3467
3428
|
var z5 = tool5.schema;
|
|
3468
3429
|
var PREFIX = "agents";
|
|
3430
|
+
var ARCHIVE_DIR = `${PREFIX}/memory/archive`;
|
|
3469
3431
|
var MEMORY_DIRS = {
|
|
3470
3432
|
all: [`${PREFIX}/memory/facts`, `${PREFIX}/memory/decisions`, `${PREFIX}/memory/patterns`],
|
|
3471
3433
|
facts: [`${PREFIX}/memory/facts`],
|
|
3472
3434
|
decisions: [`${PREFIX}/memory/decisions`],
|
|
3473
|
-
patterns: [`${PREFIX}/memory/patterns`]
|
|
3435
|
+
patterns: [`${PREFIX}/memory/patterns`],
|
|
3436
|
+
archive: [ARCHIVE_DIR]
|
|
3474
3437
|
};
|
|
3475
3438
|
var RECORD_DIR = {
|
|
3476
3439
|
fact: `${PREFIX}/memory/facts`,
|
|
3477
3440
|
decision: `${PREFIX}/memory/decisions`,
|
|
3478
3441
|
pattern: `${PREFIX}/memory/patterns`
|
|
3479
3442
|
};
|
|
3443
|
+
var PROJECT_ID_DESC = 'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.';
|
|
3480
3444
|
function today() {
|
|
3481
3445
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3482
3446
|
}
|
|
@@ -3509,12 +3473,12 @@ function makeMemoryTools(ctx) {
|
|
|
3509
3473
|
}
|
|
3510
3474
|
return {
|
|
3511
3475
|
gitlab_memory_load: tool5({
|
|
3512
|
-
description: "Load project memory to understand context, known facts, past decisions, and observed patterns.\nUse this at the start of complex tasks to check what is already known about the project.\nReturns accumulated knowledge from previous sessions.",
|
|
3476
|
+
description: "Load project memory to understand context, known facts, past decisions, and observed patterns.\nUse this at the start of complex tasks to check what is already known about the project.\nReturns accumulated knowledge from previous sessions.\nEach entry includes its slug (page path) which can be used with gitlab_memory_update or gitlab_memory_archive.\n\nBOOTSTRAP WORKFLOW \u2014 when user says 'bootstrap project memory':\n1. Get project path from run_git_command('remote', ['-v']) \u2014 NEVER guess.\n2. Call this tool to check if memory exists.\n3. If empty: gather knowledge (README, gitlab_get_project, gitlab_list_issues, gitlab_list_merge_requests, gitlab_list_pipelines, gitlab_list_project_members), then fire parallel gitlab_memory_record calls.\n4. If exists: show summary, gather current state, compare with stored facts, use gitlab_memory_update for stale, gitlab_memory_archive for outdated, gitlab_memory_record for new.\n5. Log session with gitlab_memory_log_session.",
|
|
3513
3477
|
args: {
|
|
3514
|
-
project_id: z5.string().describe(
|
|
3515
|
-
|
|
3478
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3479
|
+
type: z5.enum(["all", "facts", "decisions", "patterns", "archive"]).optional().describe(
|
|
3480
|
+
'Which memory to load: "all" (default), "facts", "decisions", "patterns", or "archive" (retired entries)'
|
|
3516
3481
|
),
|
|
3517
|
-
type: z5.enum(["all", "facts", "decisions", "patterns"]).optional().describe('Which memory to load: "all" (default), "facts", "decisions", or "patterns"'),
|
|
3518
3482
|
scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
|
|
3519
3483
|
group_id: z5.string().optional().describe("Group path (required when scope is groups)")
|
|
3520
3484
|
},
|
|
@@ -3537,7 +3501,8 @@ function makeMemoryTools(ctx) {
|
|
|
3537
3501
|
const label = dir.split("/").pop();
|
|
3538
3502
|
const pages = allPages.filter((p) => p.slug.startsWith(dir + "/") && p.content);
|
|
3539
3503
|
if (pages.length === 0) continue;
|
|
3540
|
-
const entries = pages.map((p) => p.
|
|
3504
|
+
const entries = pages.map((p) => `### ${p.slug}
|
|
3505
|
+
${p.content}`).join("\n\n---\n\n");
|
|
3541
3506
|
sections.push(
|
|
3542
3507
|
`## ${label.charAt(0).toUpperCase() + label.slice(1)} (${pages.length})
|
|
3543
3508
|
|
|
@@ -3555,9 +3520,7 @@ ${entries}`
|
|
|
3555
3520
|
gitlab_memory_record: tool5({
|
|
3556
3521
|
description: "Record a fact, decision, or pattern in project memory.\nFacts: stable truths about the project (e.g., deploy targets, tech stack, team conventions).\nDecisions: architectural choices with reasoning (why X was chosen over Y).\nPatterns: recurring observations that may evolve into skills over time.\nEach record creates its own page \u2014 safe for parallel writes.",
|
|
3557
3522
|
args: {
|
|
3558
|
-
project_id: z5.string().describe(
|
|
3559
|
-
'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
|
|
3560
|
-
),
|
|
3523
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3561
3524
|
type: z5.enum(["fact", "decision", "pattern"]).describe("Type of knowledge to record"),
|
|
3562
3525
|
content: z5.string().describe("The knowledge to record (markdown)"),
|
|
3563
3526
|
scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
|
|
@@ -3583,12 +3546,159 @@ ${entries}`
|
|
|
3583
3546
|
}
|
|
3584
3547
|
}
|
|
3585
3548
|
}),
|
|
3549
|
+
gitlab_memory_update: tool5({
|
|
3550
|
+
description: "Update an existing memory record with new content.\nUse this to correct stale facts, update issue counts, or refine decisions.\nThe slug is the page path shown in gitlab_memory_load output (e.g., agents/memory/facts/2026-04-05-project-overview).",
|
|
3551
|
+
args: {
|
|
3552
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3553
|
+
slug: z5.string().describe(
|
|
3554
|
+
'Page slug from gitlab_memory_load output (e.g., "agents/memory/facts/2026-04-05-project-overview")'
|
|
3555
|
+
),
|
|
3556
|
+
content: z5.string().describe("New content to replace the existing record (markdown)"),
|
|
3557
|
+
scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
|
|
3558
|
+
group_id: z5.string().optional().describe("Group path (required when scope is groups)")
|
|
3559
|
+
},
|
|
3560
|
+
execute: async (args) => {
|
|
3561
|
+
const auth = authAndValidate(args.project_id);
|
|
3562
|
+
const { scope, id } = resolveScope(args);
|
|
3563
|
+
try {
|
|
3564
|
+
await getWikiPage(auth.instanceUrl, auth.token, scope, id, args.slug);
|
|
3565
|
+
} catch {
|
|
3566
|
+
return `Memory record not found: ${args.slug}. Use gitlab_memory_load to see available records.`;
|
|
3567
|
+
}
|
|
3568
|
+
const date = today();
|
|
3569
|
+
const header = `*Updated: ${date}*
|
|
3570
|
+
|
|
3571
|
+
`;
|
|
3572
|
+
try {
|
|
3573
|
+
await updateWikiPage(
|
|
3574
|
+
auth.instanceUrl,
|
|
3575
|
+
auth.token,
|
|
3576
|
+
scope,
|
|
3577
|
+
id,
|
|
3578
|
+
args.slug,
|
|
3579
|
+
header + args.content
|
|
3580
|
+
);
|
|
3581
|
+
return `Updated memory record: ${args.slug}`;
|
|
3582
|
+
} catch (err) {
|
|
3583
|
+
return `Error updating memory: ${err.message}`;
|
|
3584
|
+
}
|
|
3585
|
+
}
|
|
3586
|
+
}),
|
|
3587
|
+
gitlab_memory_archive: tool5({
|
|
3588
|
+
description: "Archive an outdated memory record.\nMoves the record to the archive directory so it is no longer loaded by default.\nArchived records are still searchable via gitlab_memory_recall and loadable via gitlab_memory_load(type='archive').\nUse this for facts that are no longer true, decisions that were reversed, or patterns that stopped occurring.",
|
|
3589
|
+
args: {
|
|
3590
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3591
|
+
slug: z5.string().describe(
|
|
3592
|
+
'Page slug to archive (e.g., "agents/memory/facts/2026-04-05-open-issues-summary")'
|
|
3593
|
+
),
|
|
3594
|
+
reason: z5.string().optional().describe(
|
|
3595
|
+
'Why this record is being archived (e.g., "issue was fixed", "no longer relevant")'
|
|
3596
|
+
),
|
|
3597
|
+
scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
|
|
3598
|
+
group_id: z5.string().optional().describe("Group path (required when scope is groups)")
|
|
3599
|
+
},
|
|
3600
|
+
execute: async (args) => {
|
|
3601
|
+
const auth = authAndValidate(args.project_id);
|
|
3602
|
+
const { scope, id } = resolveScope(args);
|
|
3603
|
+
let originalContent;
|
|
3604
|
+
try {
|
|
3605
|
+
const page = await getWikiPage(auth.instanceUrl, auth.token, scope, id, args.slug);
|
|
3606
|
+
originalContent = page.content;
|
|
3607
|
+
} catch {
|
|
3608
|
+
return `Memory record not found: ${args.slug}. Use gitlab_memory_load to see available records.`;
|
|
3609
|
+
}
|
|
3610
|
+
const date = today();
|
|
3611
|
+
const suffix = args.slug.split("/").slice(3).join("/");
|
|
3612
|
+
const archiveSlug = `${ARCHIVE_DIR}/${suffix}`;
|
|
3613
|
+
const reasonLine = args.reason ? `
|
|
3614
|
+
*Reason: ${args.reason}*` : "";
|
|
3615
|
+
const archiveHeader = `*Archived: ${date} | Original: ${args.slug}*${reasonLine}
|
|
3616
|
+
|
|
3617
|
+
`;
|
|
3618
|
+
try {
|
|
3619
|
+
await createWikiPage(
|
|
3620
|
+
auth.instanceUrl,
|
|
3621
|
+
auth.token,
|
|
3622
|
+
scope,
|
|
3623
|
+
id,
|
|
3624
|
+
archiveSlug,
|
|
3625
|
+
archiveHeader + originalContent
|
|
3626
|
+
);
|
|
3627
|
+
await deleteWikiPage(auth.instanceUrl, auth.token, scope, id, args.slug);
|
|
3628
|
+
return `Archived: ${args.slug} \u2192 ${archiveSlug}`;
|
|
3629
|
+
} catch (err) {
|
|
3630
|
+
return `Error archiving memory: ${err.message}`;
|
|
3631
|
+
}
|
|
3632
|
+
}
|
|
3633
|
+
}),
|
|
3634
|
+
gitlab_memory_consolidate: tool5({
|
|
3635
|
+
description: "Review all memory records and get consolidation instructions.\nLoads all records of the specified type and returns them with their slugs,\nalong with instructions to identify and fix stale, duplicate, or contradictory entries.\nUse this periodically to keep project memory clean and accurate.",
|
|
3636
|
+
args: {
|
|
3637
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3638
|
+
type: z5.enum(["all", "facts", "decisions", "patterns"]).optional().describe(
|
|
3639
|
+
'Which memory to consolidate: "all" (default), "facts", "decisions", or "patterns"'
|
|
3640
|
+
),
|
|
3641
|
+
scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
|
|
3642
|
+
group_id: z5.string().optional().describe("Group path (required when scope is groups)")
|
|
3643
|
+
},
|
|
3644
|
+
execute: async (args) => {
|
|
3645
|
+
const auth = authAndValidate(args.project_id);
|
|
3646
|
+
const { scope, id } = resolveScope(args);
|
|
3647
|
+
const memType = args.type ?? "all";
|
|
3648
|
+
const dirs = MEMORY_DIRS[memType];
|
|
3649
|
+
if (!dirs) return `Unknown memory type: ${memType}`;
|
|
3650
|
+
try {
|
|
3651
|
+
const allPages = await listWikiPages(
|
|
3652
|
+
auth.instanceUrl,
|
|
3653
|
+
auth.token,
|
|
3654
|
+
scope,
|
|
3655
|
+
id,
|
|
3656
|
+
true
|
|
3657
|
+
);
|
|
3658
|
+
const entries = [];
|
|
3659
|
+
for (const dir of dirs) {
|
|
3660
|
+
const pages = allPages.filter((p) => p.slug.startsWith(dir + "/") && p.content);
|
|
3661
|
+
for (const p of pages) {
|
|
3662
|
+
entries.push({ slug: p.slug, content: p.content });
|
|
3663
|
+
}
|
|
3664
|
+
}
|
|
3665
|
+
if (entries.length === 0) return "No memory records to consolidate.";
|
|
3666
|
+
const listing = entries.map((e, i) => `### [${i + 1}] ${e.slug}
|
|
3667
|
+
${e.content}`).join("\n\n---\n\n");
|
|
3668
|
+
const instructions = [
|
|
3669
|
+
`## Memory Consolidation Review`,
|
|
3670
|
+
``,
|
|
3671
|
+
`Found **${entries.length} records** to review. For each record:`,
|
|
3672
|
+
``,
|
|
3673
|
+
`1. **Stale?** \u2014 Is the information still current? If not, either:`,
|
|
3674
|
+
` - Call \`gitlab_memory_update(slug, new_content)\` with corrected info`,
|
|
3675
|
+
` - Call \`gitlab_memory_archive(slug, reason)\` if no longer relevant`,
|
|
3676
|
+
``,
|
|
3677
|
+
`2. **Duplicate?** \u2014 Does another record cover the same information?`,
|
|
3678
|
+
` - Keep the better one, archive the other`,
|
|
3679
|
+
``,
|
|
3680
|
+
`3. **Contradictory?** \u2014 Do two records disagree?`,
|
|
3681
|
+
` - Verify which is correct, update one, archive the other`,
|
|
3682
|
+
``,
|
|
3683
|
+
`4. **Mergeable?** \u2014 Are there many small records about the same topic?`,
|
|
3684
|
+
` - Create one consolidated record, archive the originals`,
|
|
3685
|
+
``,
|
|
3686
|
+
`After reviewing, log a session with gitlab_memory_log_session summarizing what was cleaned up.`,
|
|
3687
|
+
``,
|
|
3688
|
+
`---`,
|
|
3689
|
+
``,
|
|
3690
|
+
listing
|
|
3691
|
+
].join("\n");
|
|
3692
|
+
return instructions;
|
|
3693
|
+
} catch (err) {
|
|
3694
|
+
return `Error loading memory for consolidation: ${err.message}`;
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3697
|
+
}),
|
|
3586
3698
|
gitlab_memory_recall: tool5({
|
|
3587
3699
|
description: "Search project knowledge for relevant information.\nSearches across all memory pages, session logs, and skills.\nUse this to check if something is already known before investigating.",
|
|
3588
3700
|
args: {
|
|
3589
|
-
project_id: z5.string().describe(
|
|
3590
|
-
'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
|
|
3591
|
-
),
|
|
3701
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3592
3702
|
query: z5.string().describe("What to search for"),
|
|
3593
3703
|
scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
|
|
3594
3704
|
group_id: z5.string().optional().describe("Group path (required when scope is groups)")
|
|
@@ -3618,9 +3728,7 @@ ${entries}`
|
|
|
3618
3728
|
gitlab_memory_log_session: tool5({
|
|
3619
3729
|
description: "Log a session summary including what was accomplished, what was learned, and any suggestions.\nUse this at the end of significant work sessions to preserve context for future sessions.",
|
|
3620
3730
|
args: {
|
|
3621
|
-
project_id: z5.string().describe(
|
|
3622
|
-
'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
|
|
3623
|
-
),
|
|
3731
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3624
3732
|
title: z5.string().describe('Brief session title (e.g., "fix-ai-gateway-healthcheck")'),
|
|
3625
3733
|
summary: z5.string().describe(
|
|
3626
3734
|
"Session summary in markdown (what happened, what was learned, what went wrong)"
|