@delorenj/pjangler 1.5.45 → 1.5.46
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 +10 -2
- package/dist/mcp-server.js +10 -2
- package/dist/project-registry-service.js +19 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11571,6 +11571,12 @@ function validateDeclaredAgent(ctx, declared) {
|
|
|
11571
11571
|
}
|
|
11572
11572
|
return { valid: details.length === 0, role: roleYaml.role, agentId: roleYaml.agentId, roleDir, details };
|
|
11573
11573
|
}
|
|
11574
|
+
function repoPathNamesRoot(value, repoRoot, homeDir) {
|
|
11575
|
+
if (typeof value !== "string") return false;
|
|
11576
|
+
if (value === repoRoot) return true;
|
|
11577
|
+
if (!homeDir || value !== "~" && !value.startsWith("~/")) return false;
|
|
11578
|
+
return resolve7(homeDir, value.slice(2)) === resolve7(repoRoot);
|
|
11579
|
+
}
|
|
11574
11580
|
function canonicalProjectJson(ctx) {
|
|
11575
11581
|
const roles = discoverRoles(ctx.repoRoot);
|
|
11576
11582
|
const existing = readProjectJson(ctx) ?? {};
|
|
@@ -11633,7 +11639,9 @@ function canonicalProjectJson(ctx) {
|
|
|
11633
11639
|
project_name: String(existing.project_name ?? titleCaseSlug(slug)),
|
|
11634
11640
|
project_description: String(existing.project_description ?? ""),
|
|
11635
11641
|
project_id: slug,
|
|
11636
|
-
|
|
11642
|
+
// A home-relative spelling that already names this repo is kept: rewriting
|
|
11643
|
+
// it to this host's absolute path would make the manifest wrong on its peers.
|
|
11644
|
+
repo_path: repoPathNamesRoot(existing.repo_path, ctx.repoRoot, ctx.homeDir) ? existing.repo_path : ctx.repoRoot,
|
|
11637
11645
|
ticket_provider: ticketProvider,
|
|
11638
11646
|
agents,
|
|
11639
11647
|
...Object.keys(automation).length ? { automation } : {},
|
|
@@ -11658,7 +11666,7 @@ function projectJsonFinding(ctx) {
|
|
|
11658
11666
|
}
|
|
11659
11667
|
if ("project_slug" in data) details.push("legacy project_slug should be migrated to project_id");
|
|
11660
11668
|
if (typeof data.project_id === "string" && data.project_id !== data.project_id.toLowerCase()) details.push("project_id must be lowercase");
|
|
11661
|
-
if (data.repo_path
|
|
11669
|
+
if (!repoPathNamesRoot(data.repo_path, ctx.repoRoot, ctx.homeDir)) details.push(`repo_path should be ${ctx.repoRoot}`);
|
|
11662
11670
|
const agents = data.agents ?? {};
|
|
11663
11671
|
for (const role of roles) {
|
|
11664
11672
|
const agent = agents[role.agentId];
|
package/dist/mcp-server.js
CHANGED
|
@@ -10734,6 +10734,12 @@ function validateDeclaredAgent(ctx, declared) {
|
|
|
10734
10734
|
}
|
|
10735
10735
|
return { valid: details.length === 0, role: roleYaml.role, agentId: roleYaml.agentId, roleDir, details };
|
|
10736
10736
|
}
|
|
10737
|
+
function repoPathNamesRoot(value, repoRoot, homeDir) {
|
|
10738
|
+
if (typeof value !== "string") return false;
|
|
10739
|
+
if (value === repoRoot) return true;
|
|
10740
|
+
if (!homeDir || value !== "~" && !value.startsWith("~/")) return false;
|
|
10741
|
+
return resolve6(homeDir, value.slice(2)) === resolve6(repoRoot);
|
|
10742
|
+
}
|
|
10737
10743
|
function canonicalProjectJson(ctx) {
|
|
10738
10744
|
const roles = discoverRoles(ctx.repoRoot);
|
|
10739
10745
|
const existing = readProjectJson(ctx) ?? {};
|
|
@@ -10796,7 +10802,9 @@ function canonicalProjectJson(ctx) {
|
|
|
10796
10802
|
project_name: String(existing.project_name ?? titleCaseSlug(slug)),
|
|
10797
10803
|
project_description: String(existing.project_description ?? ""),
|
|
10798
10804
|
project_id: slug,
|
|
10799
|
-
|
|
10805
|
+
// A home-relative spelling that already names this repo is kept: rewriting
|
|
10806
|
+
// it to this host's absolute path would make the manifest wrong on its peers.
|
|
10807
|
+
repo_path: repoPathNamesRoot(existing.repo_path, ctx.repoRoot, ctx.homeDir) ? existing.repo_path : ctx.repoRoot,
|
|
10800
10808
|
ticket_provider: ticketProvider,
|
|
10801
10809
|
agents,
|
|
10802
10810
|
...Object.keys(automation).length ? { automation } : {},
|
|
@@ -10821,7 +10829,7 @@ function projectJsonFinding(ctx) {
|
|
|
10821
10829
|
}
|
|
10822
10830
|
if ("project_slug" in data) details.push("legacy project_slug should be migrated to project_id");
|
|
10823
10831
|
if (typeof data.project_id === "string" && data.project_id !== data.project_id.toLowerCase()) details.push("project_id must be lowercase");
|
|
10824
|
-
if (data.repo_path
|
|
10832
|
+
if (!repoPathNamesRoot(data.repo_path, ctx.repoRoot, ctx.homeDir)) details.push(`repo_path should be ${ctx.repoRoot}`);
|
|
10825
10833
|
const agents = data.agents ?? {};
|
|
10826
10834
|
for (const role of roles) {
|
|
10827
10835
|
const agent = agents[role.agentId];
|
|
@@ -635,7 +635,22 @@ async function body(request) {
|
|
|
635
635
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new RegistryError("Expected JSON object", 400, "invalid_request");
|
|
636
636
|
return parsed;
|
|
637
637
|
}
|
|
638
|
+
var DEFAULT_REGISTRY_HOST = "127.0.0.1";
|
|
639
|
+
function registryBindHost(env = process.env) {
|
|
640
|
+
return env.PJ_REGISTRY_HOST?.trim() || DEFAULT_REGISTRY_HOST;
|
|
641
|
+
}
|
|
642
|
+
function isWildcardHost(host) {
|
|
643
|
+
return host === "0.0.0.0" || host === "::";
|
|
644
|
+
}
|
|
645
|
+
function registryLocalUrl(host, port) {
|
|
646
|
+
const name = isWildcardHost(host) ? "127.0.0.1" : host.includes(":") ? `[${host}]` : host;
|
|
647
|
+
return `http://${name}:${port}`;
|
|
648
|
+
}
|
|
649
|
+
function registryListeningMessage(service) {
|
|
650
|
+
return `PJangler project registry listening at ${service.url}${isWildcardHost(service.host) ? ` (bind ${service.host})` : ""}`;
|
|
651
|
+
}
|
|
638
652
|
async function createRegistryService(options = {}) {
|
|
653
|
+
const host = options.host ?? registryBindHost();
|
|
639
654
|
const pool = options.pool ?? new Pool({ database: process.env.PGDATABASE ?? "33god", connectionTimeoutMillis: 5e3, statement_timeout: 15e3 });
|
|
640
655
|
const index = new ManifestIndex(pool);
|
|
641
656
|
try {
|
|
@@ -710,7 +725,7 @@ async function createRegistryService(options = {}) {
|
|
|
710
725
|
server.keepAliveTimeout = 1e3;
|
|
711
726
|
await new Promise((resolve2, reject) => {
|
|
712
727
|
server.once("error", reject);
|
|
713
|
-
server.listen(options.port ?? Number(process.env.PJ_REGISTRY_PORT ?? 8764),
|
|
728
|
+
server.listen(options.port ?? Number(process.env.PJ_REGISTRY_PORT ?? 8764), host, () => {
|
|
714
729
|
server.off("error", reject);
|
|
715
730
|
resolve2();
|
|
716
731
|
});
|
|
@@ -723,7 +738,8 @@ async function createRegistryService(options = {}) {
|
|
|
723
738
|
server,
|
|
724
739
|
pool,
|
|
725
740
|
index,
|
|
726
|
-
|
|
741
|
+
host,
|
|
742
|
+
url: registryLocalUrl(host, typeof address === "object" ? address?.port : options.port),
|
|
727
743
|
async close() {
|
|
728
744
|
await new Promise((resolve2, reject) => server.close((error) => error ? reject(error) : resolve2()));
|
|
729
745
|
if (!options.pool) await pool.end();
|
|
@@ -732,7 +748,7 @@ async function createRegistryService(options = {}) {
|
|
|
732
748
|
}
|
|
733
749
|
async function startRegistryService() {
|
|
734
750
|
const service = await createRegistryService();
|
|
735
|
-
console.log(
|
|
751
|
+
console.log(registryListeningMessage(service));
|
|
736
752
|
const stop = () => {
|
|
737
753
|
void service.close().then(() => process.exit(0), (error) => {
|
|
738
754
|
console.error(error);
|