@codyswann/lisa 2.148.0 → 2.150.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/dist/codex/command-skill-transformer.d.ts +4 -2
- package/dist/codex/command-skill-transformer.d.ts.map +1 -1
- package/dist/codex/command-skill-transformer.js +10 -7
- package/dist/codex/command-skill-transformer.js.map +1 -1
- package/dist/codex/skills-installer.d.ts +1 -2
- package/dist/codex/skills-installer.d.ts.map +1 -1
- package/dist/codex/skills-installer.js +9 -176
- package/dist/codex/skills-installer.js.map +1 -1
- package/dist/core/config.d.ts +4 -3
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +1 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/lisa-skill-sources.d.ts +63 -0
- package/dist/core/lisa-skill-sources.d.ts.map +1 -0
- package/dist/core/lisa-skill-sources.js +197 -0
- package/dist/core/lisa-skill-sources.js.map +1 -0
- package/dist/core/lisa.d.ts +12 -0
- package/dist/core/lisa.d.ts.map +1 -1
- package/dist/core/lisa.js +53 -0
- package/dist/core/lisa.js.map +1 -1
- package/dist/opencode/manifest.d.ts +26 -0
- package/dist/opencode/manifest.d.ts.map +1 -0
- package/dist/opencode/manifest.js +94 -0
- package/dist/opencode/manifest.js.map +1 -0
- package/dist/opencode/mcp-installer.d.ts +89 -0
- package/dist/opencode/mcp-installer.d.ts.map +1 -0
- package/dist/opencode/mcp-installer.js +160 -0
- package/dist/opencode/mcp-installer.js.map +1 -0
- package/dist/opencode/settings-installer.d.ts +41 -0
- package/dist/opencode/settings-installer.d.ts.map +1 -0
- package/dist/opencode/settings-installer.js +127 -0
- package/dist/opencode/settings-installer.js.map +1 -0
- package/dist/opencode/skills-installer.d.ts +32 -0
- package/dist/opencode/skills-installer.d.ts.map +1 -0
- package/dist/opencode/skills-installer.js +159 -0
- package/dist/opencode/skills-installer.js.map +1 -0
- package/package.json +2 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/rules/reference/leaf-only-lifecycle.md +9 -4
- package/plugins/lisa/skills/github-build-intake/SKILL.md +10 -0
- package/plugins/lisa/skills/jira-build-intake/SKILL.md +10 -0
- package/plugins/lisa/skills/linear-build-intake/SKILL.md +10 -0
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/github-build-intake/SKILL.md +10 -0
- package/plugins/lisa-agy/skills/jira-build-intake/SKILL.md +10 -0
- package/plugins/lisa-agy/skills/linear-build-intake/SKILL.md +10 -0
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/rules/reference/leaf-only-lifecycle.md +9 -4
- package/plugins/lisa-copilot/skills/github-build-intake/SKILL.md +10 -0
- package/plugins/lisa-copilot/skills/jira-build-intake/SKILL.md +10 -0
- package/plugins/lisa-copilot/skills/linear-build-intake/SKILL.md +10 -0
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/rules/leaf-only-lifecycle-reference.mdc +9 -4
- package/plugins/lisa-cursor/skills/github-build-intake/SKILL.md +10 -0
- package/plugins/lisa-cursor/skills/jira-build-intake/SKILL.md +10 -0
- package/plugins/lisa-cursor/skills/linear-build-intake/SKILL.md +10 -0
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/rules/reference/leaf-only-lifecycle.md +9 -4
- package/plugins/src/base/skills/github-build-intake/SKILL.md +10 -0
- package/plugins/src/base/skills/jira-build-intake/SKILL.md +10 -0
- package/plugins/src/base/skills/linear-build-intake/SKILL.md +10 -0
- package/scripts/internal-opencode-skill-policy.json +3 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { ClaudeMcpServerEntry } from "../agy/mcp-installer.js";
|
|
2
|
+
/** Marker field tagged onto every Lisa-owned MCP server entry. */
|
|
3
|
+
export declare const LISA_MANAGED_MARKER: "_lisaManaged";
|
|
4
|
+
/** A stdio MCP server in OpenCode's shape (`command` is an argv array). */
|
|
5
|
+
export interface OpencodeLocalMcpEntry {
|
|
6
|
+
readonly type: "local";
|
|
7
|
+
readonly command: readonly string[];
|
|
8
|
+
readonly environment?: Readonly<Record<string, string>>;
|
|
9
|
+
readonly enabled: boolean;
|
|
10
|
+
readonly [LISA_MANAGED_MARKER]?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** An HTTP MCP server in OpenCode's shape (`url`, not `command`). */
|
|
13
|
+
export interface OpencodeRemoteMcpEntry {
|
|
14
|
+
readonly type: "remote";
|
|
15
|
+
readonly url: string;
|
|
16
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
17
|
+
readonly enabled: boolean;
|
|
18
|
+
readonly [LISA_MANAGED_MARKER]?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** Any MCP server entry in OpenCode's `mcp` map. */
|
|
21
|
+
export type OpencodeMcpServerEntry = OpencodeLocalMcpEntry | OpencodeRemoteMcpEntry;
|
|
22
|
+
/** Top-level `opencode.json` shape, narrowed to the keys this module touches. */
|
|
23
|
+
export interface OpencodeConfigShape {
|
|
24
|
+
readonly mcp?: Readonly<Record<string, OpencodeMcpServerEntry>>;
|
|
25
|
+
}
|
|
26
|
+
/** Result of the OpenCode MCP install pass. */
|
|
27
|
+
export interface OpencodeMcpInstallResult {
|
|
28
|
+
/** Absolute path written. */
|
|
29
|
+
readonly path: string;
|
|
30
|
+
/** Number of Lisa-managed entries written. */
|
|
31
|
+
readonly lisaEntryCount: number;
|
|
32
|
+
/** Number of host-authored entries preserved. */
|
|
33
|
+
readonly hostEntryCount: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the absolute path to a project's `opencode.json`.
|
|
37
|
+
* @param destDir - Absolute path to the host project root.
|
|
38
|
+
* @returns Absolute path to `<destDir>/opencode.json`.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveOpencodeConfigPath(destDir: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Translate a Claude/Codex-shape MCP entry to OpenCode's shape.
|
|
43
|
+
*
|
|
44
|
+
* Rules:
|
|
45
|
+
* - stdio (`command` present): `type: "local"`, fold `command` + `args` into
|
|
46
|
+
* a single argv array, rename `env` → `environment`, set `enabled: true`.
|
|
47
|
+
* - http/sse (`url` present): `type: "remote"`, keep `url` + `headers`, set
|
|
48
|
+
* `enabled: true`.
|
|
49
|
+
*
|
|
50
|
+
* The `_lisaManaged` marker is attached at write time, not in this pure transform.
|
|
51
|
+
* Throws if the entry has neither `command` nor `url` (un-translatable).
|
|
52
|
+
* @param input - Claude/Codex-format MCP server entry.
|
|
53
|
+
* @returns OpenCode-format MCP server entry.
|
|
54
|
+
*/
|
|
55
|
+
export declare function translateMcpEntryToOpencode(input: ClaudeMcpServerEntry): OpencodeMcpServerEntry;
|
|
56
|
+
/**
|
|
57
|
+
* Install Lisa's MCP servers into `<destDir>/opencode.json` using tagged-merge.
|
|
58
|
+
*
|
|
59
|
+
* Always call this — even with an empty `lisaMcpServers` — so previously written
|
|
60
|
+
* `_lisaManaged` entries are stripped when a project stops shipping MCP servers.
|
|
61
|
+
* @param lisaMcpServers - Lisa's MCP servers in Claude/Codex shape, keyed by name.
|
|
62
|
+
* @param configPath - Absolute path to the target `opencode.json`.
|
|
63
|
+
* @returns Result with the path written and entry counts.
|
|
64
|
+
*/
|
|
65
|
+
export declare function installOpencodeMcpConfig(lisaMcpServers: Readonly<Record<string, ClaudeMcpServerEntry>>, configPath: string): Promise<OpencodeMcpInstallResult>;
|
|
66
|
+
/** Merge outcome: the rewritten document plus Lisa/host entry counts. */
|
|
67
|
+
interface McpMergeResult {
|
|
68
|
+
readonly text: string;
|
|
69
|
+
readonly lisaEntryCount: number;
|
|
70
|
+
readonly hostEntryCount: number;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Merge Lisa's MCP servers into the `mcp` key of an `opencode.json` document.
|
|
74
|
+
* Pure function for testability; `installOpencodeMcpConfig` is the I/O wrapper.
|
|
75
|
+
*
|
|
76
|
+
* Tagged-merge rules:
|
|
77
|
+
* 1. Translate + tag Lisa's entries with `_lisaManaged: true`.
|
|
78
|
+
* 2. Drop every existing entry already tagged `_lisaManaged` (Lisa's prior run).
|
|
79
|
+
* 3. Preserve host-authored entries (untagged) verbatim.
|
|
80
|
+
* 4. Rewrite only the `mcp` key; the rest of the document is untouched.
|
|
81
|
+
*
|
|
82
|
+
* Throws on invalid JSONC so a corrupt host file is surfaced, not overwritten.
|
|
83
|
+
* @param existingJsonc - Current contents of `opencode.json` (or "").
|
|
84
|
+
* @param lisaMcpServers - Lisa's MCP servers in Claude/Codex shape, keyed by name.
|
|
85
|
+
* @returns The merged document text and entry counts.
|
|
86
|
+
*/
|
|
87
|
+
export declare function mergeMcpServers(existingJsonc: string, lisaMcpServers: Readonly<Record<string, ClaudeMcpServerEntry>>): McpMergeResult;
|
|
88
|
+
export {};
|
|
89
|
+
//# sourceMappingURL=mcp-installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-installer.d.ts","sourceRoot":"","sources":["../../src/opencode/mcp-installer.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAGpE,kEAAkE;AAClE,eAAO,MAAM,mBAAmB,EAAG,cAAuB,CAAC;AAO3D,2EAA2E;AAC3E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,CAAC,mBAAmB,CAAC,CAAC,EAAE,OAAO,CAAC;CAC1C;AAED,qEAAqE;AACrE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,CAAC,mBAAmB,CAAC,CAAC,EAAE,OAAO,CAAC;CAC1C;AAED,oDAAoD;AACpD,MAAM,MAAM,sBAAsB,GAC9B,qBAAqB,GACrB,sBAAsB,CAAC;AAE3B,iFAAiF;AACjF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC,CAAC;CACjE;AAED,+CAA+C;AAC/C,MAAM,WAAW,wBAAwB;IACvC,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,iDAAiD;IACjD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,oBAAoB,GAC1B,sBAAsB,CAoBxB;AAED;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,EAC9D,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,wBAAwB,CAAC,CAanC;AAED,yEAAyE;AACzE,UAAU,cAAc;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,GAC7D,cAAc,CA0ChB"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install Lisa's MCP servers into a host project's `opencode.json` `mcp` key.
|
|
3
|
+
*
|
|
4
|
+
* OpenCode does NOT load plugin-bundled MCP servers — they must be declared in
|
|
5
|
+
* config (the "Wrap" pattern). So `processOpencodeEmit` collects Lisa's servers
|
|
6
|
+
* from the built plugin `.mcp.json` files (base + each detected stack, via the
|
|
7
|
+
* shared `collectLisaMcpServers`) and writes them into the `mcp` object of the
|
|
8
|
+
* project's `opencode.json`, translated to OpenCode's transport shape:
|
|
9
|
+
*
|
|
10
|
+
* - stdio → `{ type: "local", command: [...], environment: {...}, enabled }`
|
|
11
|
+
* (`command` is a single ARRAY — argv[0] is the binary, the rest are args).
|
|
12
|
+
* - http → `{ type: "remote", url: "...", headers: {...}, enabled }`
|
|
13
|
+
*
|
|
14
|
+
* See opencode.ai/docs/mcp-servers and /docs/config.
|
|
15
|
+
*
|
|
16
|
+
* Tagged-merge convention (mirrors `src/agy/mcp-installer.ts`): every Lisa-owned
|
|
17
|
+
* server entry carries `_lisaManaged: true`, so a re-run strips Lisa's previous
|
|
18
|
+
* entries and rewrites them while preserving any host-authored servers verbatim.
|
|
19
|
+
* The edit is surgical (only the `mcp` key is rewritten via `jsonc-parser`), so
|
|
20
|
+
* sibling keys, comments, and formatting elsewhere in `opencode.json` survive.
|
|
21
|
+
* @module opencode/mcp-installer
|
|
22
|
+
*/
|
|
23
|
+
import { existsSync } from "node:fs";
|
|
24
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
25
|
+
import * as path from "node:path";
|
|
26
|
+
import { applyEdits, modify, parse as parseJsonc, } from "jsonc-parser";
|
|
27
|
+
import { CONFIG_FILENAME, OPENCODE_SCHEMA_URL } from "./settings-installer.js";
|
|
28
|
+
/** Marker field tagged onto every Lisa-owned MCP server entry. */
|
|
29
|
+
export const LISA_MANAGED_MARKER = "_lisaManaged";
|
|
30
|
+
/** JSONC edit formatting — 2-space indent, matching the repo's JSON style. */
|
|
31
|
+
const FORMATTING_OPTIONS = {
|
|
32
|
+
formattingOptions: { tabSize: 2, insertSpaces: true },
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Resolve the absolute path to a project's `opencode.json`.
|
|
36
|
+
* @param destDir - Absolute path to the host project root.
|
|
37
|
+
* @returns Absolute path to `<destDir>/opencode.json`.
|
|
38
|
+
*/
|
|
39
|
+
export function resolveOpencodeConfigPath(destDir) {
|
|
40
|
+
return path.join(destDir, CONFIG_FILENAME);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Translate a Claude/Codex-shape MCP entry to OpenCode's shape.
|
|
44
|
+
*
|
|
45
|
+
* Rules:
|
|
46
|
+
* - stdio (`command` present): `type: "local"`, fold `command` + `args` into
|
|
47
|
+
* a single argv array, rename `env` → `environment`, set `enabled: true`.
|
|
48
|
+
* - http/sse (`url` present): `type: "remote"`, keep `url` + `headers`, set
|
|
49
|
+
* `enabled: true`.
|
|
50
|
+
*
|
|
51
|
+
* The `_lisaManaged` marker is attached at write time, not in this pure transform.
|
|
52
|
+
* Throws if the entry has neither `command` nor `url` (un-translatable).
|
|
53
|
+
* @param input - Claude/Codex-format MCP server entry.
|
|
54
|
+
* @returns OpenCode-format MCP server entry.
|
|
55
|
+
*/
|
|
56
|
+
export function translateMcpEntryToOpencode(input) {
|
|
57
|
+
if (input.command !== undefined) {
|
|
58
|
+
return {
|
|
59
|
+
type: "local",
|
|
60
|
+
command: [input.command, ...(input.args ?? [])],
|
|
61
|
+
...(input.env !== undefined ? { environment: input.env } : {}),
|
|
62
|
+
enabled: true,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (input.url !== undefined) {
|
|
66
|
+
return {
|
|
67
|
+
type: "remote",
|
|
68
|
+
url: input.url,
|
|
69
|
+
...(input.headers !== undefined ? { headers: input.headers } : {}),
|
|
70
|
+
enabled: true,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
throw new Error("translateMcpEntryToOpencode: entry has neither `command` (stdio) nor `url` (http)");
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Install Lisa's MCP servers into `<destDir>/opencode.json` using tagged-merge.
|
|
77
|
+
*
|
|
78
|
+
* Always call this — even with an empty `lisaMcpServers` — so previously written
|
|
79
|
+
* `_lisaManaged` entries are stripped when a project stops shipping MCP servers.
|
|
80
|
+
* @param lisaMcpServers - Lisa's MCP servers in Claude/Codex shape, keyed by name.
|
|
81
|
+
* @param configPath - Absolute path to the target `opencode.json`.
|
|
82
|
+
* @returns Result with the path written and entry counts.
|
|
83
|
+
*/
|
|
84
|
+
export async function installOpencodeMcpConfig(lisaMcpServers, configPath) {
|
|
85
|
+
const exists = existsSync(configPath);
|
|
86
|
+
const existingContent = exists ? await readFile(configPath, "utf8") : "";
|
|
87
|
+
const merged = mergeMcpServers(existingContent, lisaMcpServers);
|
|
88
|
+
await mkdir(path.dirname(configPath), { recursive: true });
|
|
89
|
+
await writeFile(configPath, merged.text, "utf8");
|
|
90
|
+
return {
|
|
91
|
+
path: configPath,
|
|
92
|
+
lisaEntryCount: merged.lisaEntryCount,
|
|
93
|
+
hostEntryCount: merged.hostEntryCount,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Merge Lisa's MCP servers into the `mcp` key of an `opencode.json` document.
|
|
98
|
+
* Pure function for testability; `installOpencodeMcpConfig` is the I/O wrapper.
|
|
99
|
+
*
|
|
100
|
+
* Tagged-merge rules:
|
|
101
|
+
* 1. Translate + tag Lisa's entries with `_lisaManaged: true`.
|
|
102
|
+
* 2. Drop every existing entry already tagged `_lisaManaged` (Lisa's prior run).
|
|
103
|
+
* 3. Preserve host-authored entries (untagged) verbatim.
|
|
104
|
+
* 4. Rewrite only the `mcp` key; the rest of the document is untouched.
|
|
105
|
+
*
|
|
106
|
+
* Throws on invalid JSONC so a corrupt host file is surfaced, not overwritten.
|
|
107
|
+
* @param existingJsonc - Current contents of `opencode.json` (or "").
|
|
108
|
+
* @param lisaMcpServers - Lisa's MCP servers in Claude/Codex shape, keyed by name.
|
|
109
|
+
* @returns The merged document text and entry counts.
|
|
110
|
+
*/
|
|
111
|
+
export function mergeMcpServers(existingJsonc, lisaMcpServers) {
|
|
112
|
+
const lisaEntries = Object.fromEntries(Object.entries(lisaMcpServers).map(([name, entry]) => [
|
|
113
|
+
name,
|
|
114
|
+
{ ...translateMcpEntryToOpencode(entry), [LISA_MANAGED_MARKER]: true },
|
|
115
|
+
]));
|
|
116
|
+
if (existingJsonc.trim().length === 0) {
|
|
117
|
+
const doc = { $schema: OPENCODE_SCHEMA_URL, mcp: lisaEntries };
|
|
118
|
+
return {
|
|
119
|
+
text: `${JSON.stringify(doc, null, 2)}\n`,
|
|
120
|
+
lisaEntryCount: Object.keys(lisaEntries).length,
|
|
121
|
+
hostEntryCount: 0,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const current = parseJsoncOrThrow(existingJsonc);
|
|
125
|
+
const existingMcp = current.mcp !== null &&
|
|
126
|
+
typeof current.mcp === "object" &&
|
|
127
|
+
!Array.isArray(current.mcp)
|
|
128
|
+
? current.mcp
|
|
129
|
+
: {};
|
|
130
|
+
const hostEntries = Object.fromEntries(Object.entries(existingMcp).filter(([, entry]) => entry?.[LISA_MANAGED_MARKER] !== true));
|
|
131
|
+
const mergedMcp = { ...hostEntries, ...lisaEntries };
|
|
132
|
+
const edits = modify(existingJsonc, ["mcp"], mergedMcp, FORMATTING_OPTIONS);
|
|
133
|
+
const applied = applyEdits(existingJsonc, edits);
|
|
134
|
+
return {
|
|
135
|
+
text: applied.endsWith("\n") ? applied : `${applied}\n`,
|
|
136
|
+
lisaEntryCount: Object.keys(lisaEntries).length,
|
|
137
|
+
hostEntryCount: Object.keys(hostEntries).length,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Parse JSONC, throwing a descriptive error on the first syntax problem so a
|
|
142
|
+
* corrupt host `opencode.json` is surfaced rather than silently overwritten.
|
|
143
|
+
* @param jsonc - Raw `opencode.json` contents.
|
|
144
|
+
* @returns The parsed object (empty object if the root is a non-object).
|
|
145
|
+
*/
|
|
146
|
+
function parseJsoncOrThrow(jsonc) {
|
|
147
|
+
const errors = [];
|
|
148
|
+
const parsed = parseJsonc(jsonc, errors, {
|
|
149
|
+
allowTrailingComma: true,
|
|
150
|
+
disallowComments: false,
|
|
151
|
+
});
|
|
152
|
+
if (errors.length > 0) {
|
|
153
|
+
throw new Error(`opencode.json is not valid JSONC (offset ${errors[0]?.offset ?? 0}); ` +
|
|
154
|
+
`refusing to overwrite host config`);
|
|
155
|
+
}
|
|
156
|
+
return parsed !== null && typeof parsed === "object"
|
|
157
|
+
? parsed
|
|
158
|
+
: {};
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=mcp-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-installer.js","sourceRoot":"","sources":["../../src/opencode/mcp-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Filename of OpenCode's project-scope config file (at the project root). */
|
|
2
|
+
export declare const CONFIG_FILENAME = "opencode.json";
|
|
3
|
+
/** OpenCode's config JSON-schema URL, used to seed `$schema` on fresh files. */
|
|
4
|
+
export declare const OPENCODE_SCHEMA_URL = "https://opencode.ai/config.json";
|
|
5
|
+
/**
|
|
6
|
+
* Lisa-required settings forced into `opencode.json`. For these keys Lisa wins
|
|
7
|
+
* on conflict; every other key the host authors is preserved untouched.
|
|
8
|
+
*
|
|
9
|
+
* `share: "disabled"` is the headline entry — OpenCode sharing is ON by default
|
|
10
|
+
* and creates public URLs, so disabling it is an enterprise-safety guarantee.
|
|
11
|
+
*/
|
|
12
|
+
export declare const LISA_REQUIRED_SETTINGS: Readonly<Record<string, unknown>>;
|
|
13
|
+
/** Result of a settings install pass. */
|
|
14
|
+
export interface SettingsInstallResult {
|
|
15
|
+
/** Files written, relative to the project root. */
|
|
16
|
+
readonly managedFiles: readonly string[];
|
|
17
|
+
/** Whether `opencode.json` was newly created (vs. merged in place). */
|
|
18
|
+
readonly created: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Install or update Lisa's required settings in `<destDir>/opencode.json`.
|
|
22
|
+
*
|
|
23
|
+
* Host keys, comments, and formatting survive because the merge edits the
|
|
24
|
+
* document surgically rather than reserializing it.
|
|
25
|
+
* @param destDir - Absolute path to the host project root.
|
|
26
|
+
* @returns Result describing what was written.
|
|
27
|
+
*/
|
|
28
|
+
export declare function installSettings(destDir: string): Promise<SettingsInstallResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Merge Lisa-required settings into an `opencode.json` (JSONC) document. Pure
|
|
31
|
+
* function for testability; `installSettings` is the I/O wrapper.
|
|
32
|
+
*
|
|
33
|
+
* Empty input yields a clean Lisa-authored document. Non-empty input is parsed
|
|
34
|
+
* tolerantly (comments + trailing commas allowed) and edited key-by-key so
|
|
35
|
+
* surrounding host content is preserved byte-for-byte. Throws on invalid JSONC
|
|
36
|
+
* so a malformed host file is surfaced rather than silently overwritten.
|
|
37
|
+
* @param existingJsonc - Current contents of `opencode.json` (or "").
|
|
38
|
+
* @returns Merged JSON/JSONC string with host content preserved.
|
|
39
|
+
*/
|
|
40
|
+
export declare function mergeSettings(existingJsonc: string): string;
|
|
41
|
+
//# sourceMappingURL=settings-installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-installer.d.ts","sourceRoot":"","sources":["../../src/opencode/settings-installer.ts"],"names":[],"mappings":"AAgCA,8EAA8E;AAC9E,eAAO,MAAM,eAAe,kBAAkB,CAAC;AAE/C,gFAAgF;AAChF,eAAO,MAAM,mBAAmB,oCAAoC,CAAC;AAErE;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEpE,CAAC;AAOF,yCAAyC;AACzC,MAAM,WAAW,qBAAqB;IACpC,mDAAmD;IACnD,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,uEAAuE;IACvE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,qBAAqB,CAAC,CAahC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAmB3D"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manage Lisa-required settings in a host project's `opencode.json`.
|
|
3
|
+
*
|
|
4
|
+
* OpenCode reads project-scope config from `opencode.json` at the project root
|
|
5
|
+
* (JSON or JSONC — comments and trailing commas are allowed; see
|
|
6
|
+
* opencode.ai/docs/config). Config files across scopes are *merged*, not
|
|
7
|
+
* replaced, so Lisa writes only the project file and only the handful of keys it
|
|
8
|
+
* owns; every host-authored key, comment, and formatting choice is preserved by
|
|
9
|
+
* editing the document surgically via `jsonc-parser` (the JSON analogue of the
|
|
10
|
+
* `toml-patch` round-trip the Codex settings installer relies on).
|
|
11
|
+
*
|
|
12
|
+
* Lisa-owned keys (host wins for everything NOT listed; Lisa wins for these):
|
|
13
|
+
* - `share`: forced to `"disabled"`. OpenCode session sharing defaults to ON
|
|
14
|
+
* and mints PUBLIC share URLs for conversations — an enterprise data-exposure
|
|
15
|
+
* hazard. Lisa disables it so applying the fleet config can never silently
|
|
16
|
+
* publish a host's sessions.
|
|
17
|
+
*
|
|
18
|
+
* `$schema` is set to OpenCode's schema URL ONLY when absent (a default, not a
|
|
19
|
+
* force) so editor validation works on fresh files without clobbering a host
|
|
20
|
+
* that pinned a different schema.
|
|
21
|
+
* @module opencode/settings-installer
|
|
22
|
+
*/
|
|
23
|
+
import { existsSync } from "node:fs";
|
|
24
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
25
|
+
import * as path from "node:path";
|
|
26
|
+
import { applyEdits, modify, parse as parseJsonc, } from "jsonc-parser";
|
|
27
|
+
/** Filename of OpenCode's project-scope config file (at the project root). */
|
|
28
|
+
export const CONFIG_FILENAME = "opencode.json";
|
|
29
|
+
/** OpenCode's config JSON-schema URL, used to seed `$schema` on fresh files. */
|
|
30
|
+
export const OPENCODE_SCHEMA_URL = "https://opencode.ai/config.json";
|
|
31
|
+
/**
|
|
32
|
+
* Lisa-required settings forced into `opencode.json`. For these keys Lisa wins
|
|
33
|
+
* on conflict; every other key the host authors is preserved untouched.
|
|
34
|
+
*
|
|
35
|
+
* `share: "disabled"` is the headline entry — OpenCode sharing is ON by default
|
|
36
|
+
* and creates public URLs, so disabling it is an enterprise-safety guarantee.
|
|
37
|
+
*/
|
|
38
|
+
export const LISA_REQUIRED_SETTINGS = {
|
|
39
|
+
share: "disabled",
|
|
40
|
+
};
|
|
41
|
+
/** JSONC edit formatting — 2-space indent, matching the repo's JSON style. */
|
|
42
|
+
const FORMATTING_OPTIONS = {
|
|
43
|
+
formattingOptions: { tabSize: 2, insertSpaces: true },
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Install or update Lisa's required settings in `<destDir>/opencode.json`.
|
|
47
|
+
*
|
|
48
|
+
* Host keys, comments, and formatting survive because the merge edits the
|
|
49
|
+
* document surgically rather than reserializing it.
|
|
50
|
+
* @param destDir - Absolute path to the host project root.
|
|
51
|
+
* @returns Result describing what was written.
|
|
52
|
+
*/
|
|
53
|
+
export async function installSettings(destDir) {
|
|
54
|
+
const configPath = path.join(destDir, CONFIG_FILENAME);
|
|
55
|
+
const exists = existsSync(configPath);
|
|
56
|
+
const existingContent = exists ? await readFile(configPath, "utf8") : "";
|
|
57
|
+
const merged = mergeSettings(existingContent);
|
|
58
|
+
await mkdir(path.dirname(configPath), { recursive: true });
|
|
59
|
+
await writeFile(configPath, merged, "utf8");
|
|
60
|
+
return {
|
|
61
|
+
managedFiles: Object.freeze([CONFIG_FILENAME]),
|
|
62
|
+
created: !exists,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Merge Lisa-required settings into an `opencode.json` (JSONC) document. Pure
|
|
67
|
+
* function for testability; `installSettings` is the I/O wrapper.
|
|
68
|
+
*
|
|
69
|
+
* Empty input yields a clean Lisa-authored document. Non-empty input is parsed
|
|
70
|
+
* tolerantly (comments + trailing commas allowed) and edited key-by-key so
|
|
71
|
+
* surrounding host content is preserved byte-for-byte. Throws on invalid JSONC
|
|
72
|
+
* so a malformed host file is surfaced rather than silently overwritten.
|
|
73
|
+
* @param existingJsonc - Current contents of `opencode.json` (or "").
|
|
74
|
+
* @returns Merged JSON/JSONC string with host content preserved.
|
|
75
|
+
*/
|
|
76
|
+
export function mergeSettings(existingJsonc) {
|
|
77
|
+
if (existingJsonc.trim().length === 0) {
|
|
78
|
+
const fresh = { $schema: OPENCODE_SCHEMA_URL, ...LISA_REQUIRED_SETTINGS };
|
|
79
|
+
return `${JSON.stringify(fresh, null, 2)}\n`;
|
|
80
|
+
}
|
|
81
|
+
const current = parseJsoncOrThrow(existingJsonc);
|
|
82
|
+
const withForced = Object.entries(LISA_REQUIRED_SETTINGS).reduce((text, [key, value]) => upsertKey(text, [key], value, current[key]), existingJsonc);
|
|
83
|
+
// `$schema` is a default, not a force: only set it when the host omitted it.
|
|
84
|
+
const withSchema = current["$schema"] === undefined
|
|
85
|
+
? upsertKey(withForced, ["$schema"], OPENCODE_SCHEMA_URL, undefined)
|
|
86
|
+
: withForced;
|
|
87
|
+
return withSchema.endsWith("\n") ? withSchema : `${withSchema}\n`;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Parse JSONC, throwing a descriptive error on the first syntax problem.
|
|
91
|
+
*
|
|
92
|
+
* Comments and trailing commas are tolerated (OpenCode permits both); genuine
|
|
93
|
+
* syntax errors throw so a corrupt host config is never silently clobbered.
|
|
94
|
+
* @param jsonc - Raw `opencode.json` contents.
|
|
95
|
+
* @returns The parsed object (empty object if the root is a non-object).
|
|
96
|
+
*/
|
|
97
|
+
function parseJsoncOrThrow(jsonc) {
|
|
98
|
+
const errors = [];
|
|
99
|
+
const parsed = parseJsonc(jsonc, errors, {
|
|
100
|
+
allowTrailingComma: true,
|
|
101
|
+
disallowComments: false,
|
|
102
|
+
});
|
|
103
|
+
if (errors.length > 0) {
|
|
104
|
+
throw new Error(`opencode.json is not valid JSONC (offset ${errors[0]?.offset ?? 0}); ` +
|
|
105
|
+
`refusing to overwrite host config`);
|
|
106
|
+
}
|
|
107
|
+
return parsed !== null && typeof parsed === "object"
|
|
108
|
+
? parsed
|
|
109
|
+
: {};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Set `value` at `keyPath` via a surgical JSONC edit, skipping the write when
|
|
113
|
+
* the document already holds that value (keeps re-runs no-op-clean).
|
|
114
|
+
* @param text - Current document text.
|
|
115
|
+
* @param keyPath - JSON path to the key (single-segment for our keys).
|
|
116
|
+
* @param value - Value to set.
|
|
117
|
+
* @param currentValue - The value already present at `keyPath` (or undefined).
|
|
118
|
+
* @returns The edited document text.
|
|
119
|
+
*/
|
|
120
|
+
function upsertKey(text, keyPath, value, currentValue) {
|
|
121
|
+
if (currentValue === value) {
|
|
122
|
+
return text;
|
|
123
|
+
}
|
|
124
|
+
const edits = modify(text, [...keyPath], value, FORMATTING_OPTIONS);
|
|
125
|
+
return applyEdits(text, edits);
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=settings-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-installer.js","sourceRoot":"","sources":["../../src/opencode/settings-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Subdirectory inside `.opencode/skills/` where Lisa-owned skills live */
|
|
2
|
+
export declare const LISA_SKILLS_SUBDIR: string;
|
|
3
|
+
/** Result of one skill copy */
|
|
4
|
+
export interface InstalledSkill {
|
|
5
|
+
/** Skill name (matches the SKILL.md `name` frontmatter) */
|
|
6
|
+
readonly name: string;
|
|
7
|
+
/** Source kind: bundled skill folder or generated from command */
|
|
8
|
+
readonly source: "bundled" | "command";
|
|
9
|
+
/** Path written, relative to `.opencode/` */
|
|
10
|
+
readonly relativePath: string;
|
|
11
|
+
}
|
|
12
|
+
/** Aggregated result */
|
|
13
|
+
export interface SkillsInstallResult {
|
|
14
|
+
readonly installed: readonly InstalledSkill[];
|
|
15
|
+
readonly managedFiles: readonly string[];
|
|
16
|
+
/** Skill directories deleted because Lisa stopped shipping them */
|
|
17
|
+
readonly deleted: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Install all Lisa-bundled skills + command-derived skills into
|
|
21
|
+
* `.opencode/skills/lisa/`.
|
|
22
|
+
*
|
|
23
|
+
* Stale skills (in the previous manifest but no longer in Lisa's catalog) are
|
|
24
|
+
* deleted so renames in the source tree don't leave orphan directories behind.
|
|
25
|
+
* @param lisaDir - Absolute path to the Lisa repo root.
|
|
26
|
+
* @param destDir - Absolute path to the host project root.
|
|
27
|
+
* @param previousManagedFiles - Files Lisa managed on the previous run
|
|
28
|
+
* (relative to `.opencode/`); used to detect stale skill directories.
|
|
29
|
+
* @returns Result describing installed skills + managed files + deletions.
|
|
30
|
+
*/
|
|
31
|
+
export declare function installSkills(lisaDir: string, destDir: string, previousManagedFiles: readonly string[]): Promise<SkillsInstallResult>;
|
|
32
|
+
//# sourceMappingURL=skills-installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-installer.d.ts","sourceRoot":"","sources":["../../src/opencode/skills-installer.ts"],"names":[],"mappings":"AAsCA,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAW9D,+BAA+B;AAC/B,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IACvC,6CAA6C;IAC7C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,wBAAwB;AACxB,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IAC9C,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,oBAAoB,EAAE,SAAS,MAAM,EAAE,GACtC,OAAO,CAAC,mBAAmB,CAAC,CA6C9B"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install Lisa-bundled skills into a host project's `.opencode/skills/lisa/`.
|
|
3
|
+
*
|
|
4
|
+
* OpenCode discovers skills (the open Agent Skills format: SKILL.md + optional
|
|
5
|
+
* siblings) natively from `.opencode/skills/<name>/`, walking up from the cwd to
|
|
6
|
+
* the git worktree (see opencode.ai/docs/skills). It ALSO reads `.claude/skills`
|
|
7
|
+
* and `.agents/skills`, but Lisa writes into the OpenCode-owned `.opencode/`
|
|
8
|
+
* tree so its artifacts never collide with a Claude install on the same machine
|
|
9
|
+
* (OpenCode dedupes duplicate skill names with a warning — verified-by-run on
|
|
10
|
+
* opencode 1.16.2).
|
|
11
|
+
*
|
|
12
|
+
* What this installs:
|
|
13
|
+
* 1. Lisa-bundled skill folders from `plugins/<p>/skills/<n>/` copied verbatim
|
|
14
|
+
* to `.opencode/skills/lisa/<n>/` (OpenCode reads SKILL.md verbatim — no
|
|
15
|
+
* transform needed, unlike the Codex TOML/openai.yaml path).
|
|
16
|
+
* 2. Lisa commands converted to skills with a `lisa-` prefix, since the safest
|
|
17
|
+
* cross-runtime carrier for a Lisa command is a self-complete skill.
|
|
18
|
+
*
|
|
19
|
+
* Source discovery (walking the plugin tree, dedup, denylist) is shared with the
|
|
20
|
+
* Codex overlay via `core/lisa-skill-sources`.
|
|
21
|
+
* @module opencode/skills-installer
|
|
22
|
+
*/
|
|
23
|
+
import * as fse from "fs-extra";
|
|
24
|
+
import { mkdir, copyFile, readFile, rm, writeFile } from "node:fs/promises";
|
|
25
|
+
import * as path from "node:path";
|
|
26
|
+
import { discoverBundledSkills, discoverLisaCommands, loadSkillDenylist, } from "../core/lisa-skill-sources.js";
|
|
27
|
+
import { convertCommandToSkill } from "../codex/command-skill-transformer.js";
|
|
28
|
+
import { OPENCODE_CONFIG_DIR } from "./manifest.js";
|
|
29
|
+
/** Runtime label threaded into generated command-as-skill compatibility notes */
|
|
30
|
+
const OPENCODE_RUNTIME_LABEL = "OpenCode";
|
|
31
|
+
/** Subdirectory inside `.opencode/skills/` where Lisa-owned skills live */
|
|
32
|
+
export const LISA_SKILLS_SUBDIR = path.join("skills", "lisa");
|
|
33
|
+
/** Filename of the skill manifest at the root of every skill folder */
|
|
34
|
+
const SKILL_MD_FILENAME = "SKILL.md";
|
|
35
|
+
/** Path to the OpenCode skill distribution policy, relative to the Lisa root */
|
|
36
|
+
const INTERNAL_OPENCODE_SKILL_POLICY_RELATIVE_PATH = path.join("scripts", "internal-opencode-skill-policy.json");
|
|
37
|
+
/**
|
|
38
|
+
* Install all Lisa-bundled skills + command-derived skills into
|
|
39
|
+
* `.opencode/skills/lisa/`.
|
|
40
|
+
*
|
|
41
|
+
* Stale skills (in the previous manifest but no longer in Lisa's catalog) are
|
|
42
|
+
* deleted so renames in the source tree don't leave orphan directories behind.
|
|
43
|
+
* @param lisaDir - Absolute path to the Lisa repo root.
|
|
44
|
+
* @param destDir - Absolute path to the host project root.
|
|
45
|
+
* @param previousManagedFiles - Files Lisa managed on the previous run
|
|
46
|
+
* (relative to `.opencode/`); used to detect stale skill directories.
|
|
47
|
+
* @returns Result describing installed skills + managed files + deletions.
|
|
48
|
+
*/
|
|
49
|
+
export async function installSkills(lisaDir, destDir, previousManagedFiles) {
|
|
50
|
+
const skillsDir = path.join(destDir, OPENCODE_CONFIG_DIR, LISA_SKILLS_SUBDIR);
|
|
51
|
+
await fse.ensureDir(skillsDir);
|
|
52
|
+
const denylistedSkills = await loadSkillDenylist(lisaDir, INTERNAL_OPENCODE_SKILL_POLICY_RELATIVE_PATH);
|
|
53
|
+
// Step 1: bundled skills
|
|
54
|
+
const bundled = await discoverBundledSkills(lisaDir, denylistedSkills);
|
|
55
|
+
const bundledInstalls = await Promise.all(bundled.map(source => copyBundledSkill(source, skillsDir)));
|
|
56
|
+
const bundledFiles = bundled.flatMap(source => source.files.map(file => path.join(LISA_SKILLS_SUBDIR, source.skillName, file)));
|
|
57
|
+
// Step 2: command-as-skill conversions
|
|
58
|
+
const commandSkills = await discoverLisaCommands(lisaDir);
|
|
59
|
+
const commandInstalls = await Promise.all(commandSkills.map(cmd => emitCommandAsSkill(cmd, skillsDir)));
|
|
60
|
+
const commandFiles = commandInstalls.map(install => path.join(LISA_SKILLS_SUBDIR, install.name, SKILL_MD_FILENAME));
|
|
61
|
+
const installed = [
|
|
62
|
+
...bundledInstalls,
|
|
63
|
+
...commandInstalls,
|
|
64
|
+
];
|
|
65
|
+
// Step 3: delete stale skill directories
|
|
66
|
+
const deleted = await deleteStaleSkills(previousManagedFiles, new Set(installed.map(s => s.name)), destDir);
|
|
67
|
+
return {
|
|
68
|
+
installed: Object.freeze(installed),
|
|
69
|
+
managedFiles: Object.freeze([...bundledFiles, ...commandFiles]),
|
|
70
|
+
deleted: Object.freeze(deleted),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Delete skill directories that were Lisa-managed last run but aren't shipped
|
|
75
|
+
* this run. Identifies skill names from the previous manifest by looking for
|
|
76
|
+
* paths inside `.opencode/skills/lisa/<name>/...`.
|
|
77
|
+
*
|
|
78
|
+
* Whole directories are removed (not individual files) so siblings the host
|
|
79
|
+
* accidentally added inside a Lisa skill folder also disappear — Lisa owns the
|
|
80
|
+
* directory boundary, not just specific files.
|
|
81
|
+
* @param previousManagedFiles - Files Lisa managed on the previous run
|
|
82
|
+
* (relative to `.opencode/`).
|
|
83
|
+
* @param currentSkillNames - Skill names Lisa is shipping this run.
|
|
84
|
+
* @param destDir - Absolute path to the host project root.
|
|
85
|
+
* @returns Sorted list of stale skill names that were deleted.
|
|
86
|
+
*/
|
|
87
|
+
async function deleteStaleSkills(previousManagedFiles, currentSkillNames, destDir) {
|
|
88
|
+
const lisaSkillsPrefix = `${LISA_SKILLS_SUBDIR}${path.sep}`;
|
|
89
|
+
const previousSkillNames = extractPreviousSkillNames(previousManagedFiles, lisaSkillsPrefix);
|
|
90
|
+
const stale = previousSkillNames.filter(name => !currentSkillNames.has(name));
|
|
91
|
+
await Promise.all(stale.map(async (name) => {
|
|
92
|
+
const absPath = path.join(destDir, OPENCODE_CONFIG_DIR, LISA_SKILLS_SUBDIR, name);
|
|
93
|
+
if (await fse.pathExists(absPath)) {
|
|
94
|
+
await rm(absPath, { recursive: true, force: true });
|
|
95
|
+
}
|
|
96
|
+
}));
|
|
97
|
+
return Object.freeze([...stale].sort((a, b) => a.localeCompare(b)));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Pick the unique skill-folder names out of the previous manifest's file list —
|
|
101
|
+
* every path inside `.opencode/skills/lisa/<name>/...` contributes `<name>`.
|
|
102
|
+
* @param previousManagedFiles - Files Lisa managed on the previous run.
|
|
103
|
+
* @param lisaSkillsPrefix - The path prefix that identifies Lisa skill files.
|
|
104
|
+
* @returns Unique skill names extracted from those paths.
|
|
105
|
+
*/
|
|
106
|
+
function extractPreviousSkillNames(previousManagedFiles, lisaSkillsPrefix) {
|
|
107
|
+
const names = previousManagedFiles
|
|
108
|
+
.filter(file => file.startsWith(lisaSkillsPrefix))
|
|
109
|
+
.map(file => file.slice(lisaSkillsPrefix.length).split(path.sep)[0])
|
|
110
|
+
.filter((name) => Boolean(name));
|
|
111
|
+
return Array.from(new Set(names));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Copy one bundled skill folder verbatim into `.opencode/skills/lisa/`.
|
|
115
|
+
* @param source - Bundled-skill source to copy.
|
|
116
|
+
* @param skillsDir - Absolute path to `<destDir>/.opencode/skills/lisa/`.
|
|
117
|
+
* @returns Result describing the installed skill.
|
|
118
|
+
*/
|
|
119
|
+
async function copyBundledSkill(source, skillsDir) {
|
|
120
|
+
const destSkillDir = path.join(skillsDir, source.skillName);
|
|
121
|
+
// Clean-replace the Lisa-owned skill folder before copying so files removed
|
|
122
|
+
// from the source between releases don't linger inside a surviving skill.
|
|
123
|
+
// Lisa owns this directory boundary (host customizations belong outside it).
|
|
124
|
+
await rm(destSkillDir, { recursive: true, force: true });
|
|
125
|
+
await fse.ensureDir(destSkillDir);
|
|
126
|
+
await Promise.all(source.files.map(async (file) => {
|
|
127
|
+
const srcPath = path.join(source.sourceDir, file);
|
|
128
|
+
const destPath = path.join(destSkillDir, file);
|
|
129
|
+
await mkdir(path.dirname(destPath), { recursive: true });
|
|
130
|
+
await copyFile(srcPath, destPath);
|
|
131
|
+
}));
|
|
132
|
+
return {
|
|
133
|
+
name: source.skillName,
|
|
134
|
+
source: "bundled",
|
|
135
|
+
relativePath: path.join(LISA_SKILLS_SUBDIR, source.skillName),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Convert a Lisa command Markdown file into an OpenCode skill.
|
|
140
|
+
*
|
|
141
|
+
* The command body becomes the skill body, with `$ARGUMENTS` replaced by an
|
|
142
|
+
* explicit instruction to use the user's surrounding request as arguments.
|
|
143
|
+
* @param cmd - Discovered command source.
|
|
144
|
+
* @param skillsDir - Absolute path to `<destDir>/.opencode/skills/lisa/`.
|
|
145
|
+
* @returns Result describing the installed (command-derived) skill.
|
|
146
|
+
*/
|
|
147
|
+
async function emitCommandAsSkill(cmd, skillsDir) {
|
|
148
|
+
const sourceContent = await readFile(cmd.sourcePath, "utf8");
|
|
149
|
+
const skillContent = convertCommandToSkill(sourceContent, cmd.skillName, cmd.displayName, OPENCODE_RUNTIME_LABEL);
|
|
150
|
+
const destSkillDir = path.join(skillsDir, cmd.skillName);
|
|
151
|
+
await fse.ensureDir(destSkillDir);
|
|
152
|
+
await writeFile(path.join(destSkillDir, SKILL_MD_FILENAME), skillContent, "utf8");
|
|
153
|
+
return {
|
|
154
|
+
name: cmd.skillName,
|
|
155
|
+
source: "command",
|
|
156
|
+
relativePath: path.join(LISA_SKILLS_SUBDIR, cmd.skillName),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=skills-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-installer.js","sourceRoot":"","sources":["../../src/opencode/skills-installer.ts"],"names":[],"mappings":"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"}
|