@sjawhar/opencode-legion-envoy 0.6.1 → 0.7.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.
@@ -13834,12 +13834,6 @@ function isJsonRpcRequest(value) {
13834
13834
  return value.id === null || typeof value.id === "string" || typeof value.id === "number";
13835
13835
  }
13836
13836
  function dispatchShimGate(env, options = {}) {
13837
- if (env.LEGION_TREE !== undefined || env.LEGION_CONTROLLER === "1") {
13838
- return {
13839
- serve: false,
13840
- reason: "Legion sessions use envoy_dispatch via the daemon; not serving the raw dispatch tool"
13841
- };
13842
- }
13843
13837
  const remoteUrl = resolveDispatchMcpUrl(env, options);
13844
13838
  if (remoteUrl === null) {
13845
13839
  return {
@@ -13754,21 +13754,6 @@ var LegionDaemonApi = {
13754
13754
  request: architectCapability.extend({ issue: nonEmptyString, comment: exports_external.string().optional() }),
13755
13755
  response: exports_external.object({})
13756
13756
  },
13757
- DispatchThread: {
13758
- request: exports_external.strictObject({
13759
- tree: nonEmptyString,
13760
- issue: nonEmptyString,
13761
- role: legionRole,
13762
- sessionId: nonEmptyString,
13763
- secret: nonEmptyString,
13764
- parent: nonEmptyString,
13765
- subject: nonEmptyString,
13766
- body: nonEmptyString,
13767
- ask: exports_external.unknown().optional(),
13768
- urgency: exports_external.enum(["low", "med", "high", "blocking"]).optional()
13769
- }),
13770
- response: exports_external.object({ thread: exports_external.number().int(), url: nonEmptyString })
13771
- },
13772
13757
  SpawnToken: {
13773
13758
  request: architectCapability.extend({ issue: nonEmptyString, role: legionRole }),
13774
13759
  response: exports_external.object({ spawnToken: nonEmptyString })
@@ -13858,6 +13843,29 @@ function normalizeEnvoyUrl(value) {
13858
13843
  return value.replace(/\/+$/, "");
13859
13844
  }
13860
13845
 
13846
+ // ../envoy-client/src/dispatch-subscribe.ts
13847
+ var ISSUE_URL_RE = /https?:\/\/github\.com\/([^/\s"]+)\/([^/\s"]+)\/issues\/(\d+)/i;
13848
+ var DISPATCH_TOOL_RE = /(^|[-._])dispatch$/i;
13849
+ function isDispatchTool(tool) {
13850
+ return DISPATCH_TOOL_RE.test(tool);
13851
+ }
13852
+ function dispatchThreadTopic(owner, repo, thread) {
13853
+ return `notifications.github.${owner}.${repo}.issue.${thread}.>`;
13854
+ }
13855
+ function dispatchSubscriptionTopic(tool, output) {
13856
+ if (!isDispatchTool(tool))
13857
+ return null;
13858
+ const match = ISSUE_URL_RE.exec(output);
13859
+ if (!match)
13860
+ return null;
13861
+ const owner = match[1];
13862
+ const repo = match[2];
13863
+ const thread = Number(match[3]);
13864
+ if (!Number.isInteger(thread) || thread <= 0)
13865
+ return null;
13866
+ return dispatchThreadTopic(owner, repo, thread);
13867
+ }
13868
+
13861
13869
  // ../envoy-client/src/machine.ts
13862
13870
  import { hostname as hostname3 } from "os";
13863
13871
  function machineID() {
@@ -14182,29 +14190,6 @@ function injectEnvoyMcp(cfg, entry) {
14182
14190
  return {};
14183
14191
  }
14184
14192
 
14185
- // src/dispatch-subscribe.ts
14186
- var ISSUE_URL_RE = /https?:\/\/github\.com\/([^/\s"]+)\/([^/\s"]+)\/issues\/(\d+)/i;
14187
- var DISPATCH_TOOL_RE = /(^|[-._])dispatch$/i;
14188
- function isDispatchTool(tool2) {
14189
- return DISPATCH_TOOL_RE.test(tool2);
14190
- }
14191
- function dispatchThreadTopic(owner, repo, thread) {
14192
- return `notifications.github.${owner}.${repo}.issue.${thread}.>`;
14193
- }
14194
- function dispatchSubscriptionTopic(tool2, output) {
14195
- if (!isDispatchTool(tool2))
14196
- return null;
14197
- const match = ISSUE_URL_RE.exec(output);
14198
- if (!match)
14199
- return null;
14200
- const owner = match[1];
14201
- const repo = match[2];
14202
- const thread = Number(match[3]);
14203
- if (!Number.isInteger(thread) || thread <= 0)
14204
- return null;
14205
- return dispatchThreadTopic(owner, repo, thread);
14206
- }
14207
-
14208
14193
  // src/port.ts
14209
14194
  import { execFile } from "child_process";
14210
14195
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sjawhar/opencode-legion-envoy",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "type": "module",
5
5
  "main": "dist/src/server.js",
6
6
  "exports": {
package/src/server.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { agentSubject } from "@legion/contracts";
2
2
  import { envoyDefaultsFromEnvironment } from "@legion/envoy-client/defaults";
3
+ import { dispatchSubscriptionTopic } from "@legion/envoy-client/dispatch-subscribe";
3
4
  import { machineID } from "@legion/envoy-client/machine";
4
5
  import { envoyToolSpecs } from "@legion/envoy-client/tool-contract";
5
6
  import { createEnvoyClient } from "@legion/envoy-client/transport";
6
7
  import { tool } from "@opencode-ai/plugin/tool";
7
8
  import { loadEnvoyConfig } from "./config";
8
9
  import { buildDispatchMcpEntry, injectEnvoyMcp } from "./dispatch-mcp";
9
- import { dispatchSubscriptionTopic } from "./dispatch-subscribe";
10
10
  import { logger } from "./log";
11
11
  import { resolvePort } from "./port";
12
12
 
@@ -1,52 +0,0 @@
1
- // Auto-subscription wiring for the envoy_dispatch MCP tool.
2
- //
3
- // When an agent opens a Dispatch thread via the envoy_dispatch MCP tool, the
4
- // human answers by commenting on the resulting GitHub sub-issue. For the agent
5
- // to RECEIVE that answer, its session must be subscribed to the thread's Envoy
6
- // topic (notifications.github.<owner>.<repo>.issue.<thread>.>). The dispatch
7
- // tool is served by the Go dispatch server and has no OpenCode session context,
8
- // so we close the loop in the plugin (which does know the session id) from the
9
- // tool.execute.after hook.
10
- //
11
- // This module is the pure, testable core: it turns a completed tool execution
12
- // into the topic the calling session should subscribe to, or null when the
13
- // execution isn't a successful envoy_dispatch call.
14
-
15
- // Matches a GitHub issue URL anywhere in the tool output and captures
16
- // owner / repo / number. The dispatch tool returns {"thread":N,"url":"…"} as
17
- // its text content, so the URL is always present on success.
18
- const ISSUE_URL_RE = /https?:\/\/github\.com\/([^/\s"]+)\/([^/\s"]+)\/issues\/(\d+)/i;
19
-
20
- // The tool is registered on the Go MCP server as "dispatch" and exposed to
21
- // OpenCode under the "envoy" MCP server (so commonly "envoy_dispatch"). Accept
22
- // any separator a client might use while still excluding unrelated tools.
23
- const DISPATCH_TOOL_RE = /(^|[-._])dispatch$/i;
24
-
25
- export function isDispatchTool(tool: string): boolean {
26
- return DISPATCH_TOOL_RE.test(tool);
27
- }
28
-
29
- /** Build the Envoy topic carrying every event on a dispatch thread issue. */
30
- export function dispatchThreadTopic(owner: string, repo: string, thread: number): string {
31
- return `notifications.github.${owner}.${repo}.issue.${thread}.>`;
32
- }
33
-
34
- /**
35
- * Given a completed tool execution (name + textual output), return the Envoy
36
- * topic the calling session should subscribe to so it receives replies on the
37
- * dispatch thread — or null when this isn't a successful envoy_dispatch call.
38
- *
39
- * Parsing the GitHub issue URL out of the output (rather than trusting a JSON
40
- * field) keeps this robust to however OpenCode surfaces the MCP result: owner,
41
- * repo, and thread number all come from the canonical issue URL.
42
- */
43
- export function dispatchSubscriptionTopic(tool: string, output: string): string | null {
44
- if (!isDispatchTool(tool)) return null;
45
- const match = ISSUE_URL_RE.exec(output);
46
- if (!match) return null;
47
- const owner = match[1] as string;
48
- const repo = match[2] as string;
49
- const thread = Number(match[3]);
50
- if (!Number.isInteger(thread) || thread <= 0) return null;
51
- return dispatchThreadTopic(owner, repo, thread);
52
- }