@sjawhar/pi-legion-envoy 0.11.0 → 0.13.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/README.md +4 -3
- package/dist/envoy.js +8 -94
- package/dist/legion.js +256 -861
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -44,9 +44,10 @@ set -g set-clipboard on
|
|
|
44
44
|
|
|
45
45
|
This package declares two OMP extension entries in `package.json`: `extensions/envoy.ts`
|
|
46
46
|
(Envoy messaging, subscriptions, and steering delivery) and `extensions/legion.ts` (the
|
|
47
|
-
Legion lifecycle: root
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
Legion lifecycle: root and phase-worker bootstrap from the daemon's environment, and
|
|
48
|
+
daemon capabilities). The Legion daemon spawns every root and phase-worker process with
|
|
49
|
+
the installed plugin already active, so `extensions/legion.ts` loads for them automatically;
|
|
50
|
+
it is inert without `LEGION_TREE`/`LEGION_ROLE`/`LEGION_CONTROLLER` in the environment.
|
|
50
51
|
|
|
51
52
|
For local development of the messaging extension alone, link the entry into OMP:
|
|
52
53
|
|
package/dist/envoy.js
CHANGED
|
@@ -29783,9 +29783,7 @@ var LEGION_ROLES = [
|
|
|
29783
29783
|
"reviewer",
|
|
29784
29784
|
"merger"
|
|
29785
29785
|
];
|
|
29786
|
-
var ENVOY_ROLE_TOKEN = /^[a-z0-9][a-z0-9_-]*$/;
|
|
29787
29786
|
var PROJECT_TOKEN = /^[a-z0-9]+$/;
|
|
29788
|
-
var ISSUE_PART = /^[a-z0-9._-]+$/;
|
|
29789
29787
|
function isLegionRole(role) {
|
|
29790
29788
|
return LEGION_ROLES.some((candidate) => candidate === role);
|
|
29791
29789
|
}
|
|
@@ -29797,91 +29795,10 @@ function assertLegionProjectToken(project) {
|
|
|
29797
29795
|
throw new Error(`Invalid Legion project token: ${project}`);
|
|
29798
29796
|
}
|
|
29799
29797
|
}
|
|
29800
|
-
function encodeIssuePart(part) {
|
|
29801
|
-
const normalized = part.toLowerCase();
|
|
29802
|
-
if (!ISSUE_PART.test(normalized)) {
|
|
29803
|
-
throw new Error(`Invalid Legion issue token part: ${part}`);
|
|
29804
|
-
}
|
|
29805
|
-
return normalized.replaceAll("_", "_u").replaceAll(".", "_d").replaceAll("-", "_h");
|
|
29806
|
-
}
|
|
29807
|
-
function decodeIssuePart(part) {
|
|
29808
|
-
let decoded = "";
|
|
29809
|
-
for (let index = 0;index < part.length; index += 1) {
|
|
29810
|
-
const character = part[index];
|
|
29811
|
-
if (character !== "_") {
|
|
29812
|
-
decoded += character;
|
|
29813
|
-
continue;
|
|
29814
|
-
}
|
|
29815
|
-
const escapeCode = part[index + 1];
|
|
29816
|
-
if (escapeCode === "u")
|
|
29817
|
-
decoded += "_";
|
|
29818
|
-
else if (escapeCode === "d")
|
|
29819
|
-
decoded += ".";
|
|
29820
|
-
else if (escapeCode === "h")
|
|
29821
|
-
decoded += "-";
|
|
29822
|
-
else
|
|
29823
|
-
return;
|
|
29824
|
-
index += 1;
|
|
29825
|
-
}
|
|
29826
|
-
return decoded;
|
|
29827
|
-
}
|
|
29828
|
-
function formatIssueKey(owner, repo, number) {
|
|
29829
|
-
return `${owner}/${repo}#${number}`;
|
|
29830
|
-
}
|
|
29831
|
-
function parseIssueKey(s) {
|
|
29832
|
-
const match = /^([^/#]+)\/([^/#]+)#(\d+)$/.exec(s);
|
|
29833
|
-
if (!match)
|
|
29834
|
-
return;
|
|
29835
|
-
const owner = match[1];
|
|
29836
|
-
const repo = match[2];
|
|
29837
|
-
const numberPart = match[3];
|
|
29838
|
-
if (!owner || !repo || !numberPart)
|
|
29839
|
-
return;
|
|
29840
|
-
const number = Number(numberPart);
|
|
29841
|
-
if (!Number.isSafeInteger(number))
|
|
29842
|
-
return;
|
|
29843
|
-
return { owner, repo, number };
|
|
29844
|
-
}
|
|
29845
|
-
function roleToken(project, issue, role) {
|
|
29846
|
-
assertLegionProjectToken(project);
|
|
29847
|
-
const parsedIssue = parseIssueKey(issue);
|
|
29848
|
-
if (!parsedIssue)
|
|
29849
|
-
throw new Error(`Invalid IssueKey: ${issue}`);
|
|
29850
|
-
return `legion-${project}-${encodeIssuePart(parsedIssue.owner)}__${encodeIssuePart(parsedIssue.repo)}-${parsedIssue.number}-${role}`;
|
|
29851
|
-
}
|
|
29852
29798
|
function controllerToken(project) {
|
|
29853
29799
|
assertLegionProjectToken(project);
|
|
29854
29800
|
return `legion-${project}-controller`;
|
|
29855
29801
|
}
|
|
29856
|
-
function parseRoleToken(project, token) {
|
|
29857
|
-
if (!isLegionProjectToken(project))
|
|
29858
|
-
return;
|
|
29859
|
-
const prefix = `legion-${project}-`;
|
|
29860
|
-
if (!ENVOY_ROLE_TOKEN.test(token) || !token.startsWith(prefix))
|
|
29861
|
-
return;
|
|
29862
|
-
const rest = token.slice(prefix.length);
|
|
29863
|
-
if (rest === "controller")
|
|
29864
|
-
return { controller: true };
|
|
29865
|
-
const match = /^([a-z0-9_]+)__([a-z0-9_]+)-(\d+)-(architect|planner|implementer|tester|reviewer|merger)$/.exec(rest);
|
|
29866
|
-
if (!match)
|
|
29867
|
-
return;
|
|
29868
|
-
const ownerPart = match[1];
|
|
29869
|
-
const repoPart = match[2];
|
|
29870
|
-
const numberPart = match[3];
|
|
29871
|
-
const role = match[4];
|
|
29872
|
-
if (!ownerPart || !repoPart || !numberPart || !role || !isLegionRole(role))
|
|
29873
|
-
return;
|
|
29874
|
-
const owner = decodeIssuePart(ownerPart);
|
|
29875
|
-
const repo = decodeIssuePart(repoPart);
|
|
29876
|
-
const number = Number(numberPart);
|
|
29877
|
-
if (!owner || !repo || !Number.isSafeInteger(number))
|
|
29878
|
-
return;
|
|
29879
|
-
return {
|
|
29880
|
-
project,
|
|
29881
|
-
issue: formatIssueKey(owner, repo, number),
|
|
29882
|
-
role
|
|
29883
|
-
};
|
|
29884
|
-
}
|
|
29885
29802
|
|
|
29886
29803
|
// ../contracts/src/legion-daemon-api.ts
|
|
29887
29804
|
var nonEmptyString = string2().min(1);
|
|
@@ -30031,6 +29948,13 @@ var LegionDaemonApi = {
|
|
|
30031
29948
|
}),
|
|
30032
29949
|
response: object({})
|
|
30033
29950
|
},
|
|
29951
|
+
PhaseComplete: {
|
|
29952
|
+
request: strictObject({
|
|
29953
|
+
grantId: nonEmptyString,
|
|
29954
|
+
summary: nonEmptyString
|
|
29955
|
+
}),
|
|
29956
|
+
response: object({})
|
|
29957
|
+
},
|
|
30034
29958
|
SpawnWorker: {
|
|
30035
29959
|
request: architectCapability.extend({
|
|
30036
29960
|
issue: nonEmptyString,
|
|
@@ -31544,15 +31468,6 @@ async function claimEnvoyRole(sessionID, role, context) {
|
|
|
31544
31468
|
const bridge = legionRoleClaimBridge();
|
|
31545
31469
|
await (bridge.claim ?? await bridge.ready.promise)(sessionID, role, context);
|
|
31546
31470
|
}
|
|
31547
|
-
async function deleteEnvoyInterest(baseUrl, sessionID) {
|
|
31548
|
-
const response = await fetch(`${baseUrl}/v1/interests/${encodeURIComponent(sessionID)}`, {
|
|
31549
|
-
method: "DELETE"
|
|
31550
|
-
});
|
|
31551
|
-
const responseBody = await response.text();
|
|
31552
|
-
if (!response.ok) {
|
|
31553
|
-
throw new Error(`DELETE /v1/interests/${sessionID} failed with ${response.status}: ${responseBody}`);
|
|
31554
|
-
}
|
|
31555
|
-
}
|
|
31556
31471
|
function resolveSkillsDirectory() {
|
|
31557
31472
|
const moduleDirectory = dirname(fileURLToPath(import.meta.url));
|
|
31558
31473
|
const candidates = [
|
|
@@ -32073,6 +31988,5 @@ function topicsFor(parameters, fallback = []) {
|
|
|
32073
31988
|
}
|
|
32074
31989
|
export {
|
|
32075
31990
|
claimEnvoyRole,
|
|
32076
|
-
envoyExtension as default
|
|
32077
|
-
deleteEnvoyInterest
|
|
31991
|
+
envoyExtension as default
|
|
32078
31992
|
};
|