opencode-swarm 7.68.0 → 7.68.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/cli/index.js +383 -246
- package/dist/hooks/knowledge-migrator.d.ts +23 -0
- package/dist/index.js +383 -246
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -69,7 +69,7 @@ var package_default;
|
|
|
69
69
|
var init_package = __esm(() => {
|
|
70
70
|
package_default = {
|
|
71
71
|
name: "opencode-swarm",
|
|
72
|
-
version: "7.68.
|
|
72
|
+
version: "7.68.2",
|
|
73
73
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
74
74
|
main: "dist/index.js",
|
|
75
75
|
types: "dist/index.d.ts",
|
|
@@ -73712,7 +73712,7 @@ var init_history = __esm(() => {
|
|
|
73712
73712
|
init_history_service();
|
|
73713
73713
|
});
|
|
73714
73714
|
|
|
73715
|
-
// src/commands/
|
|
73715
|
+
// src/commands/pr-ref.ts
|
|
73716
73716
|
import { execSync as execSync2 } from "node:child_process";
|
|
73717
73717
|
function sanitizeUrl(raw) {
|
|
73718
73718
|
let urlStr = raw.trim();
|
|
@@ -73731,6 +73731,22 @@ function sanitizeUrl(raw) {
|
|
|
73731
73731
|
}
|
|
73732
73732
|
return urlStr.trim();
|
|
73733
73733
|
}
|
|
73734
|
+
function sanitizeInstructions(raw) {
|
|
73735
|
+
const collapsed = raw.replace(/\s+/g, " ").trim();
|
|
73736
|
+
const stripped = collapsed.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
73737
|
+
const normalized = stripped.replace(/\s+/g, " ").trim();
|
|
73738
|
+
if (normalized.length <= MAX_INSTRUCTIONS_LEN)
|
|
73739
|
+
return normalized;
|
|
73740
|
+
return `${normalized.slice(0, MAX_INSTRUCTIONS_LEN)}…`;
|
|
73741
|
+
}
|
|
73742
|
+
function hasNonAsciiHostname(hostname5) {
|
|
73743
|
+
for (const ch of hostname5) {
|
|
73744
|
+
const cp = ch.codePointAt(0);
|
|
73745
|
+
if (cp !== undefined && cp > 127)
|
|
73746
|
+
return true;
|
|
73747
|
+
}
|
|
73748
|
+
return false;
|
|
73749
|
+
}
|
|
73734
73750
|
function isPrivateHost(url3) {
|
|
73735
73751
|
const host = url3.hostname.toLowerCase();
|
|
73736
73752
|
if (host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "0.0.0.0") {
|
|
@@ -73763,13 +73779,182 @@ function validateAndSanitizeUrl(rawUrl) {
|
|
|
73763
73779
|
if (!sanitized.startsWith("https://")) {
|
|
73764
73780
|
return { error: "URL must use HTTPS scheme" };
|
|
73765
73781
|
}
|
|
73782
|
+
try {
|
|
73783
|
+
const url3 = new URL(sanitized);
|
|
73784
|
+
if (hasNonAsciiHostname(url3.hostname)) {
|
|
73785
|
+
return { error: "Non-ASCII hostnames are not allowed" };
|
|
73786
|
+
}
|
|
73787
|
+
if (isPrivateHost(url3)) {
|
|
73788
|
+
return { error: "Private or localhost URLs are not allowed" };
|
|
73789
|
+
}
|
|
73790
|
+
const githubPrPattern = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/([0-9]+)\/?$/;
|
|
73791
|
+
if (!githubPrPattern.test(sanitized)) {
|
|
73792
|
+
return {
|
|
73793
|
+
error: "URL must be a GitHub pull request URL (https://github.com/owner/repo/pull/N)"
|
|
73794
|
+
};
|
|
73795
|
+
}
|
|
73796
|
+
return { sanitized };
|
|
73797
|
+
} catch {
|
|
73798
|
+
return { error: "Invalid URL format" };
|
|
73799
|
+
}
|
|
73800
|
+
}
|
|
73801
|
+
function parsePrRef(input, cwd) {
|
|
73802
|
+
const urlMatch = input.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)\/?$/i);
|
|
73803
|
+
if (urlMatch) {
|
|
73804
|
+
return {
|
|
73805
|
+
owner: urlMatch[1],
|
|
73806
|
+
repo: urlMatch[2],
|
|
73807
|
+
number: parseInt(urlMatch[3], 10)
|
|
73808
|
+
};
|
|
73809
|
+
}
|
|
73810
|
+
const shorthandMatch = input.match(/^([^/]+)\/([^#]+)#(\d+)$/);
|
|
73811
|
+
if (shorthandMatch) {
|
|
73812
|
+
return {
|
|
73813
|
+
owner: shorthandMatch[1],
|
|
73814
|
+
repo: shorthandMatch[2],
|
|
73815
|
+
number: parseInt(shorthandMatch[3], 10)
|
|
73816
|
+
};
|
|
73817
|
+
}
|
|
73818
|
+
const bareMatch = input.match(/^(\d+)$/);
|
|
73819
|
+
if (bareMatch) {
|
|
73820
|
+
const prNumber = parseInt(bareMatch[1], 10);
|
|
73821
|
+
const remoteUrl = detectGitRemote(cwd);
|
|
73822
|
+
if (!remoteUrl) {
|
|
73823
|
+
return null;
|
|
73824
|
+
}
|
|
73825
|
+
const parsed = parseGitRemoteUrl(remoteUrl);
|
|
73826
|
+
if (!parsed) {
|
|
73827
|
+
return null;
|
|
73828
|
+
}
|
|
73829
|
+
return {
|
|
73830
|
+
owner: parsed.owner,
|
|
73831
|
+
repo: parsed.repo,
|
|
73832
|
+
number: prNumber
|
|
73833
|
+
};
|
|
73834
|
+
}
|
|
73835
|
+
return null;
|
|
73836
|
+
}
|
|
73837
|
+
function detectGitRemote(cwd) {
|
|
73838
|
+
try {
|
|
73839
|
+
const remoteUrl = _internals35.execSync("git remote get-url origin", {
|
|
73840
|
+
encoding: "utf-8",
|
|
73841
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
73842
|
+
timeout: 5000,
|
|
73843
|
+
...cwd ? { cwd } : {}
|
|
73844
|
+
}).trim();
|
|
73845
|
+
return remoteUrl || null;
|
|
73846
|
+
} catch {
|
|
73847
|
+
return null;
|
|
73848
|
+
}
|
|
73849
|
+
}
|
|
73850
|
+
function parseGitRemoteUrl(remoteUrl) {
|
|
73851
|
+
const httpsMatch = remoteUrl.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/i);
|
|
73852
|
+
if (httpsMatch) {
|
|
73853
|
+
return {
|
|
73854
|
+
owner: httpsMatch[1],
|
|
73855
|
+
repo: httpsMatch[2].replace(/\.git$/, "")
|
|
73856
|
+
};
|
|
73857
|
+
}
|
|
73858
|
+
const sshMatch = remoteUrl.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/i);
|
|
73859
|
+
if (sshMatch) {
|
|
73860
|
+
return {
|
|
73861
|
+
owner: sshMatch[1],
|
|
73862
|
+
repo: sshMatch[2].replace(/\.git$/, "")
|
|
73863
|
+
};
|
|
73864
|
+
}
|
|
73865
|
+
const pathMatch = remoteUrl.match(/\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
|
|
73866
|
+
if (pathMatch) {
|
|
73867
|
+
return {
|
|
73868
|
+
owner: pathMatch[1],
|
|
73869
|
+
repo: pathMatch[2].replace(/\.git$/, "")
|
|
73870
|
+
};
|
|
73871
|
+
}
|
|
73872
|
+
return null;
|
|
73873
|
+
}
|
|
73874
|
+
function looksLikePrRef(token) {
|
|
73875
|
+
return /^https?:\/\//i.test(token) || /^[^/]+\/[^#]+#\d+$/.test(token) || /^\d+$/.test(token);
|
|
73876
|
+
}
|
|
73877
|
+
function resolvePrCommandInput(rest, cwd) {
|
|
73878
|
+
if (rest.length === 0) {
|
|
73879
|
+
return null;
|
|
73880
|
+
}
|
|
73881
|
+
const refToken = rest[0];
|
|
73882
|
+
const instructions = sanitizeInstructions(rest.slice(1).join(" "));
|
|
73883
|
+
const isFullUrl = /^https?:\/\//i.test(refToken);
|
|
73884
|
+
const prInfo = parsePrRef(isFullUrl ? sanitizeUrl(refToken) : refToken, cwd);
|
|
73885
|
+
if (!prInfo) {
|
|
73886
|
+
return { error: `Could not parse PR reference from "${refToken}"` };
|
|
73887
|
+
}
|
|
73888
|
+
const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
|
|
73889
|
+
const result = validateAndSanitizeUrl(prUrl);
|
|
73890
|
+
if ("error" in result) {
|
|
73891
|
+
return { error: result.error };
|
|
73892
|
+
}
|
|
73893
|
+
return { prUrl: result.sanitized, instructions };
|
|
73894
|
+
}
|
|
73895
|
+
var _internals35, MAX_URL_LEN = 2048, MAX_INSTRUCTIONS_LEN = 1000;
|
|
73896
|
+
var init_pr_ref = __esm(() => {
|
|
73897
|
+
_internals35 = { execSync: execSync2 };
|
|
73898
|
+
});
|
|
73899
|
+
|
|
73900
|
+
// src/commands/issue.ts
|
|
73901
|
+
import { execSync as execSync3 } from "node:child_process";
|
|
73902
|
+
function sanitizeUrl2(raw) {
|
|
73903
|
+
let urlStr = raw.trim();
|
|
73904
|
+
urlStr = urlStr.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
73905
|
+
const fragmentIdx = urlStr.indexOf("#");
|
|
73906
|
+
if (fragmentIdx !== -1) {
|
|
73907
|
+
urlStr = urlStr.slice(0, fragmentIdx);
|
|
73908
|
+
}
|
|
73909
|
+
const queryIdx = urlStr.indexOf("?");
|
|
73910
|
+
if (queryIdx !== -1) {
|
|
73911
|
+
urlStr = urlStr.slice(0, queryIdx);
|
|
73912
|
+
}
|
|
73913
|
+
urlStr = urlStr.replace(/^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^@/]+@/, "https://");
|
|
73914
|
+
if (urlStr.length > MAX_URL_LEN2) {
|
|
73915
|
+
urlStr = urlStr.slice(0, MAX_URL_LEN2);
|
|
73916
|
+
}
|
|
73917
|
+
return urlStr.trim();
|
|
73918
|
+
}
|
|
73919
|
+
function isPrivateHost2(url3) {
|
|
73920
|
+
const host = url3.hostname.toLowerCase();
|
|
73921
|
+
if (host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "0.0.0.0") {
|
|
73922
|
+
return true;
|
|
73923
|
+
}
|
|
73924
|
+
if (host.startsWith("localhost") || host === "localhost.com") {
|
|
73925
|
+
return true;
|
|
73926
|
+
}
|
|
73927
|
+
const ipv4Private = /^10\./;
|
|
73928
|
+
const ipv4172 = /^172\.(1[6-9]|2\d|3[0-1])\./;
|
|
73929
|
+
const ipv4192 = /^192\.168\./;
|
|
73930
|
+
const ipv6Private = /^fe80:/i;
|
|
73931
|
+
const ipv6Unique = /^f[cd][0-9a-f]{2}:/i;
|
|
73932
|
+
if (ipv4Private.test(host) || ipv4172.test(host) || ipv4192.test(host) || ipv6Private.test(host) || ipv6Unique.test(host)) {
|
|
73933
|
+
return true;
|
|
73934
|
+
}
|
|
73935
|
+
if (host.startsWith("::ffff:")) {
|
|
73936
|
+
const inner = host.slice(7);
|
|
73937
|
+
if (ipv4Private.test(inner) || ipv4172.test(inner) || ipv4192.test(inner)) {
|
|
73938
|
+
return true;
|
|
73939
|
+
}
|
|
73940
|
+
}
|
|
73941
|
+
return false;
|
|
73942
|
+
}
|
|
73943
|
+
function validateAndSanitizeUrl2(rawUrl) {
|
|
73944
|
+
const sanitized = sanitizeUrl2(rawUrl);
|
|
73945
|
+
if (!sanitized) {
|
|
73946
|
+
return { error: "Empty URL" };
|
|
73947
|
+
}
|
|
73948
|
+
if (!sanitized.startsWith("https://")) {
|
|
73949
|
+
return { error: "URL must use HTTPS scheme" };
|
|
73950
|
+
}
|
|
73766
73951
|
try {
|
|
73767
73952
|
const url3 = new URL(sanitized);
|
|
73768
73953
|
const hostname5 = url3.hostname;
|
|
73769
73954
|
if (/[\u0080-\u{10FFFF}]/u.test(hostname5)) {
|
|
73770
73955
|
return { error: "Non-ASCII hostnames are not allowed" };
|
|
73771
73956
|
}
|
|
73772
|
-
if (
|
|
73957
|
+
if (isPrivateHost2(url3)) {
|
|
73773
73958
|
return { error: "Private or localhost URLs are not allowed" };
|
|
73774
73959
|
}
|
|
73775
73960
|
const githubIssuePattern = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/issues\/([0-9]+)\/?$/;
|
|
@@ -73828,7 +74013,7 @@ function parseIssueRef(input) {
|
|
|
73828
74013
|
const bareMatch = input.match(/^(\d+)$/);
|
|
73829
74014
|
if (bareMatch) {
|
|
73830
74015
|
const issueNumber = parseInt(bareMatch[1], 10);
|
|
73831
|
-
const remoteUrl =
|
|
74016
|
+
const remoteUrl = detectGitRemote2();
|
|
73832
74017
|
if (!remoteUrl) {
|
|
73833
74018
|
return null;
|
|
73834
74019
|
}
|
|
@@ -73844,9 +74029,9 @@ function parseIssueRef(input) {
|
|
|
73844
74029
|
}
|
|
73845
74030
|
return null;
|
|
73846
74031
|
}
|
|
73847
|
-
function
|
|
74032
|
+
function detectGitRemote2() {
|
|
73848
74033
|
try {
|
|
73849
|
-
const remoteUrl =
|
|
74034
|
+
const remoteUrl = execSync3("git remote get-url origin", {
|
|
73850
74035
|
encoding: "utf-8",
|
|
73851
74036
|
stdio: ["pipe", "pipe", "pipe"],
|
|
73852
74037
|
timeout: 5000
|
|
@@ -73856,23 +74041,6 @@ function detectGitRemote() {
|
|
|
73856
74041
|
return null;
|
|
73857
74042
|
}
|
|
73858
74043
|
}
|
|
73859
|
-
function parseGitRemoteUrl(remoteUrl) {
|
|
73860
|
-
const httpsMatch = remoteUrl.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/i);
|
|
73861
|
-
if (httpsMatch) {
|
|
73862
|
-
return {
|
|
73863
|
-
owner: httpsMatch[1],
|
|
73864
|
-
repo: httpsMatch[2].replace(/\.git$/, "")
|
|
73865
|
-
};
|
|
73866
|
-
}
|
|
73867
|
-
const sshMatch = remoteUrl.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/i);
|
|
73868
|
-
if (sshMatch) {
|
|
73869
|
-
return {
|
|
73870
|
-
owner: sshMatch[1],
|
|
73871
|
-
repo: sshMatch[2].replace(/\.git$/, "")
|
|
73872
|
-
};
|
|
73873
|
-
}
|
|
73874
|
-
return null;
|
|
73875
|
-
}
|
|
73876
74044
|
function handleIssueCommand(_directory, args2) {
|
|
73877
74045
|
const parsed = parseArgs5(args2);
|
|
73878
74046
|
const rawInput = parsed.rest.join(" ").trim();
|
|
@@ -73880,14 +74048,14 @@ function handleIssueCommand(_directory, args2) {
|
|
|
73880
74048
|
return USAGE5;
|
|
73881
74049
|
}
|
|
73882
74050
|
const isFullUrl = /^https?:\/\//i.test(rawInput);
|
|
73883
|
-
const issueInfo = parseIssueRef(isFullUrl ?
|
|
74051
|
+
const issueInfo = parseIssueRef(isFullUrl ? sanitizeUrl2(rawInput) : rawInput);
|
|
73884
74052
|
if (!issueInfo) {
|
|
73885
74053
|
return `Error: Could not parse issue reference from "${rawInput}"
|
|
73886
74054
|
|
|
73887
74055
|
${USAGE5}`;
|
|
73888
74056
|
}
|
|
73889
74057
|
const issueUrl = `https://github.com/${issueInfo.owner}/${issueInfo.repo}/issues/${issueInfo.number}`;
|
|
73890
|
-
const result =
|
|
74058
|
+
const result = validateAndSanitizeUrl2(issueUrl);
|
|
73891
74059
|
if ("error" in result) {
|
|
73892
74060
|
return `Error: ${result.error}
|
|
73893
74061
|
|
|
@@ -73903,8 +74071,9 @@ ${USAGE5}`;
|
|
|
73903
74071
|
const flagsStr = flags2.length > 0 ? ` ${flags2.join(" ")}` : "";
|
|
73904
74072
|
return `[MODE: ISSUE_INGEST issue="${result.sanitized}"${flagsStr}]`;
|
|
73905
74073
|
}
|
|
73906
|
-
var
|
|
74074
|
+
var MAX_URL_LEN2 = 2048, USAGE5;
|
|
73907
74075
|
var init_issue = __esm(() => {
|
|
74076
|
+
init_pr_ref();
|
|
73908
74077
|
USAGE5 = [
|
|
73909
74078
|
"Usage: /swarm issue <url|owner/repo#N|N> [--plan] [--trace] [--no-repro]",
|
|
73910
74079
|
"",
|
|
@@ -73929,6 +74098,7 @@ var KNOWLEDGE_SCHEMA_VERSION = 2;
|
|
|
73929
74098
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
73930
74099
|
import { existsSync as existsSync32, readFileSync as readFileSync17 } from "node:fs";
|
|
73931
74100
|
import { mkdir as mkdir14, readFile as readFile16, writeFile as writeFile12 } from "node:fs/promises";
|
|
74101
|
+
import * as os13 from "node:os";
|
|
73932
74102
|
import * as path53 from "node:path";
|
|
73933
74103
|
async function migrateKnowledgeToExternal(_directory, _config) {
|
|
73934
74104
|
return {
|
|
@@ -73971,9 +74141,9 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
73971
74141
|
skippedReason: "empty-context"
|
|
73972
74142
|
};
|
|
73973
74143
|
}
|
|
73974
|
-
const rawEntries =
|
|
74144
|
+
const rawEntries = _internals36.parseContextMd(contextContent);
|
|
73975
74145
|
if (rawEntries.length === 0) {
|
|
73976
|
-
await
|
|
74146
|
+
await _internals36.writeSentinel(sentinelPath, 0, 0);
|
|
73977
74147
|
return {
|
|
73978
74148
|
migrated: true,
|
|
73979
74149
|
entriesMigrated: 0,
|
|
@@ -73984,10 +74154,10 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
73984
74154
|
const existing = await readKnowledge(knowledgePath);
|
|
73985
74155
|
let migrated = 0;
|
|
73986
74156
|
let dropped = 0;
|
|
73987
|
-
const projectName =
|
|
74157
|
+
const projectName = _internals36.inferProjectName(directory);
|
|
73988
74158
|
for (const raw of rawEntries) {
|
|
73989
74159
|
if (config3.validation_enabled !== false) {
|
|
73990
|
-
const category = raw.categoryHint ??
|
|
74160
|
+
const category = raw.categoryHint ?? _internals36.inferCategoryFromText(raw.text);
|
|
73991
74161
|
const result = validateLesson(raw.text, existing.map((e) => e.lesson), {
|
|
73992
74162
|
category,
|
|
73993
74163
|
scope: "global",
|
|
@@ -74007,8 +74177,8 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
74007
74177
|
const entry = {
|
|
74008
74178
|
id: randomUUID6(),
|
|
74009
74179
|
tier: "swarm",
|
|
74010
|
-
lesson:
|
|
74011
|
-
category: raw.categoryHint ??
|
|
74180
|
+
lesson: _internals36.truncateLesson(raw.text),
|
|
74181
|
+
category: raw.categoryHint ?? _internals36.inferCategoryFromText(raw.text),
|
|
74012
74182
|
tags: [...inferredTags, `migration:${raw.sourceSection}`],
|
|
74013
74183
|
scope: "global",
|
|
74014
74184
|
confidence: 0.3,
|
|
@@ -74031,7 +74201,7 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
74031
74201
|
if (migrated > 0) {
|
|
74032
74202
|
await rewriteKnowledge(knowledgePath, existing);
|
|
74033
74203
|
}
|
|
74034
|
-
await
|
|
74204
|
+
await _internals36.writeSentinel(sentinelPath, migrated, dropped);
|
|
74035
74205
|
log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`);
|
|
74036
74206
|
return {
|
|
74037
74207
|
migrated: true,
|
|
@@ -74040,8 +74210,125 @@ async function migrateContextToKnowledge(directory, config3) {
|
|
|
74040
74210
|
entriesTotal: rawEntries.length
|
|
74041
74211
|
};
|
|
74042
74212
|
}
|
|
74213
|
+
async function migrateHiveKnowledgeLegacy(config3) {
|
|
74214
|
+
const legacyHivePath = _internals36.resolveLegacyHiveKnowledgePath();
|
|
74215
|
+
const canonicalHivePath = resolveHiveKnowledgePath();
|
|
74216
|
+
const sentinelPath = path53.join(path53.dirname(canonicalHivePath), ".hive-knowledge-migrated");
|
|
74217
|
+
if (existsSync32(sentinelPath)) {
|
|
74218
|
+
return {
|
|
74219
|
+
migrated: false,
|
|
74220
|
+
entriesMigrated: 0,
|
|
74221
|
+
entriesDropped: 0,
|
|
74222
|
+
entriesTotal: 0,
|
|
74223
|
+
skippedReason: "sentinel-exists"
|
|
74224
|
+
};
|
|
74225
|
+
}
|
|
74226
|
+
if (!existsSync32(legacyHivePath)) {
|
|
74227
|
+
return {
|
|
74228
|
+
migrated: false,
|
|
74229
|
+
entriesMigrated: 0,
|
|
74230
|
+
entriesDropped: 0,
|
|
74231
|
+
entriesTotal: 0,
|
|
74232
|
+
skippedReason: "no-context-file"
|
|
74233
|
+
};
|
|
74234
|
+
}
|
|
74235
|
+
const legacyEntries = await readKnowledge(legacyHivePath);
|
|
74236
|
+
if (legacyEntries.length === 0) {
|
|
74237
|
+
await _internals36.writeSentinel(sentinelPath, 0, 0);
|
|
74238
|
+
return {
|
|
74239
|
+
migrated: true,
|
|
74240
|
+
entriesMigrated: 0,
|
|
74241
|
+
entriesDropped: 0,
|
|
74242
|
+
entriesTotal: 0
|
|
74243
|
+
};
|
|
74244
|
+
}
|
|
74245
|
+
const existingHiveEntries = await readKnowledge(canonicalHivePath);
|
|
74246
|
+
let migrated = 0;
|
|
74247
|
+
let dropped = 0;
|
|
74248
|
+
const entryErrors = [];
|
|
74249
|
+
for (const legacyEntry of legacyEntries) {
|
|
74250
|
+
try {
|
|
74251
|
+
const lesson = legacyEntry.lesson;
|
|
74252
|
+
if (!lesson || typeof lesson !== "string" || lesson.length < 15) {
|
|
74253
|
+
dropped++;
|
|
74254
|
+
continue;
|
|
74255
|
+
}
|
|
74256
|
+
const dup = findNearDuplicate(lesson, existingHiveEntries, config3.dedup_threshold ?? 0.6);
|
|
74257
|
+
if (dup) {
|
|
74258
|
+
dropped++;
|
|
74259
|
+
continue;
|
|
74260
|
+
}
|
|
74261
|
+
const category = legacyEntry.category || "process";
|
|
74262
|
+
const validationResult = validateLesson(lesson, existingHiveEntries.map((e) => e.lesson), {
|
|
74263
|
+
category,
|
|
74264
|
+
scope: "global",
|
|
74265
|
+
confidence: 0.3
|
|
74266
|
+
});
|
|
74267
|
+
if (!validationResult.valid) {
|
|
74268
|
+
const errorMsg = `Validation failed for legacy entry: ${validationResult.reason}`;
|
|
74269
|
+
entryErrors.push(errorMsg);
|
|
74270
|
+
warn(`[knowledge-migrator] ${errorMsg}`);
|
|
74271
|
+
dropped++;
|
|
74272
|
+
continue;
|
|
74273
|
+
}
|
|
74274
|
+
const confidence = legacyEntry.confidence ?? 0.8;
|
|
74275
|
+
const scopeTag = legacyEntry.scope_tag || "global";
|
|
74276
|
+
const legacyId = legacyEntry.id;
|
|
74277
|
+
const existingIds = new Set(existingHiveEntries.map((e) => e.id));
|
|
74278
|
+
const resolvedId = legacyId && existingIds.has(legacyId) ? randomUUID6() : legacyId || randomUUID6();
|
|
74279
|
+
if (legacyId && existingIds.has(legacyId)) {
|
|
74280
|
+
warn(`[knowledge-migrator] Legacy entry ID collision for "${legacyId}", generating new UUID`);
|
|
74281
|
+
}
|
|
74282
|
+
const newHiveEntry = {
|
|
74283
|
+
id: resolvedId,
|
|
74284
|
+
tier: "hive",
|
|
74285
|
+
lesson: _internals36.truncateLesson(lesson),
|
|
74286
|
+
category,
|
|
74287
|
+
tags: ["migration:legacy-hive"],
|
|
74288
|
+
scope: scopeTag,
|
|
74289
|
+
confidence: Math.min(Math.max(confidence, 0), 1),
|
|
74290
|
+
status: "established",
|
|
74291
|
+
confirmed_by: [],
|
|
74292
|
+
retrieval_outcomes: {
|
|
74293
|
+
applied_count: 0,
|
|
74294
|
+
succeeded_after_count: 0,
|
|
74295
|
+
failed_after_count: 0
|
|
74296
|
+
},
|
|
74297
|
+
schema_version: KNOWLEDGE_SCHEMA_VERSION,
|
|
74298
|
+
created_at: legacyEntry.created_at || new Date().toISOString(),
|
|
74299
|
+
updated_at: legacyEntry.updated_at || new Date().toISOString(),
|
|
74300
|
+
source_project: "legacy-promotion",
|
|
74301
|
+
encounter_score: 1
|
|
74302
|
+
};
|
|
74303
|
+
try {
|
|
74304
|
+
await _internals36.appendKnowledge(canonicalHivePath, newHiveEntry);
|
|
74305
|
+
existingHiveEntries.push(newHiveEntry);
|
|
74306
|
+
migrated++;
|
|
74307
|
+
} catch (appendError) {
|
|
74308
|
+
const errorMsg = `Failed to append entry: ${appendError instanceof Error ? appendError.message : String(appendError)}`;
|
|
74309
|
+
entryErrors.push(errorMsg);
|
|
74310
|
+
warn(`[knowledge-migrator] ${errorMsg}`);
|
|
74311
|
+
dropped++;
|
|
74312
|
+
}
|
|
74313
|
+
} catch (entryError) {
|
|
74314
|
+
const errorMsg = `Unexpected error processing legacy entry: ${entryError instanceof Error ? entryError.message : String(entryError)}`;
|
|
74315
|
+
entryErrors.push(errorMsg);
|
|
74316
|
+
warn(`[knowledge-migrator] ${errorMsg}`);
|
|
74317
|
+
dropped++;
|
|
74318
|
+
}
|
|
74319
|
+
}
|
|
74320
|
+
await _internals36.writeSentinel(sentinelPath, migrated, dropped);
|
|
74321
|
+
log(`[knowledge-migrator] Migrated ${migrated} legacy hive entries, dropped ${dropped}`);
|
|
74322
|
+
return {
|
|
74323
|
+
migrated: true,
|
|
74324
|
+
entriesMigrated: migrated,
|
|
74325
|
+
entriesDropped: dropped,
|
|
74326
|
+
entriesTotal: legacyEntries.length,
|
|
74327
|
+
...entryErrors.length > 0 && { entryErrors }
|
|
74328
|
+
};
|
|
74329
|
+
}
|
|
74043
74330
|
function parseContextMd(content) {
|
|
74044
|
-
const sections =
|
|
74331
|
+
const sections = _internals36.splitIntoSections(content);
|
|
74045
74332
|
const entries = [];
|
|
74046
74333
|
const seen = new Set;
|
|
74047
74334
|
const sectionPatterns = [
|
|
@@ -74057,7 +74344,7 @@ function parseContextMd(content) {
|
|
|
74057
74344
|
const match = sectionPatterns.find((sp) => sp.pattern.test(section.heading));
|
|
74058
74345
|
if (!match)
|
|
74059
74346
|
continue;
|
|
74060
|
-
const bullets =
|
|
74347
|
+
const bullets = _internals36.extractBullets(section.body);
|
|
74061
74348
|
for (const bullet of bullets) {
|
|
74062
74349
|
if (bullet.length < 15)
|
|
74063
74350
|
continue;
|
|
@@ -74066,9 +74353,9 @@ function parseContextMd(content) {
|
|
|
74066
74353
|
continue;
|
|
74067
74354
|
seen.add(normalized);
|
|
74068
74355
|
entries.push({
|
|
74069
|
-
text:
|
|
74356
|
+
text: _internals36.truncateLesson(bullet),
|
|
74070
74357
|
sourceSection: match.sourceSection,
|
|
74071
|
-
categoryHint:
|
|
74358
|
+
categoryHint: _internals36.inferCategoryFromText(bullet)
|
|
74072
74359
|
});
|
|
74073
74360
|
}
|
|
74074
74361
|
}
|
|
@@ -74161,21 +74448,37 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
74161
74448
|
await mkdir14(path53.dirname(sentinelPath), { recursive: true });
|
|
74162
74449
|
await writeFile12(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
74163
74450
|
}
|
|
74164
|
-
|
|
74451
|
+
function resolveLegacyHiveKnowledgePath() {
|
|
74452
|
+
const platform = process.platform;
|
|
74453
|
+
const home = process.env.HOME || os13.homedir();
|
|
74454
|
+
let dataDir;
|
|
74455
|
+
if (platform === "win32") {
|
|
74456
|
+
dataDir = path53.join(process.env.LOCALAPPDATA || path53.join(home, "AppData", "Local"), "opencode-swarm", "Data");
|
|
74457
|
+
} else if (platform === "darwin") {
|
|
74458
|
+
dataDir = path53.join(home, "Library", "Application Support", "opencode-swarm");
|
|
74459
|
+
} else {
|
|
74460
|
+
dataDir = path53.join(process.env.XDG_DATA_HOME || path53.join(home, ".local", "share"), "opencode-swarm");
|
|
74461
|
+
}
|
|
74462
|
+
return path53.join(dataDir, "hive-knowledge.jsonl");
|
|
74463
|
+
}
|
|
74464
|
+
var _internals36;
|
|
74165
74465
|
var init_knowledge_migrator = __esm(() => {
|
|
74166
74466
|
init_logger();
|
|
74167
74467
|
init_knowledge_store();
|
|
74168
74468
|
init_knowledge_validator();
|
|
74169
|
-
|
|
74469
|
+
_internals36 = {
|
|
74470
|
+
appendKnowledge,
|
|
74170
74471
|
migrateContextToKnowledge,
|
|
74171
74472
|
migrateKnowledgeToExternal,
|
|
74473
|
+
migrateHiveKnowledgeLegacy,
|
|
74172
74474
|
parseContextMd,
|
|
74173
74475
|
splitIntoSections,
|
|
74174
74476
|
extractBullets,
|
|
74175
74477
|
inferCategoryFromText,
|
|
74176
74478
|
truncateLesson: truncateLesson2,
|
|
74177
74479
|
inferProjectName,
|
|
74178
|
-
writeSentinel
|
|
74480
|
+
writeSentinel,
|
|
74481
|
+
resolveLegacyHiveKnowledgePath
|
|
74179
74482
|
};
|
|
74180
74483
|
});
|
|
74181
74484
|
|
|
@@ -74247,24 +74550,43 @@ async function handleKnowledgeRestoreCommand(directory, args2) {
|
|
|
74247
74550
|
}
|
|
74248
74551
|
async function handleKnowledgeMigrateCommand(directory, args2) {
|
|
74249
74552
|
const targetDir = args2[0] || directory;
|
|
74553
|
+
const config3 = KnowledgeConfigSchema.parse({});
|
|
74250
74554
|
try {
|
|
74251
|
-
const
|
|
74252
|
-
|
|
74253
|
-
|
|
74555
|
+
const contextResult = await migrateContextToKnowledge(targetDir, config3);
|
|
74556
|
+
const hiveResult = await migrateHiveKnowledgeLegacy(config3);
|
|
74557
|
+
const messages = [];
|
|
74558
|
+
if (contextResult.skippedReason) {
|
|
74559
|
+
switch (contextResult.skippedReason) {
|
|
74254
74560
|
case "sentinel-exists":
|
|
74255
|
-
|
|
74561
|
+
messages.push("⏭ Context migration already completed. Delete .swarm/.knowledge-migrated to re-run.");
|
|
74562
|
+
break;
|
|
74256
74563
|
case "no-context-file":
|
|
74257
|
-
|
|
74564
|
+
messages.push("ℹ️ No .swarm/context.md found — nothing to migrate.");
|
|
74565
|
+
break;
|
|
74258
74566
|
case "empty-context":
|
|
74259
|
-
|
|
74260
|
-
|
|
74261
|
-
return "⚠️ Migration skipped for an unknown reason.";
|
|
74567
|
+
messages.push("ℹ️ .swarm/context.md is empty — nothing to migrate.");
|
|
74568
|
+
break;
|
|
74262
74569
|
}
|
|
74570
|
+
} else {
|
|
74571
|
+
messages.push(`✅ Context migration: ${contextResult.entriesMigrated} entries added, ${contextResult.entriesDropped} dropped`);
|
|
74263
74572
|
}
|
|
74264
|
-
|
|
74573
|
+
if (hiveResult.skippedReason) {
|
|
74574
|
+
switch (hiveResult.skippedReason) {
|
|
74575
|
+
case "sentinel-exists":
|
|
74576
|
+
messages.push("⏭ Hive legacy migration already completed. Delete the sentinel in the hive data dir to re-run.");
|
|
74577
|
+
break;
|
|
74578
|
+
case "no-context-file":
|
|
74579
|
+
messages.push("ℹ️ No legacy hive-knowledge.jsonl found — nothing to migrate.");
|
|
74580
|
+
break;
|
|
74581
|
+
}
|
|
74582
|
+
} else if (hiveResult.migrated) {
|
|
74583
|
+
messages.push(`✅ Hive legacy migration: ${hiveResult.entriesMigrated} entries added, ${hiveResult.entriesDropped} dropped`);
|
|
74584
|
+
}
|
|
74585
|
+
return messages.join(`
|
|
74586
|
+
`);
|
|
74265
74587
|
} catch (error93) {
|
|
74266
|
-
console.warn("[knowledge-command]
|
|
74267
|
-
return "❌ Migration failed. Check
|
|
74588
|
+
console.warn("[knowledge-command] migration error:", error93 instanceof Error ? error93.message : String(error93));
|
|
74589
|
+
return "❌ Migration failed. Check that knowledge source files are readable.";
|
|
74268
74590
|
}
|
|
74269
74591
|
}
|
|
74270
74592
|
async function handleKnowledgeListCommand(directory, _args) {
|
|
@@ -77324,7 +77646,7 @@ var init_gateway = __esm(() => {
|
|
|
77324
77646
|
|
|
77325
77647
|
// src/memory/evaluation.ts
|
|
77326
77648
|
import * as fs27 from "node:fs/promises";
|
|
77327
|
-
import * as
|
|
77649
|
+
import * as os14 from "node:os";
|
|
77328
77650
|
import * as path58 from "node:path";
|
|
77329
77651
|
async function evaluateMemoryRecallFixtures(options) {
|
|
77330
77652
|
const fixtureDirectory = path58.resolve(options.fixtureDirectory);
|
|
@@ -77336,7 +77658,7 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
77336
77658
|
for (const fixture of fixtures) {
|
|
77337
77659
|
const materialized = materializeFixture(fixture);
|
|
77338
77660
|
for (const providerName of providers) {
|
|
77339
|
-
const tempRoot = await fs27.realpath(await fs27.mkdtemp(path58.join(
|
|
77661
|
+
const tempRoot = await fs27.realpath(await fs27.mkdtemp(path58.join(os14.tmpdir(), "swarm-memory-eval-")));
|
|
77340
77662
|
const provider = createEvaluationProvider(providerName, tempRoot);
|
|
77341
77663
|
try {
|
|
77342
77664
|
await provider.initialize?.();
|
|
@@ -78652,9 +78974,9 @@ var init_memory2 = __esm(() => {
|
|
|
78652
78974
|
|
|
78653
78975
|
// src/services/plan-service.ts
|
|
78654
78976
|
async function getPlanData(directory, phaseArg) {
|
|
78655
|
-
const plan = await
|
|
78977
|
+
const plan = await _internals37.loadPlanJsonOnly(directory);
|
|
78656
78978
|
if (plan) {
|
|
78657
|
-
const fullMarkdown =
|
|
78979
|
+
const fullMarkdown = _internals37.derivePlanMarkdown(plan);
|
|
78658
78980
|
if (phaseArg === undefined || phaseArg === null || phaseArg === "") {
|
|
78659
78981
|
return {
|
|
78660
78982
|
hasPlan: true,
|
|
@@ -78697,7 +79019,7 @@ async function getPlanData(directory, phaseArg) {
|
|
|
78697
79019
|
isLegacy: false
|
|
78698
79020
|
};
|
|
78699
79021
|
}
|
|
78700
|
-
const planContent = await
|
|
79022
|
+
const planContent = await _internals37.readSwarmFileAsync(directory, "plan.md");
|
|
78701
79023
|
if (!planContent) {
|
|
78702
79024
|
return {
|
|
78703
79025
|
hasPlan: false,
|
|
@@ -78793,11 +79115,11 @@ async function handlePlanCommand(directory, args2) {
|
|
|
78793
79115
|
const planData = await getPlanData(directory, phaseArg);
|
|
78794
79116
|
return formatPlanMarkdown(planData);
|
|
78795
79117
|
}
|
|
78796
|
-
var
|
|
79118
|
+
var _internals37;
|
|
78797
79119
|
var init_plan_service = __esm(() => {
|
|
78798
79120
|
init_utils2();
|
|
78799
79121
|
init_manager();
|
|
78800
|
-
|
|
79122
|
+
_internals37 = {
|
|
78801
79123
|
loadPlanJsonOnly,
|
|
78802
79124
|
derivePlanMarkdown,
|
|
78803
79125
|
readSwarmFileAsync
|
|
@@ -78809,191 +79131,6 @@ var init_plan = __esm(() => {
|
|
|
78809
79131
|
init_plan_service();
|
|
78810
79132
|
});
|
|
78811
79133
|
|
|
78812
|
-
// src/commands/pr-ref.ts
|
|
78813
|
-
import { execSync as execSync3 } from "node:child_process";
|
|
78814
|
-
function sanitizeUrl2(raw) {
|
|
78815
|
-
let urlStr = raw.trim();
|
|
78816
|
-
urlStr = urlStr.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
78817
|
-
const fragmentIdx = urlStr.indexOf("#");
|
|
78818
|
-
if (fragmentIdx !== -1) {
|
|
78819
|
-
urlStr = urlStr.slice(0, fragmentIdx);
|
|
78820
|
-
}
|
|
78821
|
-
const queryIdx = urlStr.indexOf("?");
|
|
78822
|
-
if (queryIdx !== -1) {
|
|
78823
|
-
urlStr = urlStr.slice(0, queryIdx);
|
|
78824
|
-
}
|
|
78825
|
-
urlStr = urlStr.replace(/^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^@/]+@/, "https://");
|
|
78826
|
-
if (urlStr.length > MAX_URL_LEN2) {
|
|
78827
|
-
urlStr = urlStr.slice(0, MAX_URL_LEN2);
|
|
78828
|
-
}
|
|
78829
|
-
return urlStr.trim();
|
|
78830
|
-
}
|
|
78831
|
-
function sanitizeInstructions(raw) {
|
|
78832
|
-
const collapsed = raw.replace(/\s+/g, " ").trim();
|
|
78833
|
-
const stripped = collapsed.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
78834
|
-
const normalized = stripped.replace(/\s+/g, " ").trim();
|
|
78835
|
-
if (normalized.length <= MAX_INSTRUCTIONS_LEN)
|
|
78836
|
-
return normalized;
|
|
78837
|
-
return `${normalized.slice(0, MAX_INSTRUCTIONS_LEN)}…`;
|
|
78838
|
-
}
|
|
78839
|
-
function hasNonAsciiHostname(hostname5) {
|
|
78840
|
-
for (const ch of hostname5) {
|
|
78841
|
-
const cp = ch.codePointAt(0);
|
|
78842
|
-
if (cp !== undefined && cp > 127)
|
|
78843
|
-
return true;
|
|
78844
|
-
}
|
|
78845
|
-
return false;
|
|
78846
|
-
}
|
|
78847
|
-
function isPrivateHost2(url3) {
|
|
78848
|
-
const host = url3.hostname.toLowerCase();
|
|
78849
|
-
if (host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "0.0.0.0") {
|
|
78850
|
-
return true;
|
|
78851
|
-
}
|
|
78852
|
-
if (host.startsWith("localhost") || host === "localhost.com") {
|
|
78853
|
-
return true;
|
|
78854
|
-
}
|
|
78855
|
-
const ipv4Private = /^10\./;
|
|
78856
|
-
const ipv4172 = /^172\.(1[6-9]|2\d|3[0-1])\./;
|
|
78857
|
-
const ipv4192 = /^192\.168\./;
|
|
78858
|
-
const ipv6Private = /^fe80:/i;
|
|
78859
|
-
const ipv6Unique = /^f[cd][0-9a-f]{2}:/i;
|
|
78860
|
-
if (ipv4Private.test(host) || ipv4172.test(host) || ipv4192.test(host) || ipv6Private.test(host) || ipv6Unique.test(host)) {
|
|
78861
|
-
return true;
|
|
78862
|
-
}
|
|
78863
|
-
if (host.startsWith("::ffff:")) {
|
|
78864
|
-
const inner = host.slice(7);
|
|
78865
|
-
if (ipv4Private.test(inner) || ipv4172.test(inner) || ipv4192.test(inner)) {
|
|
78866
|
-
return true;
|
|
78867
|
-
}
|
|
78868
|
-
}
|
|
78869
|
-
return false;
|
|
78870
|
-
}
|
|
78871
|
-
function validateAndSanitizeUrl2(rawUrl) {
|
|
78872
|
-
const sanitized = sanitizeUrl2(rawUrl);
|
|
78873
|
-
if (!sanitized) {
|
|
78874
|
-
return { error: "Empty URL" };
|
|
78875
|
-
}
|
|
78876
|
-
if (!sanitized.startsWith("https://")) {
|
|
78877
|
-
return { error: "URL must use HTTPS scheme" };
|
|
78878
|
-
}
|
|
78879
|
-
try {
|
|
78880
|
-
const url3 = new URL(sanitized);
|
|
78881
|
-
if (hasNonAsciiHostname(url3.hostname)) {
|
|
78882
|
-
return { error: "Non-ASCII hostnames are not allowed" };
|
|
78883
|
-
}
|
|
78884
|
-
if (isPrivateHost2(url3)) {
|
|
78885
|
-
return { error: "Private or localhost URLs are not allowed" };
|
|
78886
|
-
}
|
|
78887
|
-
const githubPrPattern = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/([0-9]+)\/?$/;
|
|
78888
|
-
if (!githubPrPattern.test(sanitized)) {
|
|
78889
|
-
return {
|
|
78890
|
-
error: "URL must be a GitHub pull request URL (https://github.com/owner/repo/pull/N)"
|
|
78891
|
-
};
|
|
78892
|
-
}
|
|
78893
|
-
return { sanitized };
|
|
78894
|
-
} catch {
|
|
78895
|
-
return { error: "Invalid URL format" };
|
|
78896
|
-
}
|
|
78897
|
-
}
|
|
78898
|
-
function parsePrRef(input, cwd) {
|
|
78899
|
-
const urlMatch = input.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)\/?$/i);
|
|
78900
|
-
if (urlMatch) {
|
|
78901
|
-
return {
|
|
78902
|
-
owner: urlMatch[1],
|
|
78903
|
-
repo: urlMatch[2],
|
|
78904
|
-
number: parseInt(urlMatch[3], 10)
|
|
78905
|
-
};
|
|
78906
|
-
}
|
|
78907
|
-
const shorthandMatch = input.match(/^([^/]+)\/([^#]+)#(\d+)$/);
|
|
78908
|
-
if (shorthandMatch) {
|
|
78909
|
-
return {
|
|
78910
|
-
owner: shorthandMatch[1],
|
|
78911
|
-
repo: shorthandMatch[2],
|
|
78912
|
-
number: parseInt(shorthandMatch[3], 10)
|
|
78913
|
-
};
|
|
78914
|
-
}
|
|
78915
|
-
const bareMatch = input.match(/^(\d+)$/);
|
|
78916
|
-
if (bareMatch) {
|
|
78917
|
-
const prNumber = parseInt(bareMatch[1], 10);
|
|
78918
|
-
const remoteUrl = detectGitRemote2(cwd);
|
|
78919
|
-
if (!remoteUrl) {
|
|
78920
|
-
return null;
|
|
78921
|
-
}
|
|
78922
|
-
const parsed = parseGitRemoteUrl2(remoteUrl);
|
|
78923
|
-
if (!parsed) {
|
|
78924
|
-
return null;
|
|
78925
|
-
}
|
|
78926
|
-
return {
|
|
78927
|
-
owner: parsed.owner,
|
|
78928
|
-
repo: parsed.repo,
|
|
78929
|
-
number: prNumber
|
|
78930
|
-
};
|
|
78931
|
-
}
|
|
78932
|
-
return null;
|
|
78933
|
-
}
|
|
78934
|
-
function detectGitRemote2(cwd) {
|
|
78935
|
-
try {
|
|
78936
|
-
const remoteUrl = _internals37.execSync("git remote get-url origin", {
|
|
78937
|
-
encoding: "utf-8",
|
|
78938
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
78939
|
-
timeout: 5000,
|
|
78940
|
-
...cwd ? { cwd } : {}
|
|
78941
|
-
}).trim();
|
|
78942
|
-
return remoteUrl || null;
|
|
78943
|
-
} catch {
|
|
78944
|
-
return null;
|
|
78945
|
-
}
|
|
78946
|
-
}
|
|
78947
|
-
function parseGitRemoteUrl2(remoteUrl) {
|
|
78948
|
-
const httpsMatch = remoteUrl.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/i);
|
|
78949
|
-
if (httpsMatch) {
|
|
78950
|
-
return {
|
|
78951
|
-
owner: httpsMatch[1],
|
|
78952
|
-
repo: httpsMatch[2].replace(/\.git$/, "")
|
|
78953
|
-
};
|
|
78954
|
-
}
|
|
78955
|
-
const sshMatch = remoteUrl.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/i);
|
|
78956
|
-
if (sshMatch) {
|
|
78957
|
-
return {
|
|
78958
|
-
owner: sshMatch[1],
|
|
78959
|
-
repo: sshMatch[2].replace(/\.git$/, "")
|
|
78960
|
-
};
|
|
78961
|
-
}
|
|
78962
|
-
const pathMatch = remoteUrl.match(/\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
|
|
78963
|
-
if (pathMatch) {
|
|
78964
|
-
return {
|
|
78965
|
-
owner: pathMatch[1],
|
|
78966
|
-
repo: pathMatch[2].replace(/\.git$/, "")
|
|
78967
|
-
};
|
|
78968
|
-
}
|
|
78969
|
-
return null;
|
|
78970
|
-
}
|
|
78971
|
-
function looksLikePrRef(token) {
|
|
78972
|
-
return /^https?:\/\//i.test(token) || /^[^/]+\/[^#]+#\d+$/.test(token) || /^\d+$/.test(token);
|
|
78973
|
-
}
|
|
78974
|
-
function resolvePrCommandInput(rest, cwd) {
|
|
78975
|
-
if (rest.length === 0) {
|
|
78976
|
-
return null;
|
|
78977
|
-
}
|
|
78978
|
-
const refToken = rest[0];
|
|
78979
|
-
const instructions = sanitizeInstructions(rest.slice(1).join(" "));
|
|
78980
|
-
const isFullUrl = /^https?:\/\//i.test(refToken);
|
|
78981
|
-
const prInfo = parsePrRef(isFullUrl ? sanitizeUrl2(refToken) : refToken, cwd);
|
|
78982
|
-
if (!prInfo) {
|
|
78983
|
-
return { error: `Could not parse PR reference from "${refToken}"` };
|
|
78984
|
-
}
|
|
78985
|
-
const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
|
|
78986
|
-
const result = validateAndSanitizeUrl2(prUrl);
|
|
78987
|
-
if ("error" in result) {
|
|
78988
|
-
return { error: result.error };
|
|
78989
|
-
}
|
|
78990
|
-
return { prUrl: result.sanitized, instructions };
|
|
78991
|
-
}
|
|
78992
|
-
var _internals37, MAX_URL_LEN2 = 2048, MAX_INSTRUCTIONS_LEN = 1000;
|
|
78993
|
-
var init_pr_ref = __esm(() => {
|
|
78994
|
-
_internals37 = { execSync: execSync3 };
|
|
78995
|
-
});
|
|
78996
|
-
|
|
78997
79134
|
// src/commands/pr-feedback.ts
|
|
78998
79135
|
function handlePrFeedbackCommand(directory, args2) {
|
|
78999
79136
|
const rest = args2.filter((t) => t.trim().length > 0);
|
|
@@ -104023,7 +104160,7 @@ init_path_security();
|
|
|
104023
104160
|
import * as fsSync5 from "node:fs";
|
|
104024
104161
|
import { existsSync as existsSync61, realpathSync as realpathSync13 } from "node:fs";
|
|
104025
104162
|
import * as fsPromises5 from "node:fs/promises";
|
|
104026
|
-
import * as
|
|
104163
|
+
import * as os15 from "node:os";
|
|
104027
104164
|
import * as path101 from "node:path";
|
|
104028
104165
|
|
|
104029
104166
|
// src/tools/symbols.ts
|
|
@@ -104777,8 +104914,8 @@ function isRefusedWorkspaceRoot(target) {
|
|
|
104777
104914
|
refused.add(path101.resolve(p));
|
|
104778
104915
|
}
|
|
104779
104916
|
};
|
|
104780
|
-
add2(
|
|
104781
|
-
add2(
|
|
104917
|
+
add2(os15.homedir());
|
|
104918
|
+
add2(os15.tmpdir());
|
|
104782
104919
|
add2("/");
|
|
104783
104920
|
add2("/Users");
|
|
104784
104921
|
add2("/home");
|