opencode-gitlab-dap 1.16.5 → 1.17.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/dist/index.js CHANGED
@@ -3891,7 +3891,16 @@ function searchSkillsSh(query) {
3891
3891
  function downloadSkillFromSkillsSh(identifier) {
3892
3892
  const tmp = mkdtempSync(join2(tmpdir(), "skill-install-"));
3893
3893
  try {
3894
- execSync(`npx skills add ${JSON.stringify(identifier)} -y --copy`, {
3894
+ const atIdx = identifier.indexOf("@");
3895
+ let cmd;
3896
+ if (atIdx !== -1) {
3897
+ const repo = identifier.slice(0, atIdx);
3898
+ const skill = identifier.slice(atIdx + 1);
3899
+ cmd = `npx skills add ${JSON.stringify(repo)} --skill ${JSON.stringify(skill)} -y --copy`;
3900
+ } else {
3901
+ cmd = `npx skills add ${JSON.stringify(identifier)} -y --copy`;
3902
+ }
3903
+ execSync(cmd, {
3895
3904
  timeout: 6e4,
3896
3905
  cwd: tmp,
3897
3906
  encoding: "utf-8",
@@ -3944,6 +3953,73 @@ function downloadSkillFromSkillsSh(identifier) {
3944
3953
  }
3945
3954
  }
3946
3955
 
3956
+ // src/tools/skill-audit.ts
3957
+ var PROVIDER_NAMES = {
3958
+ "agent-trust-hub": "Gen Agent Trust Hub",
3959
+ socket: "Socket",
3960
+ snyk: "Snyk"
3961
+ };
3962
+ function parseIdentifierToUrl(identifier) {
3963
+ const atIdx = identifier.indexOf("@");
3964
+ if (atIdx === -1) return null;
3965
+ const ownerRepo = identifier.slice(0, atIdx);
3966
+ const skillName = identifier.slice(atIdx + 1);
3967
+ if (!ownerRepo.includes("/") || !skillName) return null;
3968
+ return `https://skills.sh/${ownerRepo}/${skillName}`;
3969
+ }
3970
+ function parseAuditHtml(html, auditUrl) {
3971
+ const secIdx = html.indexOf("Security Audits");
3972
+ if (secIdx === -1) return null;
3973
+ const section = html.slice(secIdx, secIdx + 5e3);
3974
+ const providerPattern = /href="[^"]*\/security\/(agent-trust-hub|socket|snyk)"[\s\S]*?>(Pass|Fail|Warn)</g;
3975
+ const results = [];
3976
+ let match;
3977
+ while ((match = providerPattern.exec(section)) !== null) {
3978
+ const slug = match[1];
3979
+ const status = match[2];
3980
+ results.push({
3981
+ provider: PROVIDER_NAMES[slug] ?? slug,
3982
+ status,
3983
+ detailUrl: `${auditUrl}/security/${slug}`
3984
+ });
3985
+ }
3986
+ if (results.length === 0) return null;
3987
+ return {
3988
+ results,
3989
+ hasFailure: results.some((r) => r.status === "Fail"),
3990
+ hasWarning: results.some((r) => r.status === "Warn"),
3991
+ auditUrl
3992
+ };
3993
+ }
3994
+ async function fetchSkillAudit(identifier) {
3995
+ const url = parseIdentifierToUrl(identifier);
3996
+ if (!url) return null;
3997
+ try {
3998
+ const resp = await fetch(url, {
3999
+ signal: AbortSignal.timeout(1e4),
4000
+ headers: { Accept: "text/html" }
4001
+ });
4002
+ if (!resp.ok) return null;
4003
+ const html = await resp.text();
4004
+ return parseAuditHtml(html, url);
4005
+ } catch {
4006
+ return null;
4007
+ }
4008
+ }
4009
+ function formatAuditLine(audit) {
4010
+ return audit.results.map((r) => {
4011
+ const icon = r.status === "Fail" ? "\u{1F534}" : r.status === "Warn" ? "\u{1F7E1}" : "\u{1F7E2}";
4012
+ return `${icon} ${r.provider}: ${r.status}`;
4013
+ }).join(" | ");
4014
+ }
4015
+ function formatAuditRate(audit) {
4016
+ const total = audit.results.length;
4017
+ const passed = audit.results.filter((r) => r.status === "Pass").length;
4018
+ if (passed === total) return `Security: ${passed}/${total} audits passed \u2705`;
4019
+ if (audit.hasFailure) return `Security: ${passed}/${total} audits passed \u274C`;
4020
+ return `Security: ${passed}/${total} audits passed \u26A0\uFE0F`;
4021
+ }
4022
+
3947
4023
  // src/tools/skill-tools.ts
3948
4024
  var z6 = tool6.schema;
3949
4025
  var PROJECT_ID_DESC2 = "Project path from git remote";
@@ -4228,14 +4304,32 @@ Install: \`gitlab_skill_install(name="${e.name}", source="group", group_id="${ar
4228
4304
  }
4229
4305
  const shResults = searchSkillsSh(args.query);
4230
4306
  if (shResults.length > 0) {
4307
+ const audits = await Promise.all(shResults.map((r) => fetchSkillAudit(r.identifier)));
4231
4308
  sections.push(
4232
4309
  `### skills.sh (${shResults.length})
4233
4310
 
4234
- ` + shResults.map(
4235
- (r) => `**${r.identifier}** (${r.installs})
4311
+ ` + shResults.map((r, i) => {
4312
+ const audit = audits[i];
4313
+ let line = `**${r.identifier}** (${r.installs})`;
4314
+ if (audit) {
4315
+ line += `
4316
+ ${formatAuditRate(audit)}`;
4317
+ line += `
4318
+ ${formatAuditLine(audit)}`;
4319
+ if (audit.hasFailure) {
4320
+ line += `
4321
+ \u26D4 BLOCKED \u2014 security audit failures detected. Review: ${audit.auditUrl}`;
4322
+ return line;
4323
+ }
4324
+ } else {
4325
+ line += `
4326
+ Security: unknown (audit data unavailable)`;
4327
+ }
4328
+ line += `
4236
4329
  ${r.url}
4237
- Install: \`gitlab_skill_install(name="${r.identifier}", source="skills.sh")\``
4238
- ).join("\n\n")
4330
+ Install: \`gitlab_skill_install(name="${r.identifier}", source="skills.sh")\``;
4331
+ return line;
4332
+ }).join("\n\n")
4239
4333
  );
4240
4334
  }
4241
4335
  if (sections.length === 0) {
@@ -4258,6 +4352,14 @@ Install: \`gitlab_skill_install(name="${r.identifier}", source="skills.sh")\``
4258
4352
  const projectScope = resolveScope2(args);
4259
4353
  const targetPrefix = args.draft ? DRAFTS_PREFIX : SKILLS_PREFIX;
4260
4354
  if (args.source === "skills.sh") {
4355
+ const audit = await fetchSkillAudit(args.name);
4356
+ if (audit?.hasFailure) {
4357
+ const failures = audit.results.filter((r) => r.status === "Fail").map((r) => ` \u{1F534} ${r.provider}: Fail (${r.detailUrl})`).join("\n");
4358
+ return `\u26D4 Installation BLOCKED \u2014 security audit failure(s) detected:
4359
+ ${failures}
4360
+
4361
+ Review the audit details before proceeding: ${audit.auditUrl}`;
4362
+ }
4261
4363
  const downloaded = downloadSkillFromSkillsSh(args.name);
4262
4364
  if (!downloaded) {
4263
4365
  return `Failed to download skill "${args.name}" from skills.sh.`;
@@ -4309,7 +4411,19 @@ Install: \`gitlab_skill_install(name="${r.identifier}", source="skills.sh")\``
4309
4411
  }
4310
4412
  const parts = [`${wikiCount} wiki page(s)`];
4311
4413
  if (hasBundle) parts.push(`${scriptFiles.length} bundled script(s)`);
4312
- return `Installed skill "${downloaded.name}" from skills.sh. ${parts.join(", ")}. Use gitlab_skill_setup to extract scripts.`;
4414
+ let result = `Installed skill "${downloaded.name}" from skills.sh. ${parts.join(", ")}. Use gitlab_skill_setup to extract scripts.`;
4415
+ if (audit?.hasWarning) {
4416
+ const warnings = audit.results.filter((r) => r.status === "Warn").map((r) => ` \u26A0\uFE0F ${r.provider}: Warn (${r.detailUrl})`).join("\n");
4417
+ result += `
4418
+
4419
+ \u26A0\uFE0F Security audit warnings:
4420
+ ${warnings}`;
4421
+ } else if (!audit) {
4422
+ result += `
4423
+
4424
+ (security audit data unavailable \u2014 skills.sh may be unreachable)`;
4425
+ }
4426
+ return result;
4313
4427
  } catch (err) {
4314
4428
  return `Error installing from skills.sh: ${err.message}`;
4315
4429
  }