@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 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. 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.",
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 byIdOrSlug = artifacts.find((candidate) => candidate.id === artifactReference) ?? artifacts.find((candidate) => candidate.slug === artifactReference);
33239
- if (byIdOrSlug !== undefined)
33240
- return byIdOrSlug;
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, true));
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
- try {
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
- const artifacts = await client.listProjectArtifacts(owner.project, true);
33265
- return {
33266
- owner,
33267
- artifact: artifactByReference(artifacts, artifactReference, "project")
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, ambiguous = false) {
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 ambiguous ? `"${reference}" names ${documents.length} documents on this ${owner}; use a slug: ${list}` : `document "${reference}" not found by slug; this ${owner}'s documents: ${list}`;
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 resolveArtifact(client, owner2, artifactReference) : undefined : await resolveArtifact(client, owner2, artifactReference);
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 resolveArtifact(client, owner2, artifactReference) : undefined : await resolveArtifact(client, owner2, artifactReference);
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 resolveArtifact(client, documentOwner(), stringArg(args, "artifact"));
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 resolveArtifact(client, documentOwner(), stringArg(args, "artifact"));
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 resolveArtifact(client, documentOwner(), artifactReference);
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 resolveArtifact(client, documentOwner(), artifactReference);
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 resolveArtifact(client, ref.owner, ref.artifact)).artifact.id, "all"));
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 resolveArtifact(client, ref.owner, ref.artifact)).artifact.id));
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 resolveArtifact(client, documentOwner(), stringArg(args, "artifact"));
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);