anymous 1.0.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/README.md +15 -0
- package/bin/anymous.cjs +45 -0
- package/package.json +155 -0
- package/src/account/account.ts +473 -0
- package/src/account/repo.ts +171 -0
- package/src/account/schema.ts +99 -0
- package/src/account/url.ts +8 -0
- package/src/acp/agent.ts +95 -0
- package/src/acp/config-option.ts +203 -0
- package/src/acp/content.ts +269 -0
- package/src/acp/directory.ts +212 -0
- package/src/acp/error.ts +97 -0
- package/src/acp/event.ts +342 -0
- package/src/acp/permission.ts +254 -0
- package/src/acp/profile.ts +42 -0
- package/src/acp/service.ts +1097 -0
- package/src/acp/session.ts +232 -0
- package/src/acp/tool.ts +364 -0
- package/src/acp/usage.ts +239 -0
- package/src/agent/agent.ts +581 -0
- package/src/agent/generate.txt +75 -0
- package/src/agent/prompt/compaction.txt +9 -0
- package/src/agent/prompt/debug-tools.txt +41 -0
- package/src/agent/prompt/exe-extractor.txt +37 -0
- package/src/agent/prompt/explore.txt +18 -0
- package/src/agent/prompt/memory-dump.txt +34 -0
- package/src/agent/prompt/reverser-automator.txt +24 -0
- package/src/agent/prompt/reverser-binary.txt +25 -0
- package/src/agent/prompt/reverser-dynamic.txt +29 -0
- package/src/agent/prompt/reverser-source.txt +22 -0
- package/src/agent/prompt/reverser-static.txt +28 -0
- package/src/agent/prompt/summary.txt +11 -0
- package/src/agent/prompt/title.txt +44 -0
- package/src/agent/subagent-permissions.ts +27 -0
- package/src/audio.d.ts +14 -0
- package/src/auth/index.ts +97 -0
- package/src/background/job.ts +37 -0
- package/src/bus/global.ts +22 -0
- package/src/cli/bootstrap.ts +11 -0
- package/src/cli/cmd/account.ts +264 -0
- package/src/cli/cmd/acp.ts +73 -0
- package/src/cli/cmd/agent.ts +259 -0
- package/src/cli/cmd/attach.ts +148 -0
- package/src/cli/cmd/cmd.ts +7 -0
- package/src/cli/cmd/db.ts +62 -0
- package/src/cli/cmd/debug/agent.handler.ts +193 -0
- package/src/cli/cmd/debug/agent.ts +27 -0
- package/src/cli/cmd/debug/config.ts +14 -0
- package/src/cli/cmd/debug/file.ts +73 -0
- package/src/cli/cmd/debug/index.ts +87 -0
- package/src/cli/cmd/debug/lsp.ts +50 -0
- package/src/cli/cmd/debug/ripgrep.ts +79 -0
- package/src/cli/cmd/debug/scrap.ts +16 -0
- package/src/cli/cmd/debug/skill.ts +15 -0
- package/src/cli/cmd/debug/snapshot.ts +50 -0
- package/src/cli/cmd/debug/startup.ts +11 -0
- package/src/cli/cmd/debug/v2.ts +42 -0
- package/src/cli/cmd/export.ts +292 -0
- package/src/cli/cmd/generate.ts +54 -0
- package/src/cli/cmd/github.handler.ts +1593 -0
- package/src/cli/cmd/github.shared.ts +30 -0
- package/src/cli/cmd/github.ts +42 -0
- package/src/cli/cmd/import.ts +230 -0
- package/src/cli/cmd/mcp.ts +840 -0
- package/src/cli/cmd/models.ts +66 -0
- package/src/cli/cmd/plug.ts +230 -0
- package/src/cli/cmd/pr.ts +115 -0
- package/src/cli/cmd/prompt-display.ts +1 -0
- package/src/cli/cmd/providers.ts +534 -0
- package/src/cli/cmd/run/demo.ts +1274 -0
- package/src/cli/cmd/run/entry.body.ts +205 -0
- package/src/cli/cmd/run/footer.command.tsx +1070 -0
- package/src/cli/cmd/run/footer.menu.tsx +351 -0
- package/src/cli/cmd/run/footer.permission.tsx +472 -0
- package/src/cli/cmd/run/footer.prompt.tsx +1315 -0
- package/src/cli/cmd/run/footer.question.tsx +573 -0
- package/src/cli/cmd/run/footer.subagent.tsx +175 -0
- package/src/cli/cmd/run/footer.ts +1129 -0
- package/src/cli/cmd/run/footer.view.tsx +945 -0
- package/src/cli/cmd/run/footer.width.ts +27 -0
- package/src/cli/cmd/run/permission.shared.ts +256 -0
- package/src/cli/cmd/run/prompt.editor.ts +157 -0
- package/src/cli/cmd/run/prompt.shared.ts +153 -0
- package/src/cli/cmd/run/question.shared.ts +340 -0
- package/src/cli/cmd/run/runtime.boot.ts +202 -0
- package/src/cli/cmd/run/runtime.lifecycle.ts +406 -0
- package/src/cli/cmd/run/runtime.queue.ts +349 -0
- package/src/cli/cmd/run/runtime.shared.ts +17 -0
- package/src/cli/cmd/run/runtime.stdin.ts +37 -0
- package/src/cli/cmd/run/runtime.ts +814 -0
- package/src/cli/cmd/run/scrollback.shared.ts +92 -0
- package/src/cli/cmd/run/scrollback.surface.ts +431 -0
- package/src/cli/cmd/run/scrollback.writer.tsx +352 -0
- package/src/cli/cmd/run/session-data.ts +1113 -0
- package/src/cli/cmd/run/session-replay.ts +374 -0
- package/src/cli/cmd/run/session.shared.ts +196 -0
- package/src/cli/cmd/run/splash.ts +280 -0
- package/src/cli/cmd/run/stream.transport.ts +1462 -0
- package/src/cli/cmd/run/stream.ts +175 -0
- package/src/cli/cmd/run/subagent-data.ts +876 -0
- package/src/cli/cmd/run/theme.ts +690 -0
- package/src/cli/cmd/run/tool.ts +1486 -0
- package/src/cli/cmd/run/trace.ts +94 -0
- package/src/cli/cmd/run/turn-summary.ts +47 -0
- package/src/cli/cmd/run/types.ts +350 -0
- package/src/cli/cmd/run/variant.shared.ts +216 -0
- package/src/cli/cmd/run.ts +1011 -0
- package/src/cli/cmd/serve.ts +24 -0
- package/src/cli/cmd/session.ts +147 -0
- package/src/cli/cmd/stats.ts +393 -0
- package/src/cli/cmd/tui.ts +309 -0
- package/src/cli/cmd/uninstall.ts +353 -0
- package/src/cli/cmd/upgrade.ts +74 -0
- package/src/cli/cmd/web.ts +84 -0
- package/src/cli/effect/prompt.ts +37 -0
- package/src/cli/effect-cmd.ts +96 -0
- package/src/cli/error.ts +130 -0
- package/src/cli/heap.ts +45 -0
- package/src/cli/logo.ts +1 -0
- package/src/cli/network.ts +80 -0
- package/src/cli/tui/layer.ts +8 -0
- package/src/cli/tui/validate-session.ts +29 -0
- package/src/cli/tui/worker.ts +80 -0
- package/src/cli/ui.ts +132 -0
- package/src/cli/upgrade.ts +53 -0
- package/src/command/index.ts +177 -0
- package/src/command/template/initialize.txt +66 -0
- package/src/command/template/review.txt +101 -0
- package/src/config/agent.ts +59 -0
- package/src/config/command.ts +39 -0
- package/src/config/config.ts +681 -0
- package/src/config/entry-name.ts +19 -0
- package/src/config/managed.ts +69 -0
- package/src/config/markdown.ts +36 -0
- package/src/config/parse.ts +79 -0
- package/src/config/paths.ts +45 -0
- package/src/config/plugin.ts +79 -0
- package/src/config/tui-cwd.ts +5 -0
- package/src/config/tui-host-attention.ts +21 -0
- package/src/config/tui-migrate.ts +132 -0
- package/src/config/tui.ts +276 -0
- package/src/config/variable.ts +91 -0
- package/src/control-plane/adapters/index.ts +41 -0
- package/src/control-plane/adapters/worktree.ts +96 -0
- package/src/control-plane/dev/README.md +19 -0
- package/src/control-plane/dev/debug-workspace-plugin.ts +73 -0
- package/src/control-plane/types.ts +59 -0
- package/src/control-plane/util.ts +39 -0
- package/src/control-plane/workspace-adapter-runtime.ts +51 -0
- package/src/control-plane/workspace-context.ts +26 -0
- package/src/control-plane/workspace.ts +964 -0
- package/src/effect/app-node-builder-v1.ts +12 -0
- package/src/effect/app-runtime.ts +135 -0
- package/src/effect/bootstrap-runtime.ts +19 -0
- package/src/effect/bridge.ts +84 -0
- package/src/effect/config-service.ts +67 -0
- package/src/effect/instance-ref.ts +11 -0
- package/src/effect/instance-registry.ts +12 -0
- package/src/effect/instance-state.ts +69 -0
- package/src/effect/promise.ts +17 -0
- package/src/effect/run-service.ts +47 -0
- package/src/effect/runner.ts +217 -0
- package/src/effect/runtime-flags.ts +78 -0
- package/src/env/index.ts +41 -0
- package/src/event-manifest.ts +3 -0
- package/src/event-v2-bridge.ts +71 -0
- package/src/format/formatter.ts +404 -0
- package/src/format/index.ts +203 -0
- package/src/git/index.ts +348 -0
- package/src/id/id.ts +80 -0
- package/src/ide/index.ts +54 -0
- package/src/image/image.ts +172 -0
- package/src/index.ts +142 -0
- package/src/installation/index.ts +336 -0
- package/src/lsp/client.ts +650 -0
- package/src/lsp/diagnostic.ts +29 -0
- package/src/lsp/language.ts +121 -0
- package/src/lsp/launch.ts +21 -0
- package/src/lsp/lsp.ts +507 -0
- package/src/lsp/server.ts +1983 -0
- package/src/markdown.d.ts +4 -0
- package/src/mcp/auth.ts +163 -0
- package/src/mcp/browser.ts +37 -0
- package/src/mcp/catalog.ts +170 -0
- package/src/mcp/index.ts +1004 -0
- package/src/mcp/oauth-callback.ts +194 -0
- package/src/mcp/oauth-provider.ts +259 -0
- package/src/node.ts +4 -0
- package/src/patch/index.ts +686 -0
- package/src/permission/arity.ts +163 -0
- package/src/permission/evaluate.ts +1 -0
- package/src/permission/index.ts +229 -0
- package/src/plugin/azure.ts +26 -0
- package/src/plugin/cloudflare.ts +76 -0
- package/src/plugin/digitalocean.ts +325 -0
- package/src/plugin/github-copilot/copilot.ts +414 -0
- package/src/plugin/github-copilot/models.ts +258 -0
- package/src/plugin/index.ts +314 -0
- package/src/plugin/install.ts +439 -0
- package/src/plugin/loader.ts +237 -0
- package/src/plugin/meta.ts +188 -0
- package/src/plugin/openai/README.md +31 -0
- package/src/plugin/openai/codex.ts +565 -0
- package/src/plugin/openai/ws-pool.ts +270 -0
- package/src/plugin/openai/ws.ts +381 -0
- package/src/plugin/pty-environment.ts +24 -0
- package/src/plugin/shared.ts +323 -0
- package/src/plugin/snowflake-cortex.ts +507 -0
- package/src/plugin/tui/internal.ts +10 -0
- package/src/plugin/tui/runtime.ts +1131 -0
- package/src/plugin/xai.ts +626 -0
- package/src/project/bootstrap-service.ts +9 -0
- package/src/project/bootstrap.ts +58 -0
- package/src/project/instance-context.ts +24 -0
- package/src/project/instance-runtime.ts +16 -0
- package/src/project/instance-store.ts +213 -0
- package/src/project/project.ts +483 -0
- package/src/project/vcs.ts +423 -0
- package/src/provider/auth.ts +229 -0
- package/src/provider/error.ts +188 -0
- package/src/provider/model-status.ts +8 -0
- package/src/provider/provider.ts +2006 -0
- package/src/provider/transform.ts +1832 -0
- package/src/question/index.ts +161 -0
- package/src/question/schema.ts +4 -0
- package/src/server/auth.ts +48 -0
- package/src/server/event.ts +10 -0
- package/src/server/global-lifecycle.ts +28 -0
- package/src/server/init-projectors.ts +3 -0
- package/src/server/mdns.ts +47 -0
- package/src/server/projectors.ts +1 -0
- package/src/server/proxy-util.ts +48 -0
- package/src/server/routes/instance/httpapi/AGENTS.md +39 -0
- package/src/server/routes/instance/httpapi/api.ts +97 -0
- package/src/server/routes/instance/httpapi/errors.ts +193 -0
- package/src/server/routes/instance/httpapi/groups/config.ts +65 -0
- package/src/server/routes/instance/httpapi/groups/control-plane.ts +35 -0
- package/src/server/routes/instance/httpapi/groups/control.ts +76 -0
- package/src/server/routes/instance/httpapi/groups/event.ts +29 -0
- package/src/server/routes/instance/httpapi/groups/experimental.ts +275 -0
- package/src/server/routes/instance/httpapi/groups/file.ts +185 -0
- package/src/server/routes/instance/httpapi/groups/global.ts +136 -0
- package/src/server/routes/instance/httpapi/groups/instance.ts +206 -0
- package/src/server/routes/instance/httpapi/groups/mcp.ts +156 -0
- package/src/server/routes/instance/httpapi/groups/metadata.ts +18 -0
- package/src/server/routes/instance/httpapi/groups/permission.ts +61 -0
- package/src/server/routes/instance/httpapi/groups/project-copy.ts +32 -0
- package/src/server/routes/instance/httpapi/groups/project.ts +93 -0
- package/src/server/routes/instance/httpapi/groups/provider.ts +101 -0
- package/src/server/routes/instance/httpapi/groups/pty.ts +172 -0
- package/src/server/routes/instance/httpapi/groups/query.ts +12 -0
- package/src/server/routes/instance/httpapi/groups/question.ts +74 -0
- package/src/server/routes/instance/httpapi/groups/session.ts +462 -0
- package/src/server/routes/instance/httpapi/groups/sync.ts +113 -0
- package/src/server/routes/instance/httpapi/groups/tui.ts +208 -0
- package/src/server/routes/instance/httpapi/groups/workspace.ts +141 -0
- package/src/server/routes/instance/httpapi/handlers/config.ts +34 -0
- package/src/server/routes/instance/httpapi/handlers/control-plane.ts +37 -0
- package/src/server/routes/instance/httpapi/handlers/control.ts +43 -0
- package/src/server/routes/instance/httpapi/handlers/event.ts +99 -0
- package/src/server/routes/instance/httpapi/handlers/experimental.ts +193 -0
- package/src/server/routes/instance/httpapi/handlers/file.ts +139 -0
- package/src/server/routes/instance/httpapi/handlers/global.ts +156 -0
- package/src/server/routes/instance/httpapi/handlers/instance.ts +110 -0
- package/src/server/routes/instance/httpapi/handlers/mcp.ts +111 -0
- package/src/server/routes/instance/httpapi/handlers/permission.ts +41 -0
- package/src/server/routes/instance/httpapi/handlers/project-copy.ts +83 -0
- package/src/server/routes/instance/httpapi/handlers/project.ts +63 -0
- package/src/server/routes/instance/httpapi/handlers/provider.ts +113 -0
- package/src/server/routes/instance/httpapi/handlers/pty.ts +273 -0
- package/src/server/routes/instance/httpapi/handlers/question.ts +54 -0
- package/src/server/routes/instance/httpapi/handlers/session-errors.ts +21 -0
- package/src/server/routes/instance/httpapi/handlers/session.ts +442 -0
- package/src/server/routes/instance/httpapi/handlers/sync.ts +89 -0
- package/src/server/routes/instance/httpapi/handlers/tui.ts +131 -0
- package/src/server/routes/instance/httpapi/handlers/workspace.ts +102 -0
- package/src/server/routes/instance/httpapi/lifecycle.ts +54 -0
- package/src/server/routes/instance/httpapi/middleware/authorization.ts +150 -0
- package/src/server/routes/instance/httpapi/middleware/compression.ts +64 -0
- package/src/server/routes/instance/httpapi/middleware/cors-vary.ts +29 -0
- package/src/server/routes/instance/httpapi/middleware/error.ts +43 -0
- package/src/server/routes/instance/httpapi/middleware/fence.ts +25 -0
- package/src/server/routes/instance/httpapi/middleware/instance-context.ts +43 -0
- package/src/server/routes/instance/httpapi/middleware/proxy.ts +108 -0
- package/src/server/routes/instance/httpapi/middleware/schema-error.ts +41 -0
- package/src/server/routes/instance/httpapi/middleware/workspace-routing.ts +250 -0
- package/src/server/routes/instance/httpapi/public.ts +537 -0
- package/src/server/routes/instance/httpapi/server.ts +325 -0
- package/src/server/routes/instance/httpapi/websocket-tracker.ts +60 -0
- package/src/server/server.ts +226 -0
- package/src/server/shared/fence.ts +60 -0
- package/src/server/shared/pty-ticket.ts +15 -0
- package/src/server/shared/public-ui.ts +12 -0
- package/src/server/shared/tui-control.ts +28 -0
- package/src/server/shared/ui.ts +108 -0
- package/src/server/shared/workspace-routing.ts +38 -0
- package/src/server/tui-event.ts +1 -0
- package/src/session/compaction.ts +562 -0
- package/src/session/instruction.ts +237 -0
- package/src/session/llm/AGENTS.md +90 -0
- package/src/session/llm/ai-sdk.ts +288 -0
- package/src/session/llm/native-request.ts +196 -0
- package/src/session/llm/native-runtime.ts +195 -0
- package/src/session/llm/request.ts +226 -0
- package/src/session/llm.ts +404 -0
- package/src/session/message-error.ts +14 -0
- package/src/session/message-v2.ts +734 -0
- package/src/session/message.ts +148 -0
- package/src/session/overflow.ts +34 -0
- package/src/session/processor.ts +718 -0
- package/src/session/prompt/anthropic.txt +105 -0
- package/src/session/prompt/beast.txt +147 -0
- package/src/session/prompt/build-switch.txt +5 -0
- package/src/session/prompt/codex.txt +79 -0
- package/src/session/prompt/copilot-gpt-5.txt +143 -0
- package/src/session/prompt/default.txt +95 -0
- package/src/session/prompt/gemini.txt +155 -0
- package/src/session/prompt/gpt.txt +107 -0
- package/src/session/prompt/kimi.txt +95 -0
- package/src/session/prompt/meta.txt +65 -0
- package/src/session/prompt/plan-mode.txt +70 -0
- package/src/session/prompt/plan-reminder-anthropic.txt +67 -0
- package/src/session/prompt/plan.txt +26 -0
- package/src/session/prompt/trinity.txt +97 -0
- package/src/session/prompt.ts +1631 -0
- package/src/session/reminders.ts +92 -0
- package/src/session/retry.ts +201 -0
- package/src/session/revert.ts +146 -0
- package/src/session/run-state.ts +151 -0
- package/src/session/schema.ts +26 -0
- package/src/session/session.ts +1018 -0
- package/src/session/status.ts +56 -0
- package/src/session/summary.ts +160 -0
- package/src/session/system.ts +145 -0
- package/src/session/todo.ts +74 -0
- package/src/session/tools.ts +590 -0
- package/src/share/session.ts +58 -0
- package/src/share/share-next.ts +371 -0
- package/src/skill/discovery.ts +140 -0
- package/src/skill/index.ts +354 -0
- package/src/snapshot/index.ts +807 -0
- package/src/sql.d.ts +4 -0
- package/src/storage/schema.ts +5 -0
- package/src/storage/storage.ts +327 -0
- package/src/sync/README.md +179 -0
- package/src/sync/schema.ts +11 -0
- package/src/temporary.ts +31 -0
- package/src/tool/apply_patch.ts +313 -0
- package/src/tool/apply_patch.txt +33 -0
- package/src/tool/code-mode.ts +310 -0
- package/src/tool/edit.ts +737 -0
- package/src/tool/edit.txt +10 -0
- package/src/tool/external-directory.ts +49 -0
- package/src/tool/glob.ts +76 -0
- package/src/tool/glob.txt +6 -0
- package/src/tool/grep.ts +115 -0
- package/src/tool/grep.txt +8 -0
- package/src/tool/invalid.ts +21 -0
- package/src/tool/json-schema.ts +164 -0
- package/src/tool/lsp.ts +113 -0
- package/src/tool/lsp.txt +24 -0
- package/src/tool/mcp-websearch.ts +96 -0
- package/src/tool/plan-enter.txt +14 -0
- package/src/tool/plan-exit.txt +13 -0
- package/src/tool/plan.ts +79 -0
- package/src/tool/question.ts +44 -0
- package/src/tool/question.txt +10 -0
- package/src/tool/read.ts +386 -0
- package/src/tool/read.txt +14 -0
- package/src/tool/registry.ts +450 -0
- package/src/tool/schema.ts +14 -0
- package/src/tool/shell/id.ts +19 -0
- package/src/tool/shell/prompt.ts +293 -0
- package/src/tool/shell/shell.txt +21 -0
- package/src/tool/shell.ts +645 -0
- package/src/tool/skill.ts +70 -0
- package/src/tool/skill.txt +5 -0
- package/src/tool/task.ts +360 -0
- package/src/tool/task.txt +19 -0
- package/src/tool/todo.ts +46 -0
- package/src/tool/todowrite.txt +44 -0
- package/src/tool/tool.ts +183 -0
- package/src/tool/truncate.ts +156 -0
- package/src/tool/truncation-dir.ts +4 -0
- package/src/tool/webfetch.ts +192 -0
- package/src/tool/webfetch.txt +13 -0
- package/src/tool/websearch.ts +143 -0
- package/src/tool/websearch.txt +14 -0
- package/src/tool/write.ts +104 -0
- package/src/tool/write.txt +8 -0
- package/src/util/archive.ts +17 -0
- package/src/util/bom.ts +27 -0
- package/src/util/data-url.ts +9 -0
- package/src/util/defer.ts +10 -0
- package/src/util/effect-http-client.ts +11 -0
- package/src/util/error.ts +1 -0
- package/src/util/filesystem.ts +251 -0
- package/src/util/html.ts +8 -0
- package/src/util/iife.ts +3 -0
- package/src/util/lazy.ts +20 -0
- package/src/util/local-context.ts +25 -0
- package/src/util/locale.ts +2 -0
- package/src/util/media.ts +26 -0
- package/src/util/process.ts +177 -0
- package/src/util/proxy-env.ts +72 -0
- package/src/util/queue.ts +32 -0
- package/src/util/record.ts +1 -0
- package/src/util/repository.ts +232 -0
- package/src/util/rpc.ts +66 -0
- package/src/util/signal.ts +12 -0
- package/src/util/timeout.ts +13 -0
- package/src/util/token.ts +1 -0
- package/src/util/wildcard.ts +59 -0
- package/src/worktree/index.ts +623 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { cmd } from "@/cli/cmd/cmd"
|
|
2
|
+
import { Rpc } from "@/util/rpc"
|
|
3
|
+
import { type rpc } from "../tui/worker"
|
|
4
|
+
import path from "path"
|
|
5
|
+
import { fileURLToPath } from "url"
|
|
6
|
+
import { UI } from "@/cli/ui"
|
|
7
|
+
import { errorMessage } from "@opencode-ai/tui/util/error"
|
|
8
|
+
import { withTimeout } from "@/util/timeout"
|
|
9
|
+
import { withNetworkOptions, resolveNetworkOptionsNoConfig, hasArg } from "@/cli/network"
|
|
10
|
+
import { Filesystem } from "@/util/filesystem"
|
|
11
|
+
import type { GlobalEvent } from "@opencode-ai/sdk/v2"
|
|
12
|
+
import type { EventSource } from "@opencode-ai/tui/context/sdk"
|
|
13
|
+
import { writeHeapSnapshot } from "v8"
|
|
14
|
+
import { ServerAuth } from "@/server/auth"
|
|
15
|
+
import { validateSession } from "../tui/validate-session"
|
|
16
|
+
import { win32InstallCtrlCGuard } from "@opencode-ai/tui/terminal-win32"
|
|
17
|
+
|
|
18
|
+
declare global {
|
|
19
|
+
const OPENCODE_WORKER_PATH: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type RpcClient = ReturnType<typeof Rpc.client<typeof rpc>>
|
|
23
|
+
|
|
24
|
+
function createWorkerFetch(client: RpcClient): typeof fetch {
|
|
25
|
+
const fn = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
|
|
26
|
+
const request = new Request(input, init)
|
|
27
|
+
const body = request.body ? await request.text() : undefined
|
|
28
|
+
const result = await client.call("fetch", {
|
|
29
|
+
url: request.url,
|
|
30
|
+
method: request.method,
|
|
31
|
+
headers: Object.fromEntries(request.headers.entries()),
|
|
32
|
+
body,
|
|
33
|
+
})
|
|
34
|
+
return new Response(result.body, {
|
|
35
|
+
status: result.status,
|
|
36
|
+
headers: result.headers,
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
return fn as typeof fetch
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function createEventSource(client: RpcClient): EventSource {
|
|
43
|
+
return {
|
|
44
|
+
subscribe: async (handler) => {
|
|
45
|
+
return client.on<GlobalEvent>("global.event", (e) => {
|
|
46
|
+
handler(e)
|
|
47
|
+
})
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function target() {
|
|
53
|
+
if (typeof OPENCODE_WORKER_PATH !== "undefined") return OPENCODE_WORKER_PATH
|
|
54
|
+
const dist = new URL("./cli/tui/worker.js", import.meta.url)
|
|
55
|
+
if (await Filesystem.exists(fileURLToPath(dist))) return dist
|
|
56
|
+
return new URL("../tui/worker.ts", import.meta.url)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function input(value?: string) {
|
|
60
|
+
const piped = process.stdin.isTTY ? undefined : await Bun.stdin.text()
|
|
61
|
+
if (!value) return piped
|
|
62
|
+
if (!piped) return value
|
|
63
|
+
return piped + "\n" + value
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function resolveThreadDirectory(project?: string, envPWD = process.env.PWD, cwd = process.cwd()) {
|
|
67
|
+
const root = Filesystem.resolve(envPWD ?? cwd)
|
|
68
|
+
if (project) return Filesystem.resolve(path.isAbsolute(project) ? project : path.join(root, project))
|
|
69
|
+
return Filesystem.resolve(cwd)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const TuiThreadCommand = cmd({
|
|
73
|
+
command: "$0 [project]",
|
|
74
|
+
describe: "start Anymous TUI",
|
|
75
|
+
builder: (yargs) =>
|
|
76
|
+
withNetworkOptions(yargs)
|
|
77
|
+
.positional("project", {
|
|
78
|
+
type: "string",
|
|
79
|
+
describe: "path to start Anymous in",
|
|
80
|
+
})
|
|
81
|
+
.option("model", {
|
|
82
|
+
type: "string",
|
|
83
|
+
alias: ["m"],
|
|
84
|
+
describe: "model to use in the format of provider/model",
|
|
85
|
+
})
|
|
86
|
+
.option("continue", {
|
|
87
|
+
alias: ["c"],
|
|
88
|
+
describe: "continue the last session",
|
|
89
|
+
type: "boolean",
|
|
90
|
+
})
|
|
91
|
+
.option("session", {
|
|
92
|
+
alias: ["s"],
|
|
93
|
+
type: "string",
|
|
94
|
+
describe: "session id to continue",
|
|
95
|
+
})
|
|
96
|
+
.option("fork", {
|
|
97
|
+
type: "boolean",
|
|
98
|
+
describe: "fork the session when continuing (use with --continue or --session)",
|
|
99
|
+
})
|
|
100
|
+
.option("prompt", {
|
|
101
|
+
type: "string",
|
|
102
|
+
describe: "prompt to use",
|
|
103
|
+
})
|
|
104
|
+
.option("agent", {
|
|
105
|
+
type: "string",
|
|
106
|
+
describe: "agent to use",
|
|
107
|
+
})
|
|
108
|
+
.option("auto", {
|
|
109
|
+
type: "boolean",
|
|
110
|
+
describe: "auto-approve permissions that are not explicitly denied (dangerous!)",
|
|
111
|
+
default: false,
|
|
112
|
+
})
|
|
113
|
+
.option("yolo", {
|
|
114
|
+
type: "boolean",
|
|
115
|
+
hidden: true,
|
|
116
|
+
default: false,
|
|
117
|
+
})
|
|
118
|
+
.option("dangerously-skip-permissions", {
|
|
119
|
+
type: "boolean",
|
|
120
|
+
hidden: true,
|
|
121
|
+
default: false,
|
|
122
|
+
})
|
|
123
|
+
.option("mini", {
|
|
124
|
+
type: "boolean",
|
|
125
|
+
describe: "start the minimal interactive interface",
|
|
126
|
+
default: false,
|
|
127
|
+
})
|
|
128
|
+
.option("replay", {
|
|
129
|
+
type: "boolean",
|
|
130
|
+
hidden: true,
|
|
131
|
+
})
|
|
132
|
+
.option("no-replay", {
|
|
133
|
+
type: "boolean",
|
|
134
|
+
describe: "disable mini session history replay on resume and after resize",
|
|
135
|
+
})
|
|
136
|
+
.option("replay-limit", {
|
|
137
|
+
type: "number",
|
|
138
|
+
describe: "cap visible mini replay to the newest N messages",
|
|
139
|
+
})
|
|
140
|
+
.option("demo", {
|
|
141
|
+
type: "boolean",
|
|
142
|
+
hidden: true,
|
|
143
|
+
}),
|
|
144
|
+
handler: async (args) => {
|
|
145
|
+
if (args.replay === true) {
|
|
146
|
+
UI.error("--replay is not supported; replay is enabled by default")
|
|
147
|
+
process.exitCode = 1
|
|
148
|
+
return
|
|
149
|
+
}
|
|
150
|
+
const noReplay = args.replay === false || args.noReplay === true
|
|
151
|
+
|
|
152
|
+
if (args.mini) {
|
|
153
|
+
const network = ["--port", "--hostname", "--mdns", "--no-mdns", "--mdns-domain", "--cors"].find((option) =>
|
|
154
|
+
process.argv.some((arg) => arg === option || arg.startsWith(option + "=")),
|
|
155
|
+
)
|
|
156
|
+
if (network) {
|
|
157
|
+
UI.error(`${network} cannot be used with --mini`)
|
|
158
|
+
process.exitCode = 1
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const { runMini } = await import("./run")
|
|
163
|
+
await runMini({
|
|
164
|
+
directory: resolveThreadDirectory(args.project),
|
|
165
|
+
continue: args.continue,
|
|
166
|
+
session: args.session,
|
|
167
|
+
fork: args.fork,
|
|
168
|
+
model: args.model,
|
|
169
|
+
agent: args.agent,
|
|
170
|
+
prompt: args.prompt,
|
|
171
|
+
replay: noReplay ? false : undefined,
|
|
172
|
+
replayLimit: args.replayLimit,
|
|
173
|
+
demo: args.demo,
|
|
174
|
+
})
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const unsupported = [
|
|
179
|
+
["--no-replay", noReplay],
|
|
180
|
+
["--replay-limit", args.replayLimit !== undefined],
|
|
181
|
+
["--demo", args.demo !== undefined],
|
|
182
|
+
].find((entry) => entry[1])?.[0]
|
|
183
|
+
if (unsupported) {
|
|
184
|
+
UI.error(`${unsupported} requires --mini`)
|
|
185
|
+
process.exitCode = 1
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const unguard = win32InstallCtrlCGuard()
|
|
190
|
+
try {
|
|
191
|
+
const { TuiConfig } = await import("@/config/tui")
|
|
192
|
+
if (args.fork && !args.continue && !args.session) {
|
|
193
|
+
UI.error("--fork requires --continue or --session")
|
|
194
|
+
process.exitCode = 1
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Resolve relative --project paths from PWD, then use the real cwd after
|
|
199
|
+
// chdir so the thread and worker share the same directory key.
|
|
200
|
+
const next = resolveThreadDirectory(args.project)
|
|
201
|
+
const file = await target()
|
|
202
|
+
try {
|
|
203
|
+
process.chdir(next)
|
|
204
|
+
} catch {
|
|
205
|
+
UI.error("Failed to change directory to " + next)
|
|
206
|
+
return
|
|
207
|
+
}
|
|
208
|
+
const cwd = Filesystem.resolve(process.cwd())
|
|
209
|
+
|
|
210
|
+
const worker = new Worker(file, {
|
|
211
|
+
env: Object.fromEntries(
|
|
212
|
+
Object.entries(process.env).filter((entry): entry is [string, string] => entry[1] !== undefined),
|
|
213
|
+
),
|
|
214
|
+
})
|
|
215
|
+
const client = Rpc.client<typeof rpc>(worker)
|
|
216
|
+
const reload = () => {
|
|
217
|
+
client.call("reload", undefined).catch(() => {})
|
|
218
|
+
}
|
|
219
|
+
process.on("SIGUSR2", reload)
|
|
220
|
+
|
|
221
|
+
let stopped = false
|
|
222
|
+
const stop = async () => {
|
|
223
|
+
if (stopped) return
|
|
224
|
+
stopped = true
|
|
225
|
+
process.off("SIGUSR2", reload)
|
|
226
|
+
await withTimeout(client.call("shutdown", undefined), 5000).catch(() => {})
|
|
227
|
+
worker.terminate()
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const prompt = await input(args.prompt)
|
|
231
|
+
const config = await TuiConfig.get()
|
|
232
|
+
|
|
233
|
+
const network = resolveNetworkOptionsNoConfig(args)
|
|
234
|
+
const external = hasArg("--port") || hasArg("--hostname") || network.mdns === true
|
|
235
|
+
|
|
236
|
+
const headers = external ? ServerAuth.headers() : undefined
|
|
237
|
+
|
|
238
|
+
const transport = external
|
|
239
|
+
? {
|
|
240
|
+
url: (await client.call("server", network)).url,
|
|
241
|
+
fetch: undefined,
|
|
242
|
+
events: undefined,
|
|
243
|
+
headers,
|
|
244
|
+
}
|
|
245
|
+
: {
|
|
246
|
+
url: "http://opencode.internal",
|
|
247
|
+
fetch: createWorkerFetch(client),
|
|
248
|
+
events: createEventSource(client),
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
await validateSession({
|
|
253
|
+
url: transport.url,
|
|
254
|
+
sessionID: args.session,
|
|
255
|
+
directory: cwd,
|
|
256
|
+
fetch: transport.fetch,
|
|
257
|
+
headers,
|
|
258
|
+
})
|
|
259
|
+
} catch (error) {
|
|
260
|
+
UI.error(errorMessage(error))
|
|
261
|
+
process.exitCode = 1
|
|
262
|
+
return
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
setTimeout(() => {
|
|
266
|
+
client.call("checkUpgrade", { directory: cwd }).catch(() => {})
|
|
267
|
+
}, 1000).unref?.()
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
const { Effect } = await import("effect")
|
|
271
|
+
const { run } = await import("../tui/layer")
|
|
272
|
+
const { createLegacyTuiPluginHost } = await import("@/plugin/tui/runtime")
|
|
273
|
+
await Effect.runPromise(
|
|
274
|
+
run({
|
|
275
|
+
url: transport.url,
|
|
276
|
+
async onSnapshot() {
|
|
277
|
+
const tui = writeHeapSnapshot("tui.heapsnapshot")
|
|
278
|
+
const server = await client.call("snapshot", undefined)
|
|
279
|
+
return [tui, server]
|
|
280
|
+
},
|
|
281
|
+
config,
|
|
282
|
+
pluginHost: createLegacyTuiPluginHost(),
|
|
283
|
+
directory: cwd,
|
|
284
|
+
fetch: transport.fetch,
|
|
285
|
+
headers: transport.headers,
|
|
286
|
+
events: transport.events,
|
|
287
|
+
args: {
|
|
288
|
+
continue: args.continue,
|
|
289
|
+
sessionID: args.session,
|
|
290
|
+
agent: args.agent,
|
|
291
|
+
model: args.model,
|
|
292
|
+
prompt,
|
|
293
|
+
fork: args.fork,
|
|
294
|
+
auto: args.auto || args.yolo || args["dangerously-skip-permissions"],
|
|
295
|
+
},
|
|
296
|
+
}),
|
|
297
|
+
)
|
|
298
|
+
} finally {
|
|
299
|
+
await stop()
|
|
300
|
+
}
|
|
301
|
+
} finally {
|
|
302
|
+
try {
|
|
303
|
+
unguard?.()
|
|
304
|
+
} catch {}
|
|
305
|
+
}
|
|
306
|
+
process.exit(0)
|
|
307
|
+
},
|
|
308
|
+
})
|
|
309
|
+
// scratch
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import type { Argv } from "yargs"
|
|
2
|
+
import { UI } from "../ui"
|
|
3
|
+
import * as prompts from "@clack/prompts"
|
|
4
|
+
import { Installation } from "../../installation"
|
|
5
|
+
import { Global } from "@opencode-ai/core/global"
|
|
6
|
+
import fs from "fs/promises"
|
|
7
|
+
import path from "path"
|
|
8
|
+
import os from "os"
|
|
9
|
+
import { Filesystem } from "@/util/filesystem"
|
|
10
|
+
import { Process } from "@/util/process"
|
|
11
|
+
|
|
12
|
+
interface UninstallArgs {
|
|
13
|
+
keepConfig: boolean
|
|
14
|
+
keepData: boolean
|
|
15
|
+
dryRun: boolean
|
|
16
|
+
force: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface RemovalTargets {
|
|
20
|
+
directories: Array<{ path: string; label: string; keep: boolean }>
|
|
21
|
+
shellConfig: string | null
|
|
22
|
+
binary: string | null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const UninstallCommand = {
|
|
26
|
+
command: "uninstall",
|
|
27
|
+
describe: "uninstall Anymous and remove all related files",
|
|
28
|
+
builder: (yargs: Argv) =>
|
|
29
|
+
yargs
|
|
30
|
+
.option("keep-config", {
|
|
31
|
+
alias: "c",
|
|
32
|
+
type: "boolean",
|
|
33
|
+
describe: "keep configuration files",
|
|
34
|
+
default: false,
|
|
35
|
+
})
|
|
36
|
+
.option("keep-data", {
|
|
37
|
+
alias: "d",
|
|
38
|
+
type: "boolean",
|
|
39
|
+
describe: "keep session data and snapshots",
|
|
40
|
+
default: false,
|
|
41
|
+
})
|
|
42
|
+
.option("dry-run", {
|
|
43
|
+
type: "boolean",
|
|
44
|
+
describe: "show what would be removed without removing",
|
|
45
|
+
default: false,
|
|
46
|
+
})
|
|
47
|
+
.option("force", {
|
|
48
|
+
alias: "f",
|
|
49
|
+
type: "boolean",
|
|
50
|
+
describe: "skip confirmation prompts",
|
|
51
|
+
default: false,
|
|
52
|
+
}),
|
|
53
|
+
|
|
54
|
+
handler: async (args: UninstallArgs) => {
|
|
55
|
+
UI.empty()
|
|
56
|
+
UI.println(UI.logo(" "))
|
|
57
|
+
UI.empty()
|
|
58
|
+
prompts.intro("Uninstall OpenCode")
|
|
59
|
+
|
|
60
|
+
const method = await Installation.method()
|
|
61
|
+
prompts.log.info(`Installation method: ${method}`)
|
|
62
|
+
|
|
63
|
+
const targets = await collectRemovalTargets(args, method)
|
|
64
|
+
|
|
65
|
+
await showRemovalSummary(targets, method)
|
|
66
|
+
|
|
67
|
+
if (!args.force && !args.dryRun) {
|
|
68
|
+
const confirm = await prompts.confirm({
|
|
69
|
+
message: "Are you sure you want to uninstall?",
|
|
70
|
+
initialValue: false,
|
|
71
|
+
})
|
|
72
|
+
if (!confirm || prompts.isCancel(confirm)) {
|
|
73
|
+
prompts.outro("Cancelled")
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (args.dryRun) {
|
|
79
|
+
prompts.log.warn("Dry run - no changes made")
|
|
80
|
+
prompts.outro("Done")
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
await executeUninstall(method, targets)
|
|
85
|
+
|
|
86
|
+
prompts.outro("Done")
|
|
87
|
+
},
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function collectRemovalTargets(args: UninstallArgs, method: Installation.Method): Promise<RemovalTargets> {
|
|
91
|
+
const directories: RemovalTargets["directories"] = [
|
|
92
|
+
{ path: Global.Path.data, label: "Data", keep: args.keepData },
|
|
93
|
+
{ path: Global.Path.cache, label: "Cache", keep: false },
|
|
94
|
+
{ path: Global.Path.config, label: "Config", keep: args.keepConfig },
|
|
95
|
+
{ path: Global.Path.state, label: "State", keep: false },
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
const shellConfig = method === "curl" ? await getShellConfigFile() : null
|
|
99
|
+
const binary = method === "curl" ? process.execPath : null
|
|
100
|
+
|
|
101
|
+
return { directories, shellConfig, binary }
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function showRemovalSummary(targets: RemovalTargets, method: Installation.Method) {
|
|
105
|
+
prompts.log.message("The following will be removed:")
|
|
106
|
+
|
|
107
|
+
for (const dir of targets.directories) {
|
|
108
|
+
const exists = await fs
|
|
109
|
+
.access(dir.path)
|
|
110
|
+
.then(() => true)
|
|
111
|
+
.catch(() => false)
|
|
112
|
+
if (!exists) continue
|
|
113
|
+
|
|
114
|
+
const size = await getDirectorySize(dir.path)
|
|
115
|
+
const sizeStr = formatSize(size)
|
|
116
|
+
const status = dir.keep ? UI.Style.TEXT_DIM + "(keeping)" : ""
|
|
117
|
+
const prefix = dir.keep ? "○" : "✓"
|
|
118
|
+
|
|
119
|
+
prompts.log.info(` ${prefix} ${dir.label}: ${shortenPath(dir.path)} ${UI.Style.TEXT_DIM}(${sizeStr})${status}`)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (targets.binary) {
|
|
123
|
+
prompts.log.info(` ✓ Binary: ${shortenPath(targets.binary)}`)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (targets.shellConfig) {
|
|
127
|
+
prompts.log.info(` ✓ Shell PATH in ${shortenPath(targets.shellConfig)}`)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (method !== "curl" && method !== "unknown") {
|
|
131
|
+
const cmds: Record<string, string> = {
|
|
132
|
+
npm: "npm uninstall -g opencode-ai",
|
|
133
|
+
pnpm: "pnpm uninstall -g opencode-ai",
|
|
134
|
+
bun: "bun remove -g opencode-ai",
|
|
135
|
+
yarn: "yarn global remove opencode-ai",
|
|
136
|
+
brew: "brew uninstall anymous",
|
|
137
|
+
choco: "choco uninstall anymous",
|
|
138
|
+
scoop: "scoop uninstall anymous",
|
|
139
|
+
}
|
|
140
|
+
prompts.log.info(` ✓ Package: ${cmds[method] || method}`)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function executeUninstall(method: Installation.Method, targets: RemovalTargets) {
|
|
145
|
+
const spinner = prompts.spinner()
|
|
146
|
+
const errors: string[] = []
|
|
147
|
+
|
|
148
|
+
for (const dir of targets.directories) {
|
|
149
|
+
if (dir.keep) {
|
|
150
|
+
prompts.log.step(`Skipping ${dir.label} (--keep-${dir.label.toLowerCase()})`)
|
|
151
|
+
continue
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const exists = await fs
|
|
155
|
+
.access(dir.path)
|
|
156
|
+
.then(() => true)
|
|
157
|
+
.catch(() => false)
|
|
158
|
+
if (!exists) continue
|
|
159
|
+
|
|
160
|
+
spinner.start(`Removing ${dir.label}...`)
|
|
161
|
+
const err = await fs.rm(dir.path, { recursive: true, force: true }).catch((e) => e)
|
|
162
|
+
if (err) {
|
|
163
|
+
spinner.stop(`Failed to remove ${dir.label}`, 1)
|
|
164
|
+
errors.push(`${dir.label}: ${err.message}`)
|
|
165
|
+
continue
|
|
166
|
+
}
|
|
167
|
+
spinner.stop(`Removed ${dir.label}`)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (targets.shellConfig) {
|
|
171
|
+
spinner.start("Cleaning shell config...")
|
|
172
|
+
const err = await cleanShellConfig(targets.shellConfig).catch((e) => e)
|
|
173
|
+
if (err) {
|
|
174
|
+
spinner.stop("Failed to clean shell config", 1)
|
|
175
|
+
errors.push(`Shell config: ${err.message}`)
|
|
176
|
+
} else {
|
|
177
|
+
spinner.stop("Cleaned shell config")
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (method !== "curl" && method !== "unknown") {
|
|
182
|
+
const cmds: Record<string, string[]> = {
|
|
183
|
+
npm: ["npm", "uninstall", "-g", "opencode-ai"],
|
|
184
|
+
pnpm: ["pnpm", "uninstall", "-g", "opencode-ai"],
|
|
185
|
+
bun: ["bun", "remove", "-g", "opencode-ai"],
|
|
186
|
+
yarn: ["yarn", "global", "remove", "opencode-ai"],
|
|
187
|
+
brew: ["brew", "uninstall", "opencode"],
|
|
188
|
+
choco: ["choco", "uninstall", "opencode"],
|
|
189
|
+
scoop: ["scoop", "uninstall", "opencode"],
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const cmd = cmds[method]
|
|
193
|
+
if (cmd) {
|
|
194
|
+
spinner.start(`Running ${cmd.join(" ")}...`)
|
|
195
|
+
const result = await Process.run(method === "choco" ? ["choco", "uninstall", "opencode", "-y", "-r"] : cmd, {
|
|
196
|
+
nothrow: true,
|
|
197
|
+
})
|
|
198
|
+
if (result.code !== 0) {
|
|
199
|
+
spinner.stop(`Package manager uninstall failed: exit code ${result.code}`, 1)
|
|
200
|
+
const text = `${result.stdout.toString("utf8")}\n${result.stderr.toString("utf8")}`
|
|
201
|
+
if (method === "choco" && text.includes("not running from an elevated command shell")) {
|
|
202
|
+
prompts.log.warn(`You may need to run '${cmd.join(" ")}' from an elevated command shell`)
|
|
203
|
+
} else {
|
|
204
|
+
prompts.log.warn(`You may need to run manually: ${cmd.join(" ")}`)
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
spinner.stop("Package removed")
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (method === "curl" && targets.binary) {
|
|
213
|
+
UI.empty()
|
|
214
|
+
prompts.log.message("To finish removing the binary, run:")
|
|
215
|
+
prompts.log.info(` rm "${targets.binary}"`)
|
|
216
|
+
|
|
217
|
+
const binDir = path.dirname(targets.binary)
|
|
218
|
+
if (binDir.includes(".opencode")) {
|
|
219
|
+
prompts.log.info(` rmdir "${binDir}" 2>/dev/null`)
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (errors.length > 0) {
|
|
224
|
+
UI.empty()
|
|
225
|
+
prompts.log.warn("Some operations failed:")
|
|
226
|
+
for (const err of errors) {
|
|
227
|
+
prompts.log.error(` ${err}`)
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
UI.empty()
|
|
232
|
+
prompts.log.success("Thank you for using OpenCode!")
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function getShellConfigFile(): Promise<string | null> {
|
|
236
|
+
const shell = path.basename(process.env.SHELL || "bash")
|
|
237
|
+
const home = os.homedir()
|
|
238
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || path.join(home, ".config")
|
|
239
|
+
|
|
240
|
+
const configFiles: Record<string, string[]> = {
|
|
241
|
+
fish: [path.join(xdgConfig, "fish", "config.fish")],
|
|
242
|
+
zsh: [
|
|
243
|
+
path.join(home, ".zshrc"),
|
|
244
|
+
path.join(home, ".zshenv"),
|
|
245
|
+
path.join(xdgConfig, "zsh", ".zshrc"),
|
|
246
|
+
path.join(xdgConfig, "zsh", ".zshenv"),
|
|
247
|
+
],
|
|
248
|
+
bash: [
|
|
249
|
+
path.join(home, ".bashrc"),
|
|
250
|
+
path.join(home, ".bash_profile"),
|
|
251
|
+
path.join(home, ".profile"),
|
|
252
|
+
path.join(xdgConfig, "bash", ".bashrc"),
|
|
253
|
+
path.join(xdgConfig, "bash", ".bash_profile"),
|
|
254
|
+
],
|
|
255
|
+
ash: [path.join(home, ".ashrc"), path.join(home, ".profile")],
|
|
256
|
+
sh: [path.join(home, ".profile")],
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const candidates = configFiles[shell] || configFiles.bash
|
|
260
|
+
|
|
261
|
+
for (const file of candidates) {
|
|
262
|
+
const exists = await fs
|
|
263
|
+
.access(file)
|
|
264
|
+
.then(() => true)
|
|
265
|
+
.catch(() => false)
|
|
266
|
+
if (!exists) continue
|
|
267
|
+
|
|
268
|
+
const content = await Filesystem.readText(file).catch(() => "")
|
|
269
|
+
if (content.includes("# opencode") || content.includes(".opencode/bin")) {
|
|
270
|
+
return file
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return null
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
async function cleanShellConfig(file: string) {
|
|
278
|
+
const content = await Filesystem.readText(file)
|
|
279
|
+
const lines = content.split("\n")
|
|
280
|
+
|
|
281
|
+
const filtered: string[] = []
|
|
282
|
+
let skip = false
|
|
283
|
+
|
|
284
|
+
for (const line of lines) {
|
|
285
|
+
const trimmed = line.trim()
|
|
286
|
+
|
|
287
|
+
if (trimmed === "# opencode") {
|
|
288
|
+
skip = true
|
|
289
|
+
continue
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (skip) {
|
|
293
|
+
skip = false
|
|
294
|
+
if (trimmed.includes(".opencode/bin") || trimmed.includes("fish_add_path")) {
|
|
295
|
+
continue
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (
|
|
300
|
+
(trimmed.startsWith("export PATH=") && trimmed.includes(".opencode/bin")) ||
|
|
301
|
+
(trimmed.startsWith("fish_add_path") && trimmed.includes(".opencode"))
|
|
302
|
+
) {
|
|
303
|
+
continue
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
filtered.push(line)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
while (filtered.length > 0 && filtered[filtered.length - 1].trim() === "") {
|
|
310
|
+
filtered.pop()
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const output = filtered.join("\n") + "\n"
|
|
314
|
+
await Filesystem.write(file, output)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async function getDirectorySize(dir: string): Promise<number> {
|
|
318
|
+
let total = 0
|
|
319
|
+
|
|
320
|
+
const walk = async (current: string) => {
|
|
321
|
+
const entries = await fs.readdir(current, { withFileTypes: true }).catch(() => [])
|
|
322
|
+
|
|
323
|
+
for (const entry of entries) {
|
|
324
|
+
const full = path.join(current, entry.name)
|
|
325
|
+
if (entry.isDirectory()) {
|
|
326
|
+
await walk(full)
|
|
327
|
+
continue
|
|
328
|
+
}
|
|
329
|
+
if (entry.isFile()) {
|
|
330
|
+
const stat = await fs.stat(full).catch(() => null)
|
|
331
|
+
if (stat) total += stat.size
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
await walk(dir)
|
|
337
|
+
return total
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function formatSize(bytes: number): string {
|
|
341
|
+
if (bytes < 1024) return `${bytes} B`
|
|
342
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
|
|
343
|
+
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`
|
|
344
|
+
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function shortenPath(p: string): string {
|
|
348
|
+
const home = os.homedir()
|
|
349
|
+
if (p.startsWith(home)) {
|
|
350
|
+
return p.replace(home, "~")
|
|
351
|
+
}
|
|
352
|
+
return p
|
|
353
|
+
}
|