@sjawhar/opencode-legion-envoy 0.20.2 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,6 +29,10 @@ envoy.json (`~/.config/opencode/envoy.json`, merged with `<repo>/.opencode/envoy
29
29
  the session working directory, stamps it with the OpenCode session id and title, and stores
30
30
  `details.topic` as tool metadata so a successful mutation subscribes to that exact Dispatch topic.
31
31
 
32
+ `dispatch_artifact` accepts exactly one upload source: a local `path`, or inline `content`.
33
+ An architect can post a primary specification directly with
34
+ `{ issue, name: "spec.md", content: "# Design", primary: true }`.
35
+
32
36
  It also maintains the live session registry metadata needed for Envoy to discover OpenCode sessions and their API ports.
33
37
 
34
38
  Slack topic examples must use the real Slack `team_id`, for example:
@@ -13590,6 +13590,10 @@ var ChildStatusEventPayloadSchema = object({
13590
13590
  to: string2().optional()
13591
13591
  });
13592
13592
  // ../contracts/src/dispatch-tools.ts
13593
+ function dispatchToolSchema(spec, z, opts) {
13594
+ const shape = spec.arguments(z);
13595
+ return spec.validation === undefined ? z.object(shape, opts) : z.refineObject(shape, spec.validation.check, spec.validation.message, opts);
13596
+ }
13593
13597
  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).";
13594
13598
  var ASK_URGENCIES = ["low", "med", "high", "blocking"];
13595
13599
  var DOC_EDIT_OPS = ["replace", "delete", "insert"];
@@ -13616,7 +13620,6 @@ var dispatchToolSpecs = [
13616
13620
  description: z.string().describe("Optional option context.").optional()
13617
13621
  }), { max: 8 }).describe("Optional choices, at most 8.").optional(),
13618
13622
  multiple: z.boolean().describe("Whether multiple choices may be selected.").optional(),
13619
- custom: z.boolean().describe("Whether a free-text answer is allowed.").optional(),
13620
13623
  urgency: z.enum(ASK_URGENCIES).describe("Optional decision urgency.").optional(),
13621
13624
  anchor: z.object({
13622
13625
  artifact: z.string().describe("Artifact slug or id containing the quoted text."),
@@ -13687,14 +13690,22 @@ var dispatchToolSpecs = [
13687
13690
  },
13688
13691
  {
13689
13692
  name: "dispatch_artifact",
13690
- 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}`,
13693
+ description: "Attach a local file or inline text as an issue artifact. 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. ${ISSUE_REFERENCE}`,
13691
13694
  arguments: (z) => ({
13692
13695
  issue: z.string().describe(ISSUE_REFERENCE),
13693
13696
  name: z.string().describe("Artifact filename shown in Dispatch."),
13694
- path: z.string().describe("Local path to the file to upload."),
13697
+ path: z.string().describe("Local path to the file to upload.").optional(),
13698
+ content: z.string().describe("Inline text to store as a Markdown document.").optional(),
13695
13699
  primary: z.boolean().describe("Make this document the issue primary artifact.").optional(),
13696
13700
  summary: z.string().describe("Optional version summary.").optional()
13697
- })
13701
+ }),
13702
+ validation: {
13703
+ check: (value) => {
13704
+ const input = value;
13705
+ return typeof input.path === "string" !== (typeof input.content === "string");
13706
+ },
13707
+ message: "Exactly one of path or content is required."
13708
+ }
13698
13709
  },
13699
13710
  {
13700
13711
  name: "dispatch_read",
@@ -14082,7 +14093,18 @@ function zodSchemaApi(zod) {
14082
14093
  schema = schema.max(opts.max);
14083
14094
  return schema;
14084
14095
  },
14085
- object: (shape) => api.object(shape)
14096
+ object: (shape, opts = {}) => {
14097
+ let schema = api.object(shape);
14098
+ if (opts.strict)
14099
+ schema = schema.strict();
14100
+ return schema;
14101
+ },
14102
+ refineObject: (shape, check, message, opts = {}) => {
14103
+ let schema = api.object(shape);
14104
+ if (opts.strict)
14105
+ schema = schema.strict();
14106
+ return schema.refine(check, message);
14107
+ }
14086
14108
  };
14087
14109
  }
14088
14110
  // ../envoy-client/src/defaults.ts
@@ -14351,6 +14373,9 @@ class DispatchClient {
14351
14373
  return this.#json("POST", ["api", "v1", "issues", await this.#resolveIssue(issue), "messages"], input);
14352
14374
  }
14353
14375
  async artifact(issue, input) {
14376
+ const artifactPath = ["api", "v1", "issues", await this.#resolveIssue(issue), "artifacts"];
14377
+ if ("content" in input)
14378
+ return this.#json("POST", artifactPath, input);
14354
14379
  const form = new FormData;
14355
14380
  form.set("name", input.name);
14356
14381
  if (input.primary !== undefined)
@@ -14360,7 +14385,7 @@ class DispatchClient {
14360
14385
  if (input.actor !== undefined)
14361
14386
  form.set("actor", JSON.stringify(input.actor));
14362
14387
  form.set("file", input.file, input.name);
14363
- return this.#form("POST", ["api", "v1", "issues", await this.#resolveIssue(issue), "artifacts"], form);
14388
+ return this.#form("POST", artifactPath, form);
14364
14389
  }
14365
14390
  async getArtifact(id) {
14366
14391
  return this.#json("GET", ["api", "v1", "artifacts", id]);
@@ -14545,7 +14570,7 @@ function toolSchema(tool) {
14545
14570
  const spec = dispatchToolSpecs.find((candidate) => candidate.name === tool);
14546
14571
  if (!spec)
14547
14572
  throw new Error(`Unknown Dispatch tool: ${tool}`);
14548
- return object(spec.arguments(zodSchemaApi(exports_external))).strict();
14573
+ return dispatchToolSchema(spec, zodSchemaApi(exports_external), { strict: true });
14549
14574
  }
14550
14575
  async function resolveIssueArguments(tool, args, cwd, env, exec) {
14551
14576
  if (tool === "dispatch_issue")
@@ -14722,14 +14747,12 @@ async function executeDispatchTool(input) {
14722
14747
  const resolved = anchorArgs ? await resolveArtifact(client, issue(), stringArg(anchorArgs, "artifact")) : undefined;
14723
14748
  const options = args.options;
14724
14749
  const multiple = optionalBoolean(args, "multiple");
14725
- const custom = optionalBoolean(args, "custom");
14726
14750
  const urgency = askUrgency(args);
14727
14751
  const anchored = anchorArgs && resolved ? anchor(resolved.artifact, anchorArgs) : undefined;
14728
14752
  const ask = await client.ask(issue(), {
14729
14753
  question: stringArg(args, "question"),
14730
14754
  ...Array.isArray(options) ? { options } : {},
14731
14755
  ...multiple === undefined ? {} : { multiple },
14732
- ...custom === undefined ? {} : { custom },
14733
14756
  ...urgency === undefined ? {} : { urgency },
14734
14757
  ...anchored === undefined ? {} : { anchor: anchored },
14735
14758
  actor
@@ -14829,12 +14852,20 @@ Open anchored asks/comments: ${marks.join(", ")}`,
14829
14852
  case "dispatch_artifact": {
14830
14853
  const primary = optionalBoolean(args, "primary");
14831
14854
  const summary = optionalString(args, "summary");
14832
- const result = await client.artifact(issue(), {
14833
- name: stringArg(args, "name"),
14855
+ const name = stringArg(args, "name");
14856
+ const content = optionalString(args, "content");
14857
+ const result = await client.artifact(issue(), content === undefined ? {
14858
+ name,
14834
14859
  file: Bun.file(resolvePath(input.cwd, stringArg(args, "path"))),
14835
14860
  ...primary === undefined ? {} : { primary },
14836
14861
  ...summary === undefined ? {} : { summary },
14837
14862
  actor
14863
+ } : {
14864
+ name,
14865
+ content,
14866
+ ...primary === undefined ? {} : { primary },
14867
+ ...summary === undefined ? {} : { summary },
14868
+ actor
14838
14869
  });
14839
14870
  return {
14840
14871
  text: `Uploaded ${result.artifact.name} as version ${result.version.number}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/opencode-legion-envoy",
3
- "version": "0.20.2",
3
+ "version": "0.22.0",
4
4
  "type": "module",
5
5
  "main": "dist/src/server.js",
6
6
  "exports": {
@@ -36,7 +36,6 @@ dispatch_ask({
36
36
  question,
37
37
  options?: { label, description? }[],
38
38
  multiple?,
39
- custom?,
40
39
  urgency?,
41
40
  anchor?: { artifact, quote, occurrence? },
42
41
  })
@@ -106,15 +105,22 @@ invalid actor, route, or primary artifact.
106
105
 
107
106
  ## Artifacts
108
107
 
109
- Attach an image, diagram, or file with:
108
+ Attach an image, diagram, or local file with:
110
109
 
111
110
  ```ts
112
111
  dispatch_artifact({ issue, name, path, primary?, summary? })
113
112
  ```
114
113
 
115
- It returns `details` `{ issue, topic, artifact, version }`. `path` is the local file to upload.
116
- Uploading the same `name` creates its next version. Set `primary: true` only for a markdown file
117
- to make it the issue's spec.
114
+ Or, when the text is already in the call, post a Markdown document directly:
115
+
116
+ ```ts
117
+ dispatch_artifact({ issue, name: "spec.md", content: "# Design\n...", primary: true })
118
+ ```
119
+
120
+ Exactly one of `path` and `content` is required. The inline form sends JSON with
121
+ `Content-Type: application/json`. It returns `details` `{ issue, topic, artifact, version }`.
122
+ Uploading the same `name` creates its next version. Use `content` for an architect's primary spec;
123
+ set `primary: true` only for Markdown documents.
118
124
 
119
125
  ## Messages
120
126
 
@@ -191,7 +197,6 @@ dispatch_ask({
191
197
  description: "Narrows the release but requires another deployment test.",
192
198
  },
193
199
  ],
194
- custom: false,
195
200
  urgency: "high",
196
201
  anchor: {
197
202
  artifact: "spec",