opencode-gitlab-dap 1.8.2 → 1.8.4

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
@@ -3443,13 +3443,13 @@ async function searchWikiPages(instanceUrl, token, scope, id, query) {
3443
3443
  // src/tools/memory-tools.ts
3444
3444
  var z5 = tool5.schema;
3445
3445
  var PREFIX = "agents";
3446
- var MEMORY_SLUGS = {
3446
+ var MEMORY_DIRS = {
3447
3447
  all: [`${PREFIX}/memory/facts`, `${PREFIX}/memory/decisions`, `${PREFIX}/memory/patterns`],
3448
3448
  facts: [`${PREFIX}/memory/facts`],
3449
3449
  decisions: [`${PREFIX}/memory/decisions`],
3450
3450
  patterns: [`${PREFIX}/memory/patterns`]
3451
3451
  };
3452
- var RECORD_SLUG = {
3452
+ var RECORD_DIR = {
3453
3453
  fact: `${PREFIX}/memory/facts`,
3454
3454
  decision: `${PREFIX}/memory/decisions`,
3455
3455
  pattern: `${PREFIX}/memory/patterns`
@@ -3460,21 +3460,9 @@ function today() {
3460
3460
  function slugify(text) {
3461
3461
  return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "").slice(0, 60);
3462
3462
  }
3463
- async function safeRead(instanceUrl, token, scope, id, slug) {
3464
- try {
3465
- const page = await getWikiPage(instanceUrl, token, scope, id, slug);
3466
- return page.content;
3467
- } catch {
3468
- return null;
3469
- }
3470
- }
3471
- async function appendToPage(instanceUrl, token, scope, id, slug, newContent) {
3472
- const existing = await safeRead(instanceUrl, token, scope, id, slug);
3473
- if (existing !== null) {
3474
- await updateWikiPage(instanceUrl, token, scope, id, slug, existing + "\n\n" + newContent);
3475
- } else {
3476
- await createWikiPage(instanceUrl, token, scope, id, slug, newContent);
3477
- }
3463
+ function titleFromContent(content) {
3464
+ const first = content.split("\n")[0].replace(/^[#*\->\s]+/, "").trim();
3465
+ return first.slice(0, 80) || "untitled";
3478
3466
  }
3479
3467
  function validateProjectId(projectId) {
3480
3468
  if (!projectId.includes("/")) {
@@ -3511,25 +3499,38 @@ function makeMemoryTools(ctx) {
3511
3499
  const auth = authAndValidate(args.project_id);
3512
3500
  const { scope, id } = resolveScope(args);
3513
3501
  const memType = args.type ?? "all";
3514
- const slugs = MEMORY_SLUGS[memType];
3515
- if (!slugs) return `Unknown memory type: ${memType}`;
3516
- const sections = [];
3517
- for (const slug of slugs) {
3518
- const content = await safeRead(auth.instanceUrl, auth.token, scope, id, slug);
3519
- if (content) {
3520
- const label = slug.split("/").pop();
3521
- sections.push(`## ${label.charAt(0).toUpperCase() + label.slice(1)}
3522
-
3523
- ${content}`);
3502
+ const dirs = MEMORY_DIRS[memType];
3503
+ if (!dirs) return `Unknown memory type: ${memType}`;
3504
+ try {
3505
+ const allPages = await listWikiPages(
3506
+ auth.instanceUrl,
3507
+ auth.token,
3508
+ scope,
3509
+ id,
3510
+ true
3511
+ );
3512
+ const sections = [];
3513
+ for (const dir of dirs) {
3514
+ const label = dir.split("/").pop();
3515
+ const pages = allPages.filter((p) => p.slug.startsWith(dir + "/") && p.content);
3516
+ if (pages.length === 0) continue;
3517
+ const entries = pages.map((p) => p.content).join("\n\n---\n\n");
3518
+ sections.push(
3519
+ `## ${label.charAt(0).toUpperCase() + label.slice(1)} (${pages.length})
3520
+
3521
+ ${entries}`
3522
+ );
3524
3523
  }
3524
+ if (sections.length === 0)
3525
+ return "No project memory found. Use gitlab_memory_record to start building project knowledge.";
3526
+ return sections.join("\n\n---\n\n");
3527
+ } catch (err) {
3528
+ return `Error loading memory: ${err.message}`;
3525
3529
  }
3526
- if (sections.length === 0)
3527
- return "No project memory found. Use gitlab_memory_record to start building project knowledge.";
3528
- return sections.join("\n\n---\n\n");
3529
3530
  }
3530
3531
  }),
3531
3532
  gitlab_memory_record: tool5({
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.",
3533
+ 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.",
3533
3534
  args: {
3534
3535
  project_id: z5.string().describe(
3535
3536
  'FULL project path with namespace (e.g., "gitlab-org/gitlab"). Must contain a slash. Never use just the project name.'
@@ -3542,24 +3543,18 @@ ${content}`);
3542
3543
  execute: async (args) => {
3543
3544
  const auth = authAndValidate(args.project_id);
3544
3545
  const { scope, id } = resolveScope(args);
3545
- const slug = RECORD_SLUG[args.type];
3546
- if (!slug) return `Unknown memory type: ${args.type}`;
3546
+ const dir = RECORD_DIR[args.type];
3547
+ if (!dir) return `Unknown memory type: ${args.type}`;
3547
3548
  const date = today();
3548
- let formatted;
3549
- if (args.type === "decision") {
3550
- const firstLine = args.content.split("\n")[0];
3551
- const rest = args.content.split("\n").slice(1).join("\n").trim();
3552
- formatted = `## ${date}: ${firstLine}${rest ? "\n" + rest : ""}`;
3553
- } else if (args.type === "fact") {
3554
- formatted = `## ${date}
3555
- - ${args.content.replace(/\n/g, "\n- ")}`;
3556
- } else {
3557
- formatted = `## ${date}
3558
- ${args.content}`;
3559
- }
3549
+ const title = titleFromContent(args.content);
3550
+ const slug = `${dir}/${date}-${slugify(title)}`;
3551
+ const header = `*Recorded: ${date} | Type: ${args.type}*
3552
+
3553
+ `;
3554
+ const body = header + args.content;
3560
3555
  try {
3561
- await appendToPage(auth.instanceUrl, auth.token, scope, id, slug, formatted);
3562
- return `Recorded ${args.type} in project memory.`;
3556
+ await createWikiPage(auth.instanceUrl, auth.token, scope, id, slug, body);
3557
+ return `Recorded ${args.type} in project memory: ${slug}`;
3563
3558
  } catch (err) {
3564
3559
  return `Error recording ${args.type}: ${err.message}`;
3565
3560
  }
@@ -3619,14 +3614,6 @@ ${args.content}`;
3619
3614
  await createWikiPage(auth.instanceUrl, auth.token, scope, id, slug, args.summary);
3620
3615
  return `Session logged: ${slug}`;
3621
3616
  } catch (err) {
3622
- if (err.message?.includes("already exists") || err.message?.includes("422")) {
3623
- try {
3624
- await updateWikiPage(auth.instanceUrl, auth.token, scope, id, slug, args.summary);
3625
- return `Session log updated: ${slug}`;
3626
- } catch (err2) {
3627
- return `Error logging session: ${err2.message}`;
3628
- }
3629
- }
3630
3617
  return `Error logging session: ${err.message}`;
3631
3618
  }
3632
3619
  }
@@ -3756,17 +3743,26 @@ ${draft.content}`;
3756
3743
  const { scope, id } = resolveScope2(args);
3757
3744
  const prefix = args.draft ? DRAFTS_PREFIX : SKILLS_PREFIX;
3758
3745
  const slug = `${prefix}/${args.name}`;
3759
- try {
3760
- await updateWikiPage(auth.instanceUrl, auth.token, scope, id, slug, args.content);
3761
- return `Updated ${args.draft ? "draft " : ""}skill: ${args.name}`;
3762
- } catch {
3746
+ const label = args.draft ? "draft " : "";
3747
+ for (let attempt = 0; attempt < 3; attempt++) {
3763
3748
  try {
3764
- await createWikiPage(auth.instanceUrl, auth.token, scope, id, slug, args.content);
3765
- return `Created ${args.draft ? "draft " : ""}skill: ${args.name}`;
3766
- } catch (err) {
3767
- return `Error saving skill: ${err.message}`;
3749
+ await updateWikiPage(auth.instanceUrl, auth.token, scope, id, slug, args.content);
3750
+ return `Updated ${label}skill: ${args.name}`;
3751
+ } catch {
3752
+ try {
3753
+ await createWikiPage(auth.instanceUrl, auth.token, scope, id, slug, args.content);
3754
+ return `Created ${label}skill: ${args.name}`;
3755
+ } catch (err) {
3756
+ const msg = err.message ?? "";
3757
+ if (msg.includes("Duplicate page") || msg.includes("reference update")) {
3758
+ await new Promise((r) => setTimeout(r, 1e3 * (attempt + 1)));
3759
+ continue;
3760
+ }
3761
+ return `Error saving skill: ${msg}`;
3762
+ }
3768
3763
  }
3769
3764
  }
3765
+ return `Error saving skill: failed after 3 retries`;
3770
3766
  }
3771
3767
  }),
3772
3768
  gitlab_skill_promote: tool6({