@sjawhar/pi-legion-envoy 1.5.0 → 1.7.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 +10 -7
- package/dist/envoy.js +43 -20
- package/dist/legion.js +43 -20
- package/dist/skills/dispatch/SKILL.md +12 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -103,14 +103,17 @@ Configure the shared `envoy.json` with:
|
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
The user file is `~/.config/opencode/envoy.json`; a
|
|
106
|
-
`<cwd>/.opencode/envoy.json` file shallow-merges over it.
|
|
107
|
-
`
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
`
|
|
106
|
+
`<cwd>/.opencode/envoy.json` file shallow-merges over it. A repository
|
|
107
|
+
`dispatch.serverUrl` requires `dispatch.token` in that same repository file:
|
|
108
|
+
it never combines with a user-file or process-environment credential. To
|
|
109
|
+
override a repository endpoint for one process, set `DISPATCH_URL` together
|
|
110
|
+
with `DISPATCH_TOKEN` or `DISPATCH_TOKEN_FILE`. `DISPATCH_TOKEN_FILE` (a path
|
|
111
|
+
whose trimmed contents are the token — how the Legion daemon delivers it to a
|
|
112
|
+
pane) wins over every other token source and never falls back when unreadable.
|
|
113
|
+
Omitting `dispatch.serverUrl` while `dispatch.enabled` is true targets
|
|
111
114
|
`http://localhost:8766`, the Go server's listen address. Invalid configuration,
|
|
112
|
-
an invalid URL, or an empty token leaves the twelve tools unavailable and
|
|
113
|
-
the source of the error.
|
|
115
|
+
an invalid URL, or an empty token leaves the twelve tools unavailable and
|
|
116
|
+
reports the source of the error.
|
|
114
117
|
|
|
115
118
|
Owner-scoped calls use either an issue (a native `KEY` or external `owner/repo#n` reference) or
|
|
116
119
|
an unlinked project document (`project` plus its `artifact` slug). A Legion session may omit
|
package/dist/envoy.js
CHANGED
|
@@ -29662,7 +29662,9 @@ var DispatchEventSchema = object({
|
|
|
29662
29662
|
});
|
|
29663
29663
|
var IssueEventPayloadSchema = object({
|
|
29664
29664
|
title: string2().optional(),
|
|
29665
|
+
labels: array(string2()).optional(),
|
|
29665
29666
|
status: string2().optional(),
|
|
29667
|
+
rank: string2().optional(),
|
|
29666
29668
|
route: string2().nullish()
|
|
29667
29669
|
});
|
|
29668
29670
|
var ArtifactCreatedEventPayloadSchema = object({
|
|
@@ -29836,7 +29838,8 @@ var dispatchToolSpecs = [
|
|
|
29836
29838
|
parent: z.string().describe("Optional parent issue.").optional(),
|
|
29837
29839
|
external: z.string().describe("Optional external issue reference.").optional(),
|
|
29838
29840
|
force: z.boolean().describe("Create even though POSSIBLE_DUPLICATE listed similar issues; pass it only after reading them.").optional(),
|
|
29839
|
-
spec: z.string().describe(`Optional initial primary-document markdown. ${SPEC_WRITING_GUIDANCE}`).optional()
|
|
29841
|
+
spec: z.string().describe(`Optional initial primary-document markdown. ${SPEC_WRITING_GUIDANCE}`).optional(),
|
|
29842
|
+
labels: z.array(z.string({ min: 1, max: 40 }), { max: 20 }).describe("Optional initial labels, at most 20 labels of up to 40 characters.").optional()
|
|
29840
29843
|
})
|
|
29841
29844
|
},
|
|
29842
29845
|
{
|
|
@@ -29845,7 +29848,7 @@ var dispatchToolSpecs = [
|
|
|
29845
29848
|
arguments: (z) => ({
|
|
29846
29849
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
29847
29850
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
29848
|
-
artifact: z.string().describe("Project document slug or
|
|
29851
|
+
artifact: z.string().describe("Project document artifact id, slug, or filename.").optional(),
|
|
29849
29852
|
ref: z.string().describe("Optional dispatch:// issue or document reference.").optional(),
|
|
29850
29853
|
question: z.string({ max: 800 }).describe("Decision question, at most 800 characters."),
|
|
29851
29854
|
options: z.array(z.object({
|
|
@@ -29898,7 +29901,7 @@ var dispatchToolSpecs = [
|
|
|
29898
29901
|
arguments: (z) => ({
|
|
29899
29902
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
29900
29903
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
29901
|
-
artifact: z.string().describe("
|
|
29904
|
+
artifact: z.string().describe("Project document artifact id, slug, or filename required when quote is given.").optional(),
|
|
29902
29905
|
ref: z.string().describe("Optional dispatch:// issue or document reference.").optional(),
|
|
29903
29906
|
quote: z.string().describe("Optional exact quoted document text.").optional(),
|
|
29904
29907
|
occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based occurrence of quote.").optional(),
|
|
@@ -29914,7 +29917,7 @@ var dispatchToolSpecs = [
|
|
|
29914
29917
|
arguments: (z) => ({
|
|
29915
29918
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
29916
29919
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
29917
|
-
artifact: z.string().describe("
|
|
29920
|
+
artifact: z.string().describe("Project document artifact id, slug, or filename containing the quoted text; optional when ref names it.").optional(),
|
|
29918
29921
|
ref: z.string().describe("Optional dispatch:// issue or document reference.").optional(),
|
|
29919
29922
|
quote: z.string().describe("Exact document text to replace."),
|
|
29920
29923
|
replace_with: z.string().describe("Replacement text."),
|
|
@@ -29938,7 +29941,7 @@ var dispatchToolSpecs = [
|
|
|
29938
29941
|
arguments: (z) => ({
|
|
29939
29942
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
29940
29943
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
29941
|
-
artifact: z.string().describe("
|
|
29944
|
+
artifact: z.string().describe("Project document artifact id, slug, or filename; optional when ref names it.").optional(),
|
|
29942
29945
|
ref: z.string().describe("Optional dispatch:// issue or document reference.").optional(),
|
|
29943
29946
|
ops: z.array(z.object({
|
|
29944
29947
|
op: z.enum(DOC_EDIT_OPS).describe("Edit operation."),
|
|
@@ -29959,7 +29962,7 @@ var dispatchToolSpecs = [
|
|
|
29959
29962
|
arguments: (z) => ({
|
|
29960
29963
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
29961
29964
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
29962
|
-
artifact: z.string().describe("Optional artifact slug or
|
|
29965
|
+
artifact: z.string().describe("Optional project document artifact id, slug, or filename; primary document by default for an issue.").optional(),
|
|
29963
29966
|
version: z.number({ int: true, min: 1 }).describe("Optional version number.").optional(),
|
|
29964
29967
|
ref: z.string().describe("Optional dispatch:// document reference.").optional()
|
|
29965
29968
|
}),
|
|
@@ -29971,7 +29974,7 @@ var dispatchToolSpecs = [
|
|
|
29971
29974
|
arguments: (z) => ({
|
|
29972
29975
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
29973
29976
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
29974
|
-
artifact: z.string().describe("
|
|
29977
|
+
artifact: z.string().describe("Project document artifact id, slug, or filename; primary document by default for an issue.").optional()
|
|
29975
29978
|
}),
|
|
29976
29979
|
validation: documentOwnerValidation(true)
|
|
29977
29980
|
},
|
|
@@ -30000,7 +30003,7 @@ var dispatchToolSpecs = [
|
|
|
30000
30003
|
arguments: (z) => ({
|
|
30001
30004
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
30002
30005
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
30003
|
-
artifact: z.string().describe("Project document slug or
|
|
30006
|
+
artifact: z.string().describe("Project document artifact id, slug, or filename.").optional(),
|
|
30004
30007
|
ref: z.string().describe("Optional dispatch:// issue or document reference.").optional()
|
|
30005
30008
|
}),
|
|
30006
30009
|
validation: documentOwnerValidation(true)
|
|
@@ -31300,10 +31303,25 @@ function resolveDispatchConfig(env, options = {}) {
|
|
|
31300
31303
|
return { enabled: false, url: null, token: null, error: file.reason };
|
|
31301
31304
|
}
|
|
31302
31305
|
}
|
|
31303
|
-
const
|
|
31304
|
-
|
|
31305
|
-
|
|
31306
|
-
|
|
31306
|
+
const userSettings = userFile.kind === "valid" ? userFile.settings : null;
|
|
31307
|
+
const repoSettings = repoFile.kind === "valid" ? repoFile.settings : null;
|
|
31308
|
+
const merged = { ...userSettings, ...repoSettings };
|
|
31309
|
+
const repoURL = repoSettings?.serverUrl;
|
|
31310
|
+
if (explicitUrl === undefined && merged.enabled === true && repoURL !== undefined) {
|
|
31311
|
+
const token = repoSettings?.token ?? null;
|
|
31312
|
+
if (!token) {
|
|
31313
|
+
return {
|
|
31314
|
+
enabled: false,
|
|
31315
|
+
url: null,
|
|
31316
|
+
token: null,
|
|
31317
|
+
error: "repository dispatch.serverUrl requires dispatch.token from the same .opencode/envoy.json or DISPATCH_URL with DISPATCH_TOKEN"
|
|
31318
|
+
};
|
|
31319
|
+
}
|
|
31320
|
+
const url2 = parsedDispatchUrl(repoURL, "repository dispatch.serverUrl");
|
|
31321
|
+
if (url2.error !== null)
|
|
31322
|
+
return { enabled: false, url: null, token: null, error: url2.error };
|
|
31323
|
+
return { enabled: true, url: url2.url, token, error: null };
|
|
31324
|
+
}
|
|
31307
31325
|
const rawUrl = explicitUrl !== undefined ? { value: explicitUrl, source: "DISPATCH_URL" } : merged.enabled === true ? { value: merged.serverUrl ?? DEFAULT_SERVER_URL, source: "dispatch.serverUrl" } : null;
|
|
31308
31326
|
const url2 = rawUrl ? parsedDispatchUrl(rawUrl.value, rawUrl.source) : { url: null, error: null };
|
|
31309
31327
|
let token;
|
|
@@ -31876,7 +31894,7 @@ async function resolveOwnerArguments(tool, args, cwd, env, exec) {
|
|
|
31876
31894
|
return { args, ref: null, owner: null };
|
|
31877
31895
|
const refArgument = args.ref;
|
|
31878
31896
|
const ref = typeof refArgument === "string" ? parseDispatchRef(refArgument) ?? (() => {
|
|
31879
|
-
throw new Error("ref must be a valid dispatch:// reference such as dispatch://KEY-1, " + "dispatch://KEY-1/ask/<uuid>, dispatch://KEY-1/comment/<uuid>, " + "dispatch://KEY-1/message/<uuid>, dispatch://KEY-1/artifact/<slug>, or " + "dispatch://PROJECT/artifact/<slug
|
|
31897
|
+
throw new Error("ref must be a valid dispatch:// reference such as dispatch://KEY-1, " + "dispatch://KEY-1/ask/<uuid>, dispatch://KEY-1/comment/<uuid>, " + "dispatch://KEY-1/message/<uuid>, dispatch://KEY-1/artifact/<slug>, or " + "dispatch://PROJECT/artifact/<document-ref> (an artifact id, slug, or filename)");
|
|
31880
31898
|
})() : null;
|
|
31881
31899
|
const issueArgument = args.issue;
|
|
31882
31900
|
const projectArgument = args.project;
|
|
@@ -31957,14 +31975,16 @@ async function resolveArtifact(client, owner, artifactReference) {
|
|
|
31957
31975
|
if (!(error instanceof DispatchServiceError) || error.status !== 404)
|
|
31958
31976
|
throw error;
|
|
31959
31977
|
const artifacts = await client.listProjectArtifacts(owner.project, true);
|
|
31960
|
-
const
|
|
31961
|
-
if (
|
|
31962
|
-
|
|
31963
|
-
|
|
31964
|
-
|
|
31965
|
-
|
|
31978
|
+
const artifact = artifacts.find((candidate) => candidate.id === artifactReference) ?? artifacts.find((candidate) => candidate.slug === artifactReference);
|
|
31979
|
+
if (artifact)
|
|
31980
|
+
return { owner, artifact };
|
|
31981
|
+
const names = artifacts.filter((candidate) => candidate.name === artifactReference);
|
|
31982
|
+
if (names.length > 1) {
|
|
31983
|
+
throw new Error(`artifact name ${artifactReference} is ambiguous in project ${owner.project}; ` + `${names.length} documents share it \u2014 use its slug instead`);
|
|
31984
|
+
}
|
|
31985
|
+
if (names[0] === undefined)
|
|
31966
31986
|
throw error;
|
|
31967
|
-
return { owner, artifact };
|
|
31987
|
+
return { owner, artifact: names[0] };
|
|
31968
31988
|
}
|
|
31969
31989
|
}
|
|
31970
31990
|
const issue = await client.getIssue(owner.issue);
|
|
@@ -32015,6 +32035,7 @@ function issueSummary(issue, events, references) {
|
|
|
32015
32035
|
`Title: ${issue.title}`,
|
|
32016
32036
|
`Key: ${issue.key}`,
|
|
32017
32037
|
`Status: ${issue.status}`,
|
|
32038
|
+
`Labels: ${issue.labels.length === 0 ? "none" : issue.labels.join(", ")}`,
|
|
32018
32039
|
`Route: ${issue.route ?? "none"}`,
|
|
32019
32040
|
...specApproval === undefined ? [] : [`Spec ${specApproval.replace(/^Approval/, "approval")}`],
|
|
32020
32041
|
"Open asks:",
|
|
@@ -32147,6 +32168,7 @@ async function executeDispatchTool(input) {
|
|
|
32147
32168
|
const external = optionalString(args, "external");
|
|
32148
32169
|
const force = optionalBoolean(args, "force");
|
|
32149
32170
|
const spec = optionalString(args, "spec");
|
|
32171
|
+
const labels = args.labels;
|
|
32150
32172
|
try {
|
|
32151
32173
|
const created = await client.issue({
|
|
32152
32174
|
project,
|
|
@@ -32155,6 +32177,7 @@ async function executeDispatchTool(input) {
|
|
|
32155
32177
|
...external === undefined ? {} : { external },
|
|
32156
32178
|
...force === undefined ? {} : { force },
|
|
32157
32179
|
...spec === undefined ? {} : { spec },
|
|
32180
|
+
...Array.isArray(labels) ? { labels } : {},
|
|
32158
32181
|
actor
|
|
32159
32182
|
});
|
|
32160
32183
|
return {
|
package/dist/legion.js
CHANGED
|
@@ -29661,7 +29661,9 @@ var DispatchEventSchema = object({
|
|
|
29661
29661
|
});
|
|
29662
29662
|
var IssueEventPayloadSchema = object({
|
|
29663
29663
|
title: string2().optional(),
|
|
29664
|
+
labels: array(string2()).optional(),
|
|
29664
29665
|
status: string2().optional(),
|
|
29666
|
+
rank: string2().optional(),
|
|
29665
29667
|
route: string2().nullish()
|
|
29666
29668
|
});
|
|
29667
29669
|
var ArtifactCreatedEventPayloadSchema = object({
|
|
@@ -29835,7 +29837,8 @@ var dispatchToolSpecs = [
|
|
|
29835
29837
|
parent: z.string().describe("Optional parent issue.").optional(),
|
|
29836
29838
|
external: z.string().describe("Optional external issue reference.").optional(),
|
|
29837
29839
|
force: z.boolean().describe("Create even though POSSIBLE_DUPLICATE listed similar issues; pass it only after reading them.").optional(),
|
|
29838
|
-
spec: z.string().describe(`Optional initial primary-document markdown. ${SPEC_WRITING_GUIDANCE}`).optional()
|
|
29840
|
+
spec: z.string().describe(`Optional initial primary-document markdown. ${SPEC_WRITING_GUIDANCE}`).optional(),
|
|
29841
|
+
labels: z.array(z.string({ min: 1, max: 40 }), { max: 20 }).describe("Optional initial labels, at most 20 labels of up to 40 characters.").optional()
|
|
29839
29842
|
})
|
|
29840
29843
|
},
|
|
29841
29844
|
{
|
|
@@ -29844,7 +29847,7 @@ var dispatchToolSpecs = [
|
|
|
29844
29847
|
arguments: (z) => ({
|
|
29845
29848
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
29846
29849
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
29847
|
-
artifact: z.string().describe("Project document slug or
|
|
29850
|
+
artifact: z.string().describe("Project document artifact id, slug, or filename.").optional(),
|
|
29848
29851
|
ref: z.string().describe("Optional dispatch:// issue or document reference.").optional(),
|
|
29849
29852
|
question: z.string({ max: 800 }).describe("Decision question, at most 800 characters."),
|
|
29850
29853
|
options: z.array(z.object({
|
|
@@ -29897,7 +29900,7 @@ var dispatchToolSpecs = [
|
|
|
29897
29900
|
arguments: (z) => ({
|
|
29898
29901
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
29899
29902
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
29900
|
-
artifact: z.string().describe("
|
|
29903
|
+
artifact: z.string().describe("Project document artifact id, slug, or filename required when quote is given.").optional(),
|
|
29901
29904
|
ref: z.string().describe("Optional dispatch:// issue or document reference.").optional(),
|
|
29902
29905
|
quote: z.string().describe("Optional exact quoted document text.").optional(),
|
|
29903
29906
|
occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based occurrence of quote.").optional(),
|
|
@@ -29913,7 +29916,7 @@ var dispatchToolSpecs = [
|
|
|
29913
29916
|
arguments: (z) => ({
|
|
29914
29917
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
29915
29918
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
29916
|
-
artifact: z.string().describe("
|
|
29919
|
+
artifact: z.string().describe("Project document artifact id, slug, or filename containing the quoted text; optional when ref names it.").optional(),
|
|
29917
29920
|
ref: z.string().describe("Optional dispatch:// issue or document reference.").optional(),
|
|
29918
29921
|
quote: z.string().describe("Exact document text to replace."),
|
|
29919
29922
|
replace_with: z.string().describe("Replacement text."),
|
|
@@ -29937,7 +29940,7 @@ var dispatchToolSpecs = [
|
|
|
29937
29940
|
arguments: (z) => ({
|
|
29938
29941
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
29939
29942
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
29940
|
-
artifact: z.string().describe("
|
|
29943
|
+
artifact: z.string().describe("Project document artifact id, slug, or filename; optional when ref names it.").optional(),
|
|
29941
29944
|
ref: z.string().describe("Optional dispatch:// issue or document reference.").optional(),
|
|
29942
29945
|
ops: z.array(z.object({
|
|
29943
29946
|
op: z.enum(DOC_EDIT_OPS).describe("Edit operation."),
|
|
@@ -29958,7 +29961,7 @@ var dispatchToolSpecs = [
|
|
|
29958
29961
|
arguments: (z) => ({
|
|
29959
29962
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
29960
29963
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
29961
|
-
artifact: z.string().describe("Optional artifact slug or
|
|
29964
|
+
artifact: z.string().describe("Optional project document artifact id, slug, or filename; primary document by default for an issue.").optional(),
|
|
29962
29965
|
version: z.number({ int: true, min: 1 }).describe("Optional version number.").optional(),
|
|
29963
29966
|
ref: z.string().describe("Optional dispatch:// document reference.").optional()
|
|
29964
29967
|
}),
|
|
@@ -29970,7 +29973,7 @@ var dispatchToolSpecs = [
|
|
|
29970
29973
|
arguments: (z) => ({
|
|
29971
29974
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
29972
29975
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
29973
|
-
artifact: z.string().describe("
|
|
29976
|
+
artifact: z.string().describe("Project document artifact id, slug, or filename; primary document by default for an issue.").optional()
|
|
29974
29977
|
}),
|
|
29975
29978
|
validation: documentOwnerValidation(true)
|
|
29976
29979
|
},
|
|
@@ -29999,7 +30002,7 @@ var dispatchToolSpecs = [
|
|
|
29999
30002
|
arguments: (z) => ({
|
|
30000
30003
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
30001
30004
|
project: z.string().describe("Project key owning the document.").optional(),
|
|
30002
|
-
artifact: z.string().describe("Project document slug or
|
|
30005
|
+
artifact: z.string().describe("Project document artifact id, slug, or filename.").optional(),
|
|
30003
30006
|
ref: z.string().describe("Optional dispatch:// issue or document reference.").optional()
|
|
30004
30007
|
}),
|
|
30005
30008
|
validation: documentOwnerValidation(true)
|
|
@@ -31726,10 +31729,25 @@ function resolveDispatchConfig(env, options = {}) {
|
|
|
31726
31729
|
return { enabled: false, url: null, token: null, error: file.reason };
|
|
31727
31730
|
}
|
|
31728
31731
|
}
|
|
31729
|
-
const
|
|
31730
|
-
|
|
31731
|
-
|
|
31732
|
-
|
|
31732
|
+
const userSettings = userFile.kind === "valid" ? userFile.settings : null;
|
|
31733
|
+
const repoSettings = repoFile.kind === "valid" ? repoFile.settings : null;
|
|
31734
|
+
const merged = { ...userSettings, ...repoSettings };
|
|
31735
|
+
const repoURL = repoSettings?.serverUrl;
|
|
31736
|
+
if (explicitUrl === undefined && merged.enabled === true && repoURL !== undefined) {
|
|
31737
|
+
const token = repoSettings?.token ?? null;
|
|
31738
|
+
if (!token) {
|
|
31739
|
+
return {
|
|
31740
|
+
enabled: false,
|
|
31741
|
+
url: null,
|
|
31742
|
+
token: null,
|
|
31743
|
+
error: "repository dispatch.serverUrl requires dispatch.token from the same .opencode/envoy.json or DISPATCH_URL with DISPATCH_TOKEN"
|
|
31744
|
+
};
|
|
31745
|
+
}
|
|
31746
|
+
const url2 = parsedDispatchUrl(repoURL, "repository dispatch.serverUrl");
|
|
31747
|
+
if (url2.error !== null)
|
|
31748
|
+
return { enabled: false, url: null, token: null, error: url2.error };
|
|
31749
|
+
return { enabled: true, url: url2.url, token, error: null };
|
|
31750
|
+
}
|
|
31733
31751
|
const rawUrl = explicitUrl !== undefined ? { value: explicitUrl, source: "DISPATCH_URL" } : merged.enabled === true ? { value: merged.serverUrl ?? DEFAULT_SERVER_URL, source: "dispatch.serverUrl" } : null;
|
|
31734
31752
|
const url2 = rawUrl ? parsedDispatchUrl(rawUrl.value, rawUrl.source) : { url: null, error: null };
|
|
31735
31753
|
let token;
|
|
@@ -32302,7 +32320,7 @@ async function resolveOwnerArguments(tool, args, cwd, env, exec) {
|
|
|
32302
32320
|
return { args, ref: null, owner: null };
|
|
32303
32321
|
const refArgument = args.ref;
|
|
32304
32322
|
const ref = typeof refArgument === "string" ? parseDispatchRef(refArgument) ?? (() => {
|
|
32305
|
-
throw new Error("ref must be a valid dispatch:// reference such as dispatch://KEY-1, " + "dispatch://KEY-1/ask/<uuid>, dispatch://KEY-1/comment/<uuid>, " + "dispatch://KEY-1/message/<uuid>, dispatch://KEY-1/artifact/<slug>, or " + "dispatch://PROJECT/artifact/<slug
|
|
32323
|
+
throw new Error("ref must be a valid dispatch:// reference such as dispatch://KEY-1, " + "dispatch://KEY-1/ask/<uuid>, dispatch://KEY-1/comment/<uuid>, " + "dispatch://KEY-1/message/<uuid>, dispatch://KEY-1/artifact/<slug>, or " + "dispatch://PROJECT/artifact/<document-ref> (an artifact id, slug, or filename)");
|
|
32306
32324
|
})() : null;
|
|
32307
32325
|
const issueArgument = args.issue;
|
|
32308
32326
|
const projectArgument = args.project;
|
|
@@ -32383,14 +32401,16 @@ async function resolveArtifact(client, owner, artifactReference) {
|
|
|
32383
32401
|
if (!(error instanceof DispatchServiceError) || error.status !== 404)
|
|
32384
32402
|
throw error;
|
|
32385
32403
|
const artifacts = await client.listProjectArtifacts(owner.project, true);
|
|
32386
|
-
const
|
|
32387
|
-
if (
|
|
32388
|
-
|
|
32389
|
-
|
|
32390
|
-
|
|
32391
|
-
|
|
32404
|
+
const artifact = artifacts.find((candidate) => candidate.id === artifactReference) ?? artifacts.find((candidate) => candidate.slug === artifactReference);
|
|
32405
|
+
if (artifact)
|
|
32406
|
+
return { owner, artifact };
|
|
32407
|
+
const names = artifacts.filter((candidate) => candidate.name === artifactReference);
|
|
32408
|
+
if (names.length > 1) {
|
|
32409
|
+
throw new Error(`artifact name ${artifactReference} is ambiguous in project ${owner.project}; ` + `${names.length} documents share it \u2014 use its slug instead`);
|
|
32410
|
+
}
|
|
32411
|
+
if (names[0] === undefined)
|
|
32392
32412
|
throw error;
|
|
32393
|
-
return { owner, artifact };
|
|
32413
|
+
return { owner, artifact: names[0] };
|
|
32394
32414
|
}
|
|
32395
32415
|
}
|
|
32396
32416
|
const issue = await client.getIssue(owner.issue);
|
|
@@ -32441,6 +32461,7 @@ function issueSummary(issue, events, references) {
|
|
|
32441
32461
|
`Title: ${issue.title}`,
|
|
32442
32462
|
`Key: ${issue.key}`,
|
|
32443
32463
|
`Status: ${issue.status}`,
|
|
32464
|
+
`Labels: ${issue.labels.length === 0 ? "none" : issue.labels.join(", ")}`,
|
|
32444
32465
|
`Route: ${issue.route ?? "none"}`,
|
|
32445
32466
|
...specApproval === undefined ? [] : [`Spec ${specApproval.replace(/^Approval/, "approval")}`],
|
|
32446
32467
|
"Open asks:",
|
|
@@ -32573,6 +32594,7 @@ async function executeDispatchTool(input) {
|
|
|
32573
32594
|
const external = optionalString(args, "external");
|
|
32574
32595
|
const force = optionalBoolean(args, "force");
|
|
32575
32596
|
const spec = optionalString(args, "spec");
|
|
32597
|
+
const labels = args.labels;
|
|
32576
32598
|
try {
|
|
32577
32599
|
const created = await client.issue({
|
|
32578
32600
|
project,
|
|
@@ -32581,6 +32603,7 @@ async function executeDispatchTool(input) {
|
|
|
32581
32603
|
...external === undefined ? {} : { external },
|
|
32582
32604
|
...force === undefined ? {} : { force },
|
|
32583
32605
|
...spec === undefined ? {} : { spec },
|
|
32606
|
+
...Array.isArray(labels) ? { labels } : {},
|
|
32584
32607
|
actor
|
|
32585
32608
|
});
|
|
32586
32609
|
return {
|
|
@@ -72,12 +72,15 @@ exactly one owner to every owner-scoped tool: `issue` for an issue, or `project`
|
|
|
72
72
|
[References](#references) for the resulting ref shape). On first use, an external issue reference creates its native issue in the
|
|
73
73
|
project configured for that repository in Dispatch Settings, then falls back to `DISPATCH_DEFAULT_PROJECT`.
|
|
74
74
|
|
|
75
|
+
Issue reads include `rank`, the server-owned ordering key used by project boards; reorder through `PATCH /api/v1/issues/{key}` with neighboring issue keys rather than writing a priority value.
|
|
76
|
+
|
|
75
77
|
Architects create newly tracked child work with:
|
|
76
78
|
```ts
|
|
77
|
-
dispatch_issue({ project, title, parent?, external?, spec?, force
|
|
79
|
+
dispatch_issue({ project, title, parent?, external?, spec?, force?, labels?: string[] })
|
|
78
80
|
```
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
`labels` are optional initial labels: Dispatch trims them, preserves their case, and removes case-insensitive duplicates. It returns
|
|
82
|
+
`details` `{ issue, topic }`. Use `dispatch_issue` only to create an issue; never use it to park a question. When `spec` is supplied,
|
|
83
|
+
follow [Writing a spec](#writing-a-spec).
|
|
81
84
|
|
|
82
85
|
## Search first
|
|
83
86
|
|
|
@@ -186,7 +189,7 @@ Read the current document before changing it:
|
|
|
186
189
|
dispatch_doc_read({ issue?, project?, artifact?, version?, ref? })
|
|
187
190
|
```
|
|
188
191
|
It returns live or versioned markdown with open marks. `issue` with an omitted `artifact` reads the issue specification; a project needs
|
|
189
|
-
`artifact`; and a `dispatch://PROJECT/artifact/<
|
|
192
|
+
`artifact`; and a `dispatch://PROJECT/artifact/<document-ref>` ref supplies both, where `document-ref` is the id, slug, or filename.
|
|
190
193
|
|
|
191
194
|
```ts
|
|
192
195
|
dispatch_doc_edit({ issue?, project?, artifact, ops, summary? })
|
|
@@ -264,7 +267,8 @@ Exactly one of `issue` and `project` is required. A project upload creates an un
|
|
|
264
267
|
Exactly one of `path` and `content` is required. It returns issue or project-document owner details plus `artifact`, `version`, and its
|
|
265
268
|
write `topic`. Uploading the same `name` creates its next version — so uploading `spec.md` **replaces the issue's own specification**
|
|
266
269
|
with your text. Never do that: the spec is edited in place with `dispatch_doc_edit` (see [The Spec](#the-spec)). Address an existing
|
|
267
|
-
artifact by the slug shown in the upload result or by its filename
|
|
270
|
+
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
|
|
271
|
+
slug also arrives on `artifact.created` events.
|
|
268
272
|
|
|
269
273
|
## Messages
|
|
270
274
|
|
|
@@ -313,9 +317,9 @@ dispatch://KEY/artifact/<slug>[@vN]
|
|
|
313
317
|
dispatch://KEY/ask/<id>
|
|
314
318
|
dispatch://KEY/comment/<id>
|
|
315
319
|
dispatch://KEY/message/<id>
|
|
316
|
-
dispatch://PROJECT/artifact/<
|
|
317
|
-
dispatch://PROJECT/artifact/<
|
|
318
|
-
dispatch://PROJECT/artifact/<
|
|
320
|
+
dispatch://PROJECT/artifact/<document-ref>[@vN]
|
|
321
|
+
dispatch://PROJECT/artifact/<document-ref>/ask/<id>
|
|
322
|
+
dispatch://PROJECT/artifact/<document-ref>/comment/<id>
|
|
319
323
|
```
|
|
320
324
|
|
|
321
325
|
A bare UUID or `KEY#seq` is not a reference; the `dispatch://` form is what Dispatch links and records.
|