@sjawhar/opencode-legion-envoy 0.21.0 → 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"];
@@ -13686,14 +13690,22 @@ var dispatchToolSpecs = [
13686
13690
  },
13687
13691
  {
13688
13692
  name: "dispatch_artifact",
13689
- 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}`,
13690
13694
  arguments: (z) => ({
13691
13695
  issue: z.string().describe(ISSUE_REFERENCE),
13692
13696
  name: z.string().describe("Artifact filename shown in Dispatch."),
13693
- 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(),
13694
13699
  primary: z.boolean().describe("Make this document the issue primary artifact.").optional(),
13695
13700
  summary: z.string().describe("Optional version summary.").optional()
13696
- })
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
+ }
13697
13709
  },
13698
13710
  {
13699
13711
  name: "dispatch_read",
@@ -14081,7 +14093,18 @@ function zodSchemaApi(zod) {
14081
14093
  schema = schema.max(opts.max);
14082
14094
  return schema;
14083
14095
  },
14084
- 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
+ }
14085
14108
  };
14086
14109
  }
14087
14110
  // ../envoy-client/src/defaults.ts
@@ -14350,6 +14373,9 @@ class DispatchClient {
14350
14373
  return this.#json("POST", ["api", "v1", "issues", await this.#resolveIssue(issue), "messages"], input);
14351
14374
  }
14352
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);
14353
14379
  const form = new FormData;
14354
14380
  form.set("name", input.name);
14355
14381
  if (input.primary !== undefined)
@@ -14359,7 +14385,7 @@ class DispatchClient {
14359
14385
  if (input.actor !== undefined)
14360
14386
  form.set("actor", JSON.stringify(input.actor));
14361
14387
  form.set("file", input.file, input.name);
14362
- return this.#form("POST", ["api", "v1", "issues", await this.#resolveIssue(issue), "artifacts"], form);
14388
+ return this.#form("POST", artifactPath, form);
14363
14389
  }
14364
14390
  async getArtifact(id) {
14365
14391
  return this.#json("GET", ["api", "v1", "artifacts", id]);
@@ -14544,7 +14570,7 @@ function toolSchema(tool) {
14544
14570
  const spec = dispatchToolSpecs.find((candidate) => candidate.name === tool);
14545
14571
  if (!spec)
14546
14572
  throw new Error(`Unknown Dispatch tool: ${tool}`);
14547
- return object(spec.arguments(zodSchemaApi(exports_external))).strict();
14573
+ return dispatchToolSchema(spec, zodSchemaApi(exports_external), { strict: true });
14548
14574
  }
14549
14575
  async function resolveIssueArguments(tool, args, cwd, env, exec) {
14550
14576
  if (tool === "dispatch_issue")
@@ -14826,12 +14852,20 @@ Open anchored asks/comments: ${marks.join(", ")}`,
14826
14852
  case "dispatch_artifact": {
14827
14853
  const primary = optionalBoolean(args, "primary");
14828
14854
  const summary = optionalString(args, "summary");
14829
- const result = await client.artifact(issue(), {
14830
- 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,
14831
14859
  file: Bun.file(resolvePath(input.cwd, stringArg(args, "path"))),
14832
14860
  ...primary === undefined ? {} : { primary },
14833
14861
  ...summary === undefined ? {} : { summary },
14834
14862
  actor
14863
+ } : {
14864
+ name,
14865
+ content,
14866
+ ...primary === undefined ? {} : { primary },
14867
+ ...summary === undefined ? {} : { summary },
14868
+ actor
14835
14869
  });
14836
14870
  return {
14837
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.21.0",
3
+ "version": "0.22.0",
4
4
  "type": "module",
5
5
  "main": "dist/src/server.js",
6
6
  "exports": {
@@ -105,15 +105,22 @@ invalid actor, route, or primary artifact.
105
105
 
106
106
  ## Artifacts
107
107
 
108
- Attach an image, diagram, or file with:
108
+ Attach an image, diagram, or local file with:
109
109
 
110
110
  ```ts
111
111
  dispatch_artifact({ issue, name, path, primary?, summary? })
112
112
  ```
113
113
 
114
- It returns `details` `{ issue, topic, artifact, version }`. `path` is the local file to upload.
115
- Uploading the same `name` creates its next version. Set `primary: true` only for a markdown file
116
- 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.
117
124
 
118
125
  ## Messages
119
126