litopencode 0.0.3 → 0.0.4
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 +3 -3
- package/dist/agents/registry.js +20 -3
- package/dist/agents/types.d.ts +12 -2
- package/dist/cli/args.js +1 -1
- package/dist/cli/install.js +96 -14
- package/dist/cli/json.js +3 -2
- package/dist/cli/types.d.ts +2 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +1 -32
- package/dist/server.d.ts +3 -0
- package/dist/server.js +33 -0
- package/dist/skills.js +1 -0
- package/docs/migration.md +2 -2
- package/docs/release-checklist.md +3 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
|
|
35
35
|
npx litopencode install
|
|
36
36
|
|
|
37
|
-
The installer delegates the default install path to OpenCode's own plugin installer
|
|
37
|
+
The installer delegates the default install path to OpenCode's own plugin installer. Published installs register a version-pinned entry such as <code>litopencode@0.0.4</code>; local checkout installs register the local package path for development. Then restart OpenCode. The agent switcher should show <code>lit-plan</code> and <code>lit-loop</code>.
|
|
38
38
|
|
|
39
|
-
For a preview without writing
|
|
39
|
+
For a preview without writing OpenCode config:
|
|
40
40
|
|
|
41
41
|
npx litopencode install --dry-run
|
|
42
42
|
|
|
@@ -44,7 +44,7 @@ For health checks:
|
|
|
44
44
|
|
|
45
45
|
npx litopencode doctor
|
|
46
46
|
|
|
47
|
-
By default,
|
|
47
|
+
By default, OpenCode manages <code>~/.config/opencode/opencode.jsonc</code>, or <code>$XDG_CONFIG_HOME/opencode/opencode.jsonc</code> when <code>XDG_CONFIG_HOME</code> is set. Use <code>--root <dir></code> for a custom OpenCode config directory; custom roots use a direct <code>opencode.json</code> patch for deterministic tests and previews.
|
|
48
48
|
|
|
49
49
|
### Local Source Probe
|
|
50
50
|
|
package/dist/agents/registry.js
CHANGED
|
@@ -11,20 +11,37 @@ function toolsToConfig(tools) {
|
|
|
11
11
|
}
|
|
12
12
|
return enabledTools;
|
|
13
13
|
}
|
|
14
|
+
function toolsToPermission(tools) {
|
|
15
|
+
const permission = {};
|
|
16
|
+
if (tools.includes("edit") || tools.includes("write"))
|
|
17
|
+
permission.edit = "allow";
|
|
18
|
+
if (tools.includes("bash"))
|
|
19
|
+
permission.bash = "allow";
|
|
20
|
+
if (tools.includes("webfetch"))
|
|
21
|
+
permission.webfetch = "allow";
|
|
22
|
+
return Object.keys(permission).length > 0 ? permission : undefined;
|
|
23
|
+
}
|
|
14
24
|
export function toOpenCodeAgentConfig(agent) {
|
|
15
25
|
return {
|
|
16
26
|
description: agent.summary,
|
|
17
27
|
prompt: agent.prompt,
|
|
18
|
-
mode: agent.mode,
|
|
28
|
+
mode: agent.mode === "primary" ? "all" : "subagent",
|
|
19
29
|
tools: toolsToConfig(agent.tools),
|
|
20
30
|
color: agent.color,
|
|
21
|
-
maxSteps: agent.maxSteps
|
|
31
|
+
maxSteps: agent.maxSteps,
|
|
32
|
+
...(agent.mode === "subagent" ? { hidden: true } : {}),
|
|
33
|
+
...(toolsToPermission(agent.tools) ? { permission: toolsToPermission(agent.tools) } : {})
|
|
22
34
|
};
|
|
23
35
|
}
|
|
24
36
|
export function registerLitOpenCodeAgents(config) {
|
|
37
|
+
const existingBuild = config.agent?.build ?? {};
|
|
38
|
+
const existingPlan = config.agent?.plan ?? {};
|
|
25
39
|
config.agent = {
|
|
26
|
-
...config.agent
|
|
40
|
+
...config.agent,
|
|
41
|
+
build: { ...existingBuild, mode: "subagent", hidden: true },
|
|
42
|
+
plan: { ...existingPlan, mode: "subagent", hidden: true }
|
|
27
43
|
};
|
|
44
|
+
config.default_agent = "lit-loop";
|
|
28
45
|
for (const agent of litOpenCodeAgents) {
|
|
29
46
|
config.agent[agent.id] = toOpenCodeAgentConfig(agent);
|
|
30
47
|
}
|
package/dist/agents/types.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { Config } from "@opencode-ai/plugin";
|
|
2
2
|
export type AgentTier = "default" | "role" | "specialist";
|
|
3
3
|
export type AgentMode = "primary" | "subagent";
|
|
4
|
+
export type OpenCodeAgentMode = "all" | "subagent";
|
|
4
5
|
export type AgentToolId = "read" | "write" | "edit" | "bash" | "webfetch" | "grep";
|
|
6
|
+
export type AgentPermission = "ask" | "allow" | "deny";
|
|
5
7
|
export type LitOpenCodeAgent = {
|
|
6
8
|
readonly id: string;
|
|
7
9
|
readonly name: string;
|
|
@@ -18,12 +20,20 @@ export type LitOpenCodeAgent = {
|
|
|
18
20
|
export type OpenCodeAgentConfig = {
|
|
19
21
|
readonly description: string;
|
|
20
22
|
readonly prompt: string;
|
|
21
|
-
readonly mode:
|
|
23
|
+
readonly mode: OpenCodeAgentMode;
|
|
22
24
|
readonly tools: Record<string, boolean>;
|
|
23
25
|
readonly color: string;
|
|
24
26
|
readonly maxSteps: number;
|
|
27
|
+
readonly hidden?: boolean;
|
|
28
|
+
readonly permission?: {
|
|
29
|
+
readonly edit?: AgentPermission;
|
|
30
|
+
readonly bash?: AgentPermission;
|
|
31
|
+
readonly webfetch?: AgentPermission;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export type AgentConfigTarget = Pick<Config, "agent"> & {
|
|
35
|
+
default_agent?: string;
|
|
25
36
|
};
|
|
26
|
-
export type AgentConfigTarget = Pick<Config, "agent">;
|
|
27
37
|
export declare const planningTools: readonly ("read" | "grep")[];
|
|
28
38
|
export declare const workerTools: readonly ("read" | "write" | "edit" | "bash" | "grep")[];
|
|
29
39
|
export declare const reviewTools: readonly ("read" | "bash" | "grep")[];
|
package/dist/cli/args.js
CHANGED
|
@@ -49,7 +49,7 @@ export function helpText() {
|
|
|
49
49
|
" litopencode doctor [--root <dir>]",
|
|
50
50
|
"",
|
|
51
51
|
"Commands:",
|
|
52
|
-
" install
|
|
52
|
+
" install Register litopencode with OpenCode using a branded installer UI.",
|
|
53
53
|
" doctor Report package, config, and runtime path status without writing files.",
|
|
54
54
|
"",
|
|
55
55
|
"Default root:",
|
package/dist/cli/install.js
CHANGED
|
@@ -37,20 +37,98 @@ function defaultOpenCodeRoot() {
|
|
|
37
37
|
function shouldUseOpenCodeInstaller(root) {
|
|
38
38
|
return path.resolve(root) === path.resolve(defaultOpenCodeRoot());
|
|
39
39
|
}
|
|
40
|
+
function openCodeConfigCandidates(root) {
|
|
41
|
+
const resolvedRoot = path.resolve(root);
|
|
42
|
+
return [path.join(resolvedRoot, "opencode.json"), path.join(resolvedRoot, "opencode.jsonc")];
|
|
43
|
+
}
|
|
44
|
+
async function openCodeManagedConfigFile(root) {
|
|
45
|
+
const [jsonFile, jsoncFile] = openCodeConfigCandidates(root);
|
|
46
|
+
if (await pathExists(jsonFile))
|
|
47
|
+
return jsonFile;
|
|
48
|
+
if (await pathExists(jsoncFile))
|
|
49
|
+
return jsoncFile;
|
|
50
|
+
return jsoncFile;
|
|
51
|
+
}
|
|
52
|
+
function outputText(value) {
|
|
53
|
+
if (typeof value === "string")
|
|
54
|
+
return value;
|
|
55
|
+
if (value instanceof Uint8Array)
|
|
56
|
+
return Buffer.from(value).toString("utf8");
|
|
57
|
+
return "";
|
|
58
|
+
}
|
|
59
|
+
function stripAnsi(value) {
|
|
60
|
+
return value.replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g, "");
|
|
61
|
+
}
|
|
62
|
+
function commandFailureDetail(error) {
|
|
63
|
+
if (!(error instanceof Error))
|
|
64
|
+
return String(error);
|
|
65
|
+
const failure = error;
|
|
66
|
+
const parts = [];
|
|
67
|
+
const stderr = stripAnsi(outputText(failure.stderr)).trim();
|
|
68
|
+
const stdout = stripAnsi(outputText(failure.stdout)).trim();
|
|
69
|
+
const code = typeof failure.code === "number" || typeof failure.code === "string" ? String(failure.code) : "";
|
|
70
|
+
const signal = typeof failure.signal === "string" ? failure.signal : "";
|
|
71
|
+
if (stderr.length > 0)
|
|
72
|
+
parts.push("stderr:\n" + stderr);
|
|
73
|
+
if (stdout.length > 0)
|
|
74
|
+
parts.push("stdout:\n" + stdout);
|
|
75
|
+
if (code.length > 0)
|
|
76
|
+
parts.push("exit code: " + code);
|
|
77
|
+
if (signal.length > 0)
|
|
78
|
+
parts.push("signal: " + signal);
|
|
79
|
+
if (parts.length === 0 && error.message.length > 0)
|
|
80
|
+
parts.push(error.message);
|
|
81
|
+
return parts.join("\n\n");
|
|
82
|
+
}
|
|
83
|
+
async function pathExists(filePath) {
|
|
84
|
+
try {
|
|
85
|
+
await fs.stat(filePath);
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
90
|
+
return false;
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function isLocalSourcePackage(packageRoot) {
|
|
95
|
+
const realPackageRoot = await fs.realpath(packageRoot);
|
|
96
|
+
return (await pathExists(path.join(realPackageRoot, ".git"))) && (await pathExists(path.join(realPackageRoot, "src")));
|
|
97
|
+
}
|
|
98
|
+
async function openCodeInstallTarget(metadata) {
|
|
99
|
+
if (await isLocalSourcePackage(metadata.packageRoot)) {
|
|
100
|
+
const realPackageRoot = await fs.realpath(metadata.packageRoot);
|
|
101
|
+
return { value: realPackageRoot, label: metadata.name + "@" + metadata.version + " (local checkout)" };
|
|
102
|
+
}
|
|
103
|
+
const spec = pluginSpec(metadata);
|
|
104
|
+
return { value: spec, label: spec };
|
|
105
|
+
}
|
|
40
106
|
async function installWithOpenCode(target) {
|
|
41
107
|
try {
|
|
42
|
-
await execFileAsync("opencode", ["plugin", target, "--global", "--force"], {
|
|
108
|
+
await execFileAsync("opencode", ["plugin", target.value, "--global", "--force"], {
|
|
43
109
|
timeout: 120_000,
|
|
44
110
|
maxBuffer: 1024 * 1024 * 4
|
|
45
111
|
});
|
|
46
112
|
}
|
|
47
113
|
catch (error) {
|
|
48
|
-
const detail = error
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
114
|
+
const detail = commandFailureDetail(error);
|
|
115
|
+
throw new Error("OpenCode plugin install failed for " + target.label + (detail ? ":\n" + detail : ""));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async function removeStaleOpenCodeEntries(root, target) {
|
|
119
|
+
for (const configFile of openCodeConfigCandidates(root)) {
|
|
120
|
+
const config = await readJsonObjectIfPresent(configFile);
|
|
121
|
+
const pluginValue = config?.plugin;
|
|
122
|
+
if (!Array.isArray(pluginValue))
|
|
123
|
+
continue;
|
|
124
|
+
const nextPlugin = pluginValue.filter((entry) => {
|
|
125
|
+
if (entry === target.value)
|
|
126
|
+
return true;
|
|
127
|
+
return !isLitOpenCodeEntry(entry);
|
|
128
|
+
});
|
|
129
|
+
if (nextPlugin.length === pluginValue.length)
|
|
130
|
+
continue;
|
|
131
|
+
await fs.writeFile(configFile, JSON.stringify({ ...config, plugin: nextPlugin }, null, 2) + "\n");
|
|
54
132
|
}
|
|
55
133
|
}
|
|
56
134
|
function describePluginMutation(config, target) {
|
|
@@ -135,25 +213,29 @@ function renderInstallReport(report) {
|
|
|
135
213
|
export async function install(root, dryRun) {
|
|
136
214
|
const metadata = await readPackageMetadata();
|
|
137
215
|
const paths = createRuntimePaths(root);
|
|
138
|
-
const
|
|
139
|
-
const
|
|
140
|
-
const
|
|
216
|
+
const useOpenCodeInstaller = shouldUseOpenCodeInstaller(root);
|
|
217
|
+
const configFile = useOpenCodeInstaller ? await openCodeManagedConfigFile(root) : paths.opencodeConfigFile;
|
|
218
|
+
const before = useOpenCodeInstaller ? null : await readJsonObjectIfPresent(paths.opencodeConfigFile);
|
|
219
|
+
const spec = pluginSpec(metadata);
|
|
220
|
+
const target = useOpenCodeInstaller ? await openCodeInstallTarget(metadata) : { value: spec, label: spec };
|
|
221
|
+
const mutation = describePluginMutation(before, target.value);
|
|
141
222
|
const report = {
|
|
142
223
|
dryRun,
|
|
143
|
-
path:
|
|
224
|
+
path: configFile,
|
|
144
225
|
plugin: mutation.plugin,
|
|
145
226
|
patch: mutation.patch,
|
|
146
227
|
changed: mutation.changed,
|
|
147
|
-
package: metadata
|
|
228
|
+
package: { name: metadata.name, version: metadata.version }
|
|
148
229
|
};
|
|
149
230
|
if (dryRun) {
|
|
150
231
|
return { exitCode: 0, stdout: JSON.stringify(report, null, 2) };
|
|
151
232
|
}
|
|
152
|
-
if (
|
|
233
|
+
if (useOpenCodeInstaller) {
|
|
234
|
+
await removeStaleOpenCodeEntries(root, target);
|
|
153
235
|
await installWithOpenCode(target);
|
|
154
236
|
}
|
|
155
237
|
else if (mutation.changed) {
|
|
156
|
-
const next = applyPluginMutation(before, mutation, target);
|
|
238
|
+
const next = applyPluginMutation(before, mutation, target.value);
|
|
157
239
|
await fs.mkdir(path.dirname(paths.opencodeConfigFile), { recursive: true });
|
|
158
240
|
await fs.writeFile(paths.opencodeConfigFile, JSON.stringify(next, null, 2) + "\n");
|
|
159
241
|
}
|
package/dist/cli/json.js
CHANGED
|
@@ -5,12 +5,13 @@ export function isRecord(value) {
|
|
|
5
5
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
6
|
}
|
|
7
7
|
export async function readPackageMetadata() {
|
|
8
|
-
const
|
|
8
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
9
|
+
const packagePath = path.join(packageRoot, "package.json");
|
|
9
10
|
const parsed = JSON.parse(await fs.readFile(packagePath, "utf8"));
|
|
10
11
|
if (!isRecord(parsed) || typeof parsed.name !== "string" || typeof parsed.version !== "string") {
|
|
11
12
|
throw new Error(`Malformed package metadata at ${packagePath}`);
|
|
12
13
|
}
|
|
13
|
-
return { name: parsed.name, version: parsed.version };
|
|
14
|
+
return { name: parsed.name, version: parsed.version, packageRoot };
|
|
14
15
|
}
|
|
15
16
|
export async function readJsonObjectIfPresent(filePath) {
|
|
16
17
|
let raw;
|
package/dist/cli/types.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export type CliResult = {
|
|
|
6
6
|
export type PackageMetadata = {
|
|
7
7
|
readonly name: string;
|
|
8
8
|
readonly version: string;
|
|
9
|
+
readonly packageRoot: string;
|
|
9
10
|
};
|
|
10
11
|
export type ParsedArgs = {
|
|
11
12
|
readonly command?: string;
|
|
@@ -45,5 +46,5 @@ export type InstallReport = {
|
|
|
45
46
|
readonly plugin: PluginMutation["plugin"];
|
|
46
47
|
readonly patch: readonly JsonPatchOperation[];
|
|
47
48
|
readonly changed: boolean;
|
|
48
|
-
readonly package: PackageMetadata
|
|
49
|
+
readonly package: Pick<PackageMetadata, "name" | "version">;
|
|
49
50
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import litOpenCodePlugin from "./server.ts";
|
|
2
2
|
export { appendLedgerEvent, createLitGoalOperations, initializeLitGoal, readLedgerEvents, recoverLedgerTemps, LedgerIoError, LedgerParseError, type JsonValue, type LedgerAppendResult, type LedgerEvent, type LedgerRecoveryReport, type LitGoalInitialization, type LitGoalOperations } from "./ledger.ts";
|
|
3
3
|
export { litActivationBanner, litOpenCodeCommands } from "./commands.ts";
|
|
4
4
|
export { createToolExecuteAfterHook, createToolExecuteBeforeHook } from "./hooks.ts";
|
|
@@ -7,9 +7,8 @@ export { litOpenCodeTools, litTool, litworkTool } from "./tools.ts";
|
|
|
7
7
|
export { findLitOpenCodeFeature, litOpenCodeFeatures, type LitOpenCodeBindingKind, type LitOpenCodeFeature, type LitOpenCodeFeatureBinding, type LitOpenCodeFeatureId } from "./features.ts";
|
|
8
8
|
export { findLitOpenCodeRuntimeSkill, litOpenCodeRuntimeSkills, type LitOpenCodeRuntimeSkill, type LitOpenCodeRuntimeSkillId } from "./skills.ts";
|
|
9
9
|
export declare const pluginId = "litopencode";
|
|
10
|
-
declare const litOpenCodePlugin: (input?: PluginInput) => Promise<Hooks>;
|
|
11
10
|
export declare const pluginModule: {
|
|
12
11
|
id: string;
|
|
13
|
-
server: (input?: PluginInput) => Promise<Hooks>;
|
|
12
|
+
server: (input?: import("@opencode-ai/plugin").PluginInput) => Promise<import("@opencode-ai/plugin").Hooks>;
|
|
14
13
|
};
|
|
15
14
|
export default litOpenCodePlugin;
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { createCommandActivationHook, litActivationBanner, litOpenCodeCommands } from "./commands.js";
|
|
3
|
-
import { loadConfig } from "./config.js";
|
|
4
|
-
import { createToolExecuteAfterHook, createToolExecuteBeforeHook } from "./hooks.js";
|
|
1
|
+
import litOpenCodePlugin from "./server.js";
|
|
5
2
|
export { appendLedgerEvent, createLitGoalOperations, initializeLitGoal, readLedgerEvents, recoverLedgerTemps, LedgerIoError, LedgerParseError } from "./ledger.js";
|
|
6
|
-
import { createLogger } from "./logger.js";
|
|
7
|
-
import { litOpenCodeTools } from "./tools.js";
|
|
8
3
|
export { litActivationBanner, litOpenCodeCommands } from "./commands.js";
|
|
9
4
|
export { createToolExecuteAfterHook, createToolExecuteBeforeHook } from "./hooks.js";
|
|
10
5
|
export { applyLitOpenCodeToolAfterHook, applyLitOpenCodeToolBeforeHook } from "./tool-guards.js";
|
|
@@ -12,32 +7,6 @@ export { litOpenCodeTools, litTool, litworkTool } from "./tools.js";
|
|
|
12
7
|
export { findLitOpenCodeFeature, litOpenCodeFeatures } from "./features.js";
|
|
13
8
|
export { findLitOpenCodeRuntimeSkill, litOpenCodeRuntimeSkills } from "./skills.js";
|
|
14
9
|
export const pluginId = "litopencode";
|
|
15
|
-
const litOpenCodePlugin = async (input) => {
|
|
16
|
-
const root = input?.worktree ?? input?.directory ?? ".";
|
|
17
|
-
const loaded = await loadConfig(root);
|
|
18
|
-
const logger = createLogger(loaded.paths);
|
|
19
|
-
const hooks = {
|
|
20
|
-
config: async (config) => {
|
|
21
|
-
registerLitOpenCodeAgents(config);
|
|
22
|
-
},
|
|
23
|
-
tool: litOpenCodeTools,
|
|
24
|
-
"command.execute.before": createCommandActivationHook(root),
|
|
25
|
-
dispose: async () => {
|
|
26
|
-
await logger.dispose();
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
Object.defineProperties(hooks, {
|
|
30
|
-
"tool.execute.before": {
|
|
31
|
-
value: createToolExecuteBeforeHook(),
|
|
32
|
-
enumerable: false
|
|
33
|
-
},
|
|
34
|
-
"tool.execute.after": {
|
|
35
|
-
value: createToolExecuteAfterHook(),
|
|
36
|
-
enumerable: false
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
return hooks;
|
|
40
|
-
};
|
|
41
10
|
export const pluginModule = {
|
|
42
11
|
id: pluginId,
|
|
43
12
|
server: litOpenCodePlugin
|
package/dist/server.d.ts
ADDED
package/dist/server.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { registerLitOpenCodeAgents } from "./agents.js";
|
|
2
|
+
import { createCommandActivationHook } from "./commands.js";
|
|
3
|
+
import { loadConfig } from "./config.js";
|
|
4
|
+
import { createToolExecuteAfterHook, createToolExecuteBeforeHook } from "./hooks.js";
|
|
5
|
+
import { createLogger } from "./logger.js";
|
|
6
|
+
import { litOpenCodeTools } from "./tools.js";
|
|
7
|
+
const litOpenCodePlugin = async (input) => {
|
|
8
|
+
const root = input?.worktree ?? input?.directory ?? ".";
|
|
9
|
+
const loaded = await loadConfig(root);
|
|
10
|
+
const logger = createLogger(loaded.paths);
|
|
11
|
+
const hooks = {
|
|
12
|
+
config: async (config) => {
|
|
13
|
+
registerLitOpenCodeAgents(config);
|
|
14
|
+
},
|
|
15
|
+
tool: litOpenCodeTools,
|
|
16
|
+
"command.execute.before": createCommandActivationHook(root),
|
|
17
|
+
dispose: async () => {
|
|
18
|
+
await logger.dispose();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperties(hooks, {
|
|
22
|
+
"tool.execute.before": {
|
|
23
|
+
value: createToolExecuteBeforeHook(),
|
|
24
|
+
enumerable: false
|
|
25
|
+
},
|
|
26
|
+
"tool.execute.after": {
|
|
27
|
+
value: createToolExecuteAfterHook(),
|
|
28
|
+
enumerable: false
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return hooks;
|
|
32
|
+
};
|
|
33
|
+
export default litOpenCodePlugin;
|
package/dist/skills.js
CHANGED
|
@@ -40,6 +40,7 @@ export const litOpenCodeRuntimeSkills = Object.freeze([
|
|
|
40
40
|
discovery: "Run npx litopencode install, litopencode doctor, or litopencode install --dry-run.",
|
|
41
41
|
safety: [
|
|
42
42
|
"Default installation delegates to the OpenCode plugin installer; custom roots write only the version-pinned opencode.json plugin entry.",
|
|
43
|
+
"Local checkout installs hand OpenCode the package path so unpublished versions can be tested before npm publish.",
|
|
43
44
|
"Malformed config fails closed with a typed config error."
|
|
44
45
|
]
|
|
45
46
|
},
|
package/docs/migration.md
CHANGED
|
@@ -11,9 +11,9 @@ This guide describes the supported migration shape for moving an OpenCode workfl
|
|
|
11
11
|
## Environment And Config
|
|
12
12
|
|
|
13
13
|
- Use the `LITOPENCODE_` prefix for LitOpenCode-owned environment variables.
|
|
14
|
-
- Keep OpenCode plugin configuration in `opencode.json`.
|
|
14
|
+
- Keep default OpenCode plugin configuration in OpenCode's managed `opencode.jsonc`; custom-root LitOpenCode previews use `opencode.json`.
|
|
15
15
|
- Keep LitOpenCode runtime config in `.litopencode/config.json` when project-local config is needed.
|
|
16
|
-
- Use `npx litopencode install` to delegate default setup to `opencode plugin litopencode@0.0.
|
|
16
|
+
- Use `npx litopencode install` to delegate default setup to `opencode plugin <target> --global --force`; published installs use `litopencode@0.0.4`, while local checkout installs use the package path.
|
|
17
17
|
- Use `litopencode doctor --root <workspace>` to inspect package metadata, config source, runtime paths, and ledger location without writing files.
|
|
18
18
|
- Use `litopencode install --dry-run --root <workspace>` to preview the `opencode.json` plugin mutation without writing files.
|
|
19
19
|
|
|
@@ -41,7 +41,7 @@ After the source gates pass, verify the packed artifact in a temporary directory
|
|
|
41
41
|
```sh
|
|
42
42
|
tmp="$(mktemp -d)"
|
|
43
43
|
npm pack --pack-destination "$tmp"
|
|
44
|
-
tar -xzf "$tmp"/litopencode-0.0.
|
|
44
|
+
tar -xzf "$tmp"/litopencode-0.0.4.tgz -C "$tmp"
|
|
45
45
|
node --input-type=module -e "import('$tmp/package/dist/index.js').then((m) => console.log(m.default?.id ?? m.pluginId))"
|
|
46
46
|
(
|
|
47
47
|
cd "$tmp/package"
|
|
@@ -73,7 +73,7 @@ mkdir "$tmp/consumer"
|
|
|
73
73
|
(
|
|
74
74
|
cd "$tmp/consumer"
|
|
75
75
|
npm init -y
|
|
76
|
-
npm install "$tmp"/litopencode-0.0.
|
|
76
|
+
npm install "$tmp"/litopencode-0.0.4.tgz
|
|
77
77
|
npm ls litopencode --all
|
|
78
78
|
node --input-type=module -e "import('litopencode').then((m) => console.log(m.default.id))"
|
|
79
79
|
node_modules/.bin/litopencode --help
|
|
@@ -89,7 +89,7 @@ Expected results:
|
|
|
89
89
|
- `@opencode-ai/plugin` is declared as an optional peer for TypeScript host typings without forcing npx/global installs to pull its transitive runtime tree
|
|
90
90
|
- package import prints `litopencode`
|
|
91
91
|
- CLI help, doctor, install dry-run, and write-enabled install exit 0
|
|
92
|
-
- write-enabled install creates or updates `opencode.json` without echoing unrelated config secrets
|
|
92
|
+
- write-enabled custom-root install creates or updates `opencode.json` without echoing unrelated config secrets
|
|
93
93
|
- temporary project cleanup removes the probe directory
|
|
94
94
|
|
|
95
95
|
## OpenCode Host Probe
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "litopencode",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "LitOpenCode OpenCode plugin bootstrap package.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"import": "./dist/index.js"
|
|
14
14
|
},
|
|
15
15
|
"./server": {
|
|
16
|
-
"types": "./dist/
|
|
17
|
-
"import": "./dist/
|
|
16
|
+
"types": "./dist/server.d.ts",
|
|
17
|
+
"import": "./dist/server.js"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|