@sjawhar/opencode-legion-envoy 1.9.0 → 1.11.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.
@@ -13633,10 +13633,20 @@ var CommentEventPayloadSchema = object({
13633
13633
  var MessageEventPayloadSchema = object({
13634
13634
  id: string2().optional(),
13635
13635
  body: string2().optional(),
13636
- reply_to: string2().nullish(),
13636
+ target: string2().nullish(),
13637
+ in_reply_to: string2().nullish(),
13637
13638
  reply_body: string2().optional(),
13638
13639
  author: object({ kind: string2(), id: string2() }).optional()
13639
13640
  });
13641
+ var MessageDeliveryEventPayloadSchema = object({
13642
+ message_id: string2().optional(),
13643
+ attempt: number2().int().positive().optional(),
13644
+ delivery: _enum2(["btw", "aside", "steer"]).optional(),
13645
+ session_id: string2().optional(),
13646
+ title: string2().optional(),
13647
+ state: _enum2(["sent", "failed"]).optional(),
13648
+ error: string2().optional()
13649
+ });
13640
13650
  var ChildStatusEventPayloadSchema = object({
13641
13651
  child_key: string2().optional(),
13642
13652
  from: string2().optional(),
@@ -13730,7 +13740,7 @@ var SPEC_SECTIONS = [
13730
13740
  ];
13731
13741
  var SPEC_WRITING_GUIDANCE = `When writing a spec, use these sections in order: ${SPEC_SECTIONS.join(", ")}. ` + "Write for a reader who has not seen the code: plain sentences, every identifier expanded on " + "first use, no coined shorthand; see skills/dispatch Writing for the human and Writing a spec.";
13732
13742
  var ASK_URGENCIES = ["low", "med", "high", "blocking"];
13733
- var DOC_EDIT_OPS = ["replace", "delete", "insert"];
13743
+ var DOC_EDIT_OPS = ["replace", "delete", "insert", "retype"];
13734
13744
  var dispatchToolSpecs = [
13735
13745
  {
13736
13746
  name: "dispatch_issue",
@@ -13835,12 +13845,12 @@ var dispatchToolSpecs = [
13835
13845
  arguments: (z) => ({
13836
13846
  issue: z.string().describe(ISSUE_REFERENCE),
13837
13847
  body: z.string({ max: 2000 }).describe("Update text, at most 2,000 characters."),
13838
- reply_to: z.string().describe("Optional message id or dispatch://KEY/message/<id> reference to reply to, threading " + "this message under it so the reply stays with the original in the Conversation.").optional()
13848
+ in_reply_to: z.string().describe("Optional message id or dispatch://KEY/message/<id> reference to reply to, threading " + "this message under it so the reply stays with the original in the Conversation.").optional()
13839
13849
  })
13840
13850
  },
13841
13851
  {
13842
13852
  name: "dispatch_doc_edit",
13843
- description: "Apply deterministic text edits to an issue or project document. Do not use it for review feedback or for reading; use " + "dispatch_comment, dispatch_suggest, or dispatch_doc_read instead. The spec (or any document) holds requirements, " + `design, and decisions - never progress, status, or timestamps. ${OWNER_REFERENCE} ${SPEC_WRITING_GUIDANCE}`,
13853
+ description: "Apply deterministic document edits, including retyping an identified paragraph into a schema-declared typed block. " + "Do not use it for review feedback or for reading; use dispatch_comment, dispatch_suggest, or dispatch_doc_read instead. " + `The spec (or any document) holds requirements, design, and decisions - never progress, status, or timestamps. ${OWNER_REFERENCE} ${SPEC_WRITING_GUIDANCE}`,
13844
13854
  arguments: (z) => ({
13845
13855
  issue: z.string().describe(ISSUE_REFERENCE).optional(),
13846
13856
  project: z.string().describe("Project key owning the document.").optional(),
@@ -13853,7 +13863,10 @@ var dispatchToolSpecs = [
13853
13863
  occurrence: z.number({ int: true, min: 0 }).describe("Optional zero-based match occurrence.").optional(),
13854
13864
  markdown: z.string().describe("Markdown to insert.").optional(),
13855
13865
  after: z.string().describe("Anchor after which to insert.").optional(),
13856
- before: z.string().describe("Anchor before which to insert.").optional()
13866
+ before: z.string().describe("Anchor before which to insert.").optional(),
13867
+ block: z.string().describe("Block id to retype.").optional(),
13868
+ type: z.string().describe("Typed block name for retype.").optional(),
13869
+ attributes: z.unknown().describe("Typed block attributes for retype.").optional()
13857
13870
  })).describe("Flat tagged edits; the server validates fields required for each operation."),
13858
13871
  summary: z.string().describe("Optional named-version summary.").optional()
13859
13872
  }),
@@ -14297,6 +14310,7 @@ function zodSchemaApi(zod) {
14297
14310
  },
14298
14311
  boolean: () => api.boolean(),
14299
14312
  enum: (values) => api.enum(values),
14313
+ unknown: () => api.unknown(),
14300
14314
  array: (item, opts = {}) => {
14301
14315
  let schema = api.array(item);
14302
14316
  if (opts.min !== undefined)
@@ -14998,13 +15012,13 @@ function askId(args) {
14998
15012
  }
14999
15013
  return reference.id;
15000
15014
  }
15001
- function messageReplyTo(args) {
15002
- const replyTo = optionalString(args, "reply_to");
15003
- if (replyTo === undefined || !replyTo.startsWith("dispatch://"))
15004
- return replyTo;
15005
- const reference = parseDispatchRef(replyTo);
15015
+ function messageInReplyTo(args) {
15016
+ const inReplyTo = optionalString(args, "in_reply_to");
15017
+ if (inReplyTo === undefined || !inReplyTo.startsWith("dispatch://"))
15018
+ return inReplyTo;
15019
+ const reference = parseDispatchRef(inReplyTo);
15006
15020
  if (reference?.kind !== "message") {
15007
- throw new Error("reply_to must be a bare message id or a dispatch://.../message/<id> reference");
15021
+ throw new Error("in_reply_to must be a bare message id or a dispatch://.../message/<id> reference");
15008
15022
  }
15009
15023
  return reference.id;
15010
15024
  }
@@ -15452,10 +15466,10 @@ async function executeDispatchTool(input) {
15452
15466
  };
15453
15467
  }
15454
15468
  case "dispatch_message": {
15455
- const replyTo = messageReplyTo(args);
15469
+ const inReplyTo = messageInReplyTo(args);
15456
15470
  const message = await client.message(issue(), {
15457
15471
  body: stringArg(args, "body"),
15458
- ...replyTo === undefined ? {} : { reply_to: replyTo },
15472
+ ...inReplyTo === undefined ? {} : { in_reply_to: inReplyTo },
15459
15473
  actor
15460
15474
  });
15461
15475
  const messageRef = `dispatch://${message.issue_key}/message/${message.id}`;
@@ -15477,8 +15491,10 @@ async function executeDispatchTool(input) {
15477
15491
  ...summary === undefined ? {} : { summary },
15478
15492
  actor
15479
15493
  });
15494
+ const retyped = ops.filter((operation) => operation.op === "retype").length;
15495
+ const versionText = edited.version === null ? "no new version" : `version ${edited.version.number}`;
15480
15496
  return {
15481
- text: edited.version === null ? `Applied ${edited.applied} ops (no new version)` : `Applied ${edited.applied} ops (version ${edited.version.number})`,
15497
+ text: retyped === 0 ? `Applied ${edited.applied} ops (${versionText})` : `Applied ${edited.applied} ops; retyped ${retyped} block${retyped === 1 ? "" : "s"} (${versionText})`,
15482
15498
  details: writeResultDetails(resolved, {
15483
15499
  applied: edited.applied,
15484
15500
  ...edited.version === null ? {} : { version: edited.version.number }
@@ -15790,6 +15806,7 @@ var SessionWireSchema = object({
15790
15806
  title: string2(),
15791
15807
  topics: array(string2()),
15792
15808
  roles: array(string2()).optional(),
15809
+ capabilities: array(string2()).optional(),
15793
15810
  self_subscribed: boolean2(),
15794
15811
  last_seen: number2().int().optional()
15795
15812
  });
@@ -15898,6 +15915,7 @@ function createEnvoyClient(config) {
15898
15915
  topics: expandSubscriptionTopics(input.topics),
15899
15916
  port: input.port,
15900
15917
  title: input.title,
15918
+ ...input.capabilities === undefined ? {} : { capabilities: input.capabilities },
15901
15919
  driving: input.driving,
15902
15920
  ...input.selfSubscribed === undefined ? {} : { self_subscribed: input.selfSubscribed }
15903
15921
  }))),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/opencode-legion-envoy",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "type": "module",
5
5
  "main": "dist/src/server.js",
6
6
  "exports": {
@@ -199,13 +199,16 @@ exact `EditOp` shape:
199
199
 
200
200
  ```ts
201
201
  type EditOp = {
202
- op: "replace" | "delete" | "insert";
202
+ op: "replace" | "delete" | "insert" | "retype";
203
203
  find?: string;
204
204
  with?: string;
205
205
  occurrence?: number;
206
206
  markdown?: string;
207
207
  after?: string;
208
208
  before?: string;
209
+ block?: string;
210
+ type?: string;
211
+ attributes?: Record<string, unknown>;
209
212
  };
210
213
  ```
211
214
 
@@ -221,6 +224,9 @@ and deleting a cell's quoted text removes only that text.
221
224
 
222
225
  Use `replace` for inline continuation. Use zero-based `occurrence` for a repeated target; re-read a missing or ambiguous target before
223
226
  retrying. Pass `summary` to name the version when recording a decision.
227
+ `retype` turns the paragraph with `block` into the named typed `type` in place. It keeps the
228
+ block id and uses `attributes` for client-owned typed attributes. Use it when an existing
229
+ paragraph is the question that should become a decision.
224
230
 
225
231
  ## Typed blocks
226
232
 
@@ -236,6 +242,19 @@ quoted: `:::callout{kind="warning" title="Risk"}`. Do not write Pandoc-style `::
236
242
  block. Do not set attributes the schema marks `server: true`; the server ignores them and reasserts
237
243
  its authoritative value at settlement.
238
244
 
245
+ Questions about a document must be `ask` blocks, never an `Open questions` prose section. An ask
246
+ body is one or more question paragraphs followed by an optional bullet list of options, where each
247
+ item is `Label: description`. For example:
248
+
249
+ ```md
250
+ :::ask{urgency="high" multiple="false"}
251
+ Should we ship the migration?
252
+
253
+ - Ship: Release the verified change.
254
+ - Hold: Wait for another review.
255
+ :::
256
+ ```
257
+
239
258
  ## Comments and suggestions
240
259
 
241
260
  Add feedback with:
@@ -298,6 +317,24 @@ dispatch_message({ issue, body })
298
317
  It returns `details` `{ issue, topic, message }`. `body` is capped at 2,000 characters. A message is not a decision
299
318
  (`dispatch_ask`) or document feedback (`dispatch_comment`), and it does not wake anyone unless the issue is routed.
300
319
 
320
+ ### Targeted agent messages
321
+
322
+ A human can target the issue message at a live Envoy session or role as **BTW**, **Aside**, or
323
+ **Steer**. The incoming Dispatch frame names the issue and includes a `reply_with` instruction;
324
+ reply on the same open issue with the existing tool, never a new targeted send:
325
+
326
+ ```ts
327
+ dispatch_message({
328
+ issue: "CORE-1",
329
+ in_reply_to: "<targeted-message-id>",
330
+ body: "The requested answer.",
331
+ })
332
+ ```
333
+
334
+ `in_reply_to` correlates the answer under the human's message in its Conversation card. A BTW
335
+ delivery can post its answer automatically; use this call when the frame asks the primary agent to
336
+ reply. Agent bearers cannot set `target` or `delivery`.
337
+
301
338
  ## What comes back
302
339
 
303
340
  A write result's `details.topic` subscribes the host to its owner, and the first such subscription on an issue or document also tells