@uniqbit/mate-core 0.15.3 → 0.15.4-canary.10
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/claude-plugin/.claude-plugin/plugin.json +4 -0
- package/claude-plugin/hooks/artifact-finish-nudge.mjs +8 -0
- package/claude-plugin/hooks/hooks.json +37 -0
- package/claude-plugin/hooks/session-banner.mjs +8 -0
- package/claude-plugin/hooks/ts-loader.mjs +28 -0
- package/claude-plugin/hooks/validate-artifact-path.mjs +8 -0
- package/package.json +4 -2
- package/src/cli/commands/artifact/finish/openspec.ts +1 -5
- package/src/cli/commands/companion/hub.ts +99 -0
- package/src/cli/commands/companion/link.ts +0 -5
- package/src/cli/commands/companion/tui.ts +3 -2
- package/src/cli/commands/doctor.ts +254 -170
- package/src/cli/commands/install.ts +18 -14
- package/src/cli/commands/launch/shared.ts +4 -4
- package/src/cli/commands/plugin/install.ts +94 -0
- package/src/cli/commands/plugin/plugin.ts +17 -0
- package/src/cli/commands/setup.ts +4 -6
- package/src/cli/commands/update.ts +9 -11
- package/src/cli/companion-link-wizard.tsx +22 -78
- package/src/cli/main.ts +57 -13
- package/src/cli/plugin-commands.ts +4 -4
- package/src/cli/repo-list-table.tsx +2 -7
- package/src/cli/usage.ts +7 -3
- package/src/distribution.ts +3 -5
- package/src/framework.ts +4 -36
- package/src/hooks/artifact-finish-nudge.ts +212 -0
- package/src/hooks/session-banner.ts +25 -0
- package/src/hooks/validate-artifact-path.ts +236 -0
- package/src/index.ts +4 -0
- package/src/lib/context-mode-package.ts +5 -3
- package/src/lib/install.ts +31 -43
- package/src/lib/orchestrator/adapters/base.ts +7 -8
- package/src/lib/orchestrator/adapters/claude.ts +16 -0
- package/src/lib/orchestrator/adapters/opencode.ts +10 -60
- package/src/lib/orchestrator/companion-hub.ts +380 -0
- package/src/lib/orchestrator/companion-store.ts +1 -35
- package/src/lib/orchestrator/config-store.ts +94 -7
- package/src/lib/orchestrator/editor.ts +4 -20
- package/src/lib/orchestrator/framework-context.ts +119 -24
- package/src/lib/orchestrator/global-config-store.ts +1 -5
- package/src/lib/orchestrator/launcher.ts +3 -9
- package/src/lib/orchestrator/migration.ts +0 -23
- package/src/lib/orchestrator/opencode-guidance.ts +1 -2
- package/src/lib/orchestrator/repo-local-registry.ts +3 -1
- package/src/lib/orchestrator/root-context.ts +117 -0
- package/src/lib/orchestrator/setup-compatibilities.ts +1 -1
- package/src/lib/orchestrator/setup-preflight.ts +5 -18
- package/src/lib/orchestrator/types.ts +27 -19
- package/src/lib/orchestrator/working-repo-store.ts +9 -3
- package/src/lib/package-paths.ts +37 -0
- package/src/lib/update-checker.ts +5 -5
- package/src/playbooks/companion-guidance.ts +7 -7
- package/src/runtime/env.ts +0 -4
- package/src/templates/capabilities/openspec-cap/mate-skills/{mate-artifact-finish → agents/mate-artifact-finish}/SKILL.md +8 -8
- package/src/templates/capabilities/openspec-cap/mate-skills/{mate-artifact-finish → agents/mate-artifact-finish}/references/openspec.md +3 -3
- package/src/templates/capabilities/openspec-cap/mate-skills/claude/mate-artifact-finish/SKILL.md +58 -0
- package/src/templates/capabilities/openspec-cap/mate-skills/claude/mate-artifact-finish/references/openspec.md +139 -0
- package/src/templates/capabilities/openspec-cap/mate-v1/schema.yaml +6 -5
- package/src/templates/root/TEMPLATE_AGENTS.md +2 -0
- package/src/templates/root/TEMPLATE_CLAUDE.md +2 -0
- package/src/tools/setup/__snapshots__/runtime-surface-golden.test.ts.snap +3541 -0
- package/src/tools/setup/capabilities/context-mode.ts +57 -83
- package/src/tools/setup/capabilities/graphify-shared.ts +27 -0
- package/src/tools/setup/capabilities/graphify.ts +86 -295
- package/src/tools/setup/capabilities/openspec.ts +27 -30
- package/src/tools/setup/capabilities/react-doctor.ts +37 -37
- package/src/tools/setup/capabilities/rtk.ts +4 -1
- package/src/tools/setup/capabilities/tokensave-shared.ts +6 -0
- package/src/tools/setup/capabilities/tokensave.ts +50 -71
- package/src/tools/setup/context-services.ts +29 -0
- package/src/tools/setup/dynamic-plugins/host.ts +2 -1
- package/src/tools/setup/dynamic-plugins/hydrate.ts +3 -13
- package/src/tools/setup/dynamic-plugins/install.ts +124 -109
- package/src/tools/setup/dynamic-plugins/loader.ts +23 -58
- package/src/tools/setup/dynamic-plugins/paths.ts +8 -19
- package/src/tools/setup/dynamic-plugins/registry-hint.ts +14 -0
- package/src/tools/setup/engine.ts +65 -1
- package/src/tools/setup/mate.ts +28 -31
- package/src/tools/setup/plugin.ts +81 -0
- package/src/tools/setup/plugins/gitignore.ts +19 -9
- package/src/tools/setup/plugins/guidance.ts +2 -6
- package/src/tools/setup/policy.ts +4 -7
- package/src/tools/setup/providers/agent-file-sections.ts +78 -0
- package/src/tools/setup/providers/claude-format.ts +159 -0
- package/src/tools/setup/providers/claude.ts +283 -292
- package/src/tools/setup/providers/opencode-format.ts +146 -0
- package/src/tools/setup/providers/opencode.ts +171 -66
- package/src/tools/setup/providers/skill-tree.ts +38 -0
- package/src/tools/setup.ts +12 -7
- package/src/tui.ts +5 -0
- package/src/templates/capabilities/openspec-cap/claude/hooks/mate-artifact-finish.sh +0 -161
- package/src/templates/providers/claude/.claude/hooks/mate-session-banner +0 -28
- package/src/templates/providers/claude/.claude/hooks/validate-artifact-path +0 -242
- package/src/tools/setup/dynamic-plugins/pin-store.ts +0 -30
package/src/lib/install.ts
CHANGED
|
@@ -3,10 +3,10 @@ import fs from "node:fs/promises";
|
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
|
|
6
|
-
import { defaultConfig
|
|
7
|
-
import { CompanionResolver } from "./orchestrator/companion-resolver";
|
|
6
|
+
import { defaultConfig } from "./orchestrator/config-store";
|
|
8
7
|
import { checkEngineRequirement } from "./orchestrator/engine-guard";
|
|
9
|
-
import { GlobalConfigStore } from "./orchestrator/global-config-store";
|
|
8
|
+
import type { GlobalConfigStore } from "./orchestrator/global-config-store";
|
|
9
|
+
import { resolveRootContext } from "./orchestrator/root-context";
|
|
10
10
|
import { YamlFileStore } from "./orchestrator/yaml-file-store";
|
|
11
11
|
import { FRAMEWORK_NAME } from "../framework";
|
|
12
12
|
import type { FrameworkConfig } from "./orchestrator/types";
|
|
@@ -18,7 +18,7 @@ import type { Plugin } from "../tools/setup/plugin";
|
|
|
18
18
|
export const INSTALL_CONTRACT_REVISION = 1;
|
|
19
19
|
|
|
20
20
|
export interface InstallContext {
|
|
21
|
-
kind: "core" | "companion" | "ambiguous";
|
|
21
|
+
kind: "core" | "working" | "companion" | "hub" | "ambiguous";
|
|
22
22
|
companionPath?: string;
|
|
23
23
|
config: FrameworkConfig;
|
|
24
24
|
fingerprint: string;
|
|
@@ -66,8 +66,8 @@ export function getInstallStatePath(
|
|
|
66
66
|
throw new Error("cannot resolve install state for an ambiguous companion context");
|
|
67
67
|
}
|
|
68
68
|
const key =
|
|
69
|
-
scope.kind === "companion" && scope.companionPath
|
|
70
|
-
? fingerprint({ kind:
|
|
69
|
+
(scope.kind === "companion" || scope.kind === "hub") && scope.companionPath
|
|
70
|
+
? fingerprint({ kind: scope.kind, companionPath: path.resolve(scope.companionPath) })
|
|
71
71
|
: "core";
|
|
72
72
|
return path.join(stateRoot, `${key}.yaml`);
|
|
73
73
|
}
|
|
@@ -106,50 +106,40 @@ function coreContext(): InstallContext {
|
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
kind: "companion",
|
|
114
|
-
companionPath,
|
|
115
|
-
config,
|
|
116
|
-
fingerprint: fingerprint({ kind: "companion", companionPath, config }),
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
async function hasLocalConfig(cwd: string): Promise<boolean> {
|
|
121
|
-
try {
|
|
122
|
-
await fs.access(path.join(cwd, `.${FRAMEWORK_NAME}`, "config", "framework.yaml"));
|
|
123
|
-
return true;
|
|
124
|
-
} catch {
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
109
|
+
function workingContext(): InstallContext {
|
|
110
|
+
const context = coreContext();
|
|
111
|
+
return { ...context, kind: "working" };
|
|
127
112
|
}
|
|
128
113
|
|
|
129
114
|
export async function resolveInstallContext(
|
|
130
115
|
cwd = process.cwd(),
|
|
131
116
|
deps: InstallContextDeps = {},
|
|
132
117
|
): Promise<InstallContext> {
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
if (envCompanionPath) return contextForCompanion(path.resolve(envCompanionPath));
|
|
136
|
-
|
|
137
|
-
const resolver = new CompanionResolver(deps.globalConfigStore ?? new GlobalConfigStore());
|
|
138
|
-
const resolution = await resolver.resolveWithDiagnostics(resolvedCwd);
|
|
139
|
-
if (resolution.ambiguousMatches.length > 1) {
|
|
118
|
+
const root = await resolveRootContext(cwd, deps);
|
|
119
|
+
if (root.resolution.ambiguousMatches.length > 1) {
|
|
140
120
|
return {
|
|
141
121
|
...coreContext(),
|
|
142
122
|
kind: "ambiguous",
|
|
143
123
|
message: [
|
|
144
124
|
"multiple companions match the current working repository.",
|
|
145
|
-
...resolution.ambiguousMatches.map((match) => ` - ${match.companionPath}`),
|
|
125
|
+
...root.resolution.ambiguousMatches.map((match) => ` - ${match.companionPath}`),
|
|
146
126
|
"Run `mate install` from an explicit companion context or set MATE_ARTIFACT_PATH.",
|
|
147
127
|
].join("\n"),
|
|
148
128
|
};
|
|
149
129
|
}
|
|
150
|
-
if (
|
|
151
|
-
if (
|
|
152
|
-
|
|
130
|
+
if (root.kind === "working") return workingContext();
|
|
131
|
+
if (root.kind === "core" || !root.rootPath || !root.config) return coreContext();
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
kind: root.kind,
|
|
135
|
+
companionPath: root.rootPath,
|
|
136
|
+
config: root.config,
|
|
137
|
+
fingerprint: fingerprint({
|
|
138
|
+
kind: root.kind,
|
|
139
|
+
companionPath: root.rootPath,
|
|
140
|
+
config: root.config,
|
|
141
|
+
}),
|
|
142
|
+
};
|
|
153
143
|
}
|
|
154
144
|
|
|
155
145
|
export function buildInstallPlan(
|
|
@@ -292,11 +282,7 @@ export async function inspectInstallPreflight(
|
|
|
292
282
|
): Promise<InstallPreflightResult> {
|
|
293
283
|
const context = await resolveInstallContext(cwd, deps);
|
|
294
284
|
const distribution = getActiveDistribution().config;
|
|
295
|
-
const engineCheck = checkEngineRequirement(
|
|
296
|
-
context.config,
|
|
297
|
-
distribution.name,
|
|
298
|
-
distribution.version,
|
|
299
|
-
);
|
|
285
|
+
const engineCheck = checkEngineRequirement(context.config, FRAMEWORK_NAME, distribution.version);
|
|
300
286
|
if (!engineCheck.ok) return { ok: false, reason: engineCheck.reason };
|
|
301
287
|
const plan = await inspectInstallPlan(buildInstallPlan(context));
|
|
302
288
|
if (context.kind === "ambiguous") return { ok: false, reason: context.message, plan };
|
|
@@ -333,8 +319,10 @@ export async function inspectInstallPreflight(
|
|
|
333
319
|
}
|
|
334
320
|
|
|
335
321
|
export async function reconcileInstalledCompanion(plan: InstallPlan): Promise<void> {
|
|
336
|
-
if (plan.context.kind
|
|
337
|
-
|
|
338
|
-
await syncCompanionFiles(plan.context.companionPath, plan.context.config);
|
|
322
|
+
if (plan.context.kind !== "companion" || !plan.context.companionPath) {
|
|
323
|
+
return;
|
|
339
324
|
}
|
|
325
|
+
|
|
326
|
+
const { syncCompanionFiles } = await import("../tools/setup");
|
|
327
|
+
await syncCompanionFiles(plan.context.companionPath, plan.context.config);
|
|
340
328
|
}
|
|
@@ -3,7 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
|
|
4
4
|
import { version } from "../../../../package.json";
|
|
5
5
|
import { isCommandOnPath } from "../../fs-utils";
|
|
6
|
-
import { FRAMEWORK_NAME
|
|
6
|
+
import { FRAMEWORK_NAME } from "../../../framework";
|
|
7
7
|
import { getReactDoctorBinPath, getWrapperBinPath } from "../../package-paths";
|
|
8
8
|
import {
|
|
9
9
|
GRAPHIFY_OUTPUT_SUBDIR,
|
|
@@ -17,11 +17,11 @@ import {
|
|
|
17
17
|
spawnProxyBackground as defaultSpawnProxyBackground,
|
|
18
18
|
waitForProxyReachable as defaultWaitForProxyReachable,
|
|
19
19
|
} from "../headroom/proxy";
|
|
20
|
-
import type { CapabilityConfig, GitModeProfile, LinkedRepository
|
|
20
|
+
import type { CapabilityConfig, GitModeProfile, LinkedRepository } from "../types";
|
|
21
21
|
|
|
22
22
|
export interface AdapterContext {
|
|
23
23
|
repository: LinkedRepository;
|
|
24
|
-
|
|
24
|
+
allowedAgents: string[];
|
|
25
25
|
companionPath: string;
|
|
26
26
|
capabilities: CapabilityConfig[];
|
|
27
27
|
git?: GitModeProfile;
|
|
@@ -78,18 +78,17 @@ export abstract class LaunchAdapter {
|
|
|
78
78
|
const env: NodeJS.ProcessEnv = {
|
|
79
79
|
...process.env,
|
|
80
80
|
MATE_NAME: FRAMEWORK_NAME,
|
|
81
|
-
MATE_COMMAND: frameworkCommandName(),
|
|
82
81
|
MATE_VERSION: version,
|
|
83
82
|
MATE_ARTIFACT_PATH: context.companionPath,
|
|
84
83
|
MATE_WRAPPER_BIN_PATH: wrapperBinPath,
|
|
85
84
|
PATH: prependPathEntry(process.env.PATH, wrapperBinPath),
|
|
86
85
|
MATE_GRAPHIFY_ENABLED: context.capabilities.some((c) => c.name === "graphify") ? "1" : "0",
|
|
86
|
+
MATE_OPENSPEC_ENABLED: context.capabilities.some((c) => c.name === "openspec") ? "1" : "0",
|
|
87
87
|
MATE_REACT_DOCTOR_ENABLED: reactDoctorEnabled ? "1" : "0",
|
|
88
88
|
MATE_GIT_AUTO_MODE: context.git === "auto" ? "1" : "0",
|
|
89
89
|
MATE_REPO_ID: context.repository.id,
|
|
90
90
|
MATE_REPO_PATH: context.repository.path,
|
|
91
|
-
|
|
92
|
-
MATE_POLICY_JSON: JSON.stringify(context.policy),
|
|
91
|
+
MATE_POLICY_JSON: JSON.stringify({ allowedAgents: context.allowedAgents }),
|
|
93
92
|
};
|
|
94
93
|
|
|
95
94
|
if (reactDoctorEnabled) {
|
|
@@ -149,7 +148,7 @@ export abstract class LaunchAdapter {
|
|
|
149
148
|
command: this.toolName,
|
|
150
149
|
args: builtArgs,
|
|
151
150
|
env,
|
|
152
|
-
warning: `${
|
|
151
|
+
warning: `${FRAMEWORK_NAME}: headroom capability enabled but \`headroom\` was not found on PATH; install with \`uv tool install "headroom-ai[all]"\`; launching ${this.toolName} directly\n`,
|
|
153
152
|
};
|
|
154
153
|
}
|
|
155
154
|
|
|
@@ -183,7 +182,7 @@ export abstract class LaunchAdapter {
|
|
|
183
182
|
command: this.toolName,
|
|
184
183
|
args: builtArgs,
|
|
185
184
|
env,
|
|
186
|
-
warning: `${
|
|
185
|
+
warning: `${FRAMEWORK_NAME}: headroom proxy failed to become ready on port ${port} after ${maxProxyStartAttempts} attempts; launching ${this.toolName} directly${errorDetail}\n`,
|
|
187
186
|
};
|
|
188
187
|
}
|
|
189
188
|
}
|
|
@@ -2,6 +2,7 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
|
|
3
3
|
import { buildCompanionGuidance } from "../../../playbooks/companion-guidance";
|
|
4
4
|
import { getContextModePackageRoot, validateContextModePackage } from "../../context-mode-package";
|
|
5
|
+
import { getClaudePluginRoot, validateClaudePluginAssets } from "../../package-paths";
|
|
5
6
|
import {
|
|
6
7
|
getCompanionClaudeMcpConfigPath,
|
|
7
8
|
getCompanionClaudeSettingsPath,
|
|
@@ -13,6 +14,17 @@ export class ClaudeAdapter extends LaunchAdapter {
|
|
|
13
14
|
readonly interactive = true;
|
|
14
15
|
|
|
15
16
|
async validateLaunch(context: AdapterContext): Promise<void> {
|
|
17
|
+
// The bundled mate plugin carries the artifact-path guard; never launch a
|
|
18
|
+
// managed session without it.
|
|
19
|
+
try {
|
|
20
|
+
validateClaudePluginAssets();
|
|
21
|
+
} catch (error) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
`Mate Claude plugin is unavailable: ${(error as Error).message}. Reinstall mate to repair it.`,
|
|
24
|
+
{ cause: error },
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
16
28
|
if (context.capabilities.some((capability) => capability.name === "context-mode")) {
|
|
17
29
|
try {
|
|
18
30
|
await validateContextModePackage(context.companionPath);
|
|
@@ -56,6 +68,10 @@ export class ClaudeAdapter extends LaunchAdapter {
|
|
|
56
68
|
buildCompanionGuidance(context),
|
|
57
69
|
...settingsArgs,
|
|
58
70
|
...mcpConfigArgs,
|
|
71
|
+
// Bundled mate plugin (hooks) resolved from the running mate-core
|
|
72
|
+
// installation, coexisting with the context-mode plugin dir.
|
|
73
|
+
"--plugin-dir",
|
|
74
|
+
getClaudePluginRoot(),
|
|
59
75
|
...contextModeArgs,
|
|
60
76
|
...args,
|
|
61
77
|
];
|
|
@@ -9,61 +9,15 @@ import {
|
|
|
9
9
|
getOpenCodePluginPackageReference,
|
|
10
10
|
isMateOpenCodePluginReference,
|
|
11
11
|
} from "../../opencode-plugin-package";
|
|
12
|
+
import {
|
|
13
|
+
getOpenCodePluginReferences,
|
|
14
|
+
mergeOpenCodeConfigContent,
|
|
15
|
+
readOpenCodeConfig,
|
|
16
|
+
} from "../../../tools/setup/providers/opencode-format";
|
|
12
17
|
import { buildOpenCodeGuidance } from "../opencode-guidance";
|
|
13
18
|
import { LaunchPreflightError } from "../types";
|
|
14
19
|
import { type AdapterContext, LaunchAdapter } from "./base";
|
|
15
20
|
|
|
16
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
17
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function mergeConfig(target: Record<string, unknown>, source: Record<string, unknown>): void {
|
|
21
|
-
for (const [key, sourceValue] of Object.entries(source)) {
|
|
22
|
-
const targetValue = target[key];
|
|
23
|
-
if (isRecord(targetValue) && isRecord(sourceValue)) {
|
|
24
|
-
mergeConfig(targetValue, sourceValue);
|
|
25
|
-
continue;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
target[key] = sourceValue;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function mergeOpenCodeConfigContent(
|
|
33
|
-
overlay: Record<string, unknown>,
|
|
34
|
-
env: NodeJS.ProcessEnv = process.env,
|
|
35
|
-
options: { appendSkillPaths?: string[] } = {},
|
|
36
|
-
): string {
|
|
37
|
-
let config: Record<string, unknown> = {};
|
|
38
|
-
const existing = env.OPENCODE_CONFIG_CONTENT;
|
|
39
|
-
|
|
40
|
-
if (existing) {
|
|
41
|
-
try {
|
|
42
|
-
const parsed = JSON.parse(existing) as unknown;
|
|
43
|
-
if (isRecord(parsed)) {
|
|
44
|
-
config = parsed;
|
|
45
|
-
}
|
|
46
|
-
} catch {
|
|
47
|
-
// Ignore invalid inherited config content rather than breaking launch.
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
mergeConfig(config, overlay);
|
|
52
|
-
|
|
53
|
-
if (options.appendSkillPaths && options.appendSkillPaths.length > 0) {
|
|
54
|
-
const skills = isRecord(config.skills) ? config.skills : {};
|
|
55
|
-
const paths = Array.isArray(skills.paths) ? skills.paths : [];
|
|
56
|
-
const existingPaths = new Set(paths);
|
|
57
|
-
skills.paths = [
|
|
58
|
-
...paths,
|
|
59
|
-
...options.appendSkillPaths.filter((skillPath) => !existingPaths.has(skillPath)),
|
|
60
|
-
];
|
|
61
|
-
config.skills = skills;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return JSON.stringify(config);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
21
|
export class OpenCodeAdapter extends LaunchAdapter {
|
|
68
22
|
readonly toolName = "opencode";
|
|
69
23
|
readonly interactive = true;
|
|
@@ -190,18 +144,14 @@ export class OpenCodeAdapter extends LaunchAdapter {
|
|
|
190
144
|
): Promise<string[]> {
|
|
191
145
|
const configPath = path.join(context.companionPath, configFile);
|
|
192
146
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
config = JSON.parse(await fs.readFile(configPath, "utf8"));
|
|
196
|
-
} catch {
|
|
197
|
-
return [`Unreadable OpenCode configuration: ${configPath}`];
|
|
198
|
-
}
|
|
199
|
-
if (!isRecord(config)) {
|
|
147
|
+
const { present, config } = await readOpenCodeConfig(configPath);
|
|
148
|
+
if (!present) {
|
|
200
149
|
return [`Unreadable OpenCode configuration: ${configPath}`];
|
|
201
150
|
}
|
|
202
151
|
|
|
203
|
-
const
|
|
204
|
-
|
|
152
|
+
const mateReferences = getOpenCodePluginReferences(config).filter(
|
|
153
|
+
isMateOpenCodePluginReference,
|
|
154
|
+
) as string[];
|
|
205
155
|
|
|
206
156
|
if (mateReferences.includes(expectedPluginReference)) {
|
|
207
157
|
return [];
|