@sjawhar/pi-legion-envoy 0.18.0 → 0.18.2

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.
Files changed (3) hide show
  1. package/dist/envoy.js +169 -167
  2. package/dist/legion.js +169 -173
  3. package/package.json +1 -1
package/dist/envoy.js CHANGED
@@ -16116,122 +16116,6 @@ import { existsSync } from "fs";
16116
16116
  import { dirname, resolve } from "path";
16117
16117
  import { fileURLToPath } from "url";
16118
16118
 
16119
- // ../contracts/src/dispatch-tools.ts
16120
- var ISSUE_REFERENCE = "An issue is a native KEY or external owner/repo#n reference; an external reference creates its native issue on first use in the repository's mapped project (DISPATCH_REPO_PROJECTS) or, failing that, the default project (DISPATCH_DEFAULT_PROJECT).";
16121
- var ASK_URGENCIES = ["low", "med", "high", "blocking"];
16122
- var DOC_EDIT_OPS = ["replace", "delete", "insert"];
16123
- var dispatchToolSpecs = [
16124
- {
16125
- name: "dispatch_issue",
16126
- description: "Create a native Dispatch issue for newly tracked work. Do not use it when an existing issue " + `already covers the work; read or update that issue instead. ${ISSUE_REFERENCE}`,
16127
- arguments: (z) => ({
16128
- project: z.string().describe("Project key for the new issue."),
16129
- title: z.string().describe("Concise issue title."),
16130
- parent: z.string().describe("Optional parent issue.").optional(),
16131
- external: z.string().describe("Optional external issue reference.").optional(),
16132
- spec: z.string().describe("Optional initial primary-document markdown.").optional()
16133
- })
16134
- },
16135
- {
16136
- name: "dispatch_ask",
16137
- description: "Open a durable, answerable decision on an issue. Do not use it for a status update or discussion; " + `use dispatch_message instead. Question is at most 800 characters and has at most 8 options. ${ISSUE_REFERENCE}`,
16138
- arguments: (z) => ({
16139
- issue: z.string().describe(ISSUE_REFERENCE),
16140
- question: z.string({ max: 800 }).describe("Decision question, at most 800 characters."),
16141
- options: z.array(z.object({
16142
- label: z.string().describe("Selectable option label."),
16143
- description: z.string().describe("Optional option context.").optional()
16144
- }), { max: 8 }).describe("Optional choices, at most 8.").optional(),
16145
- multiple: z.boolean().describe("Whether multiple choices may be selected.").optional(),
16146
- custom: z.boolean().describe("Whether a free-text answer is allowed.").optional(),
16147
- urgency: z.enum(ASK_URGENCIES).describe("Optional decision urgency.").optional(),
16148
- anchor: z.object({
16149
- artifact: z.string().describe("Artifact slug or id containing the quoted text."),
16150
- quote: z.string().describe("Exact text the decision concerns."),
16151
- occurrence: z.number({ int: true, min: 0 }).describe("Zero-based occurrence of the quote.").optional()
16152
- }).describe("Optional document location for the question.").optional()
16153
- })
16154
- },
16155
- {
16156
- name: "dispatch_comment",
16157
- description: "Add review feedback to an issue or document quote. Do not use it for an exact replacement; use " + `dispatch_suggest instead. Body is at most 2,000 characters. ${ISSUE_REFERENCE}`,
16158
- arguments: (z) => ({
16159
- issue: z.string().describe(ISSUE_REFERENCE),
16160
- artifact: z.string().describe("Artifact slug or id required when quote is given.").optional(),
16161
- quote: z.string().describe("Optional exact quoted document text.").optional(),
16162
- occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based occurrence of quote.").optional(),
16163
- body: z.string({ max: 2000 }).describe("Review comment, at most 2,000 characters."),
16164
- reply_to: z.string().describe("Optional comment id to reply to.").optional()
16165
- })
16166
- },
16167
- {
16168
- name: "dispatch_suggest",
16169
- 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. ${ISSUE_REFERENCE}`,
16170
- arguments: (z) => ({
16171
- issue: z.string().describe(ISSUE_REFERENCE),
16172
- artifact: z.string().describe("Artifact slug or id containing the quoted text."),
16173
- quote: z.string().describe("Exact document text to replace."),
16174
- replace_with: z.string().describe("Replacement text."),
16175
- body: z.string({ max: 2000 }).describe("Optional rationale, at most 2,000 characters.").optional(),
16176
- occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based occurrence of quote.").optional()
16177
- })
16178
- },
16179
- {
16180
- name: "dispatch_message",
16181
- description: "Post a plain issue update. Do not use it for a decision or line-specific review; use dispatch_ask " + `or dispatch_comment instead. Body is at most 2,000 characters. ${ISSUE_REFERENCE}`,
16182
- arguments: (z) => ({
16183
- issue: z.string().describe(ISSUE_REFERENCE),
16184
- body: z.string({ max: 2000 }).describe("Update text, at most 2,000 characters.")
16185
- })
16186
- },
16187
- {
16188
- name: "dispatch_doc_edit",
16189
- description: "Apply deterministic text edits to a document. Do not use it for review feedback or for reading; use " + `dispatch_comment, dispatch_suggest, or dispatch_doc_read instead. ${ISSUE_REFERENCE}`,
16190
- arguments: (z) => ({
16191
- issue: z.string().describe(ISSUE_REFERENCE),
16192
- artifact: z.string().describe("Artifact slug or id for the document."),
16193
- ops: z.array(z.object({
16194
- op: z.enum(DOC_EDIT_OPS).describe("Edit operation."),
16195
- find: z.string().describe("Text to find for replace or delete.").optional(),
16196
- with: z.string().describe("Replacement text for replace.").optional(),
16197
- occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based match occurrence.").optional(),
16198
- markdown: z.string().describe("Markdown to insert.").optional(),
16199
- after: z.string().describe("Anchor after which to insert.").optional(),
16200
- before: z.string().describe("Anchor before which to insert.").optional()
16201
- })).describe("Flat tagged edits; the server validates fields required for each operation."),
16202
- summary: z.string().describe("Optional named-version summary.").optional()
16203
- })
16204
- },
16205
- {
16206
- name: "dispatch_doc_read",
16207
- 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 or issue; issue plus an omitted artifact reads the primary document. " + `${ISSUE_REFERENCE}`,
16208
- arguments: (z) => ({
16209
- issue: z.string().describe(ISSUE_REFERENCE).optional(),
16210
- artifact: z.string().describe("Optional artifact slug or id; primary document by default.").optional(),
16211
- version: z.number({ int: true, min: 1 }).describe("Optional version number.").optional(),
16212
- ref: z.string().describe("Optional dispatch:// document reference.").optional()
16213
- })
16214
- },
16215
- {
16216
- name: "dispatch_artifact",
16217
- description: "Upload a local file as an issue artifact. Do not use it to edit a live document; use dispatch_doc_edit " + `instead. Files are limited to 25 MiB. ${ISSUE_REFERENCE}`,
16218
- arguments: (z) => ({
16219
- issue: z.string().describe(ISSUE_REFERENCE),
16220
- name: z.string().describe("Artifact filename shown in Dispatch."),
16221
- path: z.string().describe("Local path to the file to upload."),
16222
- primary: z.boolean().describe("Make this document the issue primary artifact.").optional(),
16223
- summary: z.string().describe("Optional version summary.").optional()
16224
- })
16225
- },
16226
- {
16227
- name: "dispatch_read",
16228
- description: "Read an issue summary, targeted ask, or targeted comment reply chain. Do not use it for document " + "contents; use dispatch_doc_read instead. Supply issue or ref. " + ISSUE_REFERENCE,
16229
- arguments: (z) => ({
16230
- issue: z.string().describe(ISSUE_REFERENCE).optional(),
16231
- ref: z.string().describe("Optional dispatch:// issue reference.").optional()
16232
- })
16233
- }
16234
- ];
16235
16119
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
16236
16120
  var exports_external = {};
16237
16121
  __export(exports_external, {
@@ -29764,6 +29648,160 @@ function date4(params) {
29764
29648
 
29765
29649
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
29766
29650
  config(en_default());
29651
+ // ../contracts/src/dispatch-api.ts
29652
+ var DispatchEventSchema = object({
29653
+ issue_key: string2(),
29654
+ type: string2(),
29655
+ actor: object({ kind: string2(), id: string2().optional() }).passthrough(),
29656
+ payload: object({}).passthrough()
29657
+ });
29658
+ var IssueEventPayloadSchema = object({
29659
+ title: string2().optional(),
29660
+ status: string2().optional(),
29661
+ route: string2().nullish()
29662
+ });
29663
+ var ArtifactCreatedEventPayloadSchema = object({
29664
+ artifact: object({ name: string2().optional() }).optional()
29665
+ });
29666
+ var ArtifactVersionEventPayloadSchema = object({
29667
+ name: string2().optional(),
29668
+ version: object({ number: number2().optional(), summary: string2().nullish() }).optional(),
29669
+ diff: string2().optional()
29670
+ });
29671
+ var AskEventPayloadSchema = object({
29672
+ question: string2().optional(),
29673
+ options: array(object({ label: string2().optional() })).nullish(),
29674
+ answer: object({ selected: array(string2()).nullish(), text: string2().nullish() }).nullish()
29675
+ });
29676
+ var CommentEventPayloadSchema = object({
29677
+ artifact_name: string2().optional(),
29678
+ body: string2().optional(),
29679
+ reply_to: string2().nullish(),
29680
+ anchor: object({ quote: string2().optional() }).nullish(),
29681
+ suggestion: object({ replace_with: string2().optional() }).nullish()
29682
+ });
29683
+ var MessageEventPayloadSchema = object({ body: string2().optional() });
29684
+ var ChildStatusEventPayloadSchema = object({
29685
+ child_key: string2().optional(),
29686
+ from: string2().optional(),
29687
+ to: string2().optional()
29688
+ });
29689
+ // ../contracts/src/dispatch-tools.ts
29690
+ var ISSUE_REFERENCE = "An issue is a native KEY or external owner/repo#n reference; an external reference creates its native issue on first use in the repository's mapped project (DISPATCH_REPO_PROJECTS) or, failing that, the default project (DISPATCH_DEFAULT_PROJECT).";
29691
+ var ASK_URGENCIES = ["low", "med", "high", "blocking"];
29692
+ var DOC_EDIT_OPS = ["replace", "delete", "insert"];
29693
+ var dispatchToolSpecs = [
29694
+ {
29695
+ name: "dispatch_issue",
29696
+ description: "Create a native Dispatch issue for newly tracked work. Do not use it when an existing issue " + `already covers the work; read or update that issue instead. ${ISSUE_REFERENCE}`,
29697
+ arguments: (z) => ({
29698
+ project: z.string().describe("Project key for the new issue."),
29699
+ title: z.string().describe("Concise issue title."),
29700
+ parent: z.string().describe("Optional parent issue.").optional(),
29701
+ external: z.string().describe("Optional external issue reference.").optional(),
29702
+ spec: z.string().describe("Optional initial primary-document markdown.").optional()
29703
+ })
29704
+ },
29705
+ {
29706
+ name: "dispatch_ask",
29707
+ description: "Open a durable, answerable decision on an issue. Do not use it for a status update or discussion; " + `use dispatch_message instead. Question is at most 800 characters and has at most 8 options. ${ISSUE_REFERENCE}`,
29708
+ arguments: (z) => ({
29709
+ issue: z.string().describe(ISSUE_REFERENCE),
29710
+ question: z.string({ max: 800 }).describe("Decision question, at most 800 characters."),
29711
+ options: z.array(z.object({
29712
+ label: z.string().describe("Selectable option label."),
29713
+ description: z.string().describe("Optional option context.").optional()
29714
+ }), { max: 8 }).describe("Optional choices, at most 8.").optional(),
29715
+ multiple: z.boolean().describe("Whether multiple choices may be selected.").optional(),
29716
+ custom: z.boolean().describe("Whether a free-text answer is allowed.").optional(),
29717
+ urgency: z.enum(ASK_URGENCIES).describe("Optional decision urgency.").optional(),
29718
+ anchor: z.object({
29719
+ artifact: z.string().describe("Artifact slug or id containing the quoted text."),
29720
+ quote: z.string().describe("Exact text the decision concerns."),
29721
+ occurrence: z.number({ int: true, min: 0 }).describe("Zero-based occurrence of the quote.").optional()
29722
+ }).describe("Optional document location for the question.").optional()
29723
+ })
29724
+ },
29725
+ {
29726
+ name: "dispatch_comment",
29727
+ description: "Add review feedback to an issue or document quote. Do not use it for an exact replacement; use " + `dispatch_suggest instead. Body is at most 2,000 characters. ${ISSUE_REFERENCE}`,
29728
+ arguments: (z) => ({
29729
+ issue: z.string().describe(ISSUE_REFERENCE),
29730
+ artifact: z.string().describe("Artifact slug or id required when quote is given.").optional(),
29731
+ quote: z.string().describe("Optional exact quoted document text.").optional(),
29732
+ occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based occurrence of quote.").optional(),
29733
+ body: z.string({ max: 2000 }).describe("Review comment, at most 2,000 characters."),
29734
+ reply_to: z.string().describe("Optional comment id to reply to.").optional()
29735
+ })
29736
+ },
29737
+ {
29738
+ name: "dispatch_suggest",
29739
+ 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. ${ISSUE_REFERENCE}`,
29740
+ arguments: (z) => ({
29741
+ issue: z.string().describe(ISSUE_REFERENCE),
29742
+ artifact: z.string().describe("Artifact slug or id containing the quoted text."),
29743
+ quote: z.string().describe("Exact document text to replace."),
29744
+ replace_with: z.string().describe("Replacement text."),
29745
+ body: z.string({ max: 2000 }).describe("Optional rationale, at most 2,000 characters.").optional(),
29746
+ occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based occurrence of quote.").optional()
29747
+ })
29748
+ },
29749
+ {
29750
+ name: "dispatch_message",
29751
+ description: "Post a plain issue update. Do not use it for a decision or line-specific review; use dispatch_ask " + `or dispatch_comment instead. Body is at most 2,000 characters. ${ISSUE_REFERENCE}`,
29752
+ arguments: (z) => ({
29753
+ issue: z.string().describe(ISSUE_REFERENCE),
29754
+ body: z.string({ max: 2000 }).describe("Update text, at most 2,000 characters.")
29755
+ })
29756
+ },
29757
+ {
29758
+ name: "dispatch_doc_edit",
29759
+ description: "Apply deterministic text edits to a document. Do not use it for review feedback or for reading; use " + `dispatch_comment, dispatch_suggest, or dispatch_doc_read instead. ${ISSUE_REFERENCE}`,
29760
+ arguments: (z) => ({
29761
+ issue: z.string().describe(ISSUE_REFERENCE),
29762
+ artifact: z.string().describe("Artifact slug or id for the document."),
29763
+ ops: z.array(z.object({
29764
+ op: z.enum(DOC_EDIT_OPS).describe("Edit operation."),
29765
+ find: z.string().describe("Text to find for replace or delete.").optional(),
29766
+ with: z.string().describe("Replacement text for replace.").optional(),
29767
+ occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based match occurrence.").optional(),
29768
+ markdown: z.string().describe("Markdown to insert.").optional(),
29769
+ after: z.string().describe("Anchor after which to insert.").optional(),
29770
+ before: z.string().describe("Anchor before which to insert.").optional()
29771
+ })).describe("Flat tagged edits; the server validates fields required for each operation."),
29772
+ summary: z.string().describe("Optional named-version summary.").optional()
29773
+ })
29774
+ },
29775
+ {
29776
+ name: "dispatch_doc_read",
29777
+ 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 or issue; issue plus an omitted artifact reads the primary document. " + `${ISSUE_REFERENCE}`,
29778
+ arguments: (z) => ({
29779
+ issue: z.string().describe(ISSUE_REFERENCE).optional(),
29780
+ artifact: z.string().describe("Optional artifact slug or id; primary document by default.").optional(),
29781
+ version: z.number({ int: true, min: 1 }).describe("Optional version number.").optional(),
29782
+ ref: z.string().describe("Optional dispatch:// document reference.").optional()
29783
+ })
29784
+ },
29785
+ {
29786
+ name: "dispatch_artifact",
29787
+ description: "Upload a local file as an issue artifact. Do not use it to edit a live document; use dispatch_doc_edit " + `instead. Files are limited to 25 MiB. ${ISSUE_REFERENCE}`,
29788
+ arguments: (z) => ({
29789
+ issue: z.string().describe(ISSUE_REFERENCE),
29790
+ name: z.string().describe("Artifact filename shown in Dispatch."),
29791
+ path: z.string().describe("Local path to the file to upload."),
29792
+ primary: z.boolean().describe("Make this document the issue primary artifact.").optional(),
29793
+ summary: z.string().describe("Optional version summary.").optional()
29794
+ })
29795
+ },
29796
+ {
29797
+ name: "dispatch_read",
29798
+ description: "Read an issue summary, targeted ask, or targeted comment reply chain. Do not use it for document " + "contents; use dispatch_doc_read instead. Supply issue or ref. " + ISSUE_REFERENCE,
29799
+ arguments: (z) => ({
29800
+ issue: z.string().describe(ISSUE_REFERENCE).optional(),
29801
+ ref: z.string().describe("Optional dispatch:// issue reference.").optional()
29802
+ })
29803
+ }
29804
+ ];
29767
29805
  // ../contracts/src/envelope.ts
29768
29806
  var isSubject = (value) => typeof value === "string" && value.length > 0;
29769
29807
  var EnvelopeSchema = object({
@@ -30748,57 +30786,20 @@ function replyWith(envelope) {
30748
30786
  return;
30749
30787
  return `envoy_send(session_id="${envelope.source_session}", message="...")`;
30750
30788
  }
30751
- var DispatchEventSchema = object({
30752
- issue_key: string2(),
30753
- type: string2(),
30754
- actor: object({ kind: string2(), id: string2().optional() }).passthrough(),
30755
- payload: object({}).passthrough()
30756
- });
30757
- var IssuePayloadSchema = object({
30758
- title: string2().optional(),
30759
- status: string2().optional(),
30760
- route: string2().nullish()
30761
- });
30762
- var ArtifactCreatedPayloadSchema = object({
30763
- artifact: object({ name: string2().optional() }).optional()
30764
- });
30765
- var ArtifactVersionPayloadSchema = object({
30766
- name: string2().optional(),
30767
- version: object({ number: number2().optional(), summary: string2().nullish() }).optional(),
30768
- diff: string2().optional()
30769
- });
30770
- var AskPayloadSchema = object({
30771
- question: string2().optional(),
30772
- options: array(object({ label: string2().optional() })).nullish(),
30773
- answer: object({ selected: array(string2()).nullish(), text: string2().nullish() }).nullish()
30774
- });
30775
- var CommentPayloadSchema = object({
30776
- artifact_name: string2().optional(),
30777
- body: string2().optional(),
30778
- reply_to: string2().nullish(),
30779
- anchor: object({ quote: string2().optional() }).nullish(),
30780
- suggestion: object({ replace_with: string2().optional() }).nullish()
30781
- });
30782
- var MessagePayloadSchema = object({ body: string2().optional() });
30783
- var ChildStatusPayloadSchema = object({
30784
- child_key: string2().optional(),
30785
- from: string2().optional(),
30786
- to: string2().optional()
30787
- });
30788
30789
  var DISPATCH_PAYLOAD_SCHEMAS = {
30789
- "issue.created": IssuePayloadSchema,
30790
- "issue.updated": IssuePayloadSchema,
30791
- "issue.closed": IssuePayloadSchema,
30792
- "artifact.created": ArtifactCreatedPayloadSchema,
30793
- "artifact.version": ArtifactVersionPayloadSchema,
30794
- "ask.opened": AskPayloadSchema,
30795
- "ask.answered": AskPayloadSchema,
30796
- "comment.created": CommentPayloadSchema,
30797
- "comment.resolved": CommentPayloadSchema,
30798
- "suggestion.accepted": CommentPayloadSchema,
30799
- "suggestion.rejected": CommentPayloadSchema,
30800
- "message.created": MessagePayloadSchema,
30801
- "child.status": ChildStatusPayloadSchema
30790
+ "issue.created": IssueEventPayloadSchema,
30791
+ "issue.updated": IssueEventPayloadSchema,
30792
+ "issue.closed": IssueEventPayloadSchema,
30793
+ "artifact.created": ArtifactCreatedEventPayloadSchema,
30794
+ "artifact.version": ArtifactVersionEventPayloadSchema,
30795
+ "ask.opened": AskEventPayloadSchema,
30796
+ "ask.answered": AskEventPayloadSchema,
30797
+ "comment.created": CommentEventPayloadSchema,
30798
+ "comment.resolved": CommentEventPayloadSchema,
30799
+ "suggestion.accepted": CommentEventPayloadSchema,
30800
+ "suggestion.rejected": CommentEventPayloadSchema,
30801
+ "message.created": MessageEventPayloadSchema,
30802
+ "child.status": ChildStatusEventPayloadSchema
30802
30803
  };
30803
30804
  function dispatchPayload(event) {
30804
30805
  const schema = DISPATCH_PAYLOAD_SCHEMAS[event.type];
@@ -31182,7 +31183,8 @@ class DispatchClient {
31182
31183
  form.set("primary", String(input.primary));
31183
31184
  if (input.summary !== undefined)
31184
31185
  form.set("summary", input.summary);
31185
- form.set("actor", JSON.stringify(input.actor));
31186
+ if (input.actor !== undefined)
31187
+ form.set("actor", JSON.stringify(input.actor));
31186
31188
  form.set("file", input.file, input.name);
31187
31189
  return this.#form("POST", ["api", "v1", "issues", await this.#resolveIssue(issue), "artifacts"], form);
31188
31190
  }
package/dist/legion.js CHANGED
@@ -16114,122 +16114,6 @@ var require_mod4 = __commonJS(function(exports) {
16114
16114
  // extensions/legion.ts
16115
16115
  import path4 from "path";
16116
16116
 
16117
- // ../contracts/src/dispatch-tools.ts
16118
- var ISSUE_REFERENCE = "An issue is a native KEY or external owner/repo#n reference; an external reference creates its native issue on first use in the repository's mapped project (DISPATCH_REPO_PROJECTS) or, failing that, the default project (DISPATCH_DEFAULT_PROJECT).";
16119
- var ASK_URGENCIES = ["low", "med", "high", "blocking"];
16120
- var DOC_EDIT_OPS = ["replace", "delete", "insert"];
16121
- var dispatchToolSpecs = [
16122
- {
16123
- name: "dispatch_issue",
16124
- description: "Create a native Dispatch issue for newly tracked work. Do not use it when an existing issue " + `already covers the work; read or update that issue instead. ${ISSUE_REFERENCE}`,
16125
- arguments: (z) => ({
16126
- project: z.string().describe("Project key for the new issue."),
16127
- title: z.string().describe("Concise issue title."),
16128
- parent: z.string().describe("Optional parent issue.").optional(),
16129
- external: z.string().describe("Optional external issue reference.").optional(),
16130
- spec: z.string().describe("Optional initial primary-document markdown.").optional()
16131
- })
16132
- },
16133
- {
16134
- name: "dispatch_ask",
16135
- description: "Open a durable, answerable decision on an issue. Do not use it for a status update or discussion; " + `use dispatch_message instead. Question is at most 800 characters and has at most 8 options. ${ISSUE_REFERENCE}`,
16136
- arguments: (z) => ({
16137
- issue: z.string().describe(ISSUE_REFERENCE),
16138
- question: z.string({ max: 800 }).describe("Decision question, at most 800 characters."),
16139
- options: z.array(z.object({
16140
- label: z.string().describe("Selectable option label."),
16141
- description: z.string().describe("Optional option context.").optional()
16142
- }), { max: 8 }).describe("Optional choices, at most 8.").optional(),
16143
- multiple: z.boolean().describe("Whether multiple choices may be selected.").optional(),
16144
- custom: z.boolean().describe("Whether a free-text answer is allowed.").optional(),
16145
- urgency: z.enum(ASK_URGENCIES).describe("Optional decision urgency.").optional(),
16146
- anchor: z.object({
16147
- artifact: z.string().describe("Artifact slug or id containing the quoted text."),
16148
- quote: z.string().describe("Exact text the decision concerns."),
16149
- occurrence: z.number({ int: true, min: 0 }).describe("Zero-based occurrence of the quote.").optional()
16150
- }).describe("Optional document location for the question.").optional()
16151
- })
16152
- },
16153
- {
16154
- name: "dispatch_comment",
16155
- description: "Add review feedback to an issue or document quote. Do not use it for an exact replacement; use " + `dispatch_suggest instead. Body is at most 2,000 characters. ${ISSUE_REFERENCE}`,
16156
- arguments: (z) => ({
16157
- issue: z.string().describe(ISSUE_REFERENCE),
16158
- artifact: z.string().describe("Artifact slug or id required when quote is given.").optional(),
16159
- quote: z.string().describe("Optional exact quoted document text.").optional(),
16160
- occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based occurrence of quote.").optional(),
16161
- body: z.string({ max: 2000 }).describe("Review comment, at most 2,000 characters."),
16162
- reply_to: z.string().describe("Optional comment id to reply to.").optional()
16163
- })
16164
- },
16165
- {
16166
- name: "dispatch_suggest",
16167
- 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. ${ISSUE_REFERENCE}`,
16168
- arguments: (z) => ({
16169
- issue: z.string().describe(ISSUE_REFERENCE),
16170
- artifact: z.string().describe("Artifact slug or id containing the quoted text."),
16171
- quote: z.string().describe("Exact document text to replace."),
16172
- replace_with: z.string().describe("Replacement text."),
16173
- body: z.string({ max: 2000 }).describe("Optional rationale, at most 2,000 characters.").optional(),
16174
- occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based occurrence of quote.").optional()
16175
- })
16176
- },
16177
- {
16178
- name: "dispatch_message",
16179
- description: "Post a plain issue update. Do not use it for a decision or line-specific review; use dispatch_ask " + `or dispatch_comment instead. Body is at most 2,000 characters. ${ISSUE_REFERENCE}`,
16180
- arguments: (z) => ({
16181
- issue: z.string().describe(ISSUE_REFERENCE),
16182
- body: z.string({ max: 2000 }).describe("Update text, at most 2,000 characters.")
16183
- })
16184
- },
16185
- {
16186
- name: "dispatch_doc_edit",
16187
- description: "Apply deterministic text edits to a document. Do not use it for review feedback or for reading; use " + `dispatch_comment, dispatch_suggest, or dispatch_doc_read instead. ${ISSUE_REFERENCE}`,
16188
- arguments: (z) => ({
16189
- issue: z.string().describe(ISSUE_REFERENCE),
16190
- artifact: z.string().describe("Artifact slug or id for the document."),
16191
- ops: z.array(z.object({
16192
- op: z.enum(DOC_EDIT_OPS).describe("Edit operation."),
16193
- find: z.string().describe("Text to find for replace or delete.").optional(),
16194
- with: z.string().describe("Replacement text for replace.").optional(),
16195
- occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based match occurrence.").optional(),
16196
- markdown: z.string().describe("Markdown to insert.").optional(),
16197
- after: z.string().describe("Anchor after which to insert.").optional(),
16198
- before: z.string().describe("Anchor before which to insert.").optional()
16199
- })).describe("Flat tagged edits; the server validates fields required for each operation."),
16200
- summary: z.string().describe("Optional named-version summary.").optional()
16201
- })
16202
- },
16203
- {
16204
- name: "dispatch_doc_read",
16205
- 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 or issue; issue plus an omitted artifact reads the primary document. " + `${ISSUE_REFERENCE}`,
16206
- arguments: (z) => ({
16207
- issue: z.string().describe(ISSUE_REFERENCE).optional(),
16208
- artifact: z.string().describe("Optional artifact slug or id; primary document by default.").optional(),
16209
- version: z.number({ int: true, min: 1 }).describe("Optional version number.").optional(),
16210
- ref: z.string().describe("Optional dispatch:// document reference.").optional()
16211
- })
16212
- },
16213
- {
16214
- name: "dispatch_artifact",
16215
- description: "Upload a local file as an issue artifact. Do not use it to edit a live document; use dispatch_doc_edit " + `instead. Files are limited to 25 MiB. ${ISSUE_REFERENCE}`,
16216
- arguments: (z) => ({
16217
- issue: z.string().describe(ISSUE_REFERENCE),
16218
- name: z.string().describe("Artifact filename shown in Dispatch."),
16219
- path: z.string().describe("Local path to the file to upload."),
16220
- primary: z.boolean().describe("Make this document the issue primary artifact.").optional(),
16221
- summary: z.string().describe("Optional version summary.").optional()
16222
- })
16223
- },
16224
- {
16225
- name: "dispatch_read",
16226
- description: "Read an issue summary, targeted ask, or targeted comment reply chain. Do not use it for document " + "contents; use dispatch_doc_read instead. Supply issue or ref. " + ISSUE_REFERENCE,
16227
- arguments: (z) => ({
16228
- issue: z.string().describe(ISSUE_REFERENCE).optional(),
16229
- ref: z.string().describe("Optional dispatch:// issue reference.").optional()
16230
- })
16231
- }
16232
- ];
16233
16117
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
16234
16118
  var exports_external = {};
16235
16119
  __export(exports_external, {
@@ -29762,6 +29646,160 @@ function date4(params) {
29762
29646
 
29763
29647
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/classic/external.js
29764
29648
  config(en_default());
29649
+ // ../contracts/src/dispatch-api.ts
29650
+ var DispatchEventSchema = object({
29651
+ issue_key: string2(),
29652
+ type: string2(),
29653
+ actor: object({ kind: string2(), id: string2().optional() }).passthrough(),
29654
+ payload: object({}).passthrough()
29655
+ });
29656
+ var IssueEventPayloadSchema = object({
29657
+ title: string2().optional(),
29658
+ status: string2().optional(),
29659
+ route: string2().nullish()
29660
+ });
29661
+ var ArtifactCreatedEventPayloadSchema = object({
29662
+ artifact: object({ name: string2().optional() }).optional()
29663
+ });
29664
+ var ArtifactVersionEventPayloadSchema = object({
29665
+ name: string2().optional(),
29666
+ version: object({ number: number2().optional(), summary: string2().nullish() }).optional(),
29667
+ diff: string2().optional()
29668
+ });
29669
+ var AskEventPayloadSchema = object({
29670
+ question: string2().optional(),
29671
+ options: array(object({ label: string2().optional() })).nullish(),
29672
+ answer: object({ selected: array(string2()).nullish(), text: string2().nullish() }).nullish()
29673
+ });
29674
+ var CommentEventPayloadSchema = object({
29675
+ artifact_name: string2().optional(),
29676
+ body: string2().optional(),
29677
+ reply_to: string2().nullish(),
29678
+ anchor: object({ quote: string2().optional() }).nullish(),
29679
+ suggestion: object({ replace_with: string2().optional() }).nullish()
29680
+ });
29681
+ var MessageEventPayloadSchema = object({ body: string2().optional() });
29682
+ var ChildStatusEventPayloadSchema = object({
29683
+ child_key: string2().optional(),
29684
+ from: string2().optional(),
29685
+ to: string2().optional()
29686
+ });
29687
+ // ../contracts/src/dispatch-tools.ts
29688
+ var ISSUE_REFERENCE = "An issue is a native KEY or external owner/repo#n reference; an external reference creates its native issue on first use in the repository's mapped project (DISPATCH_REPO_PROJECTS) or, failing that, the default project (DISPATCH_DEFAULT_PROJECT).";
29689
+ var ASK_URGENCIES = ["low", "med", "high", "blocking"];
29690
+ var DOC_EDIT_OPS = ["replace", "delete", "insert"];
29691
+ var dispatchToolSpecs = [
29692
+ {
29693
+ name: "dispatch_issue",
29694
+ description: "Create a native Dispatch issue for newly tracked work. Do not use it when an existing issue " + `already covers the work; read or update that issue instead. ${ISSUE_REFERENCE}`,
29695
+ arguments: (z) => ({
29696
+ project: z.string().describe("Project key for the new issue."),
29697
+ title: z.string().describe("Concise issue title."),
29698
+ parent: z.string().describe("Optional parent issue.").optional(),
29699
+ external: z.string().describe("Optional external issue reference.").optional(),
29700
+ spec: z.string().describe("Optional initial primary-document markdown.").optional()
29701
+ })
29702
+ },
29703
+ {
29704
+ name: "dispatch_ask",
29705
+ description: "Open a durable, answerable decision on an issue. Do not use it for a status update or discussion; " + `use dispatch_message instead. Question is at most 800 characters and has at most 8 options. ${ISSUE_REFERENCE}`,
29706
+ arguments: (z) => ({
29707
+ issue: z.string().describe(ISSUE_REFERENCE),
29708
+ question: z.string({ max: 800 }).describe("Decision question, at most 800 characters."),
29709
+ options: z.array(z.object({
29710
+ label: z.string().describe("Selectable option label."),
29711
+ description: z.string().describe("Optional option context.").optional()
29712
+ }), { max: 8 }).describe("Optional choices, at most 8.").optional(),
29713
+ multiple: z.boolean().describe("Whether multiple choices may be selected.").optional(),
29714
+ custom: z.boolean().describe("Whether a free-text answer is allowed.").optional(),
29715
+ urgency: z.enum(ASK_URGENCIES).describe("Optional decision urgency.").optional(),
29716
+ anchor: z.object({
29717
+ artifact: z.string().describe("Artifact slug or id containing the quoted text."),
29718
+ quote: z.string().describe("Exact text the decision concerns."),
29719
+ occurrence: z.number({ int: true, min: 0 }).describe("Zero-based occurrence of the quote.").optional()
29720
+ }).describe("Optional document location for the question.").optional()
29721
+ })
29722
+ },
29723
+ {
29724
+ name: "dispatch_comment",
29725
+ description: "Add review feedback to an issue or document quote. Do not use it for an exact replacement; use " + `dispatch_suggest instead. Body is at most 2,000 characters. ${ISSUE_REFERENCE}`,
29726
+ arguments: (z) => ({
29727
+ issue: z.string().describe(ISSUE_REFERENCE),
29728
+ artifact: z.string().describe("Artifact slug or id required when quote is given.").optional(),
29729
+ quote: z.string().describe("Optional exact quoted document text.").optional(),
29730
+ occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based occurrence of quote.").optional(),
29731
+ body: z.string({ max: 2000 }).describe("Review comment, at most 2,000 characters."),
29732
+ reply_to: z.string().describe("Optional comment id to reply to.").optional()
29733
+ })
29734
+ },
29735
+ {
29736
+ name: "dispatch_suggest",
29737
+ 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. ${ISSUE_REFERENCE}`,
29738
+ arguments: (z) => ({
29739
+ issue: z.string().describe(ISSUE_REFERENCE),
29740
+ artifact: z.string().describe("Artifact slug or id containing the quoted text."),
29741
+ quote: z.string().describe("Exact document text to replace."),
29742
+ replace_with: z.string().describe("Replacement text."),
29743
+ body: z.string({ max: 2000 }).describe("Optional rationale, at most 2,000 characters.").optional(),
29744
+ occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based occurrence of quote.").optional()
29745
+ })
29746
+ },
29747
+ {
29748
+ name: "dispatch_message",
29749
+ description: "Post a plain issue update. Do not use it for a decision or line-specific review; use dispatch_ask " + `or dispatch_comment instead. Body is at most 2,000 characters. ${ISSUE_REFERENCE}`,
29750
+ arguments: (z) => ({
29751
+ issue: z.string().describe(ISSUE_REFERENCE),
29752
+ body: z.string({ max: 2000 }).describe("Update text, at most 2,000 characters.")
29753
+ })
29754
+ },
29755
+ {
29756
+ name: "dispatch_doc_edit",
29757
+ description: "Apply deterministic text edits to a document. Do not use it for review feedback or for reading; use " + `dispatch_comment, dispatch_suggest, or dispatch_doc_read instead. ${ISSUE_REFERENCE}`,
29758
+ arguments: (z) => ({
29759
+ issue: z.string().describe(ISSUE_REFERENCE),
29760
+ artifact: z.string().describe("Artifact slug or id for the document."),
29761
+ ops: z.array(z.object({
29762
+ op: z.enum(DOC_EDIT_OPS).describe("Edit operation."),
29763
+ find: z.string().describe("Text to find for replace or delete.").optional(),
29764
+ with: z.string().describe("Replacement text for replace.").optional(),
29765
+ occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based match occurrence.").optional(),
29766
+ markdown: z.string().describe("Markdown to insert.").optional(),
29767
+ after: z.string().describe("Anchor after which to insert.").optional(),
29768
+ before: z.string().describe("Anchor before which to insert.").optional()
29769
+ })).describe("Flat tagged edits; the server validates fields required for each operation."),
29770
+ summary: z.string().describe("Optional named-version summary.").optional()
29771
+ })
29772
+ },
29773
+ {
29774
+ name: "dispatch_doc_read",
29775
+ 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 or issue; issue plus an omitted artifact reads the primary document. " + `${ISSUE_REFERENCE}`,
29776
+ arguments: (z) => ({
29777
+ issue: z.string().describe(ISSUE_REFERENCE).optional(),
29778
+ artifact: z.string().describe("Optional artifact slug or id; primary document by default.").optional(),
29779
+ version: z.number({ int: true, min: 1 }).describe("Optional version number.").optional(),
29780
+ ref: z.string().describe("Optional dispatch:// document reference.").optional()
29781
+ })
29782
+ },
29783
+ {
29784
+ name: "dispatch_artifact",
29785
+ description: "Upload a local file as an issue artifact. Do not use it to edit a live document; use dispatch_doc_edit " + `instead. Files are limited to 25 MiB. ${ISSUE_REFERENCE}`,
29786
+ arguments: (z) => ({
29787
+ issue: z.string().describe(ISSUE_REFERENCE),
29788
+ name: z.string().describe("Artifact filename shown in Dispatch."),
29789
+ path: z.string().describe("Local path to the file to upload."),
29790
+ primary: z.boolean().describe("Make this document the issue primary artifact.").optional(),
29791
+ summary: z.string().describe("Optional version summary.").optional()
29792
+ })
29793
+ },
29794
+ {
29795
+ name: "dispatch_read",
29796
+ description: "Read an issue summary, targeted ask, or targeted comment reply chain. Do not use it for document " + "contents; use dispatch_doc_read instead. Supply issue or ref. " + ISSUE_REFERENCE,
29797
+ arguments: (z) => ({
29798
+ issue: z.string().describe(ISSUE_REFERENCE).optional(),
29799
+ ref: z.string().describe("Optional dispatch:// issue reference.").optional()
29800
+ })
29801
+ }
29802
+ ];
29765
29803
  // ../contracts/src/envelope.ts
29766
29804
  var isSubject = (value) => typeof value === "string" && value.length > 0;
29767
29805
  var EnvelopeSchema = object({
@@ -30235,9 +30273,6 @@ async function handleLegionControlDirective(directive, actions) {
30235
30273
  case "reclaim-architect":
30236
30274
  await actions.reclaimArchitect();
30237
30275
  break;
30238
- case "shutdown":
30239
- actions.requestShutdown();
30240
- break;
30241
30276
  }
30242
30277
  actions.acknowledge();
30243
30278
  } catch (error) {
@@ -30249,8 +30284,6 @@ function parseControlDirective(raw) {
30249
30284
  if (typeof payload !== "object" || payload === null || !("type" in payload)) {
30250
30285
  throw new Error("Legion control directive must be an object with a type");
30251
30286
  }
30252
- if (payload.type === "shutdown")
30253
- return { type: "shutdown" };
30254
30287
  if (payload.type === "reclaim-architect") {
30255
30288
  if (!("redeliver" in payload) || typeof payload.redeliver !== "object" || payload.redeliver === null || !("topic" in payload.redeliver) || typeof payload.redeliver.topic !== "string" || !("payload" in payload.redeliver) || typeof payload.redeliver.payload !== "string" || !("eventId" in payload.redeliver) || typeof payload.redeliver.eventId !== "string") {
30256
30289
  throw new Error("Legion control directive is missing redelivery metadata");
@@ -31245,57 +31278,20 @@ function replyWith(envelope) {
31245
31278
  return;
31246
31279
  return `envoy_send(session_id="${envelope.source_session}", message="...")`;
31247
31280
  }
31248
- var DispatchEventSchema = object({
31249
- issue_key: string2(),
31250
- type: string2(),
31251
- actor: object({ kind: string2(), id: string2().optional() }).passthrough(),
31252
- payload: object({}).passthrough()
31253
- });
31254
- var IssuePayloadSchema = object({
31255
- title: string2().optional(),
31256
- status: string2().optional(),
31257
- route: string2().nullish()
31258
- });
31259
- var ArtifactCreatedPayloadSchema = object({
31260
- artifact: object({ name: string2().optional() }).optional()
31261
- });
31262
- var ArtifactVersionPayloadSchema = object({
31263
- name: string2().optional(),
31264
- version: object({ number: number2().optional(), summary: string2().nullish() }).optional(),
31265
- diff: string2().optional()
31266
- });
31267
- var AskPayloadSchema = object({
31268
- question: string2().optional(),
31269
- options: array(object({ label: string2().optional() })).nullish(),
31270
- answer: object({ selected: array(string2()).nullish(), text: string2().nullish() }).nullish()
31271
- });
31272
- var CommentPayloadSchema = object({
31273
- artifact_name: string2().optional(),
31274
- body: string2().optional(),
31275
- reply_to: string2().nullish(),
31276
- anchor: object({ quote: string2().optional() }).nullish(),
31277
- suggestion: object({ replace_with: string2().optional() }).nullish()
31278
- });
31279
- var MessagePayloadSchema = object({ body: string2().optional() });
31280
- var ChildStatusPayloadSchema = object({
31281
- child_key: string2().optional(),
31282
- from: string2().optional(),
31283
- to: string2().optional()
31284
- });
31285
31281
  var DISPATCH_PAYLOAD_SCHEMAS = {
31286
- "issue.created": IssuePayloadSchema,
31287
- "issue.updated": IssuePayloadSchema,
31288
- "issue.closed": IssuePayloadSchema,
31289
- "artifact.created": ArtifactCreatedPayloadSchema,
31290
- "artifact.version": ArtifactVersionPayloadSchema,
31291
- "ask.opened": AskPayloadSchema,
31292
- "ask.answered": AskPayloadSchema,
31293
- "comment.created": CommentPayloadSchema,
31294
- "comment.resolved": CommentPayloadSchema,
31295
- "suggestion.accepted": CommentPayloadSchema,
31296
- "suggestion.rejected": CommentPayloadSchema,
31297
- "message.created": MessagePayloadSchema,
31298
- "child.status": ChildStatusPayloadSchema
31282
+ "issue.created": IssueEventPayloadSchema,
31283
+ "issue.updated": IssueEventPayloadSchema,
31284
+ "issue.closed": IssueEventPayloadSchema,
31285
+ "artifact.created": ArtifactCreatedEventPayloadSchema,
31286
+ "artifact.version": ArtifactVersionEventPayloadSchema,
31287
+ "ask.opened": AskEventPayloadSchema,
31288
+ "ask.answered": AskEventPayloadSchema,
31289
+ "comment.created": CommentEventPayloadSchema,
31290
+ "comment.resolved": CommentEventPayloadSchema,
31291
+ "suggestion.accepted": CommentEventPayloadSchema,
31292
+ "suggestion.rejected": CommentEventPayloadSchema,
31293
+ "message.created": MessageEventPayloadSchema,
31294
+ "child.status": ChildStatusEventPayloadSchema
31299
31295
  };
31300
31296
  function dispatchPayload(event) {
31301
31297
  const schema = DISPATCH_PAYLOAD_SCHEMAS[event.type];
@@ -31672,7 +31668,8 @@ class DispatchClient {
31672
31668
  form.set("primary", String(input.primary));
31673
31669
  if (input.summary !== undefined)
31674
31670
  form.set("summary", input.summary);
31675
- form.set("actor", JSON.stringify(input.actor));
31671
+ if (input.actor !== undefined)
31672
+ form.set("actor", JSON.stringify(input.actor));
31676
31673
  form.set("file", input.file, input.name);
31677
31674
  return this.#form("POST", ["api", "v1", "issues", await this.#resolveIssue(issue), "artifacts"], form);
31678
31675
  }
@@ -33336,7 +33333,6 @@ function legionExtension(pi) {
33336
33333
  }
33337
33334
  await handleLegionControlDirective(directive, {
33338
33335
  reclaimArchitect,
33339
- requestShutdown: () => pi.sendMessage({ type: "shutdown-request" }),
33340
33336
  acknowledge: () => {
33341
33337
  if (reply)
33342
33338
  connection.publish(reply, controlCodec.encode(JSON.stringify({ type: "ack" })));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/pi-legion-envoy",
3
- "version": "0.18.0",
3
+ "version": "0.18.2",
4
4
  "type": "module",
5
5
  "omp": {
6
6
  "extensions": [