@sjawhar/pi-legion-envoy 5.13.1 → 5.15.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/envoy.js +71 -44
- package/dist/legion.js +3050 -634
- package/dist/skills/dispatch/SKILL.md +45 -4
- package/package.json +2 -2
package/dist/envoy.js
CHANGED
|
@@ -30369,13 +30369,14 @@ var dispatchToolSpecs = [
|
|
|
30369
30369
|
},
|
|
30370
30370
|
{
|
|
30371
30371
|
name: "dispatch_issues",
|
|
30372
|
-
example: { project: "AGENTC" },
|
|
30373
|
-
description: "List a project's issues for a roadmap or backlog pass: every issue in one project, each carrying " + "its status, priority, parent, labels, and open-ask count, so you can see backlog shape without " + "opening every issue. Optionally filter by status, parent, label, or how recently it changed
|
|
30372
|
+
example: { project: "AGENTC", priority: [0, 1] },
|
|
30373
|
+
description: "List a project's issues for a roadmap or backlog pass: every issue in one project, each carrying " + "its status, priority, parent, labels, and open-ask count, so you can see backlog shape without " + "opening every issue. Optionally filter by status, parent, label, priority, or how recently it " + "changed; priority takes one or more of 0-3 (P0-P3) and null for an issue with no priority, so " + "an owner's P0/P1 audit is priority [0, 1]. Do not use it to search by keyword or phrase; " + "dispatch_search remains the keyword surface. Rows are capped at limit (default 50, max 250), " + "applied to the response here, not by the server.",
|
|
30374
30374
|
arguments: (z2) => ({
|
|
30375
30375
|
project: z2.string().describe("Project key to list issues from."),
|
|
30376
30376
|
status: z2.enum(ISSUE_STATUSES).describe("Optional lifecycle status filter.").optional(),
|
|
30377
30377
|
parent: z2.string().describe("Optional parent issue key filter.").optional(),
|
|
30378
30378
|
label: z2.string().describe("Optional label filter.").optional(),
|
|
30379
|
+
priority: z2.array(z2.number({ int: true, min: 0, max: 3 }).nullable(), { min: 1, max: 5 }).describe("Optional priority filter: one or more of 0 (P0, highest) through 3 (P3, lowest), and null " + "for an issue with no priority; an issue matching any listed value is returned.").optional(),
|
|
30379
30380
|
updated_since: z2.string().describe("Optional RFC3339 timestamp; only issues updated at or after it.").optional(),
|
|
30380
30381
|
limit: z2.number({ int: true, min: 1, max: 250 }).describe("Maximum rows, 1-250; default 50.").optional()
|
|
30381
30382
|
})
|
|
@@ -32172,6 +32173,15 @@ function resolveDispatchConfig(env, options = {}) {
|
|
|
32172
32173
|
}
|
|
32173
32174
|
return { enabled: true, url: url2.url, token, error: null };
|
|
32174
32175
|
}
|
|
32176
|
+
function activeDispatchConfig(env, options = {}) {
|
|
32177
|
+
const config2 = resolveDispatchConfig(env, options);
|
|
32178
|
+
if (config2.error !== null)
|
|
32179
|
+
throw new Error(`dispatch config: ${config2.error}`);
|
|
32180
|
+
const { url: url2, token } = config2;
|
|
32181
|
+
if (!config2.enabled || url2 === null || token === null)
|
|
32182
|
+
return null;
|
|
32183
|
+
return { ...config2, url: url2, token };
|
|
32184
|
+
}
|
|
32175
32185
|
|
|
32176
32186
|
// ../envoy-client/src/dispatch-execute.ts
|
|
32177
32187
|
import { resolve as resolvePath } from "path";
|
|
@@ -32547,6 +32557,9 @@ class DispatchClient {
|
|
|
32547
32557
|
for (const [name, value] of Object.entries(query)) {
|
|
32548
32558
|
if (typeof value === "string" || typeof value === "number") {
|
|
32549
32559
|
url2.searchParams.set(name, String(value));
|
|
32560
|
+
} else if (Array.isArray(value)) {
|
|
32561
|
+
for (const item of value)
|
|
32562
|
+
url2.searchParams.append(name, String(item));
|
|
32550
32563
|
}
|
|
32551
32564
|
}
|
|
32552
32565
|
}
|
|
@@ -32824,6 +32837,10 @@ function optionalPriority(args, name) {
|
|
|
32824
32837
|
return null;
|
|
32825
32838
|
return typeof value === "number" ? value : undefined;
|
|
32826
32839
|
}
|
|
32840
|
+
function optionalPriorityFilter(args, name) {
|
|
32841
|
+
const value = args[name];
|
|
32842
|
+
return Array.isArray(value) ? value.map((item) => item ?? "none") : undefined;
|
|
32843
|
+
}
|
|
32827
32844
|
function optionalComponents(args, name) {
|
|
32828
32845
|
const value = args[name];
|
|
32829
32846
|
if (typeof value !== "object" || value === null)
|
|
@@ -33234,13 +33251,23 @@ async function resolveOwnerArguments(tool, input, cwd, env, exec, serverUrl, pro
|
|
|
33234
33251
|
const issue2 = `${repo2}#${legionIssue}`;
|
|
33235
33252
|
return { args: { ...args, issue: issue2 }, ref, owner: { kind: "issue", issue: issue2 } };
|
|
33236
33253
|
}
|
|
33237
|
-
function artifactByReference(artifacts, artifactReference, owner) {
|
|
33238
|
-
const
|
|
33239
|
-
if (
|
|
33240
|
-
return
|
|
33254
|
+
function artifactByReference(artifacts, artifactReference, owner, canonical) {
|
|
33255
|
+
const bySlug = artifacts.find((candidate) => candidate.slug === artifactReference);
|
|
33256
|
+
if (canonical && bySlug !== undefined)
|
|
33257
|
+
return bySlug;
|
|
33258
|
+
const byId = artifacts.find((candidate) => candidate.id === artifactReference);
|
|
33259
|
+
if (byId !== undefined)
|
|
33260
|
+
return byId;
|
|
33241
33261
|
const byName = artifacts.filter((candidate) => candidate.name === artifactReference);
|
|
33262
|
+
if (bySlug !== undefined) {
|
|
33263
|
+
const named = byName.filter((candidate) => candidate.id !== bySlug.id && candidate.kind === "doc");
|
|
33264
|
+
if (named.length > 0) {
|
|
33265
|
+
throw new Error(documentReferenceProblem(artifactReference, [bySlug, ...named], owner, "id"));
|
|
33266
|
+
}
|
|
33267
|
+
return bySlug;
|
|
33268
|
+
}
|
|
33242
33269
|
if (byName.length > 1) {
|
|
33243
|
-
throw new Error(documentReferenceProblem(artifactReference, byName, owner,
|
|
33270
|
+
throw new Error(documentReferenceProblem(artifactReference, byName, owner, "slug"));
|
|
33244
33271
|
}
|
|
33245
33272
|
const [artifact] = byName;
|
|
33246
33273
|
if (artifact === undefined) {
|
|
@@ -33248,43 +33275,45 @@ function artifactByReference(artifacts, artifactReference, owner) {
|
|
|
33248
33275
|
}
|
|
33249
33276
|
return artifact;
|
|
33250
33277
|
}
|
|
33251
|
-
async function resolveArtifact(client, owner, artifactReference) {
|
|
33278
|
+
async function resolveArtifact(client, owner, artifactReference, { canonical = false } = {}) {
|
|
33252
33279
|
if (owner.kind === "project") {
|
|
33253
33280
|
if (artifactReference === undefined) {
|
|
33254
33281
|
throw new Error("artifact is required for a project document");
|
|
33255
33282
|
}
|
|
33256
|
-
|
|
33257
|
-
return {
|
|
33258
|
-
owner,
|
|
33259
|
-
artifact: await client.getProjectArtifact(owner.project, artifactReference)
|
|
33260
|
-
};
|
|
33261
|
-
} catch (error48) {
|
|
33283
|
+
const routed = await client.getProjectArtifact(owner.project, artifactReference).catch((error48) => {
|
|
33262
33284
|
if (!(error48 instanceof DispatchServiceError) || error48.status !== 404)
|
|
33263
33285
|
throw error48;
|
|
33264
|
-
|
|
33265
|
-
|
|
33266
|
-
|
|
33267
|
-
|
|
33268
|
-
|
|
33269
|
-
|
|
33286
|
+
return;
|
|
33287
|
+
});
|
|
33288
|
+
if (canonical && routed !== undefined)
|
|
33289
|
+
return { owner, artifact: routed };
|
|
33290
|
+
const unlinked = await client.listProjectArtifacts(owner.project, true);
|
|
33291
|
+
const artifacts = routed === undefined ? unlinked : [routed, ...unlinked.filter((candidate) => candidate.id !== routed.id)];
|
|
33292
|
+
return {
|
|
33293
|
+
owner,
|
|
33294
|
+
artifact: artifactByReference(artifacts, artifactReference, "project", canonical)
|
|
33295
|
+
};
|
|
33270
33296
|
}
|
|
33271
33297
|
const issue2 = await client.getIssue(owner.issue);
|
|
33272
33298
|
let artifact;
|
|
33273
33299
|
if (artifactReference === undefined || artifactReference === "spec") {
|
|
33274
33300
|
artifact = issue2.artifacts.find((candidate) => candidate.primary || candidate.id === issue2.primary_artifact_id);
|
|
33275
33301
|
} else {
|
|
33276
|
-
artifact = artifactByReference(issue2.artifacts, artifactReference, "issue");
|
|
33302
|
+
artifact = artifactByReference(issue2.artifacts, artifactReference, "issue", canonical);
|
|
33277
33303
|
}
|
|
33278
33304
|
if (!artifact) {
|
|
33279
33305
|
throw new Error(documentReferenceProblem(artifactReference ?? "spec", issue2.artifacts, "issue"));
|
|
33280
33306
|
}
|
|
33281
33307
|
return { owner, issue: issue2, artifact };
|
|
33282
33308
|
}
|
|
33309
|
+
async function resolveIssueDocumentId(client, issue2, reference) {
|
|
33310
|
+
return (await resolveArtifact(client, { kind: "issue", issue: issue2 }, reference)).artifact.id;
|
|
33311
|
+
}
|
|
33283
33312
|
var documentHintLimit = 8;
|
|
33284
|
-
function documentReferenceProblem(reference, documents, owner,
|
|
33285
|
-
const hints = documents.slice(0, documentHintLimit).map((document) => `${document.slug} (${document.name})`);
|
|
33313
|
+
function documentReferenceProblem(reference, documents, owner, use) {
|
|
33314
|
+
const hints = documents.slice(0, documentHintLimit).map((document) => use === "id" ? `${document.id} (${document.slug}, ${document.name})` : `${document.slug} (${document.name})`);
|
|
33286
33315
|
const list = hints.length === 0 ? "none" : hints.join(", ");
|
|
33287
|
-
return
|
|
33316
|
+
return use === undefined ? `document "${reference}" not found by slug; this ${owner}'s documents: ${list}` : `"${reference}" names ${documents.length} documents on this ${owner}; use ${use === "id" ? "the id" : "a slug"}: ${list}`;
|
|
33288
33317
|
}
|
|
33289
33318
|
var askHintLimit = 8;
|
|
33290
33319
|
function askIDInputProblem(asks, scope) {
|
|
@@ -33674,6 +33703,10 @@ async function executeDispatchTool(input) {
|
|
|
33674
33703
|
const args = parsed.success ? parsed.data : ownerArguments.args;
|
|
33675
33704
|
const actor = toolActor(await resolveOrigin(env, exec, input.cwd), input);
|
|
33676
33705
|
const client = dispatchClient();
|
|
33706
|
+
const refDocument = ownerArguments.ref?.kind === "artifact" ? ownerArguments.ref.id : ownerArguments.ref?.artifact;
|
|
33707
|
+
const resolveDocument = (documentOwner2, reference) => resolveArtifact(client, documentOwner2, reference, {
|
|
33708
|
+
canonical: reference !== undefined && reference === refDocument
|
|
33709
|
+
});
|
|
33677
33710
|
const owner = ownerArguments.owner?.kind === "issue" ? {
|
|
33678
33711
|
kind: "issue",
|
|
33679
33712
|
issue: await resolveExistingIssue(client, ownerArguments.owner.issue)
|
|
@@ -33889,6 +33922,7 @@ async function executeDispatchTool(input) {
|
|
|
33889
33922
|
const status = optionalString(args, "status");
|
|
33890
33923
|
const parent = optionalString(args, "parent");
|
|
33891
33924
|
const label = optionalString(args, "label");
|
|
33925
|
+
const priority = optionalPriorityFilter(args, "priority");
|
|
33892
33926
|
const updatedSince = optionalString(args, "updated_since");
|
|
33893
33927
|
const limit = Math.min(Math.max(optionalNumber(args, "limit") ?? 50, 1), 250);
|
|
33894
33928
|
const issues = await client.listIssues({
|
|
@@ -33896,6 +33930,7 @@ async function executeDispatchTool(input) {
|
|
|
33896
33930
|
...status === undefined ? {} : { status },
|
|
33897
33931
|
...parent === undefined ? {} : { parent },
|
|
33898
33932
|
...label === undefined ? {} : { label },
|
|
33933
|
+
...priority === undefined ? {} : { priority },
|
|
33899
33934
|
...updatedSince === undefined ? {} : { updated_since: updatedSince }
|
|
33900
33935
|
});
|
|
33901
33936
|
const rows = issues.slice(0, limit).map((row) => ({
|
|
@@ -33962,7 +33997,7 @@ async function executeDispatchTool(input) {
|
|
|
33962
33997
|
const issueKey = ref.owner.issue;
|
|
33963
33998
|
id = await resolveIdPrefix(input.tool, "comment", ref.id, refOwnerName(ref), () => client.getComments(issueKey));
|
|
33964
33999
|
} else if (ref !== null) {
|
|
33965
|
-
const artifact = (await resolveArtifact(client, ref.owner, ref.artifact)).artifact;
|
|
34000
|
+
const artifact = (await resolveArtifact(client, ref.owner, ref.artifact, { canonical: true })).artifact;
|
|
33966
34001
|
document = artifact;
|
|
33967
34002
|
id = await resolveIdPrefix(input.tool, "comment", ref.id, refOwnerName(ref), () => client.getArtifactComments(artifact.id));
|
|
33968
34003
|
}
|
|
@@ -33974,7 +34009,7 @@ async function executeDispatchTool(input) {
|
|
|
33974
34009
|
const anchorArgs = asObject(args.anchor);
|
|
33975
34010
|
const owner2 = documentOwner();
|
|
33976
34011
|
const artifactReference = optionalString(args, "artifact") ?? (anchorArgs === null ? undefined : optionalString(anchorArgs, "artifact"));
|
|
33977
|
-
const resolved = owner2.kind === "project" || artifactReference === undefined ? owner2.kind === "project" ? await
|
|
34012
|
+
const resolved = owner2.kind === "project" || artifactReference === undefined ? owner2.kind === "project" ? await resolveDocument(owner2, artifactReference) : undefined : await resolveDocument(owner2, artifactReference);
|
|
33978
34013
|
const options = args.options;
|
|
33979
34014
|
const multiple = optionalBoolean(args, "multiple");
|
|
33980
34015
|
const urgency = askUrgency(args);
|
|
@@ -34024,7 +34059,7 @@ ${followsAsk(askOwner)}`,
|
|
|
34024
34059
|
case "dispatch_comment": {
|
|
34025
34060
|
const artifactReference = optionalString(args, "artifact");
|
|
34026
34061
|
const owner2 = documentOwner();
|
|
34027
|
-
const resolved = owner2.kind === "project" || artifactReference === undefined ? owner2.kind === "project" ? await
|
|
34062
|
+
const resolved = owner2.kind === "project" || artifactReference === undefined ? owner2.kind === "project" ? await resolveDocument(owner2, artifactReference) : undefined : await resolveDocument(owner2, artifactReference);
|
|
34028
34063
|
const anchored = resolved ? anchor(resolved.artifact, args) : undefined;
|
|
34029
34064
|
const replyTo = optionalString(args, "reply_to");
|
|
34030
34065
|
const replyToAskReference = optionalString(args, "reply_to_ask");
|
|
@@ -34077,7 +34112,7 @@ ${followsAsk(askOwner)}`,
|
|
|
34077
34112
|
};
|
|
34078
34113
|
}
|
|
34079
34114
|
case "dispatch_suggest": {
|
|
34080
|
-
const resolved = await
|
|
34115
|
+
const resolved = await resolveDocument(documentOwner(), stringArg(args, "artifact"));
|
|
34081
34116
|
const anchored = anchor(resolved.artifact, args);
|
|
34082
34117
|
if (anchored === undefined)
|
|
34083
34118
|
throw new Error("quote is required");
|
|
@@ -34132,7 +34167,7 @@ ${followsAsk(askOwner)}`,
|
|
|
34132
34167
|
};
|
|
34133
34168
|
}
|
|
34134
34169
|
case "dispatch_doc_edit": {
|
|
34135
|
-
const resolved = await
|
|
34170
|
+
const resolved = await resolveDocument(documentOwner(), stringArg(args, "artifact"));
|
|
34136
34171
|
const ops = args.ops;
|
|
34137
34172
|
const summary = optionalString(args, "summary");
|
|
34138
34173
|
const { precondition: rawPrecondition } = args;
|
|
@@ -34174,7 +34209,7 @@ ${followsAsk(askOwner)}`,
|
|
|
34174
34209
|
}
|
|
34175
34210
|
case "dispatch_doc_read": {
|
|
34176
34211
|
const artifactReference = optionalString(args, "artifact") ?? (ownerArguments.ref?.kind === "spec" || ownerArguments.ref?.kind === "artifact" ? ownerArguments.ref.id : undefined);
|
|
34177
|
-
const resolved = await
|
|
34212
|
+
const resolved = await resolveDocument(documentOwner(), artifactReference);
|
|
34178
34213
|
const version2 = optionalNumber(args, "version") ?? ownerArguments.ref?.version;
|
|
34179
34214
|
const documentPromise = client.docRead(resolved.artifact.id, version2);
|
|
34180
34215
|
const marksPromise = openArtifactMarks(client, resolved);
|
|
@@ -34203,7 +34238,7 @@ ${trailer.join(`
|
|
|
34203
34238
|
}
|
|
34204
34239
|
case "dispatch_request_approval": {
|
|
34205
34240
|
const artifactReference = optionalString(args, "artifact") ?? (ownerArguments.ref?.kind === "spec" || ownerArguments.ref?.kind === "artifact" ? ownerArguments.ref.id : undefined);
|
|
34206
|
-
const resolved = await
|
|
34241
|
+
const resolved = await resolveDocument(documentOwner(), artifactReference);
|
|
34207
34242
|
const result = await client.requestApproval(resolved.artifact.id, { actor });
|
|
34208
34243
|
if (result.ask === null) {
|
|
34209
34244
|
return {
|
|
@@ -34281,7 +34316,7 @@ ${trailer.join(`
|
|
|
34281
34316
|
case "dispatch_read": {
|
|
34282
34317
|
if (ownerArguments.ref?.kind === "ask") {
|
|
34283
34318
|
const ref = ownerArguments.ref;
|
|
34284
|
-
const id = await resolveIdPrefix(input.tool, "ask", ref.id, refOwnerName(ref), async () => ref.owner.kind === "issue" ? client.listIssueAsks(ref.owner.issue) : client.getArtifactAsks((await
|
|
34319
|
+
const id = await resolveIdPrefix(input.tool, "ask", ref.id, refOwnerName(ref), async () => ref.owner.kind === "issue" ? client.listIssueAsks(ref.owner.issue) : client.getArtifactAsks((await resolveDocument(ref.owner, ref.artifact)).artifact.id, "all"));
|
|
34285
34320
|
const askRead = await client.getAsk(id);
|
|
34286
34321
|
const askRef = refTarget(ref, "ask", id);
|
|
34287
34322
|
return {
|
|
@@ -34291,7 +34326,7 @@ ${trailer.join(`
|
|
|
34291
34326
|
}
|
|
34292
34327
|
if (ownerArguments.ref?.kind === "comment") {
|
|
34293
34328
|
const ref = ownerArguments.ref;
|
|
34294
|
-
const id = await resolveIdPrefix(input.tool, "comment", ref.id, refOwnerName(ref), async () => ref.owner.kind === "issue" ? client.getComments(ref.owner.issue) : client.getArtifactComments((await
|
|
34329
|
+
const id = await resolveIdPrefix(input.tool, "comment", ref.id, refOwnerName(ref), async () => ref.owner.kind === "issue" ? client.getComments(ref.owner.issue) : client.getArtifactComments((await resolveDocument(ref.owner, ref.artifact)).artifact.id));
|
|
34295
34330
|
const comment = await client.getComment(id);
|
|
34296
34331
|
const commentRef = refTarget(ref, "comment", id);
|
|
34297
34332
|
return {
|
|
@@ -34311,7 +34346,7 @@ ${trailer.join(`
|
|
|
34311
34346
|
};
|
|
34312
34347
|
}
|
|
34313
34348
|
if (documentOwner().kind === "project") {
|
|
34314
|
-
const resolved = await
|
|
34349
|
+
const resolved = await resolveDocument(documentOwner(), stringArg(args, "artifact"));
|
|
34315
34350
|
const documentRef = dispatchDocumentRef(resolved.artifact.project, resolved.artifact.slug);
|
|
34316
34351
|
return {
|
|
34317
34352
|
text: [
|
|
@@ -35393,16 +35428,8 @@ function envoyExtension(pi) {
|
|
|
35393
35428
|
logger.debug("extension instance loaded", { extension: import.meta.url });
|
|
35394
35429
|
const defaults = envoyDefaultsFromEnvironment(process.env);
|
|
35395
35430
|
const dispatchConfig = resolveDispatchConfig(process.env, { cwd: process.cwd() });
|
|
35396
|
-
const activeDispatchConfig = () => {
|
|
35397
|
-
const fresh = resolveDispatchConfig(process.env, { cwd: process.cwd() });
|
|
35398
|
-
if (fresh.error !== null)
|
|
35399
|
-
throw new Error(`dispatch config: ${fresh.error}`);
|
|
35400
|
-
if (!fresh.enabled || fresh.url === null || fresh.token === null)
|
|
35401
|
-
return null;
|
|
35402
|
-
return fresh;
|
|
35403
|
-
};
|
|
35404
35431
|
const currentDispatchConfig = () => {
|
|
35405
|
-
const config2 = activeDispatchConfig();
|
|
35432
|
+
const config2 = activeDispatchConfig(process.env, { cwd: process.cwd() });
|
|
35406
35433
|
if (config2 === null) {
|
|
35407
35434
|
throw new Error("Dispatch is no longer configured (dispatch.serverUrl/token missing)");
|
|
35408
35435
|
}
|
|
@@ -35466,7 +35493,7 @@ function envoyExtension(pi) {
|
|
|
35466
35493
|
});
|
|
35467
35494
|
};
|
|
35468
35495
|
const queryOpenAsks = async (requestedSessionID, since) => {
|
|
35469
|
-
const config2 = activeDispatchConfig();
|
|
35496
|
+
const config2 = activeDispatchConfig(process.env, { cwd: process.cwd() });
|
|
35470
35497
|
if (config2 === null)
|
|
35471
35498
|
return null;
|
|
35472
35499
|
const snapshot = await new DispatchClient(config2.url, config2.token, fetch, AbortSignal.timeout(OPEN_ASKS_TIMEOUT_MS)).openAsks(requestedSessionID, since);
|