@sjawhar/opencode-legion-envoy 0.7.0 → 0.9.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 +2 -2
- package/dist/bin/dispatch-mcp-shim.js +525 -9535
- package/dist/src/server.js +561 -9720
- package/package.json +6 -4
- package/skills/AGENTS.md +39 -0
- package/skills/dispatch/SKILL.md +94 -0
- package/skills/envoy/SKILL.md +404 -0
- package/skills/github/SKILL.md +203 -0
- package/skills/legion-architect/SKILL.md +202 -0
- package/skills/legion-controller/SKILL.md +136 -0
- package/skills/legion-oracle/SKILL.md +63 -0
- package/skills/legion-retro/SKILL.md +87 -0
- package/skills/legion-worker/SKILL.md +177 -0
- package/skills/legion-worker/references/config.md +259 -0
- package/skills/legion-worker/references/knowledge-injection.md +98 -0
- package/skills/legion-worker/resources/strategies/cleanup-deletion.md +22 -0
- package/skills/legion-worker/resources/strategies/systematic-rename.md +19 -0
- package/skills/linear/SKILL.md +76 -0
- package/src/config/index.ts +21 -15
- package/src/config/schema.ts +0 -5
- package/src/server.ts +29 -1
package/src/config/index.ts
CHANGED
|
@@ -2,32 +2,38 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { messageFor } from "@legion/envoy-client/errors";
|
|
5
|
-
import { logger } from "../log";
|
|
6
5
|
import { type EnvoyConfig, EnvoyConfigSchema } from "./schema";
|
|
7
6
|
|
|
8
7
|
export interface LoadEnvoyConfigOptions {
|
|
9
8
|
homeDir?: string;
|
|
10
9
|
}
|
|
11
10
|
|
|
11
|
+
/** A present but unusable envoy.json. The plugin refuses to load rather than run with dispatch silently off. */
|
|
12
|
+
export class EnvoyConfigError extends Error {
|
|
13
|
+
readonly filePath: string;
|
|
14
|
+
constructor(filePath: string, detail: string) {
|
|
15
|
+
super(`[envoy-plugin] invalid config at ${filePath}: ${detail}`);
|
|
16
|
+
this.name = "EnvoyConfigError";
|
|
17
|
+
this.filePath = filePath;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
12
21
|
function readConfigFile(filePath: string): EnvoyConfig | null {
|
|
13
22
|
if (!existsSync(filePath)) return null;
|
|
23
|
+
let raw: unknown;
|
|
14
24
|
try {
|
|
15
|
-
|
|
16
|
-
const raw = JSON.parse(content) as unknown;
|
|
17
|
-
const parsed = EnvoyConfigSchema.safeParse(raw);
|
|
18
|
-
if (!parsed.success) {
|
|
19
|
-
const issues = parsed.error.issues
|
|
20
|
-
.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
|
|
21
|
-
.join(", ");
|
|
22
|
-
logger.warn(`[envoy-plugin] Invalid config at ${filePath}: ${issues}`);
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
return parsed.data as EnvoyConfig;
|
|
25
|
+
raw = JSON.parse(readFileSync(filePath, "utf-8")) as unknown;
|
|
26
26
|
} catch (error) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
throw new EnvoyConfigError(filePath, messageFor(error));
|
|
28
|
+
}
|
|
29
|
+
const parsed = EnvoyConfigSchema.safeParse(raw);
|
|
30
|
+
if (!parsed.success) {
|
|
31
|
+
const issues = parsed.error.issues
|
|
32
|
+
.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
|
|
33
|
+
.join(", ");
|
|
34
|
+
throw new EnvoyConfigError(filePath, issues);
|
|
30
35
|
}
|
|
36
|
+
return parsed.data;
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
function mergeConfig(base: EnvoyConfig, override: EnvoyConfig): EnvoyConfig {
|
package/src/config/schema.ts
CHANGED
|
@@ -6,11 +6,6 @@ export const DispatchConfigSchema = z
|
|
|
6
6
|
.object({
|
|
7
7
|
enabled: z.boolean().optional(),
|
|
8
8
|
serverUrl: z.string().url().optional(),
|
|
9
|
-
defaultRepo: z
|
|
10
|
-
.string()
|
|
11
|
-
.regex(/^[^/]+\/[^/]+$/)
|
|
12
|
-
.optional(),
|
|
13
|
-
appClientId: z.string().optional(),
|
|
14
9
|
})
|
|
15
10
|
.strict();
|
|
16
11
|
|
package/src/server.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
1
4
|
import { agentSubject } from "@legion/contracts";
|
|
2
5
|
import { envoyDefaultsFromEnvironment } from "@legion/envoy-client/defaults";
|
|
3
6
|
import { dispatchSubscriptionTopic } from "@legion/envoy-client/dispatch-subscribe";
|
|
@@ -10,6 +13,18 @@ import { buildDispatchMcpEntry, injectEnvoyMcp } from "./dispatch-mcp";
|
|
|
10
13
|
import { logger } from "./log";
|
|
11
14
|
import { resolvePort } from "./port";
|
|
12
15
|
|
|
16
|
+
const moduleDirectory = path.dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
// Legion skills ship inside this package so OpenCode carries them without a
|
|
18
|
+
// vendor checkout. OpenCode discovers skills only from fixed directories and
|
|
19
|
+
// `config.skills.paths` — never from plugin package dirs — so the config hook
|
|
20
|
+
// below must inject this path itself.
|
|
21
|
+
// Published tarball: dist/src/server.js → <pkg>/skills (staged at prepack).
|
|
22
|
+
// Repo checkout: src/server.ts → <repo>/skills.
|
|
23
|
+
const skillsDirectory = [
|
|
24
|
+
path.resolve(moduleDirectory, "../../skills"),
|
|
25
|
+
path.resolve(moduleDirectory, "../../../skills"),
|
|
26
|
+
].find((dir) => existsSync(dir));
|
|
27
|
+
|
|
13
28
|
const [
|
|
14
29
|
subscribeSpec,
|
|
15
30
|
unsubscribeSpec,
|
|
@@ -139,7 +154,20 @@ export default async (input: { serverUrl: URL }) => {
|
|
|
139
154
|
});
|
|
140
155
|
|
|
141
156
|
return {
|
|
142
|
-
config: (
|
|
157
|
+
config: (
|
|
158
|
+
cfg: { mcp?: Record<string, unknown>; skills?: { paths?: string[] } } & Record<
|
|
159
|
+
string,
|
|
160
|
+
unknown
|
|
161
|
+
>
|
|
162
|
+
) => {
|
|
163
|
+
// Serve the bundled legion skills to every session on this serve.
|
|
164
|
+
if (skillsDirectory) {
|
|
165
|
+
cfg.skills ??= {};
|
|
166
|
+
cfg.skills.paths ??= [];
|
|
167
|
+
if (!cfg.skills.paths.includes(skillsDirectory)) {
|
|
168
|
+
cfg.skills.paths.push(skillsDirectory);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
143
171
|
// Inject the envoy MCP entry into the OpenCode config when
|
|
144
172
|
// dispatch is enabled. Centralizing this in the plugin (instead of
|
|
145
173
|
// each user's opencode.json) means:
|