@sjawhar/opencode-legion-envoy 0.38.0 → 0.39.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/README.md +2 -1
- package/dist/src/server.js +57 -1
- package/package.json +1 -1
- package/skills/dispatch/SKILL.md +14 -0
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ This package exposes:
|
|
|
14
14
|
- `envoy_sessions`
|
|
15
15
|
- `dispatch_issue`
|
|
16
16
|
- `dispatch_ask`
|
|
17
|
+
- `dispatch_edit_ask`
|
|
17
18
|
- `dispatch_resolve_ask`
|
|
18
19
|
- `dispatch_comment`
|
|
19
20
|
- `dispatch_suggest`
|
|
@@ -24,7 +25,7 @@ This package exposes:
|
|
|
24
25
|
- `dispatch_read`
|
|
25
26
|
- `dispatch_search`
|
|
26
27
|
|
|
27
|
-
The
|
|
28
|
+
The twelve native `dispatch_*` tools create and read Dispatch issues, asks, comments,
|
|
28
29
|
documents, and artifacts, or search all of them. They are present when `dispatch.enabled`
|
|
29
30
|
resolves a server URL and bearer token from envoy.json (`~/.config/opencode/envoy.json`, merged
|
|
30
31
|
with `<repo>/.opencode/envoy.json`) or the `DISPATCH_URL` and `DISPATCH_TOKEN` environment
|
package/dist/src/server.js
CHANGED
|
@@ -13717,6 +13717,27 @@ var dispatchToolSpecs = [
|
|
|
13717
13717
|
}).describe("Optional document location for the question.").optional()
|
|
13718
13718
|
})
|
|
13719
13719
|
},
|
|
13720
|
+
{
|
|
13721
|
+
name: "dispatch_edit_ask",
|
|
13722
|
+
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.",
|
|
13723
|
+
arguments: (z) => ({
|
|
13724
|
+
ask: z.string().describe("Ask id to edit."),
|
|
13725
|
+
question: z.string({ max: 800 }).describe("Replacement decision question, at most 800 characters.").optional(),
|
|
13726
|
+
options: z.array(z.object({
|
|
13727
|
+
label: z.string().describe("Selectable option label."),
|
|
13728
|
+
description: z.string().describe("Optional option context.").optional()
|
|
13729
|
+
}), { max: 8 }).describe("Replacement choices, at most 8.").optional(),
|
|
13730
|
+
multiple: z.boolean().describe("Whether multiple choices may be selected.").optional(),
|
|
13731
|
+
urgency: z.enum(ASK_URGENCIES).describe("Replacement decision urgency.").optional()
|
|
13732
|
+
}),
|
|
13733
|
+
validation: {
|
|
13734
|
+
check: (value) => {
|
|
13735
|
+
const input = value;
|
|
13736
|
+
return typeof input.question === "string" || Array.isArray(input.options) || typeof input.multiple === "boolean" || typeof input.urgency === "string";
|
|
13737
|
+
},
|
|
13738
|
+
message: "Ask edit requires at least one field besides ask."
|
|
13739
|
+
}
|
|
13740
|
+
},
|
|
13720
13741
|
{
|
|
13721
13742
|
name: "dispatch_resolve_ask",
|
|
13722
13743
|
description: "Retract an open question that is moot or resolve one after finding the answer. This closes the question without answering it.",
|
|
@@ -14482,6 +14503,9 @@ class DispatchClient {
|
|
|
14482
14503
|
async resolveAsk(id, input) {
|
|
14483
14504
|
return this.#json("POST", ["api", "v1", "asks", id, "resolve"], input);
|
|
14484
14505
|
}
|
|
14506
|
+
async editAsk(id, input) {
|
|
14507
|
+
return this.#json("PATCH", ["api", "v1", "asks", id], input);
|
|
14508
|
+
}
|
|
14485
14509
|
async comment(issue, input) {
|
|
14486
14510
|
return this.#json("POST", ["api", "v1", "issues", await this.#resolveIssue(issue), "comments"], input);
|
|
14487
14511
|
}
|
|
@@ -14638,7 +14662,12 @@ class DispatchClient {
|
|
|
14638
14662
|
var nativeIssueKeyPattern = /^[A-Z][A-Z0-9]{1,9}-[0-9]+$/;
|
|
14639
14663
|
var externalIssueRefPattern = /^([^/\s]+)\/([^/\s#]+)#([1-9][0-9]*)$/;
|
|
14640
14664
|
var bareIssueNumberPattern = /^[1-9][0-9]*$/;
|
|
14641
|
-
var issueFreeTools = new Set([
|
|
14665
|
+
var issueFreeTools = new Set([
|
|
14666
|
+
"dispatch_issue",
|
|
14667
|
+
"dispatch_edit_ask",
|
|
14668
|
+
"dispatch_resolve_ask",
|
|
14669
|
+
"dispatch_search"
|
|
14670
|
+
]);
|
|
14642
14671
|
async function askResultDetails(client, ask) {
|
|
14643
14672
|
if (ask.issue_key !== null) {
|
|
14644
14673
|
return {
|
|
@@ -14726,6 +14755,16 @@ function parseDispatchRef(ref) {
|
|
|
14726
14755
|
return { issue, kind: "comment", id: comment };
|
|
14727
14756
|
return { issue, kind: "issue", id: issue };
|
|
14728
14757
|
}
|
|
14758
|
+
function askId(args) {
|
|
14759
|
+
const ask = stringArg(args, "ask");
|
|
14760
|
+
if (!ask.startsWith("dispatch://"))
|
|
14761
|
+
return ask;
|
|
14762
|
+
const reference = parseDispatchRef(ask);
|
|
14763
|
+
if (reference?.kind !== "ask") {
|
|
14764
|
+
throw new Error("ask must be a bare ask id or a dispatch://.../ask/<id> reference");
|
|
14765
|
+
}
|
|
14766
|
+
return reference.id;
|
|
14767
|
+
}
|
|
14729
14768
|
function toolSchema(tool) {
|
|
14730
14769
|
const spec = dispatchToolSpecs.find((candidate) => candidate.name === tool);
|
|
14731
14770
|
if (!spec)
|
|
@@ -14994,6 +15033,23 @@ async function executeDispatchTool(input) {
|
|
|
14994
15033
|
details: await askResultDetails(client, ask)
|
|
14995
15034
|
};
|
|
14996
15035
|
}
|
|
15036
|
+
case "dispatch_edit_ask": {
|
|
15037
|
+
const question = optionalString(args, "question");
|
|
15038
|
+
const options = args.options;
|
|
15039
|
+
const multiple = optionalBoolean(args, "multiple");
|
|
15040
|
+
const urgency = askUrgency(args);
|
|
15041
|
+
const ask = await client.editAsk(askId(args), {
|
|
15042
|
+
...question === undefined ? {} : { question },
|
|
15043
|
+
...Array.isArray(options) ? { options } : {},
|
|
15044
|
+
...multiple === undefined ? {} : { multiple },
|
|
15045
|
+
...urgency === undefined ? {} : { urgency },
|
|
15046
|
+
actor
|
|
15047
|
+
});
|
|
15048
|
+
return {
|
|
15049
|
+
text: `Ask edited: ${ask.question}`,
|
|
15050
|
+
details: await askResultDetails(client, ask)
|
|
15051
|
+
};
|
|
15052
|
+
}
|
|
14997
15053
|
case "dispatch_comment": {
|
|
14998
15054
|
const artifactReference = optionalString(args, "artifact");
|
|
14999
15055
|
if (optionalString(args, "quote") !== undefined && artifactReference === undefined) {
|
package/package.json
CHANGED
package/skills/dispatch/SKILL.md
CHANGED
|
@@ -94,6 +94,20 @@ accepts `{ artifact, mark_id }` from a browser that has already written its mark
|
|
|
94
94
|
use the quote form. An anchor whose quote disappears becomes orphaned but remains readable against
|
|
95
95
|
its original document version.
|
|
96
96
|
|
|
97
|
+
Correct or refine an open ask in place instead of opening a second question:
|
|
98
|
+
```ts
|
|
99
|
+
dispatch_edit_ask({
|
|
100
|
+
ask,
|
|
101
|
+
question?,
|
|
102
|
+
options?: { label, description? }[],
|
|
103
|
+
multiple?,
|
|
104
|
+
urgency?,
|
|
105
|
+
})
|
|
106
|
+
```
|
|
107
|
+
At least one field besides `ask` is required. Use this only while the same decision remains
|
|
108
|
+
open: it keeps the prior text in the event log. An answered or resolved ask cannot be edited.
|
|
109
|
+
If the decision is moot or superseded, retract the old ask and open a new one.
|
|
110
|
+
|
|
97
111
|
An ask stays open until a human answers, unless its question no longer needs that answer. Retract a
|
|
98
112
|
moot or superseded question, or self-resolve one after finding the answer:
|
|
99
113
|
```ts
|