@sjawhar/pi-legion-envoy 0.10.0 → 0.12.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 +40 -94
- package/dist/legion.js +309 -877
- package/dist/skills/legion-controller/SKILL.md +3 -17
- package/dist/skills/legion-worker/SKILL.md +191 -86
- package/package.json +1 -2
- package/dist/skills/legion-worker/references/config.md +0 -259
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);
|
|
@@ -30003,6 +29920,45 @@ var LegionDaemonApi = {
|
|
|
30003
29920
|
}),
|
|
30004
29921
|
response: object({})
|
|
30005
29922
|
},
|
|
29923
|
+
WorkerStarted: {
|
|
29924
|
+
request: strictObject({
|
|
29925
|
+
tree: nonEmptyString,
|
|
29926
|
+
issue: nonEmptyString,
|
|
29927
|
+
role: legionRole,
|
|
29928
|
+
bootToken: nonEmptyString,
|
|
29929
|
+
sessionId: nonEmptyString,
|
|
29930
|
+
agentId: nonEmptyString,
|
|
29931
|
+
ompSessionFile: nonEmptyString
|
|
29932
|
+
}),
|
|
29933
|
+
response: object({
|
|
29934
|
+
roleToken: nonEmptyString,
|
|
29935
|
+
secret: nonEmptyString,
|
|
29936
|
+
gitName: nonEmptyString,
|
|
29937
|
+
gitEmail: nonEmptyString
|
|
29938
|
+
})
|
|
29939
|
+
},
|
|
29940
|
+
WorkerReady: {
|
|
29941
|
+
request: strictObject({
|
|
29942
|
+
tree: nonEmptyString,
|
|
29943
|
+
issue: nonEmptyString,
|
|
29944
|
+
role: legionRole,
|
|
29945
|
+
sessionId: nonEmptyString,
|
|
29946
|
+
generation: number2().int().nonnegative(),
|
|
29947
|
+
secret: nonEmptyString
|
|
29948
|
+
}),
|
|
29949
|
+
response: object({})
|
|
29950
|
+
},
|
|
29951
|
+
SpawnWorker: {
|
|
29952
|
+
request: architectCapability.extend({
|
|
29953
|
+
issue: nonEmptyString,
|
|
29954
|
+
role: legionRole,
|
|
29955
|
+
task: nonEmptyString
|
|
29956
|
+
}),
|
|
29957
|
+
response: object({
|
|
29958
|
+
status: _enum2(["spawned", "resumed"]),
|
|
29959
|
+
roleToken: nonEmptyString
|
|
29960
|
+
})
|
|
29961
|
+
},
|
|
30006
29962
|
Phase: {
|
|
30007
29963
|
request: strictObject({
|
|
30008
29964
|
tree: nonEmptyString,
|
|
@@ -31505,15 +31461,6 @@ async function claimEnvoyRole(sessionID, role, context) {
|
|
|
31505
31461
|
const bridge = legionRoleClaimBridge();
|
|
31506
31462
|
await (bridge.claim ?? await bridge.ready.promise)(sessionID, role, context);
|
|
31507
31463
|
}
|
|
31508
|
-
async function deleteEnvoyInterest(baseUrl, sessionID) {
|
|
31509
|
-
const response = await fetch(`${baseUrl}/v1/interests/${encodeURIComponent(sessionID)}`, {
|
|
31510
|
-
method: "DELETE"
|
|
31511
|
-
});
|
|
31512
|
-
const responseBody = await response.text();
|
|
31513
|
-
if (!response.ok) {
|
|
31514
|
-
throw new Error(`DELETE /v1/interests/${sessionID} failed with ${response.status}: ${responseBody}`);
|
|
31515
|
-
}
|
|
31516
|
-
}
|
|
31517
31464
|
function resolveSkillsDirectory() {
|
|
31518
31465
|
const moduleDirectory = dirname(fileURLToPath(import.meta.url));
|
|
31519
31466
|
const candidates = [
|
|
@@ -32034,6 +31981,5 @@ function topicsFor(parameters, fallback = []) {
|
|
|
32034
31981
|
}
|
|
32035
31982
|
export {
|
|
32036
31983
|
claimEnvoyRole,
|
|
32037
|
-
envoyExtension as default
|
|
32038
|
-
deleteEnvoyInterest
|
|
31984
|
+
envoyExtension as default
|
|
32039
31985
|
};
|