@sjawhar/pi-legion-envoy 1.57.0 → 1.57.1
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 +48 -18
- package/dist/legion.js +4 -4
- package/dist/skills/dispatch/SKILL.md +3 -1
- package/package.json +1 -1
package/dist/envoy.js
CHANGED
|
@@ -30052,7 +30052,7 @@ var dispatchToolSpecs = [
|
|
|
30052
30052
|
},
|
|
30053
30053
|
description: "Edit an open question in place. Use it to correct or refine the same decision; retract the " + "old ask and open a new one when the decision itself changes. Previous text remains in the " + "event log. Only the asking session can edit it; answered or resolved asks cannot be edited.",
|
|
30054
30054
|
arguments: (z) => ({
|
|
30055
|
-
ask: z.string().describe("Ask id
|
|
30055
|
+
ask: z.string().describe("Ask id (uuid); an 8+ hex prefix unique among this session's own open asks works too."),
|
|
30056
30056
|
question: z.string({ max: ASK_QUESTION_MAX }).describe(`Replacement decision question, at most ${ASK_QUESTION_MAX} characters.`).optional(),
|
|
30057
30057
|
options: z.array(z.object({
|
|
30058
30058
|
label: z.string().describe("Selectable option label."),
|
|
@@ -30078,7 +30078,7 @@ var dispatchToolSpecs = [
|
|
|
30078
30078
|
},
|
|
30079
30079
|
description: "Retract an open question that is moot or resolve one after finding the answer. This closes the question without answering it.",
|
|
30080
30080
|
arguments: (z) => ({
|
|
30081
|
-
ask: z.string().describe("Ask id to close."),
|
|
30081
|
+
ask: z.string().describe("Ask id (uuid) to close; an 8+ hex prefix unique among this session's own open asks " + "works too."),
|
|
30082
30082
|
kind: z.enum(["retracted", "resolved"]).describe("Whether the ask is retracted or self-resolved."),
|
|
30083
30083
|
reason: z.string({ min: 1 }).describe("Why the open ask no longer needs a human answer.")
|
|
30084
30084
|
})
|
|
@@ -30097,7 +30097,7 @@ var dispatchToolSpecs = [
|
|
|
30097
30097
|
example: { ask: "01234567-0000-4000-8000-000000000001", action: "follow" },
|
|
30098
30098
|
description: "Follow or unfollow an ask. Every session that opens or replies to an ask follows it: its answer, " + "edits, resolution, and replies reach that session directly. Unfollow to stop; follow to rejoin or " + "to hear an ask you never wrote to. Whole-issue subscription is separate: envoy_subscribe " + "notifications.dispatch.issue.<KEY>.>",
|
|
30099
30099
|
arguments: (z) => ({
|
|
30100
|
-
ask: z.string().describe("
|
|
30100
|
+
ask: z.string().describe("Ask id (uuid); an 8+ hex prefix unique among this session's own open asks works too."),
|
|
30101
30101
|
action: z.enum(["follow", "unfollow"]).describe("follow | unfollow")
|
|
30102
30102
|
}),
|
|
30103
30103
|
strict: true
|
|
@@ -32863,24 +32863,51 @@ function messageIdOf(value) {
|
|
|
32863
32863
|
return id === undefined ? undefined : normalizeUUID(id);
|
|
32864
32864
|
}
|
|
32865
32865
|
var idPrefixPattern = /^[0-9a-f][0-9a-f-]{7,}$/i;
|
|
32866
|
-
|
|
32867
|
-
|
|
32866
|
+
function refOwnerName(ref) {
|
|
32867
|
+
return ref.owner.kind === "issue" ? ref.owner.issue : `${ref.owner.project}/${ref.artifact}`;
|
|
32868
|
+
}
|
|
32869
|
+
async function resolveIdPrefix(tool, kind, id, ownerName, list) {
|
|
32870
|
+
const fullID = normalizeUUID(id);
|
|
32868
32871
|
if (fullID !== undefined)
|
|
32869
32872
|
return fullID;
|
|
32870
|
-
|
|
32871
|
-
if (!idPrefixPattern.test(ref.id)) {
|
|
32873
|
+
if (!idPrefixPattern.test(id)) {
|
|
32872
32874
|
throw new ToolInputError(tool, [
|
|
32873
|
-
`${kind} id ${
|
|
32875
|
+
`${kind} id ${id} must be a full uuid or a prefix of at least 8 hex characters`
|
|
32874
32876
|
]);
|
|
32875
32877
|
}
|
|
32876
|
-
const prefix =
|
|
32878
|
+
const prefix = id.toLowerCase();
|
|
32877
32879
|
const matches = (await list()).filter((item) => item.id.toLowerCase().startsWith(prefix));
|
|
32878
32880
|
if (matches.length === 1 && matches[0] !== undefined)
|
|
32879
32881
|
return matches[0].id;
|
|
32880
32882
|
throw new ToolInputError(tool, [
|
|
32881
|
-
matches.length === 0 ? `${kind} id ${
|
|
32883
|
+
matches.length === 0 ? `${kind} id ${id} matches none of the ${kind}s on ${ownerName}; use the full id` : `${kind} id ${id} matches ${matches.length} ${kind}s on ${ownerName}; use the full id`
|
|
32882
32884
|
]);
|
|
32883
32885
|
}
|
|
32886
|
+
var askIdShapeProblem = "ask ids are uuids (a prefix of at least 8 hex characters works)";
|
|
32887
|
+
async function sessionOpenAsks(client, sessionId) {
|
|
32888
|
+
const session = sessionId?.trim();
|
|
32889
|
+
if (!session)
|
|
32890
|
+
throw new Error("host session id is required to read this session's open asks");
|
|
32891
|
+
return (await client.openAsks(session)).asks;
|
|
32892
|
+
}
|
|
32893
|
+
function openAskHints(asks) {
|
|
32894
|
+
if (asks.length === 0)
|
|
32895
|
+
return "you have no open asks";
|
|
32896
|
+
const hints = asks.slice(0, askHintLimit).map((ask) => `${ask.id.slice(0, 8)} \u2014 ${textHead(ask.question)}`);
|
|
32897
|
+
return `your open asks: ${hints.join("; ")}`;
|
|
32898
|
+
}
|
|
32899
|
+
async function resolveAskArgument(tool, args, client, sessionId) {
|
|
32900
|
+
const id = askId(args);
|
|
32901
|
+
if (normalizeUUID(id) === undefined && !idPrefixPattern.test(id)) {
|
|
32902
|
+
const asks = await sessionOpenAsks(client, sessionId).catch(() => {
|
|
32903
|
+
return;
|
|
32904
|
+
});
|
|
32905
|
+
throw new ToolInputError(tool, [
|
|
32906
|
+
asks === undefined ? askIdShapeProblem : `${askIdShapeProblem}; ${openAskHints(asks)}`
|
|
32907
|
+
]);
|
|
32908
|
+
}
|
|
32909
|
+
return resolveIdPrefix(tool, "ask", id, "this session", () => sessionOpenAsks(client, sessionId));
|
|
32910
|
+
}
|
|
32884
32911
|
function messageInReplyTo(args) {
|
|
32885
32912
|
const inReplyTo = optionalString(args, "in_reply_to");
|
|
32886
32913
|
return inReplyTo === undefined ? undefined : messageIdOf(inReplyTo);
|
|
@@ -32899,7 +32926,8 @@ function argumentProblems(tool, args) {
|
|
|
32899
32926
|
break;
|
|
32900
32927
|
}
|
|
32901
32928
|
case "dispatch_edit_ask":
|
|
32902
|
-
case "dispatch_resolve_ask":
|
|
32929
|
+
case "dispatch_resolve_ask":
|
|
32930
|
+
case "dispatch_follow": {
|
|
32903
32931
|
const ask = optionalString(args, "ask");
|
|
32904
32932
|
if (ask?.startsWith("dispatch://") && parseDispatchRef(ask)?.kind !== "ask") {
|
|
32905
32933
|
problems.push(askIdProblem);
|
|
@@ -33693,7 +33721,8 @@ async function executeDispatchTool(input) {
|
|
|
33693
33721
|
}
|
|
33694
33722
|
case "dispatch_resolve_ask": {
|
|
33695
33723
|
const kind = stringArg(args, "kind");
|
|
33696
|
-
const
|
|
33724
|
+
const id = await resolveAskArgument(input.tool, args, client, input.sessionId);
|
|
33725
|
+
const ask = await client.resolveAsk(id, {
|
|
33697
33726
|
kind,
|
|
33698
33727
|
reason: stringArg(args, "reason"),
|
|
33699
33728
|
actor
|
|
@@ -33712,11 +33741,11 @@ async function executeDispatchTool(input) {
|
|
|
33712
33741
|
let document;
|
|
33713
33742
|
if (ref?.owner.kind === "issue") {
|
|
33714
33743
|
const issueKey = ref.owner.issue;
|
|
33715
|
-
id = await resolveIdPrefix(input.tool, "comment", ref, () => client.getComments(issueKey));
|
|
33744
|
+
id = await resolveIdPrefix(input.tool, "comment", ref.id, refOwnerName(ref), () => client.getComments(issueKey));
|
|
33716
33745
|
} else if (ref !== null) {
|
|
33717
33746
|
const artifact = (await resolveArtifact(client, ref.owner, ref.artifact)).artifact;
|
|
33718
33747
|
document = artifact;
|
|
33719
|
-
id = await resolveIdPrefix(input.tool, "comment", ref, () => client.getArtifactComments(artifact.id));
|
|
33748
|
+
id = await resolveIdPrefix(input.tool, "comment", ref.id, refOwnerName(ref), () => client.getArtifactComments(artifact.id));
|
|
33720
33749
|
}
|
|
33721
33750
|
const comment = await client.resolveComment(id, actor);
|
|
33722
33751
|
const { label, details } = await commentOwnerResult(client, comment, document);
|
|
@@ -33760,7 +33789,8 @@ ${followsAsk(askOwner)}`,
|
|
|
33760
33789
|
const options = args.options;
|
|
33761
33790
|
const multiple = optionalBoolean(args, "multiple");
|
|
33762
33791
|
const urgency = askUrgency(args);
|
|
33763
|
-
const
|
|
33792
|
+
const id = await resolveAskArgument(input.tool, args, client, input.sessionId);
|
|
33793
|
+
const ask = await client.editAsk(id, {
|
|
33764
33794
|
...question === undefined ? {} : { question },
|
|
33765
33795
|
...Array.isArray(options) ? { options } : {},
|
|
33766
33796
|
...multiple === undefined ? {} : { multiple },
|
|
@@ -33987,7 +34017,7 @@ ${trailer.join(`
|
|
|
33987
34017
|
const sessionId = input.sessionId?.trim();
|
|
33988
34018
|
if (!sessionId)
|
|
33989
34019
|
throw new Error("host session id is required for dispatch_follow");
|
|
33990
|
-
const ask =
|
|
34020
|
+
const ask = await resolveAskArgument(input.tool, args, client, sessionId);
|
|
33991
34021
|
const action = stringArg(args, "action");
|
|
33992
34022
|
if (action === "unfollow") {
|
|
33993
34023
|
await client.unfollowAsk(ask, sessionId, actor);
|
|
@@ -34003,7 +34033,7 @@ ${trailer.join(`
|
|
|
34003
34033
|
case "dispatch_read": {
|
|
34004
34034
|
if (ownerArguments.ref?.kind === "ask") {
|
|
34005
34035
|
const ref = ownerArguments.ref;
|
|
34006
|
-
const id = await resolveIdPrefix(input.tool, "ask", ref, async () => ref.owner.kind === "issue" ? client.listIssueAsks(ref.owner.issue) : client.getArtifactAsks((await resolveArtifact(client, ref.owner, ref.artifact)).artifact.id, "all"));
|
|
34036
|
+
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"));
|
|
34007
34037
|
const askRead = await client.getAsk(id);
|
|
34008
34038
|
const askRef = refTarget(ref, "ask", id);
|
|
34009
34039
|
return {
|
|
@@ -34013,7 +34043,7 @@ ${trailer.join(`
|
|
|
34013
34043
|
}
|
|
34014
34044
|
if (ownerArguments.ref?.kind === "comment") {
|
|
34015
34045
|
const ref = ownerArguments.ref;
|
|
34016
|
-
const id = await resolveIdPrefix(input.tool, "comment", ref, async () => ref.owner.kind === "issue" ? client.getComments(ref.owner.issue) : client.getArtifactComments((await resolveArtifact(client, ref.owner, ref.artifact)).artifact.id));
|
|
34046
|
+
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));
|
|
34017
34047
|
const comment = await client.getComment(id);
|
|
34018
34048
|
const commentRef = refTarget(ref, "comment", id);
|
|
34019
34049
|
return {
|
package/dist/legion.js
CHANGED
|
@@ -16145,7 +16145,7 @@ import { logger } from "@oh-my-pi/pi-utils";
|
|
|
16145
16145
|
// package.json
|
|
16146
16146
|
var package_default = {
|
|
16147
16147
|
name: "@sjawhar/pi-legion-envoy",
|
|
16148
|
-
version: "1.57.
|
|
16148
|
+
version: "1.57.1",
|
|
16149
16149
|
type: "module",
|
|
16150
16150
|
omp: {
|
|
16151
16151
|
extensions: [
|
|
@@ -29371,7 +29371,7 @@ var dispatchToolSpecs = [
|
|
|
29371
29371
|
},
|
|
29372
29372
|
description: "Edit an open question in place. Use it to correct or refine the same decision; retract the " + "old ask and open a new one when the decision itself changes. Previous text remains in the " + "event log. Only the asking session can edit it; answered or resolved asks cannot be edited.",
|
|
29373
29373
|
arguments: (z) => ({
|
|
29374
|
-
ask: z.string().describe("Ask id
|
|
29374
|
+
ask: z.string().describe("Ask id (uuid); an 8+ hex prefix unique among this session's own open asks works too."),
|
|
29375
29375
|
question: z.string({ max: ASK_QUESTION_MAX }).describe(`Replacement decision question, at most ${ASK_QUESTION_MAX} characters.`).optional(),
|
|
29376
29376
|
options: z.array(z.object({
|
|
29377
29377
|
label: z.string().describe("Selectable option label."),
|
|
@@ -29397,7 +29397,7 @@ var dispatchToolSpecs = [
|
|
|
29397
29397
|
},
|
|
29398
29398
|
description: "Retract an open question that is moot or resolve one after finding the answer. This closes the question without answering it.",
|
|
29399
29399
|
arguments: (z) => ({
|
|
29400
|
-
ask: z.string().describe("Ask id to close."),
|
|
29400
|
+
ask: z.string().describe("Ask id (uuid) to close; an 8+ hex prefix unique among this session's own open asks " + "works too."),
|
|
29401
29401
|
kind: z.enum(["retracted", "resolved"]).describe("Whether the ask is retracted or self-resolved."),
|
|
29402
29402
|
reason: z.string({ min: 1 }).describe("Why the open ask no longer needs a human answer.")
|
|
29403
29403
|
})
|
|
@@ -29416,7 +29416,7 @@ var dispatchToolSpecs = [
|
|
|
29416
29416
|
example: { ask: "01234567-0000-4000-8000-000000000001", action: "follow" },
|
|
29417
29417
|
description: "Follow or unfollow an ask. Every session that opens or replies to an ask follows it: its answer, " + "edits, resolution, and replies reach that session directly. Unfollow to stop; follow to rejoin or " + "to hear an ask you never wrote to. Whole-issue subscription is separate: envoy_subscribe " + "notifications.dispatch.issue.<KEY>.>",
|
|
29418
29418
|
arguments: (z) => ({
|
|
29419
|
-
ask: z.string().describe("
|
|
29419
|
+
ask: z.string().describe("Ask id (uuid); an 8+ hex prefix unique among this session's own open asks works too."),
|
|
29420
29420
|
action: z.enum(["follow", "unfollow"]).describe("follow | unfollow")
|
|
29421
29421
|
}),
|
|
29422
29422
|
strict: true
|
|
@@ -708,7 +708,9 @@ the host tells you once per ask. Leave a thread you no longer need, or rejoin on
|
|
|
708
708
|
dispatch_follow({ ask, action: "follow" | "unfollow" })
|
|
709
709
|
```
|
|
710
710
|
|
|
711
|
-
`ask` is the full ask id or a `dispatch://KEY/ask/<id>` reference
|
|
711
|
+
`ask` is the full ask id or a `dispatch://KEY/ask/<id>` reference; `dispatch_follow`, `dispatch_edit_ask`, and
|
|
712
|
+
`dispatch_resolve_ask` also take an 8+ hex prefix that is unique among your own open asks, and refuse anything shorter by naming
|
|
713
|
+
those asks. A human may also remove you from the ask card; either way you are
|
|
712
714
|
told with an `ask.follower_removed` notice, and a human adding you arrives as `ask.follower_added`.
|
|
713
715
|
|
|
714
716
|
No write subscribes you to an issue or document. Following covers your own asks and the threads you joined; everything else on the
|