@sjawhar/pi-legion-envoy 1.69.1 → 2.0.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/dist/legion.js +23 -17
- package/dist/skills/legion-worker/SKILL.md +10 -7
- package/package.json +2 -2
package/dist/legion.js
CHANGED
|
@@ -16111,7 +16111,7 @@ var require_mod4 = __commonJS((exports) => {
|
|
|
16111
16111
|
|
|
16112
16112
|
// extensions/legion.ts
|
|
16113
16113
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
16114
|
-
import
|
|
16114
|
+
import path4 from "path";
|
|
16115
16115
|
|
|
16116
16116
|
// ../envoy-client/src/defaults.ts
|
|
16117
16117
|
var DEFAULT_ENVOY_URL = "http://127.0.0.1:9020";
|
|
@@ -16142,7 +16142,7 @@ import { logger } from "@oh-my-pi/pi-utils";
|
|
|
16142
16142
|
// package.json
|
|
16143
16143
|
var package_default = {
|
|
16144
16144
|
name: "@sjawhar/pi-legion-envoy",
|
|
16145
|
-
version: "
|
|
16145
|
+
version: "2.0.0",
|
|
16146
16146
|
type: "module",
|
|
16147
16147
|
omp: {
|
|
16148
16148
|
extensions: [
|
|
@@ -16155,7 +16155,7 @@ var package_default = {
|
|
|
16155
16155
|
},
|
|
16156
16156
|
legion: {
|
|
16157
16157
|
daemonApiVersion: 8,
|
|
16158
|
-
goDaemonApiVersion:
|
|
16158
|
+
goDaemonApiVersion: 5
|
|
16159
16159
|
},
|
|
16160
16160
|
repository: {
|
|
16161
16161
|
type: "git",
|
|
@@ -31308,7 +31308,7 @@ function createControllerSession(persistedTranscript, checkSubagentSession, daem
|
|
|
31308
31308
|
|
|
31309
31309
|
// src/legion/grant-file.ts
|
|
31310
31310
|
import { randomUUID } from "crypto";
|
|
31311
|
-
import { chmod, rename, rm, writeFile } from "fs/promises";
|
|
31311
|
+
import { chmod, mkdir, rename, rm, writeFile } from "fs/promises";
|
|
31312
31312
|
import path from "path";
|
|
31313
31313
|
async function writeGrantFile(file2, grantId) {
|
|
31314
31314
|
if (!path.isAbsolute(file2)) {
|
|
@@ -31316,6 +31316,7 @@ async function writeGrantFile(file2, grantId) {
|
|
|
31316
31316
|
}
|
|
31317
31317
|
const temp = `${file2}.${process.pid}.${randomUUID()}`;
|
|
31318
31318
|
try {
|
|
31319
|
+
await mkdir(path.dirname(file2), { recursive: true, mode: 448 });
|
|
31319
31320
|
await writeFile(temp, grantId, { encoding: "utf8", mode: 384 });
|
|
31320
31321
|
await chmod(temp, 384);
|
|
31321
31322
|
await rename(temp, file2);
|
|
@@ -31332,9 +31333,6 @@ async function writeMintedGrant(mint) {
|
|
|
31332
31333
|
await writeGrantFile(file2, await mint());
|
|
31333
31334
|
}
|
|
31334
31335
|
|
|
31335
|
-
// src/legion/go-bootstrap.ts
|
|
31336
|
-
import path3 from "path";
|
|
31337
|
-
|
|
31338
31336
|
// ../contracts/src/legion-go-api.ts
|
|
31339
31337
|
var nonEmptyString2 = exports_external.string().min(1);
|
|
31340
31338
|
var timestamp = exports_external.iso.datetime({ offset: true });
|
|
@@ -31662,7 +31660,7 @@ function createLegionGoDaemonClient(baseUrl, fetchFn = fetch) {
|
|
|
31662
31660
|
|
|
31663
31661
|
// src/legion/jj-attribution.ts
|
|
31664
31662
|
import { execFile } from "child_process";
|
|
31665
|
-
import { mkdir, rename as rename2, writeFile as writeFile2 } from "fs/promises";
|
|
31663
|
+
import { mkdir as mkdir2, rename as rename2, writeFile as writeFile2 } from "fs/promises";
|
|
31666
31664
|
import path2 from "path";
|
|
31667
31665
|
import { promisify } from "util";
|
|
31668
31666
|
var UUID = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";
|
|
@@ -31695,7 +31693,7 @@ async function exportJjSessionAttribution(sessionFile, stateDir, env = process.e
|
|
|
31695
31693
|
if (!base)
|
|
31696
31694
|
return;
|
|
31697
31695
|
try {
|
|
31698
|
-
await
|
|
31696
|
+
await mkdir2(stateDir, { recursive: true });
|
|
31699
31697
|
const tmp = `${overlay}.${process.pid}.tmp`;
|
|
31700
31698
|
await writeFile2(tmp, `[templates]
|
|
31701
31699
|
commit_trailers = '"Omp-Session: ${id}"'
|
|
@@ -31799,7 +31797,6 @@ async function bootstrapGoClaim(context, state) {
|
|
|
31799
31797
|
try {
|
|
31800
31798
|
const stateDir = requiredEnvironment(process.env, "LEGION_STATE_DIR");
|
|
31801
31799
|
await exportJjSessionAttribution(sessionFile, stateDir);
|
|
31802
|
-
process.env.LEGION_GRANT_FILE = path3.join(stateDir, "secrets", `${claim.claimToken}-grant`);
|
|
31803
31800
|
state.setCapability({
|
|
31804
31801
|
kind: "phase-worker",
|
|
31805
31802
|
sessionID,
|
|
@@ -32369,7 +32366,7 @@ function createLegionTool(deps) {
|
|
|
32369
32366
|
|
|
32370
32367
|
// src/subagent-session.ts
|
|
32371
32368
|
import fs from "fs";
|
|
32372
|
-
import
|
|
32369
|
+
import path3 from "path";
|
|
32373
32370
|
import * as host from "@oh-my-pi/pi-coding-agent";
|
|
32374
32371
|
var LEGION_BOOTSTRAPPED_SESSION = Symbol.for("legion.pi-envoy.bootstrapped-session");
|
|
32375
32372
|
var bootstrappedSessionStore = globalThis;
|
|
@@ -32380,7 +32377,7 @@ async function isSubagentSession(context) {
|
|
|
32380
32377
|
await context.sessionManager.ensureOnDisk();
|
|
32381
32378
|
const sessionFile = context.sessionManager.getSessionFile();
|
|
32382
32379
|
if (sessionFile !== undefined && fs.existsSync(sessionFile)) {
|
|
32383
|
-
return fs.existsSync(`${
|
|
32380
|
+
return fs.existsSync(`${path3.dirname(sessionFile)}.jsonl`);
|
|
32384
32381
|
}
|
|
32385
32382
|
const bootstrapped = bootstrappedSessionStore[LEGION_BOOTSTRAPPED_SESSION];
|
|
32386
32383
|
return bootstrapped !== undefined && bootstrapped !== sessionFile;
|
|
@@ -32444,7 +32441,16 @@ var callReadyWithRetry = async (label, call) => {
|
|
|
32444
32441
|
}
|
|
32445
32442
|
}
|
|
32446
32443
|
};
|
|
32447
|
-
|
|
32444
|
+
var GH_RESOLVED_URL = /(?:^|[\s;,"])(?:pr|issue):\/\//i;
|
|
32445
|
+
function needsGrant({ toolName, input }) {
|
|
32446
|
+
if (toolName === "bash")
|
|
32447
|
+
return typeof input.command === "string";
|
|
32448
|
+
if (toolName === "github")
|
|
32449
|
+
return true;
|
|
32450
|
+
const paths = Array.isArray(input.paths) ? input.paths : [input.path];
|
|
32451
|
+
return paths.some((entry) => typeof entry === "string" && GH_RESOLVED_URL.test(entry));
|
|
32452
|
+
}
|
|
32453
|
+
async function wrapWithGrant(mint) {
|
|
32448
32454
|
try {
|
|
32449
32455
|
await writeMintedGrant(async () => (await mint()).grantId);
|
|
32450
32456
|
return;
|
|
@@ -32458,7 +32464,7 @@ async function persistedTranscript(context) {
|
|
|
32458
32464
|
if (!sessionFile?.endsWith(".jsonl")) {
|
|
32459
32465
|
throw new Error("Legion session must have a persisted transcript");
|
|
32460
32466
|
}
|
|
32461
|
-
const agentId =
|
|
32467
|
+
const agentId = path4.basename(sessionFile, ".jsonl");
|
|
32462
32468
|
if (!agentId)
|
|
32463
32469
|
throw new Error("Legion session transcript has no agent id");
|
|
32464
32470
|
return { sessionFile, agentId };
|
|
@@ -32970,11 +32976,11 @@ function legionExtension(pi) {
|
|
|
32970
32976
|
return { block: true, reason: "the merger only verifies and reports" };
|
|
32971
32977
|
}
|
|
32972
32978
|
}
|
|
32973
|
-
if (toolCall
|
|
32979
|
+
if (!needsGrant(toolCall))
|
|
32974
32980
|
return;
|
|
32975
32981
|
if (active === undefined) {
|
|
32976
32982
|
if (controllerSession.isClaimedSession(sessionID)) {
|
|
32977
|
-
return
|
|
32983
|
+
return wrapWithGrant(() => controllerSession.mintGrant(sessionID));
|
|
32978
32984
|
}
|
|
32979
32985
|
if (process.env.LEGION_ROLE !== undefined && process.env.LEGION_CONTROLLER !== "1") {
|
|
32980
32986
|
return {
|
|
@@ -32984,7 +32990,7 @@ function legionExtension(pi) {
|
|
|
32984
32990
|
}
|
|
32985
32991
|
return;
|
|
32986
32992
|
}
|
|
32987
|
-
return
|
|
32993
|
+
return wrapWithGrant(() => process.env.LEGION_DAEMON_API === "go" ? goRoleDaemon().grant({
|
|
32988
32994
|
tree: active.tree,
|
|
32989
32995
|
issue: active.issue,
|
|
32990
32996
|
sessionId: sessionID,
|
|
@@ -189,14 +189,17 @@ comments live on that path too, so edit them with `gh pr comment`) — printing
|
|
|
189
189
|
`Legion issues live on Dispatch; use dispatch_message or dispatch_comment on <your LEGION_ISSUE>`:
|
|
190
190
|
Legion never reads or writes a GitHub issue (LEGION-78). `pr comment`, `pr review`,
|
|
191
191
|
`api …/pulls/…`, `api graphql`, and issue reads are unaffected. The credential reaches `legion`
|
|
192
|
-
through the file `$LEGION_GRANT_FILE` names, written before each of your bash
|
|
193
|
-
|
|
192
|
+
through the file `$LEGION_GRANT_FILE` names, written by the extension before each of your bash
|
|
193
|
+
commands, each `github` tool call, and each `read`/`grep` of a `pr://` or `issue://` URL (and by
|
|
194
|
+
the `legion` tool before its `handoff_complete`); never `cat`, `echo`, copy, or
|
|
194
195
|
`export` it — `legion credential`, `legion gh`, `jj git push`, and `handoff_complete` read it
|
|
195
|
-
themselves. The file is the pane's, not the
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
seconds of that call and 403s afterwards — a timing
|
|
199
|
-
credentialed commands from your own bash calls
|
|
196
|
+
themselves. The file is the pane's, not the command's, and a grant lives 60 seconds: a `task`
|
|
197
|
+
subagent, an `eval` subprocess, or a background job in your pane reads the grant your last such
|
|
198
|
+
call wrote, and a `github` tool `run_watch` keeps polling `gh` on the one written when the call
|
|
199
|
+
began, so each succeeds only within 60 seconds of that call and 403s afterwards — a timing
|
|
200
|
+
artifact, not a broken credential. Run credentialed commands from your own bash calls, and watch a
|
|
201
|
+
run that may outlast a minute with `gh run watch` in bash, which redeems once and then runs on the
|
|
202
|
+
token it got.
|
|
200
203
|
|
|
201
204
|
## GitHub PR comment attribution
|
|
202
205
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sjawhar/pi-legion-envoy",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"omp": {
|
|
6
6
|
"extensions": [
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"legion": {
|
|
15
15
|
"daemonApiVersion": 8,
|
|
16
|
-
"goDaemonApiVersion":
|
|
16
|
+
"goDaemonApiVersion": 5
|
|
17
17
|
},
|
|
18
18
|
"repository": {
|
|
19
19
|
"type": "git",
|