@xn-intenton-z2a/agentic-lib 7.4.16 → 7.4.18
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/bin/agentic-lib.js
CHANGED
package/package.json
CHANGED
|
@@ -541,8 +541,17 @@ function parseReasoning(content) {
|
|
|
541
541
|
async function executeDispatch(octokit, repo, actionName, params, ctx) {
|
|
542
542
|
const workflowFile = actionName.replace("dispatch:", "") + ".yml";
|
|
543
543
|
const inputs = {};
|
|
544
|
-
if (params["pr-number"]) inputs["pr-number"] = params["pr-number"];
|
|
545
|
-
if (params["issue-number"])
|
|
544
|
+
if (params["pr-number"]) inputs["pr-number"] = String(params["pr-number"]);
|
|
545
|
+
if (params["issue-number"]) {
|
|
546
|
+
const issueNum = String(params["issue-number"]);
|
|
547
|
+
// Guard: reject placeholder issue numbers from LLM (e.g. "<created_issue_number>")
|
|
548
|
+
if (/^\d+$/.test(issueNum)) {
|
|
549
|
+
inputs["issue-number"] = issueNum;
|
|
550
|
+
} else {
|
|
551
|
+
core.warning(`dispatch: ignoring non-numeric issue-number: ${issueNum}`);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
if (params.mode) inputs.mode = String(params.mode);
|
|
546
555
|
|
|
547
556
|
// Pass discussion-url when dispatching the bot
|
|
548
557
|
if (workflowFile === "agentic-lib-bot.yml" && ctx?.activeDiscussionUrl) {
|
|
@@ -579,8 +588,61 @@ async function executeDispatch(octokit, repo, actionName, params, ctx) {
|
|
|
579
588
|
}
|
|
580
589
|
|
|
581
590
|
async function executeCreateIssue(octokit, repo, params, ctx) {
|
|
582
|
-
|
|
583
|
-
|
|
591
|
+
// Derive title: use params.title, fall back to first line of body, fall back to feature name
|
|
592
|
+
let title = (params.title || "").trim();
|
|
593
|
+
const bodyText = (params.body || params.details || "").trim();
|
|
594
|
+
const feature = (params.feature || "").trim();
|
|
595
|
+
|
|
596
|
+
if (!title && bodyText) {
|
|
597
|
+
// Extract title from body: use first heading or first non-empty line
|
|
598
|
+
const headingMatch = bodyText.match(/^#+ (.+)/m);
|
|
599
|
+
const titleMatch = bodyText.match(/^Title:\s*(.+)/im);
|
|
600
|
+
if (titleMatch) {
|
|
601
|
+
title = titleMatch[1].trim();
|
|
602
|
+
} else if (headingMatch) {
|
|
603
|
+
title = headingMatch[1].trim();
|
|
604
|
+
} else {
|
|
605
|
+
// Use first line, truncated
|
|
606
|
+
title = bodyText.split("\n")[0].substring(0, 120).trim();
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
if (!title && feature) {
|
|
610
|
+
title = `feat: implement ${feature}`;
|
|
611
|
+
}
|
|
612
|
+
if (!title) {
|
|
613
|
+
core.warning("create-issue: no title, body, or feature provided — skipping");
|
|
614
|
+
return "skipped:no-title";
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
const rawLabels = params.labels;
|
|
618
|
+
const labels = Array.isArray(rawLabels)
|
|
619
|
+
? rawLabels.map((l) => String(l).trim()).filter(Boolean)
|
|
620
|
+
: typeof rawLabels === "string"
|
|
621
|
+
? rawLabels.split(",").map((l) => l.trim()).filter(Boolean)
|
|
622
|
+
: ["automated"];
|
|
623
|
+
if (!labels.includes("automated")) labels.push("automated");
|
|
624
|
+
|
|
625
|
+
// Build rich issue body with context
|
|
626
|
+
const bodyParts = [];
|
|
627
|
+
if (bodyText) {
|
|
628
|
+
bodyParts.push(bodyText);
|
|
629
|
+
}
|
|
630
|
+
if (feature) {
|
|
631
|
+
bodyParts.push("");
|
|
632
|
+
bodyParts.push(`## Related Feature`);
|
|
633
|
+
bodyParts.push(`Feature spec: \`features/${feature}.md\``);
|
|
634
|
+
}
|
|
635
|
+
// Add mission context from MISSION.md
|
|
636
|
+
const missionText = ctx?.mission || "";
|
|
637
|
+
if (missionText) {
|
|
638
|
+
const missionHeading = missionText.match(/^#\s+(.+)/m);
|
|
639
|
+
const missionName = missionHeading ? missionHeading[1].trim() : "MISSION.md";
|
|
640
|
+
bodyParts.push("");
|
|
641
|
+
bodyParts.push(`## Context`);
|
|
642
|
+
bodyParts.push(`Mission: ${missionName}`);
|
|
643
|
+
bodyParts.push(`Created by: agentic-step supervisor`);
|
|
644
|
+
}
|
|
645
|
+
const body = bodyParts.join("\n");
|
|
584
646
|
|
|
585
647
|
// Dedup guard: skip if a similarly-titled issue was closed in the last hour
|
|
586
648
|
// Exclude issues closed before the init timestamp (cross-scenario protection)
|
|
@@ -610,13 +672,18 @@ async function executeCreateIssue(octokit, repo, params, ctx) {
|
|
|
610
672
|
}
|
|
611
673
|
|
|
612
674
|
core.info(`Creating issue: ${title}`);
|
|
613
|
-
const { data: issue } = await octokit.rest.issues.create({ ...repo, title, labels });
|
|
675
|
+
const { data: issue } = await octokit.rest.issues.create({ ...repo, title, body, labels });
|
|
614
676
|
return `created-issue:#${issue.number}`;
|
|
615
677
|
}
|
|
616
678
|
|
|
617
679
|
async function executeLabelIssue(octokit, repo, params) {
|
|
618
680
|
const issueNumber = Number(params["issue-number"]);
|
|
619
|
-
const
|
|
681
|
+
const rawLabels = params.labels;
|
|
682
|
+
const labels = Array.isArray(rawLabels)
|
|
683
|
+
? rawLabels.map((l) => String(l).trim()).filter(Boolean)
|
|
684
|
+
: typeof rawLabels === "string"
|
|
685
|
+
? rawLabels.split(",").map((l) => l.trim()).filter(Boolean)
|
|
686
|
+
: [];
|
|
620
687
|
if (issueNumber && labels.length > 0) {
|
|
621
688
|
core.info(`Labelling issue #${issueNumber}: ${labels.join(", ")}`);
|
|
622
689
|
await octokit.rest.issues.addLabels({ ...repo, issue_number: issueNumber, labels });
|
|
@@ -677,13 +744,36 @@ async function executeSetSchedule(octokit, repo, frequency) {
|
|
|
677
744
|
}
|
|
678
745
|
|
|
679
746
|
async function executeAction(octokit, repo, action, params, ctx) {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
if (
|
|
685
|
-
|
|
686
|
-
|
|
747
|
+
// LLMs sometimes inline params in the action string as pipe-delimited key: value pairs
|
|
748
|
+
// e.g. "github:create-issue | title: foo | body: bar" instead of using the params object
|
|
749
|
+
let cleanAction = action;
|
|
750
|
+
let mergedParams = { ...params };
|
|
751
|
+
if (action.includes(" | ")) {
|
|
752
|
+
const parts = action.split(" | ");
|
|
753
|
+
cleanAction = parts[0].trim();
|
|
754
|
+
for (let i = 1; i < parts.length; i++) {
|
|
755
|
+
const colonIdx = parts[i].indexOf(":");
|
|
756
|
+
if (colonIdx > 0) {
|
|
757
|
+
const key = parts[i].substring(0, colonIdx).trim();
|
|
758
|
+
const value = parts[i].substring(colonIdx + 1).trim();
|
|
759
|
+
// Only add to params if not already set (explicit params take precedence)
|
|
760
|
+
if (!(key in mergedParams)) {
|
|
761
|
+
mergedParams[key] = value;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
if (cleanAction !== action) {
|
|
766
|
+
core.info(`Parsed inline params from action string: ${cleanAction} + ${Object.keys(mergedParams).join(", ")}`);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
if (cleanAction.startsWith("dispatch:")) return executeDispatch(octokit, repo, cleanAction, mergedParams, ctx);
|
|
771
|
+
if (cleanAction.startsWith("set-schedule:")) return executeSetSchedule(octokit, repo, cleanAction.replace("set-schedule:", ""));
|
|
772
|
+
if (cleanAction === "nop") return "nop";
|
|
773
|
+
const handler = ACTION_HANDLERS[cleanAction];
|
|
774
|
+
if (handler) return handler(octokit, repo, mergedParams, ctx);
|
|
775
|
+
core.debug(`Ignoring unrecognised action: ${cleanAction}`);
|
|
776
|
+
return `unknown:${cleanAction}`;
|
|
687
777
|
}
|
|
688
778
|
|
|
689
779
|
/**
|
|
@@ -58,6 +58,14 @@ runs:
|
|
|
58
58
|
sleep $((attempt * 2))
|
|
59
59
|
continue
|
|
60
60
|
}
|
|
61
|
+
# After rebase, check if our changes survived (rebase may drop empty commits)
|
|
62
|
+
LOCAL_SHA=$(git rev-parse HEAD)
|
|
63
|
+
REMOTE_SHA=$(git rev-parse "origin/$REF" 2>/dev/null || echo "")
|
|
64
|
+
if [ "$LOCAL_SHA" = "$REMOTE_SHA" ]; then
|
|
65
|
+
echo "Rebase dropped local commit (already on remote) — nothing to push"
|
|
66
|
+
PUSH_SUCCESS="true"
|
|
67
|
+
break
|
|
68
|
+
fi
|
|
61
69
|
fi
|
|
62
70
|
# Use HEAD:refs/heads/$REF to handle detached HEAD state
|
|
63
71
|
# (actions/checkout with a SHA puts us in detached HEAD, so
|