plan: fix inconsistencies in npm package plan

This commit is contained in:
2026-03-17 10:57:10 +05:30
parent a47c457504
commit 81ba9c7bc9
+34 -67
View File
@@ -226,16 +226,17 @@ export function getBinaryName(context?: { config?: { multiModelBinary?: string }
```typescript ```typescript
// src/core/launch.ts // src/core/launch.ts
import type { MultiModelOptions, MultiModelResult } from "../types.js"; import type { MultiModelOptions, MultiModelResult } from "../types";
import { import {
runCommand, shellQuote, normalizeModels, findDuplicates, runCommand, shellQuote, normalizeModels, findDuplicates,
createWindowPlans, suggestModels, formatInvalidModelError, createWindowPlans, suggestModels, formatInvalidModelError,
sanitizeName, getWorktreePath, undoWorktree, getBinaryName sanitizeName, getWorktreePath, undoWorktree, getBinaryName
} from "./utils.js"; } from "./utils";
export async function launchMultiModel(options: MultiModelOptions): Promise<MultiModelResult> { export async function launchMultiModel(options: MultiModelOptions): Promise<MultiModelResult> {
// Core implementation from current multi-model.ts // Core implementation from current multi-model.ts
// All the validation, tmux setup, worktree creation, etc. // All the validation, tmux setup, worktree creation, etc.
const safeSessionName = sanitizeName(options.sessionName);
// Returns result with instructions for connecting and cleanup // Returns result with instructions for connecting and cleanup
return { return {
@@ -267,8 +268,8 @@ Or manually:
```typescript ```typescript
// src/core/close.ts // src/core/close.ts
import type { CloseSessionOptions, CloseSessionResult } from "../types.ts"; import type { CloseSessionOptions, CloseSessionResult } from "../types";
import { runCommand, getWorktreePath, getWorktreesForSession, sanitizeName } from "./utils.ts"; import { runCommand, getWorktreePath, getWorktreesForSession, sanitizeName } from "./utils";
import * as readline from "readline"; import * as readline from "readline";
async function promptUser(question: string): Promise<string> { async function promptUser(question: string): Promise<string> {
@@ -320,7 +321,7 @@ export async function closeMultiModel(options: CloseSessionOptions): Promise<Clo
let cleanupPerformed = false; let cleanupPerformed = false;
// Cleanup worktrees and optionally branches // Cleanup worktrees and optionally branches
if (options.cleanup) { if (options.cleanupWorktrees) {
for (const worktree of worktrees) { for (const worktree of worktrees) {
try { try {
// Remove worktree // Remove worktree
@@ -368,10 +369,10 @@ export async function closeMultiModel(options: CloseSessionOptions): Promise<Clo
```typescript ```typescript
// src/core/index.ts // src/core/index.ts
export { launchMultiModel } from "./launch.ts"; export { launchMultiModel } from "./launch";
export { closeMultiModel } from "./close.ts"; export { closeMultiModel } from "./close";
export * from "./utils.ts"; export * from "./utils";
export * from "../types.ts"; export * from "../types";
``` ```
### 7. Create Open Tool Definition ### 7. Create Open Tool Definition
@@ -379,8 +380,8 @@ export * from "../types.ts";
```typescript ```typescript
// src/tools/open.ts // src/tools/open.ts
import { tool, type ToolContext } from "@opencode-ai/plugin"; import { tool, type ToolContext } from "@opencode-ai/plugin";
import { launchMultiModel } from "../core/launch.ts"; import { launchMultiModel } from "../core/launch";
import { getBinaryName } from "../core/utils.ts"; import { getBinaryName } from "../core/utils";
export const openTool = tool({ export const openTool = tool({
name: "multi-model-open", name: "multi-model-open",
@@ -410,7 +411,7 @@ export const openTool = tool({
} }
}); });
export default openTool;
``` ```
### 8. Create Close Tool Definition ### 8. Create Close Tool Definition
@@ -418,14 +419,14 @@ export default openTool;
```typescript ```typescript
// src/tools/close.ts // src/tools/close.ts
import { tool, type ToolContext } from "@opencode-ai/plugin"; import { tool, type ToolContext } from "@opencode-ai/plugin";
import { closeMultiModel } from "../core/close.ts"; import { closeMultiModel } from "../core/close";
export const closeTool = tool({ export const closeTool = tool({
name: "multi-model-close", name: "multi-model-close",
description: "Close a multi-model tmux session and optionally cleanup worktrees and branches", description: "Close a multi-model tmux session and optionally cleanup worktrees and branches",
args: { args: {
sessionName: tool.schema.string().min(1).describe("tmux session name to close"), sessionName: tool.schema.string().min(1).describe("tmux session name to close"),
cleanupWorktrees: tool.schema.boolean().optional().describe("whether to remove worktrees and delete branches (default: true)"),(default: true)"), cleanupWorktrees: tool.schema.boolean().default(true).describe("whether to remove worktrees and delete branches (default: true)"),
}, },
async execute(args, context: ToolContext) { async execute(args, context: ToolContext) {
// In plugin mode, we skip confirmation (force=true) since there's no interactive terminal // In plugin mode, we skip confirmation (force=true) since there's no interactive terminal
@@ -450,7 +451,7 @@ export const closeTool = tool({
} }
}); });
export default closeTool;
``` ```
### 9. Create Plugin Entry Point ### 9. Create Plugin Entry Point
@@ -458,8 +459,8 @@ export default closeTool;
```typescript ```typescript
// src/index.ts // src/index.ts
import type { Plugin } from "@opencode-ai/plugin"; import type { Plugin } from "@opencode-ai/plugin";
import { openTool } from "./tools/open.ts"; import { openTool } from "./tools/open";
import { closeTool } from "./tools/close.ts"; import { closeTool } from "./tools/close";
export const OpenCodeMultiModelPlugin: Plugin = async (ctx) => { export const OpenCodeMultiModelPlugin: Plugin = async (ctx) => {
return { return {
@@ -470,9 +471,8 @@ export const OpenCodeMultiModelPlugin: Plugin = async (ctx) => {
}; };
}; };
export default OpenCodeMultiModelPlugin;
export { openTool, closeTool }; export { openTool, closeTool };
export * from "./core/index.ts"; export * from "./core/index";
``` ```
### 10. Create CLI Entry Point (with env support) ### 10. Create CLI Entry Point (with env support)
@@ -481,9 +481,9 @@ export * from "./core/index.ts";
// src/cli.ts // src/cli.ts
#!/usr/bin/env node #!/usr/bin/env node
import { Command } from "commander"; import { Command } from "commander";
import { launchMultiModel } from "./core/launch.js"; import { launchMultiModel } from "./core/launch";
import { closeMultiModel } from "./core/close.js"; import { closeMultiModel } from "./core/close";
import { getBinaryName } from "./core/utils.js"; import { getBinaryName } from "./core/utils";
const program = new Command(); const program = new Command();
@@ -527,16 +527,14 @@ program
.command("close") .command("close")
.description("Close a multi-model tmux session") .description("Close a multi-model tmux session")
.argument("<session-name>", "Name of the tmux session to close") .argument("<session-name>", "Name of the tmux session to close")
.option("-c, --cleanup", "Remove worktrees and delete branches", false) .option("-c, --cleanup-worktrees", "Remove worktrees and delete branches", true)
.option("-f, --force", "Skip confirmation prompts", false) .option("-f, --force", "Skip confirmation prompts", false)
.option("-k, --keep-branches", "Keep git branches (only remove worktrees)", false)
.action(async (sessionName, options) => { .action(async (sessionName, options) => {
try { try {
const result = await closeMultiModel({ const result = await closeMultiModel({
sessionName, sessionName,
cleanup: options.cleanup, cleanupWorktrees: options.cleanupWorktrees,
force: options.force, force: options.force,
keepBranches: options.keepBranches
}); });
if (result.success) { if (result.success) {
@@ -557,35 +555,6 @@ program
} }
}); });
// Default to open command for backwards compatibility
program
.argument("[session-name]", "Name for the tmux session (deprecated, use 'open' command)")
.option("-m, --models <models...>", "Model IDs to launch", [])
.option("-b, --binary <binary>", "Binary to use")
.action(async (sessionName, options) => {
if (!sessionName) {
program.help();
return;
}
console.warn("Warning: Direct session name is deprecated. Use 'opencode-multi-model open <session-name>' instead.");
const binaryName = options.binary || getBinaryName();
const result = await launchMultiModel({
sessionName,
models: options.models,
binaryName
});
if (result.success) {
console.log(result.instructions);
} else {
console.error(`✗ Failed: ${result.error}`);
process.exit(1);
}
});
program.parse(); program.parse();
``` ```
@@ -595,10 +564,10 @@ program.parse();
// .opencode/tools/multi-model.ts // .opencode/tools/multi-model.ts
// Re-export both open and close tools for project-level use // Re-export both open and close tools for project-level use
import { openTool, closeTool } from "../../src/tools/open.js"; import { openTool } from "../../src/tools/open";
import { closeTool } from "../../src/tools/close";
export { openTool, closeTool }; export { openTool, closeTool };
export default openTool; // Default to open for backwards compatibility
``` ```
### 12. Add Build Configuration ### 12. Add Build Configuration
@@ -636,7 +605,7 @@ export default openTool; // Default to open for backwards compatibility
**Tests**: Copy `.opencode/multi-model.test.ts` to `tests/multi-model.test.ts` and update imports: **Tests**: Copy `.opencode/multi-model.test.ts` to `tests/multi-model.test.ts` and update imports:
- Change `import multiModelTool, { __testing_helpers } from "./tools/multi-model"` - Change `import multiModelTool, { __testing_helpers } from "./tools/multi-model"`
- To `import { launchMultiModel, closeMultiModel, runCommand, ... } from "../src/core"` - To `import { launchMultiModel, closeMultiModel } from "../src/core"` and `import { runCommand, ... } from "../src/core/utils"`
The existing tests should work with minimal changes since the core logic remains the same. The existing tests should work with minimal changes since the core logic remains the same.
@@ -679,7 +648,6 @@ opencode-multi-model open my-session -m openai/gpt-4o
// .opencode/tools/multi-model.ts // .opencode/tools/multi-model.ts
import { openTool, closeTool } from "@username/opencode-multi-model" import { openTool, closeTool } from "@username/opencode-multi-model"
export { openTool, closeTool } export { openTool, closeTool }
export default openTool
``` ```
## Usage ## Usage
@@ -695,7 +663,7 @@ sessionName: my-session, models: ["openai/gpt-4o", "anthropic/claude-3-5-sonnet"
**Close a session:** **Close a session:**
``` ```
Use multi-model-close tool: Use multi-model-close tool:
sessionName: my-session, cleanup: true sessionName: my-session, cleanupWorktrees: true
``` ```
### CLI Usage ### CLI Usage
@@ -719,7 +687,7 @@ opencode-multi-model open my-session -m openai/gpt-4o
opencode-multi-model close my-session opencode-multi-model close my-session
# Close and cleanup worktrees # Close and cleanup worktrees
opencode-multi-model close my-session --cleanup opencode-multi-model close my-session --cleanup-worktrees
``` ```
**Help:** **Help:**
@@ -767,13 +735,12 @@ For local development and testing without publishing:
```typescript ```typescript
// .opencode/tools/multi-model.ts // .opencode/tools/multi-model.ts
import { openTool, closeTool } from "../../src/tools/open.js" import { openTool } from "../../src/tools/open"
import { closeTool } from "../../src/tools/close"
export { openTool, closeTool } export { openTool, closeTool }
export default openTool
``` ```
This allows testing the tool without publishing to npm. This allows testing the tool without publishing to npm.
```
## Files to Create/Modify ## Files to Create/Modify
@@ -846,7 +813,7 @@ npm install -g @username/opencode-multi-model
opencode-multi-model open compare-session -m openai/gpt-4o anthropic/claude-3-opus google/gemini-pro opencode-multi-model open compare-session -m openai/gpt-4o anthropic/claude-3-opus google/gemini-pro
# Close session with cleanup # Close session with cleanup
opencode-multi-model close compare-session --cleanup opencode-multi-model close compare-session --cleanup-worktrees
``` ```
### Developer - Project Tool ### Developer - Project Tool
@@ -854,9 +821,9 @@ opencode-multi-model close compare-session --cleanup
```typescript ```typescript
// .opencode/tools/multi-model.ts // .opencode/tools/multi-model.ts
// For testing local changes before publishing // For testing local changes before publishing
import { openTool, closeTool } from "../../src/tools/open.js" import { openTool } from "../../src/tools/open"
import { closeTool } from "../../src/tools/close"
export { openTool, closeTool } export { openTool, closeTool }
export default openTool
``` ```
This allows testing the tool without publishing to npm. This allows testing the tool without publishing to npm.