opencode-gitlab-dap 1.8.1 → 1.8.2

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/dist/index.js CHANGED
@@ -3476,6 +3476,12 @@ async function appendToPage(instanceUrl, token, scope, id, slug, newContent) {
3476
3476
  await createWikiPage(instanceUrl, token, scope, id, slug, newContent);
3477
3477
  }
3478
3478
  }
3479
+ function validateProjectId(projectId) {
3480
+ if (!projectId.includes("/")) {
3481
+ return `Invalid project_id "${projectId}". Must be the full project path containing at least one slash (e.g., "my-group/my-project"), not just the project name.`;
3482
+ }
3483
+ return null;
3484
+ }
3479
3485
  function resolveScope(args) {
3480
3486
  if (args.scope === "groups" && args.group_id) {
3481
3487
  return { scope: "groups", id: args.group_id };
@@ -3483,18 +3489,26 @@ function resolveScope(args) {
3483
3489
  return { scope: "projects", id: args.project_id };
3484
3490
  }
3485
3491
  function makeMemoryTools(ctx) {
3492
+ function authAndValidate(projectId) {
3493
+ const auth = ctx.ensureAuth();
3494
+ if (!auth) throw new Error("GitLab authentication not available");
3495
+ const err = validateProjectId(projectId);
3496
+ if (err) throw new Error(err);
3497
+ return auth;
3498
+ }
3486
3499
  return {
3487
3500
  gitlab_memory_load: tool5({
3488
3501
  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.",
3489
3502
  args: {
3490
- project_id: z5.string().describe('Project path (e.g., "gitlab-org/gitlab"). Use the same value consistently.'),
3503
+ project_id: z5.string().describe(
3504
+ 'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
3505
+ ),
3491
3506
  type: z5.enum(["all", "facts", "decisions", "patterns"]).optional().describe('Which memory to load: "all" (default), "facts", "decisions", or "patterns"'),
3492
3507
  scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
3493
3508
  group_id: z5.string().optional().describe("Group path (required when scope is groups)")
3494
3509
  },
3495
3510
  execute: async (args) => {
3496
- const auth = ctx.ensureAuth();
3497
- if (!auth) throw new Error("GitLab authentication not available");
3511
+ const auth = authAndValidate(args.project_id);
3498
3512
  const { scope, id } = resolveScope(args);
3499
3513
  const memType = args.type ?? "all";
3500
3514
  const slugs = MEMORY_SLUGS[memType];
@@ -3517,15 +3531,16 @@ ${content}`);
3517
3531
  gitlab_memory_record: tool5({
3518
3532
  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.\nEntries are automatically timestamped and appended to the appropriate memory page.\nMultiple facts can be recorded in a single call by separating them with newlines.",
3519
3533
  args: {
3520
- project_id: z5.string().describe('Project path (e.g., "gitlab-org/gitlab"). Use the same value consistently.'),
3534
+ project_id: z5.string().describe(
3535
+ 'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
3536
+ ),
3521
3537
  type: z5.enum(["fact", "decision", "pattern"]).describe("Type of knowledge to record"),
3522
3538
  content: z5.string().describe("The knowledge to record (markdown)"),
3523
3539
  scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
3524
3540
  group_id: z5.string().optional().describe("Group path (required when scope is groups)")
3525
3541
  },
3526
3542
  execute: async (args) => {
3527
- const auth = ctx.ensureAuth();
3528
- if (!auth) throw new Error("GitLab authentication not available");
3543
+ const auth = authAndValidate(args.project_id);
3529
3544
  const { scope, id } = resolveScope(args);
3530
3545
  const slug = RECORD_SLUG[args.type];
3531
3546
  if (!slug) return `Unknown memory type: ${args.type}`;
@@ -3553,14 +3568,15 @@ ${args.content}`;
3553
3568
  gitlab_memory_recall: tool5({
3554
3569
  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.",
3555
3570
  args: {
3556
- project_id: z5.string().describe('Project path (e.g., "gitlab-org/gitlab"). Use the same value consistently.'),
3571
+ project_id: z5.string().describe(
3572
+ 'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
3573
+ ),
3557
3574
  query: z5.string().describe("What to search for"),
3558
3575
  scope: z5.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
3559
3576
  group_id: z5.string().optional().describe("Group path (required when scope is groups)")
3560
3577
  },
3561
3578
  execute: async (args) => {
3562
- const auth = ctx.ensureAuth();
3563
- if (!auth) throw new Error("GitLab authentication not available");
3579
+ const auth = authAndValidate(args.project_id);
3564
3580
  const { scope, id } = resolveScope(args);
3565
3581
  try {
3566
3582
  const results = await searchWikiPages(
@@ -3584,7 +3600,9 @@ ${args.content}`;
3584
3600
  gitlab_memory_log_session: tool5({
3585
3601
  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.",
3586
3602
  args: {
3587
- project_id: z5.string().describe('Project path (e.g., "gitlab-org/gitlab"). Use the same value consistently.'),
3603
+ project_id: z5.string().describe(
3604
+ 'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
3605
+ ),
3588
3606
  title: z5.string().describe('Brief session title (e.g., "fix-ai-gateway-healthcheck")'),
3589
3607
  summary: z5.string().describe(
3590
3608
  "Session summary in markdown (what happened, what was learned, what went wrong)"
@@ -3593,8 +3611,7 @@ ${args.content}`;
3593
3611
  group_id: z5.string().optional().describe("Group path (required when scope is groups)")
3594
3612
  },
3595
3613
  execute: async (args) => {
3596
- const auth = ctx.ensureAuth();
3597
- if (!auth) throw new Error("GitLab authentication not available");
3614
+ const auth = authAndValidate(args.project_id);
3598
3615
  const { scope, id } = resolveScope(args);
3599
3616
  const date = today();
3600
3617
  const slug = `${PREFIX}/memory/sessions/${date}-${slugify(args.title)}`;
@@ -3629,19 +3646,33 @@ function resolveScope2(args) {
3629
3646
  }
3630
3647
  return { scope: "projects", id: args.project_id };
3631
3648
  }
3649
+ function validateProjectId2(projectId) {
3650
+ if (!projectId.includes("/")) {
3651
+ return `Invalid project_id "${projectId}". Must be the full project path containing at least one slash (e.g., "my-group/my-project"), not just the project name.`;
3652
+ }
3653
+ return null;
3654
+ }
3632
3655
  function makeSkillTools(ctx) {
3656
+ function authAndValidate(projectId) {
3657
+ const auth = ctx.ensureAuth();
3658
+ if (!auth) throw new Error("GitLab authentication not available");
3659
+ const err = validateProjectId2(projectId);
3660
+ if (err) throw new Error(err);
3661
+ return auth;
3662
+ }
3633
3663
  return {
3634
3664
  gitlab_skill_list: tool6({
3635
3665
  description: "List available project skills and optionally draft skills.\nSkills define step-by-step procedures for common tasks (e.g., incident retros, debugging, deployments).",
3636
3666
  args: {
3637
- project_id: z6.string().describe('Project path (e.g., "gitlab-org/gitlab"). Use the same value consistently.'),
3667
+ project_id: z6.string().describe(
3668
+ 'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
3669
+ ),
3638
3670
  include_drafts: z6.boolean().optional().describe("Also list draft skills (default: false)"),
3639
3671
  scope: z6.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
3640
3672
  group_id: z6.string().optional().describe("Group path (required when scope is groups)")
3641
3673
  },
3642
3674
  execute: async (args) => {
3643
- const auth = ctx.ensureAuth();
3644
- if (!auth) throw new Error("GitLab authentication not available");
3675
+ const auth = authAndValidate(args.project_id);
3645
3676
  const { scope, id } = resolveScope2(args);
3646
3677
  try {
3647
3678
  const pages = await listWikiPages(auth.instanceUrl, auth.token, scope, id);
@@ -3671,14 +3702,15 @@ function makeSkillTools(ctx) {
3671
3702
  gitlab_skill_load: tool6({
3672
3703
  description: "Load a specific skill by name.\nSkills contain step-by-step instructions for common tasks.\nChecks published skills first, then falls back to draft skills.",
3673
3704
  args: {
3674
- project_id: z6.string().describe('Project path (e.g., "gitlab-org/gitlab"). Use the same value consistently.'),
3705
+ project_id: z6.string().describe(
3706
+ 'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
3707
+ ),
3675
3708
  name: z6.string().describe('Skill name (e.g., "incident-retro", "helm-rollback")'),
3676
3709
  scope: z6.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
3677
3710
  group_id: z6.string().optional().describe("Group path (required when scope is groups)")
3678
3711
  },
3679
3712
  execute: async (args) => {
3680
- const auth = ctx.ensureAuth();
3681
- if (!auth) throw new Error("GitLab authentication not available");
3713
+ const auth = authAndValidate(args.project_id);
3682
3714
  const { scope, id } = resolveScope2(args);
3683
3715
  try {
3684
3716
  const page = await getWikiPage(
@@ -3710,7 +3742,9 @@ ${draft.content}`;
3710
3742
  gitlab_skill_save: tool6({
3711
3743
  description: "Create or update a skill.\nSkills define step-by-step procedures for common tasks.\nUse draft=true for skills that haven't been proven yet.",
3712
3744
  args: {
3713
- project_id: z6.string().describe('Project path (e.g., "gitlab-org/gitlab"). Use the same value consistently.'),
3745
+ project_id: z6.string().describe(
3746
+ 'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
3747
+ ),
3714
3748
  name: z6.string().describe('Skill name (e.g., "incident-retro")'),
3715
3749
  content: z6.string().describe("Skill content in markdown"),
3716
3750
  draft: z6.boolean().optional().describe("Save as draft skill (default: false)"),
@@ -3718,8 +3752,7 @@ ${draft.content}`;
3718
3752
  group_id: z6.string().optional().describe("Group path (required when scope is groups)")
3719
3753
  },
3720
3754
  execute: async (args) => {
3721
- const auth = ctx.ensureAuth();
3722
- if (!auth) throw new Error("GitLab authentication not available");
3755
+ const auth = authAndValidate(args.project_id);
3723
3756
  const { scope, id } = resolveScope2(args);
3724
3757
  const prefix = args.draft ? DRAFTS_PREFIX : SKILLS_PREFIX;
3725
3758
  const slug = `${prefix}/${args.name}`;
@@ -3739,14 +3772,15 @@ ${draft.content}`;
3739
3772
  gitlab_skill_promote: tool6({
3740
3773
  description: "Promote a draft skill to published.\nMoves the skill from the drafts directory to the published skills directory.",
3741
3774
  args: {
3742
- project_id: z6.string().describe('Project path (e.g., "gitlab-org/gitlab"). Use the same value consistently.'),
3775
+ project_id: z6.string().describe(
3776
+ 'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
3777
+ ),
3743
3778
  name: z6.string().describe("Skill name to promote"),
3744
3779
  scope: z6.enum(["projects", "groups"]).optional().describe("Scope (default: projects)"),
3745
3780
  group_id: z6.string().optional().describe("Group path (required when scope is groups)")
3746
3781
  },
3747
3782
  execute: async (args) => {
3748
- const auth = ctx.ensureAuth();
3749
- if (!auth) throw new Error("GitLab authentication not available");
3783
+ const auth = authAndValidate(args.project_id);
3750
3784
  const { scope, id } = resolveScope2(args);
3751
3785
  const draftSlug = `${DRAFTS_PREFIX}/${args.name}`;
3752
3786
  const publishedSlug = `${SKILLS_PREFIX}/${args.name}`;