@sjawhar/pi-legion-envoy 5.4.3 → 5.5.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 +35 -11
- package/dist/legion.js +1 -1
- package/dist/skills/dispatch/SKILL.md +8 -0
- package/dist/skills/envoy/SKILL.md +9 -0
- package/package.json +1 -1
package/dist/envoy.js
CHANGED
|
@@ -35039,13 +35039,45 @@ var ROLE_CLAIM_ENTRY = "envoy-role-claim";
|
|
|
35039
35039
|
var OPEN_ASKS_TIMEOUT_MS = 3000;
|
|
35040
35040
|
var LEGION_MANAGED_ENTRY = "legion-managed-session";
|
|
35041
35041
|
var ASK_REMINDER_MESSAGE = "dispatch-ask-reminder";
|
|
35042
|
-
var
|
|
35042
|
+
var ASK_PROMPT_LINE_SEPARATOR = /\r\n|[\r\n\u0085\u2028\u2029]/;
|
|
35043
|
+
function askPromptQuestionHead(question) {
|
|
35044
|
+
const firstLineEnd = question.search(ASK_PROMPT_LINE_SEPARATOR);
|
|
35045
|
+
const firstLine = firstLineEnd === -1 ? question : question.slice(0, firstLineEnd);
|
|
35046
|
+
let normalized;
|
|
35047
|
+
let segmentStart = 0;
|
|
35048
|
+
for (let index = 0;index < firstLine.length; index += 1) {
|
|
35049
|
+
const codePoint = firstLine.charCodeAt(index);
|
|
35050
|
+
if (codePoint > 31 && (codePoint < 127 || codePoint > 159))
|
|
35051
|
+
continue;
|
|
35052
|
+
normalized ??= [];
|
|
35053
|
+
normalized.push(firstLine.slice(segmentStart, index), " ");
|
|
35054
|
+
segmentStart = index + 1;
|
|
35055
|
+
}
|
|
35056
|
+
return (normalized === undefined ? firstLine : `${normalized.join("")}${firstLine.slice(segmentStart)}`).trim();
|
|
35057
|
+
}
|
|
35058
|
+
var ASK_SELF_CHECK_PROMPT = (asks) => {
|
|
35059
|
+
const askLimit = 5;
|
|
35060
|
+
const questionLimit = 120;
|
|
35061
|
+
const promptAsks = asks.length === 0 ? "There are no open asks in Dispatch." : [
|
|
35062
|
+
"Your open asks in Dispatch:",
|
|
35063
|
+
...asks.slice(0, askLimit).map((ask) => {
|
|
35064
|
+
const firstLine = askPromptQuestionHead(ask.question);
|
|
35065
|
+
const question = firstLine.length <= questionLimit ? firstLine : `${firstLine.slice(0, questionLimit - 1)}\u2026`;
|
|
35066
|
+
return `- ${question}`;
|
|
35067
|
+
}),
|
|
35068
|
+
...asks.length > askLimit ? [`+${asks.length - askLimit} more`] : []
|
|
35069
|
+
].join(`
|
|
35070
|
+
`);
|
|
35071
|
+
return "Your run has just ended. " + `${promptAsks}
|
|
35072
|
+
|
|
35073
|
+
` + "Are you right now waiting on a human for anything none of those asks covers? " + "Answer with exactly one word and nothing else: WAITING or PROCEEDING. " + "WAITING \u2014 you stopped because you need a decision, an approval, or information from a human. " + "PROCEEDING \u2014 you finished, you will carry on by yourself, or you are waiting only on tools, " + "subagents, or events.";
|
|
35074
|
+
};
|
|
35043
35075
|
var WAITING_VERDICT = /^\W*WAITING\b/;
|
|
35044
35076
|
var ECHOED_CHOICE = /\bPROCEEDING\b/;
|
|
35045
35077
|
var isWaitingVerdict = (reply) => WAITING_VERDICT.test(reply) && !ECHOED_CHOICE.test(reply);
|
|
35046
35078
|
var ASK_SELF_CHECK_TIMEOUT_MS = 60000;
|
|
35047
35079
|
var ASK_CHECKS_PER_PERIOD = 5;
|
|
35048
|
-
var UNASKED_WAIT_REMINDER = "You just said you are waiting on a human
|
|
35080
|
+
var UNASKED_WAIT_REMINDER = "You just said you are waiting on a human for something no open ask in Dispatch covers. Open an ask for it now with dispatch_ask (or dispatch_request_approval for a document), naming exactly what you need and from whom.";
|
|
35049
35081
|
var ASK_OPENING_TOOLS = ["dispatch_ask", "dispatch_request_approval"];
|
|
35050
35082
|
var DISPATCH_TOOL_PREFIX = "dispatch_";
|
|
35051
35083
|
function isLegionManagedEntry(entry) {
|
|
@@ -35846,19 +35878,11 @@ function envoyExtension(pi) {
|
|
|
35846
35878
|
return;
|
|
35847
35879
|
if (runSeq !== seenRun)
|
|
35848
35880
|
return;
|
|
35849
|
-
if (open.snapshot.count > 0 || open.snapshot.opened_since) {
|
|
35850
|
-
askAwareness = {
|
|
35851
|
-
...askAwareness,
|
|
35852
|
-
check_due: false,
|
|
35853
|
-
baseline_as_of: open.snapshot.as_of
|
|
35854
|
-
};
|
|
35855
|
-
return;
|
|
35856
|
-
}
|
|
35857
35881
|
const abort = new AbortController;
|
|
35858
35882
|
askCheckAbort = abort;
|
|
35859
35883
|
let answered;
|
|
35860
35884
|
try {
|
|
35861
|
-
answered = askEphemeral({ prompt: ASK_SELF_CHECK_PROMPT, signal: abort.signal }).then((reply) => reply.replyText, (error48) => {
|
|
35885
|
+
answered = askEphemeral({ prompt: ASK_SELF_CHECK_PROMPT(open.snapshot.asks), signal: abort.signal }).then((reply) => reply.replyText, (error48) => {
|
|
35862
35886
|
if (!abort.signal.aborted)
|
|
35863
35887
|
logSelfCheckFailure(id, error48);
|
|
35864
35888
|
return;
|
package/dist/legion.js
CHANGED
|
@@ -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: "5.
|
|
16145
|
+
version: "5.5.0",
|
|
16146
16146
|
type: "module",
|
|
16147
16147
|
omp: {
|
|
16148
16148
|
extensions: [
|
|
@@ -653,6 +653,14 @@ dispatch_suggest({ issue?, project?, artifact, ref?, quote, replace_with, body?,
|
|
|
653
653
|
It returns issue or project-document owner details plus `comment`. A human accepts or rejects a suggestion.
|
|
654
654
|
Errors: `TARGET_AMBIGUOUS` (add `occurrence`), `TARGET_NOT_FOUND` (re-read first), `INVALID_ANCHOR`/`ANCHOR_MISSING`/`ANCHOR_ORPHANED`
|
|
655
655
|
(bad, unwritten, or stale quote), `INVALID_MARKDOWN`/`DOC_SCHEMA` (malformed content), `CAP_EXCEEDED`, `ISSUE_CLOSED`.
|
|
656
|
+
Suggest only what the quoted block can hold. The accept, not the suggestion, checks that: an
|
|
657
|
+
accept whose `replace_with` would break an ask block that was readable before it is refused with
|
|
658
|
+
`INVALID_ASK_BLOCK` - a question given a code block, text after an ask's options, a second option
|
|
659
|
+
list, or an emptied question; one that names an id the document holds outside the text it
|
|
660
|
+
replaces, an ask under a held id included, with `INVALID_MARKDOWN`; and one no part of the
|
|
661
|
+
document can hold where it sits (a code block over a table cell's whole text), or whose quote runs
|
|
662
|
+
into an ask or callout from the text before it, with `INVALID_OP`. Either changes nothing: the human sees the reason with no Retry, and the suggestion
|
|
663
|
+
stays open until someone rejects or replaces it.
|
|
656
664
|
|
|
657
665
|
## Artifacts
|
|
658
666
|
|
|
@@ -95,6 +95,15 @@ targeted. Reply through the rendered `reply_with` (or a current Envoy session ID
|
|
|
95
95
|
and go stale. Put the artefact URL in the message itself. FYIs set `expects_reply="none"`; set
|
|
96
96
|
`urgency` only when it is genuinely urgent.
|
|
97
97
|
|
|
98
|
+
**A peer's message is its sender's view at `at`, not the current state.** Before you wait on, act
|
|
99
|
+
on, or repeat a fact a message carries about a third thing (a deploy pending, a PR held, an ask
|
|
100
|
+
unanswered), re-read it at the live source the fact names, and always once it is over an hour
|
|
101
|
+
old: the deployment's status, the issue's event log, the ask's own state (`dispatch_open_asks`,
|
|
102
|
+
whose description already says to call it before saying you are waiting on a human). On
|
|
103
|
+
2026-09-26 a peer's 05:20Z "needs a manual deploy before I can run it" was false by 05:22Z, when
|
|
104
|
+
the platform had deployed on its own; waiting on the message instead of the deployment's status
|
|
105
|
+
held the work it gated for eleven hours.
|
|
106
|
+
|
|
98
107
|
Every `/v1` error response is JSON; when a field is at fault, `expected` names that field.
|
|
99
108
|
|
|
100
109
|
```text
|