mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-24 11:14:23 +01:00
126 lines
3.9 KiB
TypeScript
126 lines
3.9 KiB
TypeScript
import { App } from "./app";
|
|
import { Server } from "./server/server";
|
|
import fs from "fs/promises";
|
|
import path from "path";
|
|
import { Bus } from "./bus";
|
|
import { Session } from "./session/session";
|
|
import cac from "cac";
|
|
import { Share } from "./share/share";
|
|
import { Storage } from "./storage/storage";
|
|
import { LLM } from "./llm/llm";
|
|
|
|
const cli = cac("opencode");
|
|
|
|
cli.command("", "Start the opencode in interactive mode").action(async () => {
|
|
await App.provide({ directory: process.cwd() }, async () => {
|
|
await Share.init();
|
|
Server.listen();
|
|
|
|
Bun.spawnSync({
|
|
stderr: "inherit",
|
|
stdout: "inherit",
|
|
stdin: "inherit",
|
|
cmd: ["go", "run", "cmd/main.go"],
|
|
});
|
|
});
|
|
});
|
|
|
|
cli.command("generate", "Generate OpenAPI and event specs").action(async () => {
|
|
const specs = await Server.openapi();
|
|
const dir = "gen";
|
|
await fs.rmdir(dir, { recursive: true }).catch(() => {});
|
|
await fs.mkdir(dir, { recursive: true });
|
|
await Bun.write(
|
|
path.join(dir, "openapi.json"),
|
|
JSON.stringify(specs, null, 2),
|
|
);
|
|
await Bun.write(
|
|
path.join(dir, "event.json"),
|
|
JSON.stringify(Bus.specs(), null, 2),
|
|
);
|
|
});
|
|
|
|
cli
|
|
.command("run [...message]", "Run a chat message")
|
|
.action(async (message: string[]) => {
|
|
await App.provide({ directory: process.cwd() }, async () => {
|
|
console.log("Thinking...");
|
|
await Share.init();
|
|
const session = await Session.create();
|
|
console.log(
|
|
`Share ID: ${Share.URL.replace("api.", "")}/share?id=${session.id}`,
|
|
);
|
|
|
|
let index = 0;
|
|
Bus.subscribe(Storage.Event.Write, async (payload) => {
|
|
const [root, , type, messageID] = payload.properties.key.split("/");
|
|
if (root !== "session" && type !== "message") return;
|
|
const message = await Session.messages(session.id).then((x) =>
|
|
x.find((x) => x.id === messageID),
|
|
);
|
|
if (!message) return;
|
|
|
|
for (; index < message.parts.length; index++) {
|
|
const part = message.parts[index];
|
|
if (part.type === "text") continue;
|
|
if (part.type === "step-start") continue;
|
|
if (
|
|
part.type === "tool-invocation" &&
|
|
part.toolInvocation.state !== "result"
|
|
)
|
|
break;
|
|
|
|
if (part.type === "tool-invocation") {
|
|
console.log(`🔧 ${part.toolInvocation.toolName}`);
|
|
if (
|
|
part.toolInvocation.state === "result" &&
|
|
"result" in part.toolInvocation
|
|
) {
|
|
const result = part.toolInvocation.result;
|
|
if (typeof result === "string") {
|
|
const lines = result.split("\n");
|
|
const truncated = lines.slice(0, 4);
|
|
if (lines.length > 4) truncated.push("...");
|
|
console.log(truncated.join("\n"));
|
|
} else if (result && typeof result === "object") {
|
|
const jsonStr = JSON.stringify(result, null, 2);
|
|
const lines = jsonStr.split("\n");
|
|
const truncated = lines.slice(0, 4);
|
|
if (lines.length > 4) truncated.push("...");
|
|
console.log(truncated.join("\n"));
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
console.log(part);
|
|
}
|
|
});
|
|
|
|
const providers = await LLM.providers();
|
|
const providerID = Object.keys(providers)[0];
|
|
const modelID = Object.keys(providers[providerID].info.models!)[0];
|
|
console.log("using", providerID, modelID);
|
|
const result = await Session.chat({
|
|
sessionID: session.id,
|
|
providerID,
|
|
modelID,
|
|
parts: [
|
|
{
|
|
type: "text",
|
|
text: message.join(" "),
|
|
},
|
|
],
|
|
});
|
|
|
|
for (const part of result.parts) {
|
|
if (part.type === "text") {
|
|
console.log("opencode:", part.text);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
cli.help();
|
|
cli.version("1.0.0");
|
|
cli.parse();
|