opencode-gitlab-dap 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -8
- package/dist/index.cjs +196 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +196 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -110,7 +110,7 @@ The plugin provides a multi-round design workflow:
|
|
|
110
110
|
|
|
111
111
|
The vendored `flow_v2.json` schema from GitLab Rails powers client-side validation using `ajv`, catching errors before hitting the API.
|
|
112
112
|
|
|
113
|
-
###
|
|
113
|
+
### 31 Tools
|
|
114
114
|
|
|
115
115
|
#### DAP Tools (20)
|
|
116
116
|
|
|
@@ -137,18 +137,23 @@ The vendored `flow_v2.json` schema from GitLab Rails powers client-side validati
|
|
|
137
137
|
| `gitlab_get_workflow_status` | Monitor workflow execution status and logs |
|
|
138
138
|
| `gitlab_list_project_mcp_servers` | List MCP servers available for project agents |
|
|
139
139
|
|
|
140
|
-
#### Project Knowledge Tools (
|
|
140
|
+
#### Project Knowledge Tools (11)
|
|
141
141
|
|
|
142
142
|
Persistent project memory and reusable skills. Knowledge is stored in GitLab project/group wikis but tools abstract the storage — the agent works with facts, decisions, patterns, and skills.
|
|
143
143
|
|
|
144
|
+
Say **"bootstrap project memory"** to automatically inspect a project and build its knowledge base. If memory already exists, it does a smart refresh — updating stale facts and archiving outdated entries.
|
|
145
|
+
|
|
144
146
|
##### Memory Tools
|
|
145
147
|
|
|
146
|
-
| Tool | Description
|
|
147
|
-
| --------------------------- |
|
|
148
|
-
| `gitlab_memory_load` | Load project memory (facts, decisions, patterns,
|
|
149
|
-
| `gitlab_memory_record` | Record a fact, decision, or pattern (auto-timestamped)
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
148
|
+
| Tool | Description |
|
|
149
|
+
| --------------------------- | --------------------------------------------------------------- |
|
|
150
|
+
| `gitlab_memory_load` | Load project memory (facts, decisions, patterns, archive) |
|
|
151
|
+
| `gitlab_memory_record` | Record a fact, decision, or pattern (auto-timestamped) |
|
|
152
|
+
| `gitlab_memory_update` | Update an existing memory record with corrected content |
|
|
153
|
+
| `gitlab_memory_archive` | Archive an outdated record (moved to archive, still searchable) |
|
|
154
|
+
| `gitlab_memory_consolidate` | Review all memory and get cleanup instructions |
|
|
155
|
+
| `gitlab_memory_recall` | Search project knowledge for relevant information |
|
|
156
|
+
| `gitlab_memory_log_session` | Log a session summary with learnings |
|
|
152
157
|
|
|
153
158
|
##### Skill Tools
|
|
154
159
|
|
package/dist/index.cjs
CHANGED
|
@@ -2265,23 +2265,40 @@ When you complete a significant task, consider using gitlab_memory_log_session t
|
|
|
2265
2265
|
When the user says "bootstrap project memory", "initialize memory", or "build project knowledge":
|
|
2266
2266
|
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.
|
|
2267
2267
|
2. Call gitlab_memory_load with the extracted project path to check if memory already exists.
|
|
2268
|
-
3. If memory
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2268
|
+
3. **If memory is empty** \u2014 do a full bootstrap:
|
|
2269
|
+
a. Gather project knowledge:
|
|
2270
|
+
- Read the project README, key config files, and codebase structure (use file/repo tools).
|
|
2271
|
+
- Fetch project details via gitlab_get_project.
|
|
2272
|
+
- List open issues (gitlab_list_issues, state=opened, limit=20).
|
|
2273
|
+
- List open merge requests (gitlab_list_merge_requests, state=opened, limit=10).
|
|
2274
|
+
- Check recent pipelines (gitlab_list_pipelines, limit=5).
|
|
2275
|
+
- List project members (gitlab_list_project_members).
|
|
2276
|
+
b. Record each category as separate memory entries using gitlab_memory_record:
|
|
2277
|
+
- fact: project overview (name, purpose, tech stack, language, dependencies)
|
|
2278
|
+
- fact: architecture and codebase structure (key files, modules, patterns)
|
|
2279
|
+
- fact: CI/CD pipeline configuration (stages, jobs, deployment targets)
|
|
2280
|
+
- fact: open issues summary (count, key issues, labels)
|
|
2281
|
+
- fact: open MRs summary (count, key MRs, review status)
|
|
2282
|
+
- fact: team and contributors
|
|
2283
|
+
- pattern: development workflow observations (branching, review process, release cycle)
|
|
2284
|
+
c. Log a session with gitlab_memory_log_session summarizing the bootstrap.
|
|
2285
|
+
4. **If memory exists** \u2014 do a smart refresh:
|
|
2286
|
+
a. Show a brief summary of existing memory to the user (how many facts, decisions, patterns, date range).
|
|
2287
|
+
b. Gather CURRENT project state (same data as step 3a).
|
|
2288
|
+
c. Compare current state with each stored fact. For each record:
|
|
2289
|
+
- If the fact is still accurate \u2192 keep it (no action).
|
|
2290
|
+
- If the fact is outdated \u2192 call gitlab_memory_update(slug, corrected_content).
|
|
2291
|
+
- If the fact is no longer relevant (e.g., closed issue) \u2192 call gitlab_memory_archive(slug, reason).
|
|
2292
|
+
- If something new is found that's not in memory \u2192 call gitlab_memory_record.
|
|
2293
|
+
d. Log a session with gitlab_memory_log_session summarizing the refresh (what was updated, archived, added).
|
|
2294
|
+
|
|
2295
|
+
### Memory Consolidation
|
|
2296
|
+
When the user says "consolidate memory", "clean up memory", or "review memory":
|
|
2297
|
+
1. Call gitlab_memory_consolidate to load all records with review instructions.
|
|
2298
|
+
2. Follow the returned instructions to identify stale, duplicate, or contradictory entries.
|
|
2299
|
+
3. Use gitlab_memory_update, gitlab_memory_archive, and gitlab_memory_record as needed.
|
|
2300
|
+
4. Log a consolidation session.
|
|
2301
|
+
|
|
2285
2302
|
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.`;
|
|
2286
2303
|
|
|
2287
2304
|
// src/hooks.ts
|
|
@@ -3635,17 +3652,20 @@ async function searchWikiPages(instanceUrl, token, scope, id, query) {
|
|
|
3635
3652
|
// src/tools/memory-tools.ts
|
|
3636
3653
|
var z5 = import_plugin5.tool.schema;
|
|
3637
3654
|
var PREFIX = "agents";
|
|
3655
|
+
var ARCHIVE_DIR = `${PREFIX}/memory/archive`;
|
|
3638
3656
|
var MEMORY_DIRS = {
|
|
3639
3657
|
all: [`${PREFIX}/memory/facts`, `${PREFIX}/memory/decisions`, `${PREFIX}/memory/patterns`],
|
|
3640
3658
|
facts: [`${PREFIX}/memory/facts`],
|
|
3641
3659
|
decisions: [`${PREFIX}/memory/decisions`],
|
|
3642
|
-
patterns: [`${PREFIX}/memory/patterns`]
|
|
3660
|
+
patterns: [`${PREFIX}/memory/patterns`],
|
|
3661
|
+
archive: [ARCHIVE_DIR]
|
|
3643
3662
|
};
|
|
3644
3663
|
var RECORD_DIR = {
|
|
3645
3664
|
fact: `${PREFIX}/memory/facts`,
|
|
3646
3665
|
decision: `${PREFIX}/memory/decisions`,
|
|
3647
3666
|
pattern: `${PREFIX}/memory/patterns`
|
|
3648
3667
|
};
|
|
3668
|
+
var PROJECT_ID_DESC = 'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.';
|
|
3649
3669
|
function today() {
|
|
3650
3670
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3651
3671
|
}
|
|
@@ -3678,12 +3698,12 @@ function makeMemoryTools(ctx) {
|
|
|
3678
3698
|
}
|
|
3679
3699
|
return {
|
|
3680
3700
|
gitlab_memory_load: (0, import_plugin5.tool)({
|
|
3681
|
-
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.",
|
|
3701
|
+
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.",
|
|
3682
3702
|
args: {
|
|
3683
|
-
project_id: z5.string().describe(
|
|
3684
|
-
|
|
3703
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3704
|
+
type: z5.enum(["all", "facts", "decisions", "patterns", "archive"]).optional().describe(
|
|
3705
|
+
'Which memory to load: "all" (default), "facts", "decisions", "patterns", or "archive" (retired entries)'
|
|
3685
3706
|
),
|
|
3686
|
-
type: z5.enum(["all", "facts", "decisions", "patterns"]).optional().describe('Which memory to load: "all" (default), "facts", "decisions", or "patterns"'),
|
|
3687
3707
|
scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
|
|
3688
3708
|
group_id: z5.string().optional().describe("Group path (required when scope is groups)")
|
|
3689
3709
|
},
|
|
@@ -3706,7 +3726,8 @@ function makeMemoryTools(ctx) {
|
|
|
3706
3726
|
const label = dir.split("/").pop();
|
|
3707
3727
|
const pages = allPages.filter((p) => p.slug.startsWith(dir + "/") && p.content);
|
|
3708
3728
|
if (pages.length === 0) continue;
|
|
3709
|
-
const entries = pages.map((p) => p.
|
|
3729
|
+
const entries = pages.map((p) => `### ${p.slug}
|
|
3730
|
+
${p.content}`).join("\n\n---\n\n");
|
|
3710
3731
|
sections.push(
|
|
3711
3732
|
`## ${label.charAt(0).toUpperCase() + label.slice(1)} (${pages.length})
|
|
3712
3733
|
|
|
@@ -3724,9 +3745,7 @@ ${entries}`
|
|
|
3724
3745
|
gitlab_memory_record: (0, import_plugin5.tool)({
|
|
3725
3746
|
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.",
|
|
3726
3747
|
args: {
|
|
3727
|
-
project_id: z5.string().describe(
|
|
3728
|
-
'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
|
|
3729
|
-
),
|
|
3748
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3730
3749
|
type: z5.enum(["fact", "decision", "pattern"]).describe("Type of knowledge to record"),
|
|
3731
3750
|
content: z5.string().describe("The knowledge to record (markdown)"),
|
|
3732
3751
|
scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
|
|
@@ -3752,12 +3771,159 @@ ${entries}`
|
|
|
3752
3771
|
}
|
|
3753
3772
|
}
|
|
3754
3773
|
}),
|
|
3774
|
+
gitlab_memory_update: (0, import_plugin5.tool)({
|
|
3775
|
+
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).",
|
|
3776
|
+
args: {
|
|
3777
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3778
|
+
slug: z5.string().describe(
|
|
3779
|
+
'Page slug from gitlab_memory_load output (e.g., "agents/memory/facts/2026-04-05-project-overview")'
|
|
3780
|
+
),
|
|
3781
|
+
content: z5.string().describe("New content to replace the existing record (markdown)"),
|
|
3782
|
+
scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
|
|
3783
|
+
group_id: z5.string().optional().describe("Group path (required when scope is groups)")
|
|
3784
|
+
},
|
|
3785
|
+
execute: async (args) => {
|
|
3786
|
+
const auth = authAndValidate(args.project_id);
|
|
3787
|
+
const { scope, id } = resolveScope(args);
|
|
3788
|
+
try {
|
|
3789
|
+
await getWikiPage(auth.instanceUrl, auth.token, scope, id, args.slug);
|
|
3790
|
+
} catch {
|
|
3791
|
+
return `Memory record not found: ${args.slug}. Use gitlab_memory_load to see available records.`;
|
|
3792
|
+
}
|
|
3793
|
+
const date = today();
|
|
3794
|
+
const header = `*Updated: ${date}*
|
|
3795
|
+
|
|
3796
|
+
`;
|
|
3797
|
+
try {
|
|
3798
|
+
await updateWikiPage(
|
|
3799
|
+
auth.instanceUrl,
|
|
3800
|
+
auth.token,
|
|
3801
|
+
scope,
|
|
3802
|
+
id,
|
|
3803
|
+
args.slug,
|
|
3804
|
+
header + args.content
|
|
3805
|
+
);
|
|
3806
|
+
return `Updated memory record: ${args.slug}`;
|
|
3807
|
+
} catch (err) {
|
|
3808
|
+
return `Error updating memory: ${err.message}`;
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3811
|
+
}),
|
|
3812
|
+
gitlab_memory_archive: (0, import_plugin5.tool)({
|
|
3813
|
+
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.",
|
|
3814
|
+
args: {
|
|
3815
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3816
|
+
slug: z5.string().describe(
|
|
3817
|
+
'Page slug to archive (e.g., "agents/memory/facts/2026-04-05-open-issues-summary")'
|
|
3818
|
+
),
|
|
3819
|
+
reason: z5.string().optional().describe(
|
|
3820
|
+
'Why this record is being archived (e.g., "issue was fixed", "no longer relevant")'
|
|
3821
|
+
),
|
|
3822
|
+
scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
|
|
3823
|
+
group_id: z5.string().optional().describe("Group path (required when scope is groups)")
|
|
3824
|
+
},
|
|
3825
|
+
execute: async (args) => {
|
|
3826
|
+
const auth = authAndValidate(args.project_id);
|
|
3827
|
+
const { scope, id } = resolveScope(args);
|
|
3828
|
+
let originalContent;
|
|
3829
|
+
try {
|
|
3830
|
+
const page = await getWikiPage(auth.instanceUrl, auth.token, scope, id, args.slug);
|
|
3831
|
+
originalContent = page.content;
|
|
3832
|
+
} catch {
|
|
3833
|
+
return `Memory record not found: ${args.slug}. Use gitlab_memory_load to see available records.`;
|
|
3834
|
+
}
|
|
3835
|
+
const date = today();
|
|
3836
|
+
const suffix = args.slug.split("/").slice(3).join("/");
|
|
3837
|
+
const archiveSlug = `${ARCHIVE_DIR}/${suffix}`;
|
|
3838
|
+
const reasonLine = args.reason ? `
|
|
3839
|
+
*Reason: ${args.reason}*` : "";
|
|
3840
|
+
const archiveHeader = `*Archived: ${date} | Original: ${args.slug}*${reasonLine}
|
|
3841
|
+
|
|
3842
|
+
`;
|
|
3843
|
+
try {
|
|
3844
|
+
await createWikiPage(
|
|
3845
|
+
auth.instanceUrl,
|
|
3846
|
+
auth.token,
|
|
3847
|
+
scope,
|
|
3848
|
+
id,
|
|
3849
|
+
archiveSlug,
|
|
3850
|
+
archiveHeader + originalContent
|
|
3851
|
+
);
|
|
3852
|
+
await deleteWikiPage(auth.instanceUrl, auth.token, scope, id, args.slug);
|
|
3853
|
+
return `Archived: ${args.slug} \u2192 ${archiveSlug}`;
|
|
3854
|
+
} catch (err) {
|
|
3855
|
+
return `Error archiving memory: ${err.message}`;
|
|
3856
|
+
}
|
|
3857
|
+
}
|
|
3858
|
+
}),
|
|
3859
|
+
gitlab_memory_consolidate: (0, import_plugin5.tool)({
|
|
3860
|
+
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.",
|
|
3861
|
+
args: {
|
|
3862
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3863
|
+
type: z5.enum(["all", "facts", "decisions", "patterns"]).optional().describe(
|
|
3864
|
+
'Which memory to consolidate: "all" (default), "facts", "decisions", or "patterns"'
|
|
3865
|
+
),
|
|
3866
|
+
scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
|
|
3867
|
+
group_id: z5.string().optional().describe("Group path (required when scope is groups)")
|
|
3868
|
+
},
|
|
3869
|
+
execute: async (args) => {
|
|
3870
|
+
const auth = authAndValidate(args.project_id);
|
|
3871
|
+
const { scope, id } = resolveScope(args);
|
|
3872
|
+
const memType = args.type ?? "all";
|
|
3873
|
+
const dirs = MEMORY_DIRS[memType];
|
|
3874
|
+
if (!dirs) return `Unknown memory type: ${memType}`;
|
|
3875
|
+
try {
|
|
3876
|
+
const allPages = await listWikiPages(
|
|
3877
|
+
auth.instanceUrl,
|
|
3878
|
+
auth.token,
|
|
3879
|
+
scope,
|
|
3880
|
+
id,
|
|
3881
|
+
true
|
|
3882
|
+
);
|
|
3883
|
+
const entries = [];
|
|
3884
|
+
for (const dir of dirs) {
|
|
3885
|
+
const pages = allPages.filter((p) => p.slug.startsWith(dir + "/") && p.content);
|
|
3886
|
+
for (const p of pages) {
|
|
3887
|
+
entries.push({ slug: p.slug, content: p.content });
|
|
3888
|
+
}
|
|
3889
|
+
}
|
|
3890
|
+
if (entries.length === 0) return "No memory records to consolidate.";
|
|
3891
|
+
const listing = entries.map((e, i) => `### [${i + 1}] ${e.slug}
|
|
3892
|
+
${e.content}`).join("\n\n---\n\n");
|
|
3893
|
+
const instructions = [
|
|
3894
|
+
`## Memory Consolidation Review`,
|
|
3895
|
+
``,
|
|
3896
|
+
`Found **${entries.length} records** to review. For each record:`,
|
|
3897
|
+
``,
|
|
3898
|
+
`1. **Stale?** \u2014 Is the information still current? If not, either:`,
|
|
3899
|
+
` - Call \`gitlab_memory_update(slug, new_content)\` with corrected info`,
|
|
3900
|
+
` - Call \`gitlab_memory_archive(slug, reason)\` if no longer relevant`,
|
|
3901
|
+
``,
|
|
3902
|
+
`2. **Duplicate?** \u2014 Does another record cover the same information?`,
|
|
3903
|
+
` - Keep the better one, archive the other`,
|
|
3904
|
+
``,
|
|
3905
|
+
`3. **Contradictory?** \u2014 Do two records disagree?`,
|
|
3906
|
+
` - Verify which is correct, update one, archive the other`,
|
|
3907
|
+
``,
|
|
3908
|
+
`4. **Mergeable?** \u2014 Are there many small records about the same topic?`,
|
|
3909
|
+
` - Create one consolidated record, archive the originals`,
|
|
3910
|
+
``,
|
|
3911
|
+
`After reviewing, log a session with gitlab_memory_log_session summarizing what was cleaned up.`,
|
|
3912
|
+
``,
|
|
3913
|
+
`---`,
|
|
3914
|
+
``,
|
|
3915
|
+
listing
|
|
3916
|
+
].join("\n");
|
|
3917
|
+
return instructions;
|
|
3918
|
+
} catch (err) {
|
|
3919
|
+
return `Error loading memory for consolidation: ${err.message}`;
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3922
|
+
}),
|
|
3755
3923
|
gitlab_memory_recall: (0, import_plugin5.tool)({
|
|
3756
3924
|
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.",
|
|
3757
3925
|
args: {
|
|
3758
|
-
project_id: z5.string().describe(
|
|
3759
|
-
'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
|
|
3760
|
-
),
|
|
3926
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3761
3927
|
query: z5.string().describe("What to search for"),
|
|
3762
3928
|
scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
|
|
3763
3929
|
group_id: z5.string().optional().describe("Group path (required when scope is groups)")
|
|
@@ -3787,9 +3953,7 @@ ${entries}`
|
|
|
3787
3953
|
gitlab_memory_log_session: (0, import_plugin5.tool)({
|
|
3788
3954
|
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.",
|
|
3789
3955
|
args: {
|
|
3790
|
-
project_id: z5.string().describe(
|
|
3791
|
-
'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
|
|
3792
|
-
),
|
|
3956
|
+
project_id: z5.string().describe(PROJECT_ID_DESC),
|
|
3793
3957
|
title: z5.string().describe('Brief session title (e.g., "fix-ai-gateway-healthcheck")'),
|
|
3794
3958
|
summary: z5.string().describe(
|
|
3795
3959
|
"Session summary in markdown (what happened, what was learned, what went wrong)"
|