@sjawhar/pi-legion-envoy 1.51.1 → 1.52.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 +219 -32
- package/dist/legion.js +86 -3
- package/package.json +1 -1
package/dist/envoy.js
CHANGED
|
@@ -29726,6 +29726,24 @@ var AskEditedEventPayloadSchema = object({
|
|
|
29726
29726
|
}),
|
|
29727
29727
|
edited_by: object({ kind: string2(), id: string2() }).passthrough()
|
|
29728
29728
|
});
|
|
29729
|
+
var CommentMentionSchema = object({
|
|
29730
|
+
target: string2(),
|
|
29731
|
+
delivery: _enum2(DELIVERY_CAPABILITIES),
|
|
29732
|
+
session_id: string2().nullable()
|
|
29733
|
+
});
|
|
29734
|
+
var CommentDeliverySchema = object({
|
|
29735
|
+
comment_id: string2(),
|
|
29736
|
+
target: string2(),
|
|
29737
|
+
attempt: number2().int().positive(),
|
|
29738
|
+
delivery: _enum2(DELIVERY_CAPABILITIES),
|
|
29739
|
+
session_id: string2().nullable(),
|
|
29740
|
+
envelope_id: string2().nullable(),
|
|
29741
|
+
state: _enum2(["pending", "sent", "failed"]),
|
|
29742
|
+
error: string2().nullable(),
|
|
29743
|
+
resolve_error: string2().nullable(),
|
|
29744
|
+
reply_id: string2().nullable(),
|
|
29745
|
+
created_at: string2()
|
|
29746
|
+
});
|
|
29729
29747
|
var CommentEventPayloadSchema = object({
|
|
29730
29748
|
id: string2().optional(),
|
|
29731
29749
|
artifact_name: string2().optional(),
|
|
@@ -29741,7 +29759,9 @@ var CommentEventPayloadSchema = object({
|
|
|
29741
29759
|
anchor: object({ block_id: string2().nullable().optional(), quote: string2().optional() }).nullish(),
|
|
29742
29760
|
suggestion: object({ replace_with: string2().optional() }).nullish(),
|
|
29743
29761
|
author: object({ kind: string2(), id: string2() }).optional(),
|
|
29744
|
-
created_at: string2().optional()
|
|
29762
|
+
created_at: string2().optional(),
|
|
29763
|
+
mentions: array(CommentMentionSchema).optional(),
|
|
29764
|
+
deliveries: array(CommentDeliverySchema).optional()
|
|
29745
29765
|
});
|
|
29746
29766
|
var MessageEventPayloadSchema = object({
|
|
29747
29767
|
id: string2().optional(),
|
|
@@ -29751,8 +29771,9 @@ var MessageEventPayloadSchema = object({
|
|
|
29751
29771
|
reply_body: string2().optional(),
|
|
29752
29772
|
author: object({ kind: string2(), id: string2() }).optional()
|
|
29753
29773
|
});
|
|
29774
|
+
var DispatchTargetedResourceIDSchema = uuid2();
|
|
29754
29775
|
var DispatchTargetedMessagePayloadSchema = MessageEventPayloadSchema.extend({
|
|
29755
|
-
id:
|
|
29776
|
+
id: DispatchTargetedResourceIDSchema,
|
|
29756
29777
|
issue_key: string2().nullable(),
|
|
29757
29778
|
author: object({ kind: string2(), id: string2() }),
|
|
29758
29779
|
body: string2(),
|
|
@@ -29761,6 +29782,31 @@ var DispatchTargetedMessagePayloadSchema = MessageEventPayloadSchema.extend({
|
|
|
29761
29782
|
deliveries: array(unknown()),
|
|
29762
29783
|
created_at: string2()
|
|
29763
29784
|
});
|
|
29785
|
+
var DispatchTargetedCommentPayloadSchema = CommentEventPayloadSchema.extend({
|
|
29786
|
+
id: DispatchTargetedResourceIDSchema,
|
|
29787
|
+
issue_key: string2().nullable(),
|
|
29788
|
+
artifact_id: string2().nullable(),
|
|
29789
|
+
author: object({ kind: string2(), id: string2() }),
|
|
29790
|
+
body: string2(),
|
|
29791
|
+
reply_to: string2().nullable(),
|
|
29792
|
+
ask_id: string2().nullable(),
|
|
29793
|
+
mentions: array(CommentMentionSchema),
|
|
29794
|
+
deliveries: array(CommentDeliverySchema),
|
|
29795
|
+
created_at: string2(),
|
|
29796
|
+
artifact_name: string2()
|
|
29797
|
+
});
|
|
29798
|
+
var DispatchTargetedMessageDeliverySchema = object({
|
|
29799
|
+
attempt: number2().int().positive(),
|
|
29800
|
+
mode: _enum2(DELIVERY_CAPABILITIES)
|
|
29801
|
+
});
|
|
29802
|
+
var DispatchTargetedCommentDeliverySchema = DispatchTargetedMessageDeliverySchema.extend({
|
|
29803
|
+
comment_id: DispatchTargetedResourceIDSchema,
|
|
29804
|
+
target: string2()
|
|
29805
|
+
});
|
|
29806
|
+
var DispatchTargetedDeliverySchema = union([
|
|
29807
|
+
DispatchTargetedCommentDeliverySchema,
|
|
29808
|
+
DispatchTargetedMessageDeliverySchema
|
|
29809
|
+
]);
|
|
29764
29810
|
var MessageDeliveryEventPayloadSchema = object({
|
|
29765
29811
|
message_id: string2().optional(),
|
|
29766
29812
|
attempt: number2().int().positive().optional(),
|
|
@@ -29908,6 +29954,7 @@ var DOC_EDIT_OPS = ["replace", "delete", "insert", "retype", "move"];
|
|
|
29908
29954
|
var dispatchToolSpecs = [
|
|
29909
29955
|
{
|
|
29910
29956
|
name: "dispatch_issue",
|
|
29957
|
+
example: { project: "DSP", title: "Native workspace" },
|
|
29911
29958
|
description: "Create a native Dispatch issue for newly tracked work. Search first with dispatch_search; if potentially duplicate issues exist, this returns 409 POSSIBLE_DUPLICATE unless force is true after reading them. " + `Do not use it when an existing issue already covers the work; read or update that issue instead. ${ISSUE_REFERENCE}`,
|
|
29912
29959
|
arguments: (z) => ({
|
|
29913
29960
|
project: z.string().describe("Project key for the new issue."),
|
|
@@ -29924,6 +29971,7 @@ var dispatchToolSpecs = [
|
|
|
29924
29971
|
},
|
|
29925
29972
|
{
|
|
29926
29973
|
name: "dispatch_issue_update",
|
|
29974
|
+
example: { issue: "DSP-1", status: "in_progress" },
|
|
29927
29975
|
description: "Update an existing issue: move its lifecycle status, retitle it, replace its labels, link a URL " + "(the pull request that delivers it, a run, a document), set its route, set or clear its parent, " + "or attach it to architecture components. Status is one of " + `${ISSUE_STATUSES.join(", ")}; outside Legion, move it yourself as the work advances; inside ` + "Legion the daemon moves it. external_links are " + "merged into the issue's existing links by URL, so linking the pull request you just opened " + "keeps every earlier link. components replaces the issue's own attachment and is allowed on a " + "closed issue. Priority is the human's and is not settable here. At least one " + `field besides issue is required. ${ISSUE_REFERENCE}`,
|
|
29928
29976
|
arguments: (z) => ({
|
|
29929
29977
|
issue: z.string().describe(ISSUE_REFERENCE),
|
|
@@ -29946,6 +29994,7 @@ var dispatchToolSpecs = [
|
|
|
29946
29994
|
},
|
|
29947
29995
|
{
|
|
29948
29996
|
name: "dispatch_ask",
|
|
29997
|
+
example: { issue: "DSP-1", question: "Ship this?" },
|
|
29949
29998
|
description: "Open a durable, answerable decision on an issue or project document. Do not use it for a status update or discussion; " + "use dispatch_message instead. A to-do a human must complete is a question phrased as that to-do, with the options you want (for example Done / Can't). " + "Anchor a document question, thread reply_to/reply_to_ask, or cite a dispatch:// " + `reference \u2014 it must be answerable from its own text and anchor alone, never "see above". A quote anchor is pinned to its block. Question is at most ${ASK_QUESTION_MAX} ` + `characters and has at most 8 options. ${OWNER_REFERENCE}`,
|
|
29950
29999
|
arguments: (z) => ({
|
|
29951
30000
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -29969,6 +30018,10 @@ var dispatchToolSpecs = [
|
|
|
29969
30018
|
},
|
|
29970
30019
|
{
|
|
29971
30020
|
name: "dispatch_edit_ask",
|
|
30021
|
+
example: {
|
|
30022
|
+
ask: "01234567-0000-4000-8000-000000000001",
|
|
30023
|
+
question: "Ship the revised plan?"
|
|
30024
|
+
},
|
|
29972
30025
|
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.",
|
|
29973
30026
|
arguments: (z) => ({
|
|
29974
30027
|
ask: z.string().describe("Ask id to edit."),
|
|
@@ -29990,6 +30043,11 @@ var dispatchToolSpecs = [
|
|
|
29990
30043
|
},
|
|
29991
30044
|
{
|
|
29992
30045
|
name: "dispatch_resolve_ask",
|
|
30046
|
+
example: {
|
|
30047
|
+
ask: "01234567-0000-4000-8000-000000000001",
|
|
30048
|
+
kind: "retracted",
|
|
30049
|
+
reason: "A newer question supersedes this one."
|
|
30050
|
+
},
|
|
29993
30051
|
description: "Retract an open question that is moot or resolve one after finding the answer. This closes the question without answering it.",
|
|
29994
30052
|
arguments: (z) => ({
|
|
29995
30053
|
ask: z.string().describe("Ask id to close."),
|
|
@@ -29999,6 +30057,7 @@ var dispatchToolSpecs = [
|
|
|
29999
30057
|
},
|
|
30000
30058
|
{
|
|
30001
30059
|
name: "dispatch_resolve_comment",
|
|
30060
|
+
example: { comment: "01234567-0000-4000-8000-000000000001" },
|
|
30002
30061
|
description: "Resolve a review comment thread once it has been addressed - typically your own comment " + "after the document was fixed. Any session or human may resolve any open comment on an " + "open issue or project document; reopening a resolved comment is human-only (the dashboard). " + "Not for asks: use dispatch_resolve_ask.",
|
|
30003
30062
|
arguments: (z) => ({
|
|
30004
30063
|
comment: z.string().describe("Comment id (uuid), or a dispatch://KEY/comment/<id> or " + "dispatch://PROJECT/artifact/<slug>/comment/<id> reference; a reference accepts an " + "8+ character id prefix that is unique on its owner.")
|
|
@@ -30007,6 +30066,7 @@ var dispatchToolSpecs = [
|
|
|
30007
30066
|
},
|
|
30008
30067
|
{
|
|
30009
30068
|
name: "dispatch_follow",
|
|
30069
|
+
example: { ask: "01234567-0000-4000-8000-000000000001", action: "follow" },
|
|
30010
30070
|
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>.>",
|
|
30011
30071
|
arguments: (z) => ({
|
|
30012
30072
|
ask: z.string().describe("Full ask id (uuid)."),
|
|
@@ -30016,6 +30076,7 @@ var dispatchToolSpecs = [
|
|
|
30016
30076
|
},
|
|
30017
30077
|
{
|
|
30018
30078
|
name: "dispatch_comment",
|
|
30079
|
+
example: { issue: "DSP-1", body: "Looks good." },
|
|
30019
30080
|
description: "Add review feedback to an issue or project document quote, or reply to a question asked with dispatch_ask. " + "Do not use it for an exact replacement; use " + `dispatch_suggest instead. A quote anchor is pinned to its block. Body is at most 2,000 characters. ${OWNER_REFERENCE}`,
|
|
30020
30081
|
arguments: (z) => ({
|
|
30021
30082
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -30033,6 +30094,12 @@ var dispatchToolSpecs = [
|
|
|
30033
30094
|
},
|
|
30034
30095
|
{
|
|
30035
30096
|
name: "dispatch_suggest",
|
|
30097
|
+
example: {
|
|
30098
|
+
issue: "DSP-1",
|
|
30099
|
+
artifact: "spec",
|
|
30100
|
+
quote: "old wording",
|
|
30101
|
+
replace_with: "new wording"
|
|
30102
|
+
},
|
|
30036
30103
|
description: "Propose an exact replacement for quoted document text. Do not use it for general feedback; use " + `dispatch_comment instead. Optional explanation is at most 2,000 characters. ${OWNER_REFERENCE}`,
|
|
30037
30104
|
arguments: (z) => ({
|
|
30038
30105
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -30048,6 +30115,7 @@ var dispatchToolSpecs = [
|
|
|
30048
30115
|
},
|
|
30049
30116
|
{
|
|
30050
30117
|
name: "dispatch_message",
|
|
30118
|
+
example: { issue: "DSP-1", body: "Implementation started." },
|
|
30051
30119
|
description: "Post a note humans must read now: a reply to a human's message, a deliverable that landed, or a blocker only " + "they can clear. Never progress or status updates - Dispatch is a high-signal record, not a log. Not a decision " + `(dispatch_ask) or document feedback (dispatch_comment). Body is at most 2,000 characters. ${ISSUE_REFERENCE}`,
|
|
30052
30120
|
arguments: (z) => ({
|
|
30053
30121
|
issue: z.string().describe(ISSUE_REFERENCE),
|
|
@@ -30057,6 +30125,11 @@ var dispatchToolSpecs = [
|
|
|
30057
30125
|
},
|
|
30058
30126
|
{
|
|
30059
30127
|
name: "dispatch_doc_edit",
|
|
30128
|
+
example: {
|
|
30129
|
+
issue: "DSP-1",
|
|
30130
|
+
artifact: "spec",
|
|
30131
|
+
ops: [{ op: "replace", find: "old", with: "new" }]
|
|
30132
|
+
},
|
|
30060
30133
|
description: "Apply deterministic document edits: replace or delete quoted text, insert markdown at an anchor, retype an identified paragraph or typed block into a schema-declared typed block, and delete or move a whole block by its id. " + "Do not use it for review feedback or for reading; use dispatch_comment, dispatch_suggest, or dispatch_doc_read instead. " + "For replace, delete, and quote anchors, find text as rendered: inline Markdown (**bold**, `code`) is tolerated; a leading '# ' matches a heading. replace is inline: with is the new text of the matched span, so a leading list or heading marker stays literal text. " + "A delete whose find is a block's entire text removes the block (a list emptied of its items goes too); delete with block removes any block by id, and move with block relocates one. " + 'Insert and move anchors also accept "start", "end", "heading:<exact heading text>", and "block:<id>"; block ids are the #id of a typed block or a row of GET /api/v1/artifacts/{id}/blocks. ' + `The spec (or any document) holds requirements, design, and decisions - never progress, status, or timestamps. ${OWNER_REFERENCE} ${SPEC_WRITING_GUIDANCE}`,
|
|
30061
30134
|
arguments: (z) => ({
|
|
30062
30135
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -30081,6 +30154,7 @@ var dispatchToolSpecs = [
|
|
|
30081
30154
|
},
|
|
30082
30155
|
{
|
|
30083
30156
|
name: "dispatch_doc_read",
|
|
30157
|
+
example: { issue: "DSP-1" },
|
|
30084
30158
|
description: "Read a live document or a named document version. Do not use it for issue status, asks, or events; " + "use dispatch_read instead. Supply ref, issue, or project plus artifact; issue plus an omitted artifact reads the primary document. " + OWNER_REFERENCE,
|
|
30085
30159
|
arguments: (z) => ({
|
|
30086
30160
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -30093,6 +30167,7 @@ var dispatchToolSpecs = [
|
|
|
30093
30167
|
},
|
|
30094
30168
|
{
|
|
30095
30169
|
name: "dispatch_request_approval",
|
|
30170
|
+
example: { issue: "DSP-1" },
|
|
30096
30171
|
description: "Ask a human to approve a document at its current version - the exception path for a spec " + "that departs from what was settled or proposes children, not a step for every issue. Opens an " + "approval ask (Approve / Request changes) in the human's Inbox; the answer pins a review to the " + "document version and arrives as artifact.approved or artifact.changes_requested. A later edit " + "makes an approval stale; request again for the new version. Idempotent while a request is open. " + OWNER_REFERENCE,
|
|
30097
30172
|
arguments: (z) => ({
|
|
30098
30173
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -30103,6 +30178,8 @@ var dispatchToolSpecs = [
|
|
|
30103
30178
|
},
|
|
30104
30179
|
{
|
|
30105
30180
|
name: "dispatch_artifact",
|
|
30181
|
+
example: { issue: "DSP-1", name: "design.md", content: `# Design
|
|
30182
|
+
` },
|
|
30106
30183
|
description: "Attach a local file or inline text as an issue artifact or project document. Do not use it to edit a live document; use " + `dispatch_doc_edit instead. Exactly one of path or content is required; artifacts are limited to 25 MiB. ${OWNER_REFERENCE}`,
|
|
30107
30184
|
arguments: (z) => ({
|
|
30108
30185
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -30122,6 +30199,7 @@ var dispatchToolSpecs = [
|
|
|
30122
30199
|
},
|
|
30123
30200
|
{
|
|
30124
30201
|
name: "dispatch_read",
|
|
30202
|
+
example: { issue: "DSP-1" },
|
|
30125
30203
|
description: "Read an issue or project-document summary, targeted ask, or targeted comment reply chain. Do not use it for document " + "contents; use dispatch_doc_read instead. Supply ref, issue, or project plus artifact. " + "Every read ends with `Referenced by:` (what cites or hangs off this node, each with its dispatch:// address, " + "an excerpt, and when) and `Links:` (what it cites), so tracing provenance is one call. " + OWNER_REFERENCE,
|
|
30126
30204
|
arguments: (z) => ({
|
|
30127
30205
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -30133,6 +30211,7 @@ var dispatchToolSpecs = [
|
|
|
30133
30211
|
},
|
|
30134
30212
|
{
|
|
30135
30213
|
name: "dispatch_search",
|
|
30214
|
+
example: { query: "astrolabe" },
|
|
30136
30215
|
description: "Search every issue, document, comment, ask, and message for a keyword or phrase and get deep links. " + "Use it before creating an issue or a design document, and to find where a word was written. " + 'Websearch syntax: "quoted phrase", -excluded, OR.',
|
|
30137
30216
|
arguments: (z) => ({
|
|
30138
30217
|
query: z.string({ min: 2 }).describe("Keyword, phrase, or websearch expression; at least 2 characters."),
|
|
@@ -30142,6 +30221,7 @@ var dispatchToolSpecs = [
|
|
|
30142
30221
|
},
|
|
30143
30222
|
{
|
|
30144
30223
|
name: "dispatch_issues",
|
|
30224
|
+
example: { project: "AGENTC" },
|
|
30145
30225
|
description: "List a project's issues for a roadmap or backlog pass: every issue in one project, each carrying " + "its status, priority, parent, labels, and open-ask count, so you can see backlog shape without " + "opening every issue. Optionally filter by status, parent, label, or how recently it changed. Do " + "not use it to search by keyword or phrase; dispatch_search remains the keyword surface. Rows are " + "capped at limit (default 50, max 250), applied to the response here, not by the server.",
|
|
30146
30226
|
arguments: (z) => ({
|
|
30147
30227
|
project: z.string().describe("Project key to list issues from."),
|
|
@@ -30154,6 +30234,7 @@ var dispatchToolSpecs = [
|
|
|
30154
30234
|
},
|
|
30155
30235
|
{
|
|
30156
30236
|
name: "dispatch_architecture_sync",
|
|
30237
|
+
example: { project: "CORE" },
|
|
30157
30238
|
description: "Import a project's architecture model from its configured source repository now, instead of " + "waiting for the server's five-minute schedule. Returns the imported commit and component " + "count, or the recorded error when the model was rejected (the previous model stays up). " + "The source itself is configured by a human in Settings; 404 SOURCE_NOT_FOUND without one.",
|
|
30158
30239
|
arguments: (z) => ({
|
|
30159
30240
|
project: z.string().describe("Project key whose architecture source to sync, such as CORE.")
|
|
@@ -30162,6 +30243,7 @@ var dispatchToolSpecs = [
|
|
|
30162
30243
|
},
|
|
30163
30244
|
{
|
|
30164
30245
|
name: "dispatch_open_asks",
|
|
30246
|
+
example: {},
|
|
30165
30247
|
description: "List active unanswered asks, oldest first, with age and whose reply is needed. Omit project to " + "see only this session's own authored asks (call before saying you are waiting for human input); " + "supply project to see every open ask across that project's issues and documents, whoever authored " + "them.",
|
|
30166
30248
|
arguments: (z) => ({
|
|
30167
30249
|
project: z.string().describe("Project key; when supplied, lists every open ask in the project instead of only this session's own.").optional()
|
|
@@ -30170,6 +30252,7 @@ var dispatchToolSpecs = [
|
|
|
30170
30252
|
},
|
|
30171
30253
|
{
|
|
30172
30254
|
name: "dispatch_whoami",
|
|
30255
|
+
example: {},
|
|
30173
30256
|
description: "Who Dispatch takes this session for: {session, owner}. owner is the lowercase GitHub login of the human whose personal token you run under (the default assignee of issues you create), or null under the shared token.",
|
|
30174
30257
|
arguments: () => ({}),
|
|
30175
30258
|
strict: true
|
|
@@ -31290,13 +31373,18 @@ var TolerantInboundEnvelopeSchema = object({
|
|
|
31290
31373
|
source: InboundEnvelopeSchema.shape.source.optional().catch(undefined),
|
|
31291
31374
|
sender: object(tolerantShape(InboundSenderSchema.shape)).optional().catch(undefined)
|
|
31292
31375
|
}).passthrough();
|
|
31376
|
+
function dispatchReplyPath(resource, id) {
|
|
31377
|
+
const collection = resource === "message" ? "messages" : "comments";
|
|
31378
|
+
return `/api/v1/${collection}/${encodeURIComponent(id)}/reply`;
|
|
31379
|
+
}
|
|
31293
31380
|
async function postDeliveryReply(config, sessionId, delivery, result) {
|
|
31294
|
-
const response = await fetch(`${config.url}
|
|
31381
|
+
const response = await fetch(`${config.url}${dispatchReplyPath(delivery.resource, delivery.id)}`, {
|
|
31295
31382
|
method: "POST",
|
|
31296
31383
|
headers: { Authorization: `Bearer ${config.token}`, "Content-Type": "application/json" },
|
|
31297
31384
|
body: JSON.stringify({
|
|
31298
31385
|
actor: { kind: "session", id: sessionId },
|
|
31299
31386
|
attempt: delivery.attempt,
|
|
31387
|
+
...delivery.replyFields,
|
|
31300
31388
|
...result
|
|
31301
31389
|
})
|
|
31302
31390
|
});
|
|
@@ -31315,21 +31403,32 @@ function rememberBounded(seen, key, limit) {
|
|
|
31315
31403
|
seen.delete(oldest.value);
|
|
31316
31404
|
}
|
|
31317
31405
|
}
|
|
31318
|
-
|
|
31319
|
-
|
|
31320
|
-
|
|
31321
|
-
});
|
|
31406
|
+
function isCommentTargetedDelivery(delivery) {
|
|
31407
|
+
return "comment_id" in delivery;
|
|
31408
|
+
}
|
|
31322
31409
|
var DispatchTargetedFrameSchema = object({
|
|
31323
31410
|
event: DispatchEventSchema,
|
|
31324
|
-
delivery:
|
|
31325
|
-
}).
|
|
31411
|
+
delivery: DispatchTargetedDeliverySchema
|
|
31412
|
+
}).superRefine(({ event, delivery }, context) => {
|
|
31413
|
+
if (event.type === "message.created" && !isCommentTargetedDelivery(delivery) && DispatchTargetedMessagePayloadSchema.safeParse(event.payload).success) {
|
|
31414
|
+
return;
|
|
31415
|
+
}
|
|
31416
|
+
if (event.type === "comment.created" && isCommentTargetedDelivery(delivery) && DispatchTargetedCommentPayloadSchema.safeParse(event.payload).success) {
|
|
31417
|
+
return;
|
|
31418
|
+
}
|
|
31419
|
+
context.addIssue({
|
|
31420
|
+
code: "custom",
|
|
31421
|
+
message: event.type === "comment.created" ? "targeted delivery requires a complete comment.created event" : "targeted delivery requires a complete message.created event"
|
|
31422
|
+
});
|
|
31423
|
+
});
|
|
31326
31424
|
var RecoverableDispatchDeliveryFailureSchema = object({
|
|
31327
31425
|
event: object({
|
|
31426
|
+
type: _enum2(["message.created", "comment.created"]),
|
|
31328
31427
|
issue_key: string2().nullable(),
|
|
31329
31428
|
payload: object({ id: string2(), body: string2().optional() }).passthrough()
|
|
31330
31429
|
}).passthrough(),
|
|
31331
|
-
delivery:
|
|
31332
|
-
});
|
|
31430
|
+
delivery: DispatchTargetedDeliverySchema
|
|
31431
|
+
}).refine(({ event, delivery }) => event.type === "comment.created" ? isCommentTargetedDelivery(delivery) : !isCommentTargetedDelivery(delivery) && DispatchTargetedResourceIDSchema.safeParse(event.payload.id).success, { message: "delivery resource must match its event type" });
|
|
31333
31432
|
function senderLabel(envelope) {
|
|
31334
31433
|
const sender = envelope.source_session ?? envelope.source ?? "unknown";
|
|
31335
31434
|
return envelope.sender?.title === undefined ? sender : `${sender} (${envelope.sender.title})`;
|
|
@@ -31474,12 +31573,19 @@ function parseDispatchFrame(rawPayload) {
|
|
|
31474
31573
|
}
|
|
31475
31574
|
const recoverable = RecoverableDispatchDeliveryFailureSchema.safeParse(value);
|
|
31476
31575
|
if (recoverable.success) {
|
|
31576
|
+
const delivery = recoverable.data.delivery;
|
|
31577
|
+
const commentDelivery = isCommentTargetedDelivery(delivery);
|
|
31578
|
+
const resource = commentDelivery ? "comment" : "message";
|
|
31579
|
+
const id = commentDelivery ? delivery.comment_id : recoverable.data.event.payload.id;
|
|
31477
31580
|
return {
|
|
31478
31581
|
raw: value,
|
|
31479
31582
|
rejectedDelivery: {
|
|
31480
|
-
|
|
31481
|
-
|
|
31482
|
-
|
|
31583
|
+
resource,
|
|
31584
|
+
id,
|
|
31585
|
+
attempt: delivery.attempt,
|
|
31586
|
+
mode: delivery.mode,
|
|
31587
|
+
replyPath: dispatchReplyPath(resource, id),
|
|
31588
|
+
replyFields: commentDelivery ? { target: delivery.target } : {},
|
|
31483
31589
|
issueKey: recoverable.data.event.issue_key,
|
|
31484
31590
|
body: recoverable.data.event.payload.body ?? ""
|
|
31485
31591
|
},
|
|
@@ -31596,15 +31702,18 @@ function renderInbound(raw, sessionID, subject) {
|
|
|
31596
31702
|
}
|
|
31597
31703
|
dispatchReply = dispatchCommentReplyWith(frame.event, topic, commentPayload);
|
|
31598
31704
|
if (frame.event.type === "message.created") {
|
|
31599
|
-
const message =
|
|
31600
|
-
const requested =
|
|
31601
|
-
if (message.success && requested.success &&
|
|
31705
|
+
const message = DispatchTargetedMessagePayloadSchema.safeParse(frame.event.payload);
|
|
31706
|
+
const requested = DispatchTargetedDeliverySchema.safeParse(frame.delivery);
|
|
31707
|
+
if (message.success && requested.success && !isCommentTargetedDelivery(requested.data)) {
|
|
31602
31708
|
delivery = {
|
|
31709
|
+
resource: "message",
|
|
31710
|
+
id: message.data.id,
|
|
31603
31711
|
attempt: requested.data.attempt,
|
|
31604
31712
|
mode: requested.data.mode,
|
|
31605
|
-
|
|
31713
|
+
replyPath: dispatchReplyPath("message", message.data.id),
|
|
31714
|
+
replyFields: {},
|
|
31606
31715
|
issueKey: frame.event.issue_key,
|
|
31607
|
-
body: message.data.body
|
|
31716
|
+
body: message.data.body
|
|
31608
31717
|
};
|
|
31609
31718
|
if (frame.event.issue_key !== null) {
|
|
31610
31719
|
dispatchReply = {
|
|
@@ -31613,6 +31722,21 @@ function renderInbound(raw, sessionID, subject) {
|
|
|
31613
31722
|
};
|
|
31614
31723
|
}
|
|
31615
31724
|
}
|
|
31725
|
+
} else if (frame.event.type === "comment.created") {
|
|
31726
|
+
const comment = DispatchTargetedCommentPayloadSchema.safeParse(frame.event.payload);
|
|
31727
|
+
const requested = DispatchTargetedDeliverySchema.safeParse(frame.delivery);
|
|
31728
|
+
if (comment.success && requested.success && isCommentTargetedDelivery(requested.data)) {
|
|
31729
|
+
delivery = {
|
|
31730
|
+
resource: "comment",
|
|
31731
|
+
id: requested.data.comment_id,
|
|
31732
|
+
attempt: requested.data.attempt,
|
|
31733
|
+
mode: requested.data.mode,
|
|
31734
|
+
replyPath: dispatchReplyPath("comment", requested.data.comment_id),
|
|
31735
|
+
replyFields: { target: requested.data.target },
|
|
31736
|
+
issueKey: frame.event.issue_key,
|
|
31737
|
+
body: comment.data.body
|
|
31738
|
+
};
|
|
31739
|
+
}
|
|
31616
31740
|
}
|
|
31617
31741
|
dispatchEvent = {
|
|
31618
31742
|
owner: dispatchOwner(frame.event, topic),
|
|
@@ -32260,9 +32384,11 @@ class ToolInputError extends Error {
|
|
|
32260
32384
|
problems;
|
|
32261
32385
|
constructor(tool, problems) {
|
|
32262
32386
|
const count = problems.length;
|
|
32387
|
+
const help = dispatchInputHelp(tool);
|
|
32263
32388
|
super([
|
|
32264
32389
|
`${tool} was not called: ${count} problem${count === 1 ? "" : "s"}`,
|
|
32265
|
-
...problems.map((problem) => `- ${problem}`)
|
|
32390
|
+
...problems.map((problem) => `- ${problem}`),
|
|
32391
|
+
...help === undefined ? [] : help.map((line) => `- ${line}`)
|
|
32266
32392
|
].join(`
|
|
32267
32393
|
`));
|
|
32268
32394
|
this.name = "ToolInputError";
|
|
@@ -32270,6 +32396,14 @@ class ToolInputError extends Error {
|
|
|
32270
32396
|
this.problems = problems;
|
|
32271
32397
|
}
|
|
32272
32398
|
}
|
|
32399
|
+
function dispatchInputHelp(tool) {
|
|
32400
|
+
const spec = dispatchToolSpecs.find((candidate) => candidate.name === tool);
|
|
32401
|
+
if (spec === undefined)
|
|
32402
|
+
return;
|
|
32403
|
+
const schema = dispatchToolSchema(spec, zodSchemaApi(exports_external), { strict: true });
|
|
32404
|
+
const allowed = Object.keys(shapeOf(schema) ?? {}).join(", ") || "none";
|
|
32405
|
+
return [`Allowed keys: ${allowed}`, `Example: ${tool}(${JSON.stringify(spec.example)})`];
|
|
32406
|
+
}
|
|
32273
32407
|
function unwrap(schema) {
|
|
32274
32408
|
let current = schema;
|
|
32275
32409
|
while (current !== undefined) {
|
|
@@ -32574,7 +32708,21 @@ function refTarget(ref, kind, id) {
|
|
|
32574
32708
|
const ownerRef = ref.owner.kind === "issue" ? dispatchIssueRef(ref.owner.issue) : dispatchDocumentRef(ref.owner.project, `${ref.artifact}`);
|
|
32575
32709
|
return dispatchChildRef(ownerRef, kind, id);
|
|
32576
32710
|
}
|
|
32577
|
-
var
|
|
32711
|
+
var canonicalUUIDPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
32712
|
+
var compactUUIDPattern = /^[0-9a-f]{32}$/i;
|
|
32713
|
+
function normalizeUUID(value) {
|
|
32714
|
+
let compact = value;
|
|
32715
|
+
if (value.slice(0, 9).toLowerCase() === "urn:uuid:") {
|
|
32716
|
+
compact = value.slice(9);
|
|
32717
|
+
} else if (value.length === 38 && value.startsWith("{") && value.endsWith("}")) {
|
|
32718
|
+
compact = value.slice(1, -1);
|
|
32719
|
+
}
|
|
32720
|
+
if (canonicalUUIDPattern.test(compact))
|
|
32721
|
+
compact = compact.replaceAll("-", "");
|
|
32722
|
+
if (!compactUUIDPattern.test(compact))
|
|
32723
|
+
return;
|
|
32724
|
+
return `${compact.slice(0, 8)}-${compact.slice(8, 12)}-${compact.slice(12, 16)}-${compact.slice(16, 20)}-${compact.slice(20)}`.toLowerCase();
|
|
32725
|
+
}
|
|
32578
32726
|
var askIdProblem = "ask must be a bare ask id or a dispatch://.../ask/<id> reference";
|
|
32579
32727
|
var commentIdProblem = "comment must be a bare comment id or a dispatch://.../comment/<id> reference";
|
|
32580
32728
|
var messageIdProblem = "in_reply_to must be a full message id (uuid) or a dispatch://KEY/message/<id> reference";
|
|
@@ -32587,12 +32735,13 @@ function messageIdOf(value) {
|
|
|
32587
32735
|
const reference = parseDispatchRef(value);
|
|
32588
32736
|
return reference?.kind === "message" ? reference.id : undefined;
|
|
32589
32737
|
})() : value;
|
|
32590
|
-
return id
|
|
32738
|
+
return id === undefined ? undefined : normalizeUUID(id);
|
|
32591
32739
|
}
|
|
32592
32740
|
var idPrefixPattern = /^[0-9a-f][0-9a-f-]{7,}$/i;
|
|
32593
32741
|
async function resolveIdPrefix(tool, kind, ref, list) {
|
|
32594
|
-
|
|
32595
|
-
|
|
32742
|
+
const fullID = normalizeUUID(ref.id);
|
|
32743
|
+
if (fullID !== undefined)
|
|
32744
|
+
return fullID;
|
|
32596
32745
|
const ownerName = ref.owner.kind === "issue" ? ref.owner.issue : `${ref.owner.project}/${ref.artifact}`;
|
|
32597
32746
|
if (!idPrefixPattern.test(ref.id)) {
|
|
32598
32747
|
throw new ToolInputError(tool, [
|
|
@@ -32824,21 +32973,53 @@ async function resolveArtifact(client, owner, artifactReference) {
|
|
|
32824
32973
|
return { owner, artifact };
|
|
32825
32974
|
const names = artifacts.filter((candidate) => candidate.name === artifactReference);
|
|
32826
32975
|
if (names.length > 1) {
|
|
32827
|
-
throw new Error(
|
|
32976
|
+
throw new Error(documentReferenceProblem(artifactReference, names, "project", true));
|
|
32977
|
+
}
|
|
32978
|
+
if (names[0] === undefined) {
|
|
32979
|
+
throw new Error(documentReferenceProblem(artifactReference, artifacts, "project"));
|
|
32828
32980
|
}
|
|
32829
|
-
if (names[0] === undefined)
|
|
32830
|
-
throw error;
|
|
32831
32981
|
return { owner, artifact: names[0] };
|
|
32832
32982
|
}
|
|
32833
32983
|
}
|
|
32834
32984
|
const issue = await client.getIssue(owner.issue);
|
|
32835
|
-
|
|
32985
|
+
let artifact;
|
|
32986
|
+
if (artifactReference === undefined || artifactReference === "spec") {
|
|
32987
|
+
artifact = issue.artifacts.find((candidate) => candidate.primary || candidate.id === issue.primary_artifact_id);
|
|
32988
|
+
} else {
|
|
32989
|
+
artifact = issue.artifacts.find((candidate) => candidate.id === artifactReference || candidate.slug === artifactReference);
|
|
32990
|
+
if (artifact === undefined) {
|
|
32991
|
+
const names = issue.artifacts.filter((candidate) => candidate.name === artifactReference);
|
|
32992
|
+
if (names.length > 1) {
|
|
32993
|
+
throw new Error(documentReferenceProblem(artifactReference, names, "issue", true));
|
|
32994
|
+
}
|
|
32995
|
+
artifact = names[0];
|
|
32996
|
+
}
|
|
32997
|
+
}
|
|
32836
32998
|
if (!artifact) {
|
|
32837
|
-
|
|
32838
|
-
throw new Error(`artifact "${artifactReference ?? "spec"}" was not found on issue ${issue.key}; artifacts: ${slugs.length === 0 ? "none" : slugs.join(", ")}`);
|
|
32999
|
+
throw new Error(documentReferenceProblem(artifactReference ?? "spec", issue.artifacts, "issue"));
|
|
32839
33000
|
}
|
|
32840
33001
|
return { owner, issue, artifact };
|
|
32841
33002
|
}
|
|
33003
|
+
var documentHintLimit = 8;
|
|
33004
|
+
function documentReferenceProblem(reference, documents, owner, ambiguous = false) {
|
|
33005
|
+
const hints = documents.slice(0, documentHintLimit).map((document) => `${document.slug} (${document.name})`);
|
|
33006
|
+
const list = hints.length === 0 ? "none" : hints.join(", ");
|
|
33007
|
+
return ambiguous ? `"${reference}" names ${documents.length} documents on this ${owner}; use a slug: ${list}` : `document "${reference}" not found by slug; this ${owner}'s documents: ${list}`;
|
|
33008
|
+
}
|
|
33009
|
+
var askHintLimit = 8;
|
|
33010
|
+
function askIDInputProblem(asks, scope) {
|
|
33011
|
+
const hints = asks.slice(0, askHintLimit).map((ask) => `${ask.id.slice(0, 8)}\u2026 ${textHead(ask.question)}`);
|
|
33012
|
+
return `ask IDs are UUIDs; use the full ask ID; ${scope} open asks: ${hints.length === 0 ? "none" : hints.join(", ")}`;
|
|
33013
|
+
}
|
|
33014
|
+
async function invalidReplyToAskProblem(client, owner, resolved) {
|
|
33015
|
+
if (owner.kind === "issue") {
|
|
33016
|
+
const issue = resolved?.issue ?? await client.getIssue(owner.issue);
|
|
33017
|
+
return askIDInputProblem(issue.open_asks, "this issue's");
|
|
33018
|
+
}
|
|
33019
|
+
if (resolved === undefined)
|
|
33020
|
+
throw new Error("project document is missing its resolved artifact");
|
|
33021
|
+
return askIDInputProblem(await client.getArtifactAsks(resolved.artifact.id, "open"), "this document's");
|
|
33022
|
+
}
|
|
32842
33023
|
function anchor(artifact, args) {
|
|
32843
33024
|
const quote = optionalString(args, "quote");
|
|
32844
33025
|
if (quote === undefined)
|
|
@@ -33442,7 +33623,13 @@ ${followsAsk(askOwner)}`,
|
|
|
33442
33623
|
const resolved = owner.kind === "project" || artifactReference === undefined ? owner.kind === "project" ? await resolveArtifact(client, owner, artifactReference) : undefined : await resolveArtifact(client, owner, artifactReference);
|
|
33443
33624
|
const anchored = resolved ? anchor(resolved.artifact, args) : undefined;
|
|
33444
33625
|
const replyTo = optionalString(args, "reply_to");
|
|
33445
|
-
const
|
|
33626
|
+
const replyToAskReference = optionalString(args, "reply_to_ask");
|
|
33627
|
+
const replyToAsk = replyToAskReference === undefined ? undefined : normalizeUUID(replyToAskReference);
|
|
33628
|
+
if (replyToAskReference !== undefined && replyToAsk === undefined) {
|
|
33629
|
+
throw new ToolInputError(input.tool, [
|
|
33630
|
+
await invalidReplyToAskProblem(client, owner, resolved)
|
|
33631
|
+
]);
|
|
33632
|
+
}
|
|
33446
33633
|
const requestedTurn = optionalString(args, "turn");
|
|
33447
33634
|
const commentInput = {
|
|
33448
33635
|
body: stringArg(args, "body"),
|
|
@@ -34370,7 +34557,7 @@ function envoyExtension(pi) {
|
|
|
34370
34557
|
}
|
|
34371
34558
|
try {
|
|
34372
34559
|
if (rendered.rejectedDelivery !== undefined) {
|
|
34373
|
-
console.warn(`[envoy] rejecting malformed Dispatch targeted delivery ${rendered.rejectedDelivery.
|
|
34560
|
+
console.warn(`[envoy] rejecting malformed Dispatch targeted delivery ${rendered.rejectedDelivery.id}`);
|
|
34374
34561
|
await postDispatchReply(rendered.rejectedDelivery, {
|
|
34375
34562
|
error: "Invalid Dispatch targeted delivery frame"
|
|
34376
34563
|
});
|
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.
|
|
16148
|
+
version: "1.52.0",
|
|
16149
16149
|
type: "module",
|
|
16150
16150
|
omp: {
|
|
16151
16151
|
extensions: [
|
|
@@ -29045,6 +29045,24 @@ var AskEditedEventPayloadSchema = object({
|
|
|
29045
29045
|
}),
|
|
29046
29046
|
edited_by: object({ kind: string2(), id: string2() }).passthrough()
|
|
29047
29047
|
});
|
|
29048
|
+
var CommentMentionSchema = object({
|
|
29049
|
+
target: string2(),
|
|
29050
|
+
delivery: _enum2(DELIVERY_CAPABILITIES),
|
|
29051
|
+
session_id: string2().nullable()
|
|
29052
|
+
});
|
|
29053
|
+
var CommentDeliverySchema = object({
|
|
29054
|
+
comment_id: string2(),
|
|
29055
|
+
target: string2(),
|
|
29056
|
+
attempt: number2().int().positive(),
|
|
29057
|
+
delivery: _enum2(DELIVERY_CAPABILITIES),
|
|
29058
|
+
session_id: string2().nullable(),
|
|
29059
|
+
envelope_id: string2().nullable(),
|
|
29060
|
+
state: _enum2(["pending", "sent", "failed"]),
|
|
29061
|
+
error: string2().nullable(),
|
|
29062
|
+
resolve_error: string2().nullable(),
|
|
29063
|
+
reply_id: string2().nullable(),
|
|
29064
|
+
created_at: string2()
|
|
29065
|
+
});
|
|
29048
29066
|
var CommentEventPayloadSchema = object({
|
|
29049
29067
|
id: string2().optional(),
|
|
29050
29068
|
artifact_name: string2().optional(),
|
|
@@ -29060,7 +29078,9 @@ var CommentEventPayloadSchema = object({
|
|
|
29060
29078
|
anchor: object({ block_id: string2().nullable().optional(), quote: string2().optional() }).nullish(),
|
|
29061
29079
|
suggestion: object({ replace_with: string2().optional() }).nullish(),
|
|
29062
29080
|
author: object({ kind: string2(), id: string2() }).optional(),
|
|
29063
|
-
created_at: string2().optional()
|
|
29081
|
+
created_at: string2().optional(),
|
|
29082
|
+
mentions: array(CommentMentionSchema).optional(),
|
|
29083
|
+
deliveries: array(CommentDeliverySchema).optional()
|
|
29064
29084
|
});
|
|
29065
29085
|
var MessageEventPayloadSchema = object({
|
|
29066
29086
|
id: string2().optional(),
|
|
@@ -29070,8 +29090,9 @@ var MessageEventPayloadSchema = object({
|
|
|
29070
29090
|
reply_body: string2().optional(),
|
|
29071
29091
|
author: object({ kind: string2(), id: string2() }).optional()
|
|
29072
29092
|
});
|
|
29093
|
+
var DispatchTargetedResourceIDSchema = uuid2();
|
|
29073
29094
|
var DispatchTargetedMessagePayloadSchema = MessageEventPayloadSchema.extend({
|
|
29074
|
-
id:
|
|
29095
|
+
id: DispatchTargetedResourceIDSchema,
|
|
29075
29096
|
issue_key: string2().nullable(),
|
|
29076
29097
|
author: object({ kind: string2(), id: string2() }),
|
|
29077
29098
|
body: string2(),
|
|
@@ -29080,6 +29101,31 @@ var DispatchTargetedMessagePayloadSchema = MessageEventPayloadSchema.extend({
|
|
|
29080
29101
|
deliveries: array(unknown()),
|
|
29081
29102
|
created_at: string2()
|
|
29082
29103
|
});
|
|
29104
|
+
var DispatchTargetedCommentPayloadSchema = CommentEventPayloadSchema.extend({
|
|
29105
|
+
id: DispatchTargetedResourceIDSchema,
|
|
29106
|
+
issue_key: string2().nullable(),
|
|
29107
|
+
artifact_id: string2().nullable(),
|
|
29108
|
+
author: object({ kind: string2(), id: string2() }),
|
|
29109
|
+
body: string2(),
|
|
29110
|
+
reply_to: string2().nullable(),
|
|
29111
|
+
ask_id: string2().nullable(),
|
|
29112
|
+
mentions: array(CommentMentionSchema),
|
|
29113
|
+
deliveries: array(CommentDeliverySchema),
|
|
29114
|
+
created_at: string2(),
|
|
29115
|
+
artifact_name: string2()
|
|
29116
|
+
});
|
|
29117
|
+
var DispatchTargetedMessageDeliverySchema = object({
|
|
29118
|
+
attempt: number2().int().positive(),
|
|
29119
|
+
mode: _enum2(DELIVERY_CAPABILITIES)
|
|
29120
|
+
});
|
|
29121
|
+
var DispatchTargetedCommentDeliverySchema = DispatchTargetedMessageDeliverySchema.extend({
|
|
29122
|
+
comment_id: DispatchTargetedResourceIDSchema,
|
|
29123
|
+
target: string2()
|
|
29124
|
+
});
|
|
29125
|
+
var DispatchTargetedDeliverySchema = union([
|
|
29126
|
+
DispatchTargetedCommentDeliverySchema,
|
|
29127
|
+
DispatchTargetedMessageDeliverySchema
|
|
29128
|
+
]);
|
|
29083
29129
|
var MessageDeliveryEventPayloadSchema = object({
|
|
29084
29130
|
message_id: string2().optional(),
|
|
29085
29131
|
attempt: number2().int().positive().optional(),
|
|
@@ -29227,6 +29273,7 @@ var DOC_EDIT_OPS = ["replace", "delete", "insert", "retype", "move"];
|
|
|
29227
29273
|
var dispatchToolSpecs = [
|
|
29228
29274
|
{
|
|
29229
29275
|
name: "dispatch_issue",
|
|
29276
|
+
example: { project: "DSP", title: "Native workspace" },
|
|
29230
29277
|
description: "Create a native Dispatch issue for newly tracked work. Search first with dispatch_search; if potentially duplicate issues exist, this returns 409 POSSIBLE_DUPLICATE unless force is true after reading them. " + `Do not use it when an existing issue already covers the work; read or update that issue instead. ${ISSUE_REFERENCE}`,
|
|
29231
29278
|
arguments: (z) => ({
|
|
29232
29279
|
project: z.string().describe("Project key for the new issue."),
|
|
@@ -29243,6 +29290,7 @@ var dispatchToolSpecs = [
|
|
|
29243
29290
|
},
|
|
29244
29291
|
{
|
|
29245
29292
|
name: "dispatch_issue_update",
|
|
29293
|
+
example: { issue: "DSP-1", status: "in_progress" },
|
|
29246
29294
|
description: "Update an existing issue: move its lifecycle status, retitle it, replace its labels, link a URL " + "(the pull request that delivers it, a run, a document), set its route, set or clear its parent, " + "or attach it to architecture components. Status is one of " + `${ISSUE_STATUSES.join(", ")}; outside Legion, move it yourself as the work advances; inside ` + "Legion the daemon moves it. external_links are " + "merged into the issue's existing links by URL, so linking the pull request you just opened " + "keeps every earlier link. components replaces the issue's own attachment and is allowed on a " + "closed issue. Priority is the human's and is not settable here. At least one " + `field besides issue is required. ${ISSUE_REFERENCE}`,
|
|
29247
29295
|
arguments: (z) => ({
|
|
29248
29296
|
issue: z.string().describe(ISSUE_REFERENCE),
|
|
@@ -29265,6 +29313,7 @@ var dispatchToolSpecs = [
|
|
|
29265
29313
|
},
|
|
29266
29314
|
{
|
|
29267
29315
|
name: "dispatch_ask",
|
|
29316
|
+
example: { issue: "DSP-1", question: "Ship this?" },
|
|
29268
29317
|
description: "Open a durable, answerable decision on an issue or project document. Do not use it for a status update or discussion; " + "use dispatch_message instead. A to-do a human must complete is a question phrased as that to-do, with the options you want (for example Done / Can't). " + "Anchor a document question, thread reply_to/reply_to_ask, or cite a dispatch:// " + `reference \u2014 it must be answerable from its own text and anchor alone, never "see above". A quote anchor is pinned to its block. Question is at most ${ASK_QUESTION_MAX} ` + `characters and has at most 8 options. ${OWNER_REFERENCE}`,
|
|
29269
29318
|
arguments: (z) => ({
|
|
29270
29319
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -29288,6 +29337,10 @@ var dispatchToolSpecs = [
|
|
|
29288
29337
|
},
|
|
29289
29338
|
{
|
|
29290
29339
|
name: "dispatch_edit_ask",
|
|
29340
|
+
example: {
|
|
29341
|
+
ask: "01234567-0000-4000-8000-000000000001",
|
|
29342
|
+
question: "Ship the revised plan?"
|
|
29343
|
+
},
|
|
29291
29344
|
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.",
|
|
29292
29345
|
arguments: (z) => ({
|
|
29293
29346
|
ask: z.string().describe("Ask id to edit."),
|
|
@@ -29309,6 +29362,11 @@ var dispatchToolSpecs = [
|
|
|
29309
29362
|
},
|
|
29310
29363
|
{
|
|
29311
29364
|
name: "dispatch_resolve_ask",
|
|
29365
|
+
example: {
|
|
29366
|
+
ask: "01234567-0000-4000-8000-000000000001",
|
|
29367
|
+
kind: "retracted",
|
|
29368
|
+
reason: "A newer question supersedes this one."
|
|
29369
|
+
},
|
|
29312
29370
|
description: "Retract an open question that is moot or resolve one after finding the answer. This closes the question without answering it.",
|
|
29313
29371
|
arguments: (z) => ({
|
|
29314
29372
|
ask: z.string().describe("Ask id to close."),
|
|
@@ -29318,6 +29376,7 @@ var dispatchToolSpecs = [
|
|
|
29318
29376
|
},
|
|
29319
29377
|
{
|
|
29320
29378
|
name: "dispatch_resolve_comment",
|
|
29379
|
+
example: { comment: "01234567-0000-4000-8000-000000000001" },
|
|
29321
29380
|
description: "Resolve a review comment thread once it has been addressed - typically your own comment " + "after the document was fixed. Any session or human may resolve any open comment on an " + "open issue or project document; reopening a resolved comment is human-only (the dashboard). " + "Not for asks: use dispatch_resolve_ask.",
|
|
29322
29381
|
arguments: (z) => ({
|
|
29323
29382
|
comment: z.string().describe("Comment id (uuid), or a dispatch://KEY/comment/<id> or " + "dispatch://PROJECT/artifact/<slug>/comment/<id> reference; a reference accepts an " + "8+ character id prefix that is unique on its owner.")
|
|
@@ -29326,6 +29385,7 @@ var dispatchToolSpecs = [
|
|
|
29326
29385
|
},
|
|
29327
29386
|
{
|
|
29328
29387
|
name: "dispatch_follow",
|
|
29388
|
+
example: { ask: "01234567-0000-4000-8000-000000000001", action: "follow" },
|
|
29329
29389
|
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>.>",
|
|
29330
29390
|
arguments: (z) => ({
|
|
29331
29391
|
ask: z.string().describe("Full ask id (uuid)."),
|
|
@@ -29335,6 +29395,7 @@ var dispatchToolSpecs = [
|
|
|
29335
29395
|
},
|
|
29336
29396
|
{
|
|
29337
29397
|
name: "dispatch_comment",
|
|
29398
|
+
example: { issue: "DSP-1", body: "Looks good." },
|
|
29338
29399
|
description: "Add review feedback to an issue or project document quote, or reply to a question asked with dispatch_ask. " + "Do not use it for an exact replacement; use " + `dispatch_suggest instead. A quote anchor is pinned to its block. Body is at most 2,000 characters. ${OWNER_REFERENCE}`,
|
|
29339
29400
|
arguments: (z) => ({
|
|
29340
29401
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -29352,6 +29413,12 @@ var dispatchToolSpecs = [
|
|
|
29352
29413
|
},
|
|
29353
29414
|
{
|
|
29354
29415
|
name: "dispatch_suggest",
|
|
29416
|
+
example: {
|
|
29417
|
+
issue: "DSP-1",
|
|
29418
|
+
artifact: "spec",
|
|
29419
|
+
quote: "old wording",
|
|
29420
|
+
replace_with: "new wording"
|
|
29421
|
+
},
|
|
29355
29422
|
description: "Propose an exact replacement for quoted document text. Do not use it for general feedback; use " + `dispatch_comment instead. Optional explanation is at most 2,000 characters. ${OWNER_REFERENCE}`,
|
|
29356
29423
|
arguments: (z) => ({
|
|
29357
29424
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -29367,6 +29434,7 @@ var dispatchToolSpecs = [
|
|
|
29367
29434
|
},
|
|
29368
29435
|
{
|
|
29369
29436
|
name: "dispatch_message",
|
|
29437
|
+
example: { issue: "DSP-1", body: "Implementation started." },
|
|
29370
29438
|
description: "Post a note humans must read now: a reply to a human's message, a deliverable that landed, or a blocker only " + "they can clear. Never progress or status updates - Dispatch is a high-signal record, not a log. Not a decision " + `(dispatch_ask) or document feedback (dispatch_comment). Body is at most 2,000 characters. ${ISSUE_REFERENCE}`,
|
|
29371
29439
|
arguments: (z) => ({
|
|
29372
29440
|
issue: z.string().describe(ISSUE_REFERENCE),
|
|
@@ -29376,6 +29444,11 @@ var dispatchToolSpecs = [
|
|
|
29376
29444
|
},
|
|
29377
29445
|
{
|
|
29378
29446
|
name: "dispatch_doc_edit",
|
|
29447
|
+
example: {
|
|
29448
|
+
issue: "DSP-1",
|
|
29449
|
+
artifact: "spec",
|
|
29450
|
+
ops: [{ op: "replace", find: "old", with: "new" }]
|
|
29451
|
+
},
|
|
29379
29452
|
description: "Apply deterministic document edits: replace or delete quoted text, insert markdown at an anchor, retype an identified paragraph or typed block into a schema-declared typed block, and delete or move a whole block by its id. " + "Do not use it for review feedback or for reading; use dispatch_comment, dispatch_suggest, or dispatch_doc_read instead. " + "For replace, delete, and quote anchors, find text as rendered: inline Markdown (**bold**, `code`) is tolerated; a leading '# ' matches a heading. replace is inline: with is the new text of the matched span, so a leading list or heading marker stays literal text. " + "A delete whose find is a block's entire text removes the block (a list emptied of its items goes too); delete with block removes any block by id, and move with block relocates one. " + 'Insert and move anchors also accept "start", "end", "heading:<exact heading text>", and "block:<id>"; block ids are the #id of a typed block or a row of GET /api/v1/artifacts/{id}/blocks. ' + `The spec (or any document) holds requirements, design, and decisions - never progress, status, or timestamps. ${OWNER_REFERENCE} ${SPEC_WRITING_GUIDANCE}`,
|
|
29380
29453
|
arguments: (z) => ({
|
|
29381
29454
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -29400,6 +29473,7 @@ var dispatchToolSpecs = [
|
|
|
29400
29473
|
},
|
|
29401
29474
|
{
|
|
29402
29475
|
name: "dispatch_doc_read",
|
|
29476
|
+
example: { issue: "DSP-1" },
|
|
29403
29477
|
description: "Read a live document or a named document version. Do not use it for issue status, asks, or events; " + "use dispatch_read instead. Supply ref, issue, or project plus artifact; issue plus an omitted artifact reads the primary document. " + OWNER_REFERENCE,
|
|
29404
29478
|
arguments: (z) => ({
|
|
29405
29479
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -29412,6 +29486,7 @@ var dispatchToolSpecs = [
|
|
|
29412
29486
|
},
|
|
29413
29487
|
{
|
|
29414
29488
|
name: "dispatch_request_approval",
|
|
29489
|
+
example: { issue: "DSP-1" },
|
|
29415
29490
|
description: "Ask a human to approve a document at its current version - the exception path for a spec " + "that departs from what was settled or proposes children, not a step for every issue. Opens an " + "approval ask (Approve / Request changes) in the human's Inbox; the answer pins a review to the " + "document version and arrives as artifact.approved or artifact.changes_requested. A later edit " + "makes an approval stale; request again for the new version. Idempotent while a request is open. " + OWNER_REFERENCE,
|
|
29416
29491
|
arguments: (z) => ({
|
|
29417
29492
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -29422,6 +29497,8 @@ var dispatchToolSpecs = [
|
|
|
29422
29497
|
},
|
|
29423
29498
|
{
|
|
29424
29499
|
name: "dispatch_artifact",
|
|
29500
|
+
example: { issue: "DSP-1", name: "design.md", content: `# Design
|
|
29501
|
+
` },
|
|
29425
29502
|
description: "Attach a local file or inline text as an issue artifact or project document. Do not use it to edit a live document; use " + `dispatch_doc_edit instead. Exactly one of path or content is required; artifacts are limited to 25 MiB. ${OWNER_REFERENCE}`,
|
|
29426
29503
|
arguments: (z) => ({
|
|
29427
29504
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -29441,6 +29518,7 @@ var dispatchToolSpecs = [
|
|
|
29441
29518
|
},
|
|
29442
29519
|
{
|
|
29443
29520
|
name: "dispatch_read",
|
|
29521
|
+
example: { issue: "DSP-1" },
|
|
29444
29522
|
description: "Read an issue or project-document summary, targeted ask, or targeted comment reply chain. Do not use it for document " + "contents; use dispatch_doc_read instead. Supply ref, issue, or project plus artifact. " + "Every read ends with `Referenced by:` (what cites or hangs off this node, each with its dispatch:// address, " + "an excerpt, and when) and `Links:` (what it cites), so tracing provenance is one call. " + OWNER_REFERENCE,
|
|
29445
29523
|
arguments: (z) => ({
|
|
29446
29524
|
issue: z.string().describe(ISSUE_REFERENCE).optional(),
|
|
@@ -29452,6 +29530,7 @@ var dispatchToolSpecs = [
|
|
|
29452
29530
|
},
|
|
29453
29531
|
{
|
|
29454
29532
|
name: "dispatch_search",
|
|
29533
|
+
example: { query: "astrolabe" },
|
|
29455
29534
|
description: "Search every issue, document, comment, ask, and message for a keyword or phrase and get deep links. " + "Use it before creating an issue or a design document, and to find where a word was written. " + 'Websearch syntax: "quoted phrase", -excluded, OR.',
|
|
29456
29535
|
arguments: (z) => ({
|
|
29457
29536
|
query: z.string({ min: 2 }).describe("Keyword, phrase, or websearch expression; at least 2 characters."),
|
|
@@ -29461,6 +29540,7 @@ var dispatchToolSpecs = [
|
|
|
29461
29540
|
},
|
|
29462
29541
|
{
|
|
29463
29542
|
name: "dispatch_issues",
|
|
29543
|
+
example: { project: "AGENTC" },
|
|
29464
29544
|
description: "List a project's issues for a roadmap or backlog pass: every issue in one project, each carrying " + "its status, priority, parent, labels, and open-ask count, so you can see backlog shape without " + "opening every issue. Optionally filter by status, parent, label, or how recently it changed. Do " + "not use it to search by keyword or phrase; dispatch_search remains the keyword surface. Rows are " + "capped at limit (default 50, max 250), applied to the response here, not by the server.",
|
|
29465
29545
|
arguments: (z) => ({
|
|
29466
29546
|
project: z.string().describe("Project key to list issues from."),
|
|
@@ -29473,6 +29553,7 @@ var dispatchToolSpecs = [
|
|
|
29473
29553
|
},
|
|
29474
29554
|
{
|
|
29475
29555
|
name: "dispatch_architecture_sync",
|
|
29556
|
+
example: { project: "CORE" },
|
|
29476
29557
|
description: "Import a project's architecture model from its configured source repository now, instead of " + "waiting for the server's five-minute schedule. Returns the imported commit and component " + "count, or the recorded error when the model was rejected (the previous model stays up). " + "The source itself is configured by a human in Settings; 404 SOURCE_NOT_FOUND without one.",
|
|
29477
29558
|
arguments: (z) => ({
|
|
29478
29559
|
project: z.string().describe("Project key whose architecture source to sync, such as CORE.")
|
|
@@ -29481,6 +29562,7 @@ var dispatchToolSpecs = [
|
|
|
29481
29562
|
},
|
|
29482
29563
|
{
|
|
29483
29564
|
name: "dispatch_open_asks",
|
|
29565
|
+
example: {},
|
|
29484
29566
|
description: "List active unanswered asks, oldest first, with age and whose reply is needed. Omit project to " + "see only this session's own authored asks (call before saying you are waiting for human input); " + "supply project to see every open ask across that project's issues and documents, whoever authored " + "them.",
|
|
29485
29567
|
arguments: (z) => ({
|
|
29486
29568
|
project: z.string().describe("Project key; when supplied, lists every open ask in the project instead of only this session's own.").optional()
|
|
@@ -29489,6 +29571,7 @@ var dispatchToolSpecs = [
|
|
|
29489
29571
|
},
|
|
29490
29572
|
{
|
|
29491
29573
|
name: "dispatch_whoami",
|
|
29574
|
+
example: {},
|
|
29492
29575
|
description: "Who Dispatch takes this session for: {session, owner}. owner is the lowercase GitHub login of the human whose personal token you run under (the default assignee of issues you create), or null under the shared token.",
|
|
29493
29576
|
arguments: () => ({}),
|
|
29494
29577
|
strict: true
|