@sjawhar/opencode-legion-envoy 3.9.0 → 3.10.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/src/server.js +45 -32
- package/package.json +1 -1
- package/skills/dispatch/SKILL.md +5 -2
package/dist/src/server.js
CHANGED
|
@@ -16041,13 +16041,23 @@ async function resolveOwnerArguments(tool, input, cwd, env, exec, serverUrl, pro
|
|
|
16041
16041
|
const issue2 = `${repo2}#${legionIssue}`;
|
|
16042
16042
|
return { args: { ...args, issue: issue2 }, ref, owner: { kind: "issue", issue: issue2 } };
|
|
16043
16043
|
}
|
|
16044
|
-
function artifactByReference(artifacts, artifactReference, owner) {
|
|
16045
|
-
const
|
|
16046
|
-
if (
|
|
16047
|
-
return
|
|
16044
|
+
function artifactByReference(artifacts, artifactReference, owner, canonical) {
|
|
16045
|
+
const bySlug = artifacts.find((candidate) => candidate.slug === artifactReference);
|
|
16046
|
+
if (canonical && bySlug !== undefined)
|
|
16047
|
+
return bySlug;
|
|
16048
|
+
const byId = artifacts.find((candidate) => candidate.id === artifactReference);
|
|
16049
|
+
if (byId !== undefined)
|
|
16050
|
+
return byId;
|
|
16048
16051
|
const byName = artifacts.filter((candidate) => candidate.name === artifactReference);
|
|
16052
|
+
if (bySlug !== undefined) {
|
|
16053
|
+
const named = byName.filter((candidate) => candidate.id !== bySlug.id && candidate.kind === "doc");
|
|
16054
|
+
if (named.length > 0) {
|
|
16055
|
+
throw new Error(documentReferenceProblem(artifactReference, [bySlug, ...named], owner, "id"));
|
|
16056
|
+
}
|
|
16057
|
+
return bySlug;
|
|
16058
|
+
}
|
|
16049
16059
|
if (byName.length > 1) {
|
|
16050
|
-
throw new Error(documentReferenceProblem(artifactReference, byName, owner,
|
|
16060
|
+
throw new Error(documentReferenceProblem(artifactReference, byName, owner, "slug"));
|
|
16051
16061
|
}
|
|
16052
16062
|
const [artifact] = byName;
|
|
16053
16063
|
if (artifact === undefined) {
|
|
@@ -16055,32 +16065,31 @@ function artifactByReference(artifacts, artifactReference, owner) {
|
|
|
16055
16065
|
}
|
|
16056
16066
|
return artifact;
|
|
16057
16067
|
}
|
|
16058
|
-
async function resolveArtifact(client, owner, artifactReference) {
|
|
16068
|
+
async function resolveArtifact(client, owner, artifactReference, { canonical = false } = {}) {
|
|
16059
16069
|
if (owner.kind === "project") {
|
|
16060
16070
|
if (artifactReference === undefined) {
|
|
16061
16071
|
throw new Error("artifact is required for a project document");
|
|
16062
16072
|
}
|
|
16063
|
-
|
|
16064
|
-
return {
|
|
16065
|
-
owner,
|
|
16066
|
-
artifact: await client.getProjectArtifact(owner.project, artifactReference)
|
|
16067
|
-
};
|
|
16068
|
-
} catch (error48) {
|
|
16073
|
+
const routed = await client.getProjectArtifact(owner.project, artifactReference).catch((error48) => {
|
|
16069
16074
|
if (!(error48 instanceof DispatchServiceError) || error48.status !== 404)
|
|
16070
16075
|
throw error48;
|
|
16071
|
-
|
|
16072
|
-
|
|
16073
|
-
|
|
16074
|
-
|
|
16075
|
-
|
|
16076
|
-
|
|
16076
|
+
return;
|
|
16077
|
+
});
|
|
16078
|
+
if (canonical && routed !== undefined)
|
|
16079
|
+
return { owner, artifact: routed };
|
|
16080
|
+
const unlinked = await client.listProjectArtifacts(owner.project, true);
|
|
16081
|
+
const artifacts = routed === undefined ? unlinked : [routed, ...unlinked.filter((candidate) => candidate.id !== routed.id)];
|
|
16082
|
+
return {
|
|
16083
|
+
owner,
|
|
16084
|
+
artifact: artifactByReference(artifacts, artifactReference, "project", canonical)
|
|
16085
|
+
};
|
|
16077
16086
|
}
|
|
16078
16087
|
const issue2 = await client.getIssue(owner.issue);
|
|
16079
16088
|
let artifact;
|
|
16080
16089
|
if (artifactReference === undefined || artifactReference === "spec") {
|
|
16081
16090
|
artifact = issue2.artifacts.find((candidate) => candidate.primary || candidate.id === issue2.primary_artifact_id);
|
|
16082
16091
|
} else {
|
|
16083
|
-
artifact = artifactByReference(issue2.artifacts, artifactReference, "issue");
|
|
16092
|
+
artifact = artifactByReference(issue2.artifacts, artifactReference, "issue", canonical);
|
|
16084
16093
|
}
|
|
16085
16094
|
if (!artifact) {
|
|
16086
16095
|
throw new Error(documentReferenceProblem(artifactReference ?? "spec", issue2.artifacts, "issue"));
|
|
@@ -16088,10 +16097,10 @@ async function resolveArtifact(client, owner, artifactReference) {
|
|
|
16088
16097
|
return { owner, issue: issue2, artifact };
|
|
16089
16098
|
}
|
|
16090
16099
|
var documentHintLimit = 8;
|
|
16091
|
-
function documentReferenceProblem(reference, documents, owner,
|
|
16092
|
-
const hints = documents.slice(0, documentHintLimit).map((document) => `${document.slug} (${document.name})`);
|
|
16100
|
+
function documentReferenceProblem(reference, documents, owner, use) {
|
|
16101
|
+
const hints = documents.slice(0, documentHintLimit).map((document) => use === "id" ? `${document.id} (${document.slug}, ${document.name})` : `${document.slug} (${document.name})`);
|
|
16093
16102
|
const list = hints.length === 0 ? "none" : hints.join(", ");
|
|
16094
|
-
return
|
|
16103
|
+
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}`;
|
|
16095
16104
|
}
|
|
16096
16105
|
var askHintLimit = 8;
|
|
16097
16106
|
function askIDInputProblem(asks, scope) {
|
|
@@ -16481,6 +16490,10 @@ async function executeDispatchTool(input) {
|
|
|
16481
16490
|
const args = parsed.success ? parsed.data : ownerArguments.args;
|
|
16482
16491
|
const actor = toolActor(await resolveOrigin(env, exec, input.cwd), input);
|
|
16483
16492
|
const client = dispatchClient();
|
|
16493
|
+
const refDocument = ownerArguments.ref?.kind === "artifact" ? ownerArguments.ref.id : ownerArguments.ref?.artifact;
|
|
16494
|
+
const resolveDocument = (documentOwner2, reference) => resolveArtifact(client, documentOwner2, reference, {
|
|
16495
|
+
canonical: reference !== undefined && reference === refDocument
|
|
16496
|
+
});
|
|
16484
16497
|
const owner = ownerArguments.owner?.kind === "issue" ? {
|
|
16485
16498
|
kind: "issue",
|
|
16486
16499
|
issue: await resolveExistingIssue(client, ownerArguments.owner.issue)
|
|
@@ -16771,7 +16784,7 @@ async function executeDispatchTool(input) {
|
|
|
16771
16784
|
const issueKey = ref.owner.issue;
|
|
16772
16785
|
id = await resolveIdPrefix(input.tool, "comment", ref.id, refOwnerName(ref), () => client.getComments(issueKey));
|
|
16773
16786
|
} else if (ref !== null) {
|
|
16774
|
-
const artifact = (await resolveArtifact(client, ref.owner, ref.artifact)).artifact;
|
|
16787
|
+
const artifact = (await resolveArtifact(client, ref.owner, ref.artifact, { canonical: true })).artifact;
|
|
16775
16788
|
document = artifact;
|
|
16776
16789
|
id = await resolveIdPrefix(input.tool, "comment", ref.id, refOwnerName(ref), () => client.getArtifactComments(artifact.id));
|
|
16777
16790
|
}
|
|
@@ -16783,7 +16796,7 @@ async function executeDispatchTool(input) {
|
|
|
16783
16796
|
const anchorArgs = asObject(args.anchor);
|
|
16784
16797
|
const owner2 = documentOwner();
|
|
16785
16798
|
const artifactReference = optionalString(args, "artifact") ?? (anchorArgs === null ? undefined : optionalString(anchorArgs, "artifact"));
|
|
16786
|
-
const resolved = owner2.kind === "project" || artifactReference === undefined ? owner2.kind === "project" ? await
|
|
16799
|
+
const resolved = owner2.kind === "project" || artifactReference === undefined ? owner2.kind === "project" ? await resolveDocument(owner2, artifactReference) : undefined : await resolveDocument(owner2, artifactReference);
|
|
16787
16800
|
const options = args.options;
|
|
16788
16801
|
const multiple = optionalBoolean(args, "multiple");
|
|
16789
16802
|
const urgency = askUrgency(args);
|
|
@@ -16833,7 +16846,7 @@ ${followsAsk(askOwner)}`,
|
|
|
16833
16846
|
case "dispatch_comment": {
|
|
16834
16847
|
const artifactReference = optionalString(args, "artifact");
|
|
16835
16848
|
const owner2 = documentOwner();
|
|
16836
|
-
const resolved = owner2.kind === "project" || artifactReference === undefined ? owner2.kind === "project" ? await
|
|
16849
|
+
const resolved = owner2.kind === "project" || artifactReference === undefined ? owner2.kind === "project" ? await resolveDocument(owner2, artifactReference) : undefined : await resolveDocument(owner2, artifactReference);
|
|
16837
16850
|
const anchored = resolved ? anchor(resolved.artifact, args) : undefined;
|
|
16838
16851
|
const replyTo = optionalString(args, "reply_to");
|
|
16839
16852
|
const replyToAskReference = optionalString(args, "reply_to_ask");
|
|
@@ -16886,7 +16899,7 @@ ${followsAsk(askOwner)}`,
|
|
|
16886
16899
|
};
|
|
16887
16900
|
}
|
|
16888
16901
|
case "dispatch_suggest": {
|
|
16889
|
-
const resolved = await
|
|
16902
|
+
const resolved = await resolveDocument(documentOwner(), stringArg(args, "artifact"));
|
|
16890
16903
|
const anchored = anchor(resolved.artifact, args);
|
|
16891
16904
|
if (anchored === undefined)
|
|
16892
16905
|
throw new Error("quote is required");
|
|
@@ -16941,7 +16954,7 @@ ${followsAsk(askOwner)}`,
|
|
|
16941
16954
|
};
|
|
16942
16955
|
}
|
|
16943
16956
|
case "dispatch_doc_edit": {
|
|
16944
|
-
const resolved = await
|
|
16957
|
+
const resolved = await resolveDocument(documentOwner(), stringArg(args, "artifact"));
|
|
16945
16958
|
const ops = args.ops;
|
|
16946
16959
|
const summary = optionalString(args, "summary");
|
|
16947
16960
|
const { precondition: rawPrecondition } = args;
|
|
@@ -16983,7 +16996,7 @@ ${followsAsk(askOwner)}`,
|
|
|
16983
16996
|
}
|
|
16984
16997
|
case "dispatch_doc_read": {
|
|
16985
16998
|
const artifactReference = optionalString(args, "artifact") ?? (ownerArguments.ref?.kind === "spec" || ownerArguments.ref?.kind === "artifact" ? ownerArguments.ref.id : undefined);
|
|
16986
|
-
const resolved = await
|
|
16999
|
+
const resolved = await resolveDocument(documentOwner(), artifactReference);
|
|
16987
17000
|
const version2 = optionalNumber(args, "version") ?? ownerArguments.ref?.version;
|
|
16988
17001
|
const documentPromise = client.docRead(resolved.artifact.id, version2);
|
|
16989
17002
|
const marksPromise = openArtifactMarks(client, resolved);
|
|
@@ -17012,7 +17025,7 @@ ${trailer.join(`
|
|
|
17012
17025
|
}
|
|
17013
17026
|
case "dispatch_request_approval": {
|
|
17014
17027
|
const artifactReference = optionalString(args, "artifact") ?? (ownerArguments.ref?.kind === "spec" || ownerArguments.ref?.kind === "artifact" ? ownerArguments.ref.id : undefined);
|
|
17015
|
-
const resolved = await
|
|
17028
|
+
const resolved = await resolveDocument(documentOwner(), artifactReference);
|
|
17016
17029
|
const result = await client.requestApproval(resolved.artifact.id, { actor });
|
|
17017
17030
|
if (result.ask === null) {
|
|
17018
17031
|
return {
|
|
@@ -17090,7 +17103,7 @@ ${trailer.join(`
|
|
|
17090
17103
|
case "dispatch_read": {
|
|
17091
17104
|
if (ownerArguments.ref?.kind === "ask") {
|
|
17092
17105
|
const ref = ownerArguments.ref;
|
|
17093
|
-
const id = await resolveIdPrefix(input.tool, "ask", ref.id, refOwnerName(ref), async () => ref.owner.kind === "issue" ? client.listIssueAsks(ref.owner.issue) : client.getArtifactAsks((await
|
|
17106
|
+
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"));
|
|
17094
17107
|
const askRead = await client.getAsk(id);
|
|
17095
17108
|
const askRef = refTarget(ref, "ask", id);
|
|
17096
17109
|
return {
|
|
@@ -17100,7 +17113,7 @@ ${trailer.join(`
|
|
|
17100
17113
|
}
|
|
17101
17114
|
if (ownerArguments.ref?.kind === "comment") {
|
|
17102
17115
|
const ref = ownerArguments.ref;
|
|
17103
|
-
const id = await resolveIdPrefix(input.tool, "comment", ref.id, refOwnerName(ref), async () => ref.owner.kind === "issue" ? client.getComments(ref.owner.issue) : client.getArtifactComments((await
|
|
17116
|
+
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));
|
|
17104
17117
|
const comment = await client.getComment(id);
|
|
17105
17118
|
const commentRef = refTarget(ref, "comment", id);
|
|
17106
17119
|
return {
|
|
@@ -17120,7 +17133,7 @@ ${trailer.join(`
|
|
|
17120
17133
|
};
|
|
17121
17134
|
}
|
|
17122
17135
|
if (documentOwner().kind === "project") {
|
|
17123
|
-
const resolved = await
|
|
17136
|
+
const resolved = await resolveDocument(documentOwner(), stringArg(args, "artifact"));
|
|
17124
17137
|
const documentRef = dispatchDocumentRef(resolved.artifact.project, resolved.artifact.slug);
|
|
17125
17138
|
return {
|
|
17126
17139
|
text: [
|
package/package.json
CHANGED
package/skills/dispatch/SKILL.md
CHANGED
|
@@ -603,7 +603,8 @@ dispatch_doc_read({ issue?, project?, artifact?, version?, ref? })
|
|
|
603
603
|
```
|
|
604
604
|
It returns live or versioned markdown with open marks. A live read ends with a document token; `issue` with an
|
|
605
605
|
omitted `artifact` reads the issue specification; a project needs `artifact`; and a
|
|
606
|
-
`dispatch://PROJECT/artifact/<document-ref>` ref supplies both, where `document-ref` is the id
|
|
606
|
+
`dispatch://PROJECT/artifact/<document-ref>` ref supplies both, where `document-ref` is the slug (an id or a
|
|
607
|
+
filename resolves when no document has that slug).
|
|
607
608
|
|
|
608
609
|
Editing one is [Editing a document](references/document-edits.md): the shape of `dispatch_doc_edit`,
|
|
609
610
|
how to quote the text you mean, one `replace` per paragraph, preconditions against a stale edit, and
|
|
@@ -741,7 +742,9 @@ Exactly one of `path` and `content` is required. It returns issue or project-doc
|
|
|
741
742
|
Uploading the same `name` creates its next version — so uploading `spec.md` **replaces the issue's own specification**
|
|
742
743
|
with your text. Never do that: the spec is edited in place with `dispatch_doc_edit` (see [Editing a document](references/document-edits.md)). Address an existing
|
|
743
744
|
artifact by the slug shown in the upload result or by its filename, and a project document by its artifact id, slug, or filename; the
|
|
744
|
-
slug also arrives on `artifact.created` events.
|
|
745
|
+
slug also arrives on `artifact.created` events. Dispatch suffixes a slug two documents would share, so one document's
|
|
746
|
+
filename can be another's slug (`plan v2` takes `plan-v2`, then a document named `plan-v2` takes `plan-v2-2`): a bare
|
|
747
|
+
`artifact` that names both is refused with each one's id, while a `dispatch://` reference's document part is always the slug.
|
|
745
748
|
|
|
746
749
|
**Where a deliverable goes.** Text the human must read to decide — a draft message, a proposal,
|
|
747
750
|
a summary — goes in the spec as a section: the spec is the one document they open. A separate
|