@agntk/agent-harness 0.1.2 → 0.1.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/cli/index.js CHANGED
@@ -3490,7 +3490,7 @@ Customize the workflows in your workflows/ directory.`);
3490
3490
  }
3491
3491
  return;
3492
3492
  }
3493
- const { universalInstall } = await import("../universal-installer-QGS4SJGX.js");
3493
+ const { universalInstall } = await import("../universal-installer-AAXXYM5A.js");
3494
3494
  const result = await universalInstall(dir, source, {
3495
3495
  type: opts.type,
3496
3496
  id: opts.id,
package/dist/index.js CHANGED
@@ -12444,8 +12444,215 @@ function inferContentType(filePath, sourceContentTypes) {
12444
12444
  import { existsSync as existsSync32, readFileSync as readFileSync25, writeFileSync as writeFileSync18, mkdirSync as mkdirSync16, copyFileSync as copyFileSync2 } from "fs";
12445
12445
  import { join as join32, basename as basename9, extname } from "path";
12446
12446
  import { tmpdir as tmpdir2 } from "os";
12447
+ import { createRequire } from "module";
12447
12448
  import matter4 from "gray-matter";
12448
12449
  import { parse as parseYaml3 } from "yaml";
12450
+ function getHarnessVersion() {
12451
+ try {
12452
+ const require2 = createRequire(import.meta.url);
12453
+ const candidates = [
12454
+ "../package.json",
12455
+ "../../package.json",
12456
+ "../../../package.json"
12457
+ ];
12458
+ for (const candidate of candidates) {
12459
+ try {
12460
+ const pkg = require2(candidate);
12461
+ if (pkg.name === "@agntk/agent-harness" && pkg.version) {
12462
+ return pkg.version;
12463
+ }
12464
+ } catch {
12465
+ }
12466
+ }
12467
+ return "unknown";
12468
+ } catch {
12469
+ return "unknown";
12470
+ }
12471
+ }
12472
+ async function resolveGithubCommitSha(url) {
12473
+ const match2 = url.match(
12474
+ /^https?:\/\/raw\.githubusercontent\.com\/([^/]+)\/([^/]+)\/([^/]+)\/(.+)$/
12475
+ );
12476
+ if (!match2) return null;
12477
+ const [, owner, repo, ref, path] = match2;
12478
+ if (/^[0-9a-f]{40}$/i.test(ref)) return ref;
12479
+ const apiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${ref}`;
12480
+ const controller = new AbortController();
12481
+ const timeout = setTimeout(() => controller.abort(), 5e3);
12482
+ try {
12483
+ const response = await fetch(apiUrl, {
12484
+ signal: controller.signal,
12485
+ headers: { "Accept": "application/vnd.github+json" }
12486
+ });
12487
+ if (!response.ok) return null;
12488
+ const data = await response.json();
12489
+ if (typeof data.sha === "string" && /^[0-9a-f]{40}$/i.test(data.sha)) {
12490
+ return data.sha;
12491
+ }
12492
+ return null;
12493
+ } catch {
12494
+ return null;
12495
+ } finally {
12496
+ clearTimeout(timeout);
12497
+ }
12498
+ }
12499
+ var SIBLING_LICENSE_NAMES = [
12500
+ "LICENSE",
12501
+ "LICENSE.txt",
12502
+ "LICENSE.md",
12503
+ "COPYING",
12504
+ "COPYING.txt"
12505
+ ];
12506
+ function classifyLicenseText(text) {
12507
+ const lower = text.toLowerCase();
12508
+ if (lower.includes("all rights reserved")) {
12509
+ return "PROPRIETARY";
12510
+ }
12511
+ if (lower.includes("mit license")) return "MIT";
12512
+ if (lower.includes("apache license, version 2.0") || lower.includes("apache-2.0"))
12513
+ return "Apache-2.0";
12514
+ if (lower.includes("mozilla public license version 2.0") || lower.includes("mpl-2.0"))
12515
+ return "MPL-2.0";
12516
+ if (lower.includes("gnu affero general public license")) return "AGPL-3.0";
12517
+ if (lower.includes("gnu lesser general public license")) {
12518
+ if (lower.includes("version 3")) return "LGPL-3.0";
12519
+ if (lower.includes("version 2")) return "LGPL-2.1";
12520
+ }
12521
+ if (lower.includes("gnu general public license")) {
12522
+ if (lower.includes("version 3")) return "GPL-3.0";
12523
+ if (lower.includes("version 2")) return "GPL-2.0";
12524
+ }
12525
+ if (lower.includes("isc license")) return "ISC";
12526
+ if (lower.includes("cc0 1.0 universal") || lower.includes("cc0-1.0")) return "CC0-1.0";
12527
+ if (lower.includes("creative commons attribution-sharealike 4.0")) return "CC-BY-SA-4.0";
12528
+ if (lower.includes("creative commons attribution 4.0") || lower.includes("cc-by-4.0"))
12529
+ return "CC-BY-4.0";
12530
+ if (lower.includes("redistribution and use in source and binary forms") && lower.includes("neither the name of")) {
12531
+ return "BSD-3-Clause";
12532
+ }
12533
+ if (lower.includes("redistribution and use in source and binary forms")) {
12534
+ return "BSD-2-Clause";
12535
+ }
12536
+ if (lower.includes("this is free and unencumbered software released into the public domain")) {
12537
+ return "Unlicense";
12538
+ }
12539
+ return "UNKNOWN";
12540
+ }
12541
+ function extractCopyright(text) {
12542
+ const lines = text.split(/\r?\n/);
12543
+ for (const line of lines) {
12544
+ const trimmed = line.trim();
12545
+ if (/^©\s*\d{4}/.test(trimmed) || /^copyright\b.*\d{4}/i.test(trimmed)) {
12546
+ return trimmed;
12547
+ }
12548
+ }
12549
+ return void 0;
12550
+ }
12551
+ async function fetchSiblingLicense(siblingUrl) {
12552
+ const controller = new AbortController();
12553
+ const timeout = setTimeout(() => controller.abort(), 5e3);
12554
+ try {
12555
+ const response = await fetch(siblingUrl, { signal: controller.signal });
12556
+ if (!response.ok) return null;
12557
+ return await response.text();
12558
+ } catch {
12559
+ return null;
12560
+ } finally {
12561
+ clearTimeout(timeout);
12562
+ }
12563
+ }
12564
+ async function fetchGithubRepoLicense(owner, repo) {
12565
+ const apiUrl = `https://api.github.com/repos/${owner}/${repo}/license`;
12566
+ const controller = new AbortController();
12567
+ const timeout = setTimeout(() => controller.abort(), 5e3);
12568
+ try {
12569
+ const response = await fetch(apiUrl, {
12570
+ signal: controller.signal,
12571
+ headers: { "Accept": "application/vnd.github+json" }
12572
+ });
12573
+ if (!response.ok) return null;
12574
+ const data = await response.json();
12575
+ const spdxId = data.license?.spdx_id;
12576
+ if (!spdxId || spdxId === "NOASSERTION") return null;
12577
+ let body;
12578
+ if (data.content && data.encoding === "base64") {
12579
+ try {
12580
+ body = Buffer.from(data.content, "base64").toString("utf-8");
12581
+ } catch {
12582
+ body = void 0;
12583
+ }
12584
+ }
12585
+ return { spdxId, htmlUrl: data.html_url ?? "", body };
12586
+ } catch {
12587
+ return null;
12588
+ } finally {
12589
+ clearTimeout(timeout);
12590
+ }
12591
+ }
12592
+ async function detectLicense(sourceUrl) {
12593
+ const match2 = sourceUrl.match(
12594
+ /^https?:\/\/raw\.githubusercontent\.com\/([^/]+)\/([^/]+)\/([^/]+)\/(.+)$/
12595
+ );
12596
+ if (!match2) {
12597
+ return { spdxId: "UNKNOWN" };
12598
+ }
12599
+ const [, owner, repo, ref, path] = match2;
12600
+ const lastSlash = path.lastIndexOf("/");
12601
+ const dir = lastSlash >= 0 ? path.slice(0, lastSlash) : "";
12602
+ const dirPrefix = dir ? `${dir}/` : "";
12603
+ for (const siblingName of SIBLING_LICENSE_NAMES) {
12604
+ const siblingUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${dirPrefix}${siblingName}`;
12605
+ const text = await fetchSiblingLicense(siblingUrl);
12606
+ if (text) {
12607
+ const spdxId = classifyLicenseText(text);
12608
+ const copyright = extractCopyright(text);
12609
+ return { spdxId, copyright, licenseSource: siblingUrl };
12610
+ }
12611
+ }
12612
+ const repoLicense = await fetchGithubRepoLicense(owner, repo);
12613
+ if (repoLicense) {
12614
+ const copyright = repoLicense.body ? extractCopyright(repoLicense.body) : void 0;
12615
+ return {
12616
+ spdxId: repoLicense.spdxId,
12617
+ copyright,
12618
+ licenseSource: repoLicense.htmlUrl || void 0
12619
+ };
12620
+ }
12621
+ return { spdxId: "UNKNOWN" };
12622
+ }
12623
+ async function recordProvenance(content, originalSource) {
12624
+ let parsed;
12625
+ try {
12626
+ parsed = matter4(content);
12627
+ } catch {
12628
+ return content;
12629
+ }
12630
+ const data = parsed.data;
12631
+ if (!data.source) {
12632
+ data.source = originalSource;
12633
+ }
12634
+ if (!data.source_commit) {
12635
+ const sha = await resolveGithubCommitSha(originalSource);
12636
+ if (sha) {
12637
+ data.source_commit = sha;
12638
+ }
12639
+ }
12640
+ if (!data.license || !data.copyright || !data.license_source) {
12641
+ const license = await detectLicense(originalSource);
12642
+ if (!data.license) {
12643
+ data.license = license.spdxId;
12644
+ }
12645
+ if (!data.copyright && license.copyright) {
12646
+ data.copyright = license.copyright;
12647
+ }
12648
+ if (!data.license_source && license.licenseSource) {
12649
+ data.license_source = license.licenseSource;
12650
+ }
12651
+ }
12652
+ data.installed_at = (/* @__PURE__ */ new Date()).toISOString();
12653
+ data.installed_by = `agent-harness@${getHarnessVersion()}`;
12654
+ return matter4.stringify(parsed.content, data);
12655
+ }
12449
12656
  var VALID_TYPES2 = ["rule", "instinct", "skill", "playbook", "workflow", "tool", "agent"];
12450
12657
  var TYPE_DIRS2 = {
12451
12658
  rule: "rules",
@@ -12852,10 +13059,15 @@ async function universalInstall(harnessDir, source, options) {
12852
13059
  result.format = detection;
12853
13060
  const normalized = normalizeToHarness(content, filename, detection, options);
12854
13061
  result.fixes.push(...normalized.fixes);
13062
+ let finalContent = normalized.content;
13063
+ if (source.startsWith("http://") || source.startsWith("https://")) {
13064
+ finalContent = await recordProvenance(finalContent, source);
13065
+ result.fixes.push("Recorded provenance (source, installed_at, installed_by)");
13066
+ }
12855
13067
  const tempDir = join32(tmpdir2(), "harness-install");
12856
13068
  mkdirSync16(tempDir, { recursive: true });
12857
13069
  const tempPath = join32(tempDir, normalized.filename);
12858
- writeFileSync18(tempPath, normalized.content, "utf-8");
13070
+ writeFileSync18(tempPath, finalContent, "utf-8");
12859
13071
  if (!options?.skipFix) {
12860
13072
  const fixResult = fixCapability(tempPath);
12861
13073
  result.fixes.push(...fixResult.fixes_applied);