rird 1.0.200
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/AGENTS.md +27 -0
- package/Dockerfile +18 -0
- package/README.md +15 -0
- package/bin/opencode +336 -0
- package/bin/pty-wrapper.js +285 -0
- package/bunfig.toml +4 -0
- package/facebook_ads_library.png +0 -0
- package/nul`nif +0 -0
- package/package.json +111 -0
- package/parsers-config.ts +239 -0
- package/rird-1.0.199.tgz +0 -0
- package/script/build-windows.ts +54 -0
- package/script/build.ts +167 -0
- package/script/postinstall.mjs +544 -0
- package/script/publish-registries.ts +187 -0
- package/script/publish.ts +72 -0
- package/script/schema.ts +47 -0
- package/src/acp/README.md +164 -0
- package/src/acp/agent.ts +1063 -0
- package/src/acp/session.ts +101 -0
- package/src/acp/types.ts +22 -0
- package/src/agent/agent.ts +367 -0
- package/src/agent/generate.txt +75 -0
- package/src/agent/prompt/compaction.txt +12 -0
- package/src/agent/prompt/explore.txt +18 -0
- package/src/agent/prompt/summary.txt +10 -0
- package/src/agent/prompt/title.txt +36 -0
- package/src/auth/index.ts +70 -0
- package/src/bun/index.ts +114 -0
- package/src/bus/bus-event.ts +43 -0
- package/src/bus/global.ts +10 -0
- package/src/bus/index.ts +105 -0
- package/src/cli/bootstrap.ts +17 -0
- package/src/cli/cmd/acp.ts +88 -0
- package/src/cli/cmd/agent.ts +256 -0
- package/src/cli/cmd/auth.ts +391 -0
- package/src/cli/cmd/cmd.ts +7 -0
- package/src/cli/cmd/debug/config.ts +15 -0
- package/src/cli/cmd/debug/file.ts +91 -0
- package/src/cli/cmd/debug/index.ts +43 -0
- package/src/cli/cmd/debug/lsp.ts +48 -0
- package/src/cli/cmd/debug/ripgrep.ts +83 -0
- package/src/cli/cmd/debug/scrap.ts +15 -0
- package/src/cli/cmd/debug/skill.ts +15 -0
- package/src/cli/cmd/debug/snapshot.ts +48 -0
- package/src/cli/cmd/export.ts +88 -0
- package/src/cli/cmd/generate.ts +38 -0
- package/src/cli/cmd/github.ts +1400 -0
- package/src/cli/cmd/import.ts +98 -0
- package/src/cli/cmd/mcp.ts +654 -0
- package/src/cli/cmd/models.ts +77 -0
- package/src/cli/cmd/pr.ts +112 -0
- package/src/cli/cmd/run.ts +368 -0
- package/src/cli/cmd/serve.ts +31 -0
- package/src/cli/cmd/session.ts +106 -0
- package/src/cli/cmd/stats.ts +298 -0
- package/src/cli/cmd/tui/app.tsx +696 -0
- package/src/cli/cmd/tui/attach.ts +30 -0
- package/src/cli/cmd/tui/component/border.tsx +21 -0
- package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
- package/src/cli/cmd/tui/component/dialog-command.tsx +124 -0
- package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
- package/src/cli/cmd/tui/component/dialog-model.tsx +245 -0
- package/src/cli/cmd/tui/component/dialog-provider.tsx +224 -0
- package/src/cli/cmd/tui/component/dialog-session-list.tsx +102 -0
- package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
- package/src/cli/cmd/tui/component/dialog-stash.tsx +86 -0
- package/src/cli/cmd/tui/component/dialog-status.tsx +162 -0
- package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
- package/src/cli/cmd/tui/component/dialog-theme-list.tsx +50 -0
- package/src/cli/cmd/tui/component/did-you-know.tsx +85 -0
- package/src/cli/cmd/tui/component/logo.tsx +35 -0
- package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +574 -0
- package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
- package/src/cli/cmd/tui/component/prompt/index.tsx +1090 -0
- package/src/cli/cmd/tui/component/prompt/stash.tsx +101 -0
- package/src/cli/cmd/tui/component/tips.ts +27 -0
- package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
- package/src/cli/cmd/tui/context/args.tsx +14 -0
- package/src/cli/cmd/tui/context/directory.ts +13 -0
- package/src/cli/cmd/tui/context/exit.tsx +23 -0
- package/src/cli/cmd/tui/context/helper.tsx +25 -0
- package/src/cli/cmd/tui/context/keybind.tsx +101 -0
- package/src/cli/cmd/tui/context/kv.tsx +49 -0
- package/src/cli/cmd/tui/context/local.tsx +354 -0
- package/src/cli/cmd/tui/context/prompt.tsx +18 -0
- package/src/cli/cmd/tui/context/route.tsx +46 -0
- package/src/cli/cmd/tui/context/sdk.tsx +74 -0
- package/src/cli/cmd/tui/context/sync.tsx +372 -0
- package/src/cli/cmd/tui/context/theme/aura.json +69 -0
- package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
- package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
- package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
- package/src/cli/cmd/tui/context/theme/catppuccin.json +112 -0
- package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
- package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
- package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
- package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
- package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
- package/src/cli/cmd/tui/context/theme/github.json +233 -0
- package/src/cli/cmd/tui/context/theme/gruvbox.json +95 -0
- package/src/cli/cmd/tui/context/theme/kanagawa.json +77 -0
- package/src/cli/cmd/tui/context/theme/lucent-orng.json +227 -0
- package/src/cli/cmd/tui/context/theme/material.json +235 -0
- package/src/cli/cmd/tui/context/theme/matrix.json +77 -0
- package/src/cli/cmd/tui/context/theme/mercury.json +252 -0
- package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
- package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
- package/src/cli/cmd/tui/context/theme/nord.json +223 -0
- package/src/cli/cmd/tui/context/theme/one-dark.json +84 -0
- package/src/cli/cmd/tui/context/theme/orng.json +245 -0
- package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
- package/src/cli/cmd/tui/context/theme/rird.json +245 -0
- package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
- package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
- package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
- package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
- package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
- package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
- package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
- package/src/cli/cmd/tui/context/theme.tsx +1109 -0
- package/src/cli/cmd/tui/event.ts +40 -0
- package/src/cli/cmd/tui/routes/home.tsx +138 -0
- package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +64 -0
- package/src/cli/cmd/tui/routes/session/dialog-message.tsx +109 -0
- package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +26 -0
- package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
- package/src/cli/cmd/tui/routes/session/footer.tsx +88 -0
- package/src/cli/cmd/tui/routes/session/header.tsx +125 -0
- package/src/cli/cmd/tui/routes/session/index.tsx +1864 -0
- package/src/cli/cmd/tui/routes/session/sidebar.tsx +318 -0
- package/src/cli/cmd/tui/spawn.ts +60 -0
- package/src/cli/cmd/tui/thread.ts +142 -0
- package/src/cli/cmd/tui/ui/dialog-alert.tsx +57 -0
- package/src/cli/cmd/tui/ui/dialog-confirm.tsx +83 -0
- package/src/cli/cmd/tui/ui/dialog-help.tsx +38 -0
- package/src/cli/cmd/tui/ui/dialog-prompt.tsx +77 -0
- package/src/cli/cmd/tui/ui/dialog-select.tsx +332 -0
- package/src/cli/cmd/tui/ui/dialog.tsx +170 -0
- package/src/cli/cmd/tui/ui/spinner.ts +368 -0
- package/src/cli/cmd/tui/ui/toast.tsx +100 -0
- package/src/cli/cmd/tui/util/clipboard.ts +127 -0
- package/src/cli/cmd/tui/util/editor.ts +32 -0
- package/src/cli/cmd/tui/util/terminal.ts +114 -0
- package/src/cli/cmd/tui/worker.ts +63 -0
- package/src/cli/cmd/uninstall.ts +344 -0
- package/src/cli/cmd/upgrade.ts +100 -0
- package/src/cli/cmd/web.ts +84 -0
- package/src/cli/error.ts +56 -0
- package/src/cli/ui.ts +84 -0
- package/src/cli/upgrade.ts +25 -0
- package/src/command/index.ts +80 -0
- package/src/command/template/initialize.txt +10 -0
- package/src/command/template/review.txt +97 -0
- package/src/config/config.ts +995 -0
- package/src/config/markdown.ts +41 -0
- package/src/env/index.ts +26 -0
- package/src/file/ignore.ts +83 -0
- package/src/file/index.ts +328 -0
- package/src/file/ripgrep.ts +393 -0
- package/src/file/time.ts +64 -0
- package/src/file/watcher.ts +103 -0
- package/src/flag/flag.ts +46 -0
- package/src/format/formatter.ts +315 -0
- package/src/format/index.ts +137 -0
- package/src/global/index.ts +52 -0
- package/src/id/id.ts +73 -0
- package/src/ide/index.ts +76 -0
- package/src/index.ts +240 -0
- package/src/installation/index.ts +239 -0
- package/src/lsp/client.ts +229 -0
- package/src/lsp/index.ts +485 -0
- package/src/lsp/language.ts +116 -0
- package/src/lsp/server.ts +1895 -0
- package/src/mcp/auth.ts +135 -0
- package/src/mcp/index.ts +690 -0
- package/src/mcp/oauth-callback.ts +200 -0
- package/src/mcp/oauth-provider.ts +154 -0
- package/src/patch/index.ts +622 -0
- package/src/permission/index.ts +199 -0
- package/src/plugin/index.ts +91 -0
- package/src/project/bootstrap.ts +31 -0
- package/src/project/instance.ts +78 -0
- package/src/project/project.ts +221 -0
- package/src/project/state.ts +65 -0
- package/src/project/vcs.ts +76 -0
- package/src/provider/auth.ts +143 -0
- package/src/provider/models-macro.ts +11 -0
- package/src/provider/models.ts +106 -0
- package/src/provider/provider.ts +1071 -0
- package/src/provider/sdk/openai-compatible/src/README.md +5 -0
- package/src/provider/sdk/openai-compatible/src/index.ts +2 -0
- package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +100 -0
- package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +303 -0
- package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +22 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +18 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +22 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +207 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +1713 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +177 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +1 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +88 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +128 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +115 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +65 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +104 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +103 -0
- package/src/provider/transform.ts +455 -0
- package/src/pty/index.ts +231 -0
- package/src/security/guardrails.test.ts +341 -0
- package/src/security/guardrails.ts +558 -0
- package/src/security/index.ts +19 -0
- package/src/server/error.ts +36 -0
- package/src/server/project.ts +79 -0
- package/src/server/server.ts +2642 -0
- package/src/server/tui.ts +71 -0
- package/src/session/compaction.ts +223 -0
- package/src/session/index.ts +461 -0
- package/src/session/llm.ts +201 -0
- package/src/session/message-v2.ts +690 -0
- package/src/session/message.ts +189 -0
- package/src/session/processor.ts +409 -0
- package/src/session/prompt/act-switch.txt +5 -0
- package/src/session/prompt/anthropic-20250930.txt +166 -0
- package/src/session/prompt/anthropic.txt +85 -0
- package/src/session/prompt/anthropic_spoof.txt +1 -0
- package/src/session/prompt/beast.txt +103 -0
- package/src/session/prompt/codex.txt +304 -0
- package/src/session/prompt/copilot-gpt-5.txt +138 -0
- package/src/session/prompt/gemini.txt +85 -0
- package/src/session/prompt/max-steps.txt +16 -0
- package/src/session/prompt/plan-reminder-anthropic.txt +35 -0
- package/src/session/prompt/plan.txt +24 -0
- package/src/session/prompt/polaris.txt +84 -0
- package/src/session/prompt/qwen.txt +106 -0
- package/src/session/prompt.ts +1509 -0
- package/src/session/retry.ts +86 -0
- package/src/session/revert.ts +108 -0
- package/src/session/sensitive-filter.test.ts +327 -0
- package/src/session/sensitive-filter.ts +466 -0
- package/src/session/status.ts +76 -0
- package/src/session/summary.ts +194 -0
- package/src/session/system.ts +120 -0
- package/src/session/todo.ts +37 -0
- package/src/share/share-next.ts +194 -0
- package/src/share/share.ts +87 -0
- package/src/shell/shell.ts +67 -0
- package/src/skill/index.ts +1 -0
- package/src/skill/skill.ts +83 -0
- package/src/snapshot/index.ts +197 -0
- package/src/storage/storage.ts +226 -0
- package/src/tests/agent.test.ts +308 -0
- package/src/tests/build-guards.test.ts +267 -0
- package/src/tests/config.test.ts +664 -0
- package/src/tests/tool-registry.test.ts +589 -0
- package/src/tool/bash.ts +317 -0
- package/src/tool/bash.txt +158 -0
- package/src/tool/batch.ts +175 -0
- package/src/tool/batch.txt +24 -0
- package/src/tool/codesearch.ts +168 -0
- package/src/tool/codesearch.txt +12 -0
- package/src/tool/edit.ts +675 -0
- package/src/tool/edit.txt +10 -0
- package/src/tool/glob.ts +65 -0
- package/src/tool/glob.txt +6 -0
- package/src/tool/grep.ts +121 -0
- package/src/tool/grep.txt +8 -0
- package/src/tool/invalid.ts +17 -0
- package/src/tool/ls.ts +110 -0
- package/src/tool/ls.txt +1 -0
- package/src/tool/lsp-diagnostics.ts +26 -0
- package/src/tool/lsp-diagnostics.txt +1 -0
- package/src/tool/lsp-hover.ts +31 -0
- package/src/tool/lsp-hover.txt +1 -0
- package/src/tool/lsp.ts +87 -0
- package/src/tool/lsp.txt +19 -0
- package/src/tool/multiedit.ts +46 -0
- package/src/tool/multiedit.txt +41 -0
- package/src/tool/patch.ts +233 -0
- package/src/tool/patch.txt +1 -0
- package/src/tool/read.ts +219 -0
- package/src/tool/read.txt +12 -0
- package/src/tool/registry.ts +162 -0
- package/src/tool/skill.ts +100 -0
- package/src/tool/task.ts +136 -0
- package/src/tool/task.txt +51 -0
- package/src/tool/todo.ts +39 -0
- package/src/tool/todoread.txt +14 -0
- package/src/tool/todowrite.txt +167 -0
- package/src/tool/tool.ts +71 -0
- package/src/tool/webfetch.ts +198 -0
- package/src/tool/webfetch.txt +13 -0
- package/src/tool/websearch.ts +180 -0
- package/src/tool/websearch.txt +11 -0
- package/src/tool/write.ts +110 -0
- package/src/tool/write.txt +8 -0
- package/src/util/archive.ts +16 -0
- package/src/util/color.ts +19 -0
- package/src/util/context.ts +25 -0
- package/src/util/defer.ts +12 -0
- package/src/util/eventloop.ts +20 -0
- package/src/util/filesystem.ts +83 -0
- package/src/util/fn.ts +11 -0
- package/src/util/iife.ts +3 -0
- package/src/util/keybind.ts +102 -0
- package/src/util/lazy.ts +11 -0
- package/src/util/license.ts +325 -0
- package/src/util/locale.ts +81 -0
- package/src/util/lock.ts +98 -0
- package/src/util/log.ts +180 -0
- package/src/util/queue.ts +32 -0
- package/src/util/rpc.ts +42 -0
- package/src/util/scrap.ts +10 -0
- package/src/util/signal.ts +12 -0
- package/src/util/timeout.ts +14 -0
- package/src/util/token.ts +7 -0
- package/src/util/wildcard.ts +54 -0
- package/sst-env.d.ts +9 -0
- package/test/agent/agent.test.ts +146 -0
- package/test/bun.test.ts +53 -0
- package/test/cli/github-remote.test.ts +80 -0
- package/test/config/agent-color.test.ts +66 -0
- package/test/config/config.test.ts +535 -0
- package/test/config/markdown.test.ts +89 -0
- package/test/file/ignore.test.ts +10 -0
- package/test/fixture/fixture.ts +36 -0
- package/test/fixture/lsp/fake-lsp-server.js +77 -0
- package/test/ide/ide.test.ts +82 -0
- package/test/keybind.test.ts +421 -0
- package/test/lsp/client.test.ts +95 -0
- package/test/mcp/headers.test.ts +153 -0
- package/test/patch/patch.test.ts +348 -0
- package/test/preload.ts +57 -0
- package/test/project/project.test.ts +72 -0
- package/test/provider/provider.test.ts +1809 -0
- package/test/provider/transform.test.ts +411 -0
- package/test/session/retry.test.ts +111 -0
- package/test/session/session.test.ts +71 -0
- package/test/skill/skill.test.ts +131 -0
- package/test/snapshot/snapshot.test.ts +939 -0
- package/test/tool/__snapshots__/tool.test.ts.snap +9 -0
- package/test/tool/bash.test.ts +434 -0
- package/test/tool/grep.test.ts +108 -0
- package/test/tool/patch.test.ts +259 -0
- package/test/tool/read.test.ts +42 -0
- package/test/util/iife.test.ts +36 -0
- package/test/util/lazy.test.ts +50 -0
- package/test/util/timeout.test.ts +21 -0
- package/test/util/wildcard.test.ts +55 -0
- package/tsconfig.json +16 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# RIRD agent guidelines
|
|
2
|
+
|
|
3
|
+
## Build/Test Commands
|
|
4
|
+
|
|
5
|
+
- **Install**: `bun install`
|
|
6
|
+
- **Run**: `bun run index.ts`
|
|
7
|
+
- **Typecheck**: `bun run typecheck` (npm run typecheck)
|
|
8
|
+
- **Test**: `bun test` (runs all tests)
|
|
9
|
+
- **Single test**: `bun test test/tool/tool.test.ts` (specific test file)
|
|
10
|
+
|
|
11
|
+
## Code Style
|
|
12
|
+
|
|
13
|
+
- **Runtime**: Bun with TypeScript ESM modules
|
|
14
|
+
- **Imports**: Use relative imports for local modules, named imports preferred
|
|
15
|
+
- **Types**: Zod schemas for validation, TypeScript interfaces for structure
|
|
16
|
+
- **Naming**: camelCase for variables/functions, PascalCase for classes/namespaces
|
|
17
|
+
- **Error handling**: Use Result patterns, avoid throwing exceptions in tools
|
|
18
|
+
- **File structure**: Namespace-based organization (e.g., `Tool.define()`, `Session.create()`)
|
|
19
|
+
|
|
20
|
+
## Architecture
|
|
21
|
+
|
|
22
|
+
- **Tools**: Implement `Tool.Info` interface with `execute()` method
|
|
23
|
+
- **Context**: Pass `sessionID` in tool context, use `App.provide()` for DI
|
|
24
|
+
- **Validation**: All inputs validated with Zod schemas
|
|
25
|
+
- **Logging**: Use `Log.create({ service: "name" })` pattern
|
|
26
|
+
- **Storage**: Use `Storage` namespace for persistence
|
|
27
|
+
- **API Client**: Go TUI communicates with TypeScript server via stainless SDK. When adding/modifying server endpoints in `packages/opencode/src/server/server.ts`, ask the user to generate a new client SDK to proceed with client-side changes.
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
FROM alpine AS base
|
|
2
|
+
|
|
3
|
+
# Disable the runtime transpiler cache by default inside Docker containers.
|
|
4
|
+
# On ephemeral containers, the cache is not useful
|
|
5
|
+
ARG BUN_RUNTIME_TRANSPILER_CACHE_PATH=0
|
|
6
|
+
ENV BUN_RUNTIME_TRANSPILER_CACHE_PATH=${BUN_RUNTIME_TRANSPILER_CACHE_PATH}
|
|
7
|
+
RUN apk add libgcc libstdc++ ripgrep
|
|
8
|
+
|
|
9
|
+
FROM base AS build-amd64
|
|
10
|
+
COPY dist/opencode-linux-x64-baseline-musl/bin/opencode /usr/local/bin/opencode
|
|
11
|
+
|
|
12
|
+
FROM base AS build-arm64
|
|
13
|
+
COPY dist/opencode-linux-arm64-musl/bin/opencode /usr/local/bin/opencode
|
|
14
|
+
|
|
15
|
+
ARG TARGETARCH
|
|
16
|
+
FROM build-${TARGETARCH}
|
|
17
|
+
RUN opencode --version
|
|
18
|
+
ENTRYPOINT ["opencode"]
|
package/README.md
ADDED
package/bin/opencode
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const childProcess = require("child_process")
|
|
4
|
+
const fs = require("fs")
|
|
5
|
+
const path = require("path")
|
|
6
|
+
const os = require("os")
|
|
7
|
+
|
|
8
|
+
// Handle CLI commands before passing to binary
|
|
9
|
+
const command = process.argv[2]
|
|
10
|
+
|
|
11
|
+
// Version
|
|
12
|
+
if (command === "--version" || command === "-v") {
|
|
13
|
+
const pkg = require("../package.json")
|
|
14
|
+
console.log("RIRD v" + pkg.version)
|
|
15
|
+
process.exit(0)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Help
|
|
19
|
+
if (command === "--help" || command === "-h" || command === "help") {
|
|
20
|
+
console.log("")
|
|
21
|
+
console.log(" RIRD AI")
|
|
22
|
+
console.log(" rird.ai")
|
|
23
|
+
console.log("")
|
|
24
|
+
console.log("Usage: rird [command]")
|
|
25
|
+
console.log("")
|
|
26
|
+
console.log(" rird Start RIRD AI")
|
|
27
|
+
console.log(" rird <task> Run with task description")
|
|
28
|
+
console.log(" rird activate <key> Activate license")
|
|
29
|
+
console.log(" rird status Check license status")
|
|
30
|
+
console.log(" rird upgrade Update to latest version")
|
|
31
|
+
console.log(" rird --help Show help")
|
|
32
|
+
console.log(" rird --version Show version")
|
|
33
|
+
console.log("")
|
|
34
|
+
process.exit(0)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Upgrade
|
|
38
|
+
if (command === "upgrade" || command === "update") {
|
|
39
|
+
console.log("")
|
|
40
|
+
console.log(" RIRD AI")
|
|
41
|
+
console.log(" Upgrading to latest version...")
|
|
42
|
+
console.log("")
|
|
43
|
+
|
|
44
|
+
const platform = os.platform()
|
|
45
|
+
let result
|
|
46
|
+
|
|
47
|
+
if (platform === "win32") {
|
|
48
|
+
// Windows: Use npm to update (simpler and more reliable)
|
|
49
|
+
console.log("Running: npm install -g rird-ai@main")
|
|
50
|
+
console.log("")
|
|
51
|
+
result = childProcess.spawnSync(
|
|
52
|
+
"npm",
|
|
53
|
+
["install", "-g", "rird-ai@main"],
|
|
54
|
+
{ stdio: "inherit", shell: true }
|
|
55
|
+
)
|
|
56
|
+
} else {
|
|
57
|
+
// Unix/macOS: Use curl
|
|
58
|
+
result = childProcess.spawnSync(
|
|
59
|
+
"bash",
|
|
60
|
+
["-c", "curl -fsSL https://rird.ai/install.sh | bash"],
|
|
61
|
+
{ stdio: "inherit" }
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (result.error) {
|
|
66
|
+
console.error("Upgrade failed:", result.error.message)
|
|
67
|
+
process.exit(1)
|
|
68
|
+
}
|
|
69
|
+
process.exit(result.status || 0)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Branding replacements for output - order matters (specific patterns first)
|
|
73
|
+
const REPLACEMENTS = [
|
|
74
|
+
// URLs and paths
|
|
75
|
+
{ from: /sst\/opencode/gi, to: "rird.ai" },
|
|
76
|
+
{ from: /opencode\.ai/gi, to: "rird.ai" },
|
|
77
|
+
{ from: /rird\.ai\/desktop/gi, to: "rird.ai" },
|
|
78
|
+
{ from: /https?:\/\/[^\s]*opencode[^\s]*/gi, to: (match) => match.replace(/opencode/gi, "rird") },
|
|
79
|
+
// Known fake/test model names
|
|
80
|
+
{ from: /OpenCode Zen/gi, to: "RIRD AI" },
|
|
81
|
+
{ from: /OpenCode\/Zen/gi, to: "RIRD AI" },
|
|
82
|
+
{ from: /opencode-zen/gi, to: "rird-brain" },
|
|
83
|
+
{ from: /Big Pickle/gi, to: "RIRD AI" },
|
|
84
|
+
{ from: /big-pickle/gi, to: "rird-brain" },
|
|
85
|
+
{ from: /gpt-5-nano/gi, to: "RIRD Brain" },
|
|
86
|
+
{ from: /GPT-5 Nano/gi, to: "RIRD Brain" },
|
|
87
|
+
// Provider/model name patterns (catch OpenCode/anything)
|
|
88
|
+
{ from: /OpenCode\s*\/\s*(\w+)/gi, to: "RIRD/$1" },
|
|
89
|
+
// Generic branding
|
|
90
|
+
{ from: /OpenCode/g, to: "RIRD" },
|
|
91
|
+
{ from: /opencode/g, to: "rird" },
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
function replaceBranding(data) {
|
|
95
|
+
let str = data.toString()
|
|
96
|
+
for (const { from, to } of REPLACEMENTS) {
|
|
97
|
+
str = str.replace(from, to)
|
|
98
|
+
}
|
|
99
|
+
return str
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function runWithPty(target, args, env) {
|
|
103
|
+
let pty = null
|
|
104
|
+
try {
|
|
105
|
+
pty = require("bun-pty")
|
|
106
|
+
} catch (e1) {
|
|
107
|
+
try {
|
|
108
|
+
pty = require("node-pty")
|
|
109
|
+
} catch (e2) {
|
|
110
|
+
return false // PTY not available
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const cols = process.stdout.columns || 80
|
|
115
|
+
const rows = process.stdout.rows || 24
|
|
116
|
+
const cwd = env.RIRD_ENGINE_DIR || process.cwd()
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const ptyProcess = pty.spawn(target, args, {
|
|
120
|
+
name: "xterm-256color",
|
|
121
|
+
cols: cols,
|
|
122
|
+
rows: rows,
|
|
123
|
+
cwd: cwd,
|
|
124
|
+
env: env,
|
|
125
|
+
...(os.platform() === "win32" && {
|
|
126
|
+
useConpty: true,
|
|
127
|
+
conptyInheritCursor: true,
|
|
128
|
+
}),
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
// Handle output with branding replacement
|
|
132
|
+
ptyProcess.onData((data) => {
|
|
133
|
+
process.stdout.write(replaceBranding(data))
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
// Handle input
|
|
137
|
+
if (process.stdin.isTTY) {
|
|
138
|
+
process.stdin.setRawMode(true)
|
|
139
|
+
}
|
|
140
|
+
process.stdin.resume()
|
|
141
|
+
process.stdin.on("data", (data) => {
|
|
142
|
+
ptyProcess.write(data.toString())
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
// Handle terminal resize
|
|
146
|
+
process.stdout.on("resize", () => {
|
|
147
|
+
ptyProcess.resize(
|
|
148
|
+
process.stdout.columns || 80,
|
|
149
|
+
process.stdout.rows || 24
|
|
150
|
+
)
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
// Handle exit
|
|
154
|
+
let exited = false
|
|
155
|
+
ptyProcess.onExit(({ exitCode }) => {
|
|
156
|
+
if (exited) return
|
|
157
|
+
exited = true
|
|
158
|
+
if (process.stdin.isTTY) {
|
|
159
|
+
process.stdin.setRawMode(false)
|
|
160
|
+
}
|
|
161
|
+
process.stdin.pause()
|
|
162
|
+
process.exit(exitCode || 0)
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
// Handle signals - pass to child, don't exit wrapper
|
|
166
|
+
process.on("SIGINT", () => {
|
|
167
|
+
if (!exited) ptyProcess.write("\x03") // Send Ctrl+C to PTY
|
|
168
|
+
})
|
|
169
|
+
process.on("SIGTERM", () => {
|
|
170
|
+
if (!exited) ptyProcess.kill()
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
return true // PTY started successfully
|
|
174
|
+
} catch (err) {
|
|
175
|
+
return false // PTY failed
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function runWithPipes(target, args, env) {
|
|
180
|
+
const cwd = env.RIRD_ENGINE_DIR || process.cwd()
|
|
181
|
+
const child = childProcess.spawn(target, args, {
|
|
182
|
+
env: env,
|
|
183
|
+
cwd: cwd,
|
|
184
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
let exited = false
|
|
188
|
+
|
|
189
|
+
child.stdout.on("data", (data) => {
|
|
190
|
+
if (!exited) process.stdout.write(replaceBranding(data))
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
child.stderr.on("data", (data) => {
|
|
194
|
+
if (!exited) process.stderr.write(replaceBranding(data))
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
process.stdin.pipe(child.stdin)
|
|
198
|
+
|
|
199
|
+
child.on("exit", (code) => {
|
|
200
|
+
if (exited) return
|
|
201
|
+
exited = true
|
|
202
|
+
process.stdin.unpipe(child.stdin)
|
|
203
|
+
process.stdin.pause()
|
|
204
|
+
process.exit(code || 0)
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
child.on("error", (err) => {
|
|
208
|
+
if (exited) return
|
|
209
|
+
exited = true
|
|
210
|
+
console.error("Failed to start process:", err.message)
|
|
211
|
+
process.exit(1)
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
process.on("SIGINT", () => {
|
|
215
|
+
if (!exited) child.kill("SIGINT")
|
|
216
|
+
})
|
|
217
|
+
process.on("SIGTERM", () => {
|
|
218
|
+
if (!exited) child.kill("SIGTERM")
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function run(target) {
|
|
223
|
+
// Set config path to RIRD config
|
|
224
|
+
const rirdHome = process.env.RIRD_HOME || path.join(os.homedir(), ".rird")
|
|
225
|
+
const brainDir = path.join(rirdHome, "brain")
|
|
226
|
+
const configPath = path.join(brainDir, "rird.json")
|
|
227
|
+
|
|
228
|
+
// Ensure brain directory exists
|
|
229
|
+
if (!fs.existsSync(brainDir)) {
|
|
230
|
+
fs.mkdirSync(brainDir, { recursive: true })
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Create default config if it doesn't exist
|
|
234
|
+
if (!fs.existsSync(configPath)) {
|
|
235
|
+
const defaultConfig = {
|
|
236
|
+
name: "RIRD AI",
|
|
237
|
+
autoupdate: false,
|
|
238
|
+
instructions: [
|
|
239
|
+
"You are RIRD AI with browser automation and computer control.",
|
|
240
|
+
"Use file tools (Write, Edit) for saving data.",
|
|
241
|
+
"Execute tasks autonomously and efficiently."
|
|
242
|
+
],
|
|
243
|
+
permission: {
|
|
244
|
+
edit: "allow",
|
|
245
|
+
bash: "allow",
|
|
246
|
+
skill: "allow",
|
|
247
|
+
webfetch: "allow",
|
|
248
|
+
external_directory: "allow"
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2))
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const env = { ...process.env }
|
|
255
|
+
env.OPENCODE_CONFIG = configPath
|
|
256
|
+
env.RIRD_ENGINE_DIR = brainDir
|
|
257
|
+
env.RIRD_DISABLE_AUTOUPDATE = "true"
|
|
258
|
+
env.OPENCODE_DISABLE_AUTOUPDATE = "true"
|
|
259
|
+
env.OPENCODE_SKIP_UPDATE = "true"
|
|
260
|
+
|
|
261
|
+
const args = process.argv.slice(2)
|
|
262
|
+
|
|
263
|
+
// Try PTY first for full terminal support with branding replacement
|
|
264
|
+
if (runWithPty(target, args, env)) {
|
|
265
|
+
return // PTY started successfully
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Fall back to pipes with branding replacement
|
|
269
|
+
runWithPipes(target, args, env)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const envPath = process.env.OPENCODE_BIN_PATH
|
|
273
|
+
if (envPath) {
|
|
274
|
+
run(envPath)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const scriptPath = fs.realpathSync(__filename)
|
|
278
|
+
const scriptDir = path.dirname(scriptPath)
|
|
279
|
+
|
|
280
|
+
const platformMap = {
|
|
281
|
+
darwin: "darwin",
|
|
282
|
+
linux: "linux",
|
|
283
|
+
win32: "windows",
|
|
284
|
+
}
|
|
285
|
+
const archMap = {
|
|
286
|
+
x64: "x64",
|
|
287
|
+
arm64: "arm64",
|
|
288
|
+
arm: "arm",
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
let platform = platformMap[os.platform()]
|
|
292
|
+
if (!platform) {
|
|
293
|
+
platform = os.platform()
|
|
294
|
+
}
|
|
295
|
+
let arch = archMap[os.arch()]
|
|
296
|
+
if (!arch) {
|
|
297
|
+
arch = os.arch()
|
|
298
|
+
}
|
|
299
|
+
const base = "rird-" + platform + "-" + arch
|
|
300
|
+
const binary = platform === "windows" ? "opencode.exe" : "opencode"
|
|
301
|
+
|
|
302
|
+
function findBinary(startDir) {
|
|
303
|
+
let current = startDir
|
|
304
|
+
for (;;) {
|
|
305
|
+
const modules = path.join(current, "node_modules")
|
|
306
|
+
if (fs.existsSync(modules)) {
|
|
307
|
+
const entries = fs.readdirSync(modules)
|
|
308
|
+
for (const entry of entries) {
|
|
309
|
+
if (!entry.startsWith(base)) {
|
|
310
|
+
continue
|
|
311
|
+
}
|
|
312
|
+
const candidate = path.join(modules, entry, "bin", binary)
|
|
313
|
+
if (fs.existsSync(candidate)) {
|
|
314
|
+
return candidate
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
const parent = path.dirname(current)
|
|
319
|
+
if (parent === current) {
|
|
320
|
+
return
|
|
321
|
+
}
|
|
322
|
+
current = parent
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const resolved = findBinary(scriptDir)
|
|
327
|
+
if (!resolved) {
|
|
328
|
+
console.error(
|
|
329
|
+
'It seems that your package manager failed to install the right version of the RIRD CLI for your platform. You can try manually installing the "' +
|
|
330
|
+
base +
|
|
331
|
+
'" package',
|
|
332
|
+
)
|
|
333
|
+
process.exit(1)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
run(resolved)
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PTY Wrapper for RIRD
|
|
5
|
+
*
|
|
6
|
+
* Intercepts OpenCode binary output and replaces branding strings.
|
|
7
|
+
* Works on Windows, macOS, and Linux.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* node pty-wrapper.js <path-to-binary> [args...]
|
|
11
|
+
*
|
|
12
|
+
* Environment:
|
|
13
|
+
* RIRD_NO_PTY=1 - Disable PTY, use simple pipes (fallback mode)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const childProcess = require("child_process")
|
|
17
|
+
const fs = require("fs")
|
|
18
|
+
const path = require("path")
|
|
19
|
+
const os = require("os")
|
|
20
|
+
|
|
21
|
+
// Branding replacements for output - order matters (specific patterns first)
|
|
22
|
+
const REPLACEMENTS = [
|
|
23
|
+
// URLs and paths
|
|
24
|
+
{ from: /sst\/opencode/gi, to: "rird.ai" },
|
|
25
|
+
{ from: /opencode\.ai/gi, to: "rird.ai" },
|
|
26
|
+
{ from: /rird\.ai\/desktop/gi, to: "rird.ai" },
|
|
27
|
+
{ from: /https?:\/\/[^\s]*opencode[^\s]*/gi, to: (match) => match.replace(/opencode/gi, "rird") },
|
|
28
|
+
// Known fake/test model names
|
|
29
|
+
{ from: /OpenCode Zen/gi, to: "RIRD AI" },
|
|
30
|
+
{ from: /OpenCode\/Zen/gi, to: "RIRD AI" },
|
|
31
|
+
{ from: /opencode-zen/gi, to: "rird-brain" },
|
|
32
|
+
{ from: /Big Pickle/gi, to: "RIRD AI" },
|
|
33
|
+
{ from: /big-pickle/gi, to: "rird-brain" },
|
|
34
|
+
{ from: /gpt-5-nano/gi, to: "RIRD Brain" },
|
|
35
|
+
{ from: /GPT-5 Nano/gi, to: "RIRD Brain" },
|
|
36
|
+
// Provider/model name patterns (catch OpenCode/anything)
|
|
37
|
+
{ from: /OpenCode\s*\/\s*(\w+)/gi, to: "RIRD/$1" },
|
|
38
|
+
// Generic branding
|
|
39
|
+
{ from: /OpenCode/g, to: "RIRD" },
|
|
40
|
+
{ from: /opencode/g, to: "rird" },
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Replace branding strings in a buffer/string
|
|
45
|
+
*/
|
|
46
|
+
function replaceBranding(data) {
|
|
47
|
+
let str = data.toString()
|
|
48
|
+
for (const { from, to } of REPLACEMENTS) {
|
|
49
|
+
str = str.replace(from, to)
|
|
50
|
+
}
|
|
51
|
+
return str
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Try to load node-pty dynamically
|
|
56
|
+
*/
|
|
57
|
+
function tryLoadPty() {
|
|
58
|
+
try {
|
|
59
|
+
// Try bun-pty first (listed in package.json)
|
|
60
|
+
return require("bun-pty")
|
|
61
|
+
} catch (e1) {
|
|
62
|
+
try {
|
|
63
|
+
// Fall back to node-pty
|
|
64
|
+
return require("node-pty")
|
|
65
|
+
} catch (e2) {
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Run with PTY (interactive TUI support)
|
|
73
|
+
*/
|
|
74
|
+
function runWithPty(pty, binaryPath, args, env) {
|
|
75
|
+
const isWindows = os.platform() === "win32"
|
|
76
|
+
const shell = isWindows ? "cmd.exe" : undefined
|
|
77
|
+
|
|
78
|
+
// Get terminal size
|
|
79
|
+
const cols = process.stdout.columns || 80
|
|
80
|
+
const rows = process.stdout.rows || 24
|
|
81
|
+
|
|
82
|
+
// Spawn PTY
|
|
83
|
+
const ptyProcess = pty.spawn(binaryPath, args, {
|
|
84
|
+
name: "xterm-256color",
|
|
85
|
+
cols: cols,
|
|
86
|
+
rows: rows,
|
|
87
|
+
cwd: process.cwd(),
|
|
88
|
+
env: env,
|
|
89
|
+
// Windows-specific options
|
|
90
|
+
...(isWindows && {
|
|
91
|
+
useConpty: true,
|
|
92
|
+
conptyInheritCursor: true,
|
|
93
|
+
}),
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// Handle output with branding replacement
|
|
97
|
+
ptyProcess.onData((data) => {
|
|
98
|
+
const replaced = replaceBranding(data)
|
|
99
|
+
process.stdout.write(replaced)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
// Handle input
|
|
103
|
+
if (process.stdin.isTTY) {
|
|
104
|
+
process.stdin.setRawMode(true)
|
|
105
|
+
}
|
|
106
|
+
process.stdin.resume()
|
|
107
|
+
process.stdin.on("data", (data) => {
|
|
108
|
+
ptyProcess.write(data.toString())
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
// Handle terminal resize
|
|
112
|
+
process.stdout.on("resize", () => {
|
|
113
|
+
ptyProcess.resize(
|
|
114
|
+
process.stdout.columns || 80,
|
|
115
|
+
process.stdout.rows || 24
|
|
116
|
+
)
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
// Handle exit
|
|
120
|
+
ptyProcess.onExit(({ exitCode }) => {
|
|
121
|
+
if (process.stdin.isTTY) {
|
|
122
|
+
process.stdin.setRawMode(false)
|
|
123
|
+
}
|
|
124
|
+
process.exit(exitCode)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// Handle signals
|
|
128
|
+
process.on("SIGINT", () => {
|
|
129
|
+
ptyProcess.kill("SIGINT")
|
|
130
|
+
})
|
|
131
|
+
process.on("SIGTERM", () => {
|
|
132
|
+
ptyProcess.kill("SIGTERM")
|
|
133
|
+
})
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Run with simple pipes (fallback mode, less interactive)
|
|
138
|
+
*/
|
|
139
|
+
function runWithPipes(binaryPath, args, env) {
|
|
140
|
+
const isWindows = os.platform() === "win32"
|
|
141
|
+
|
|
142
|
+
// Use spawn with pipe for stdout/stderr to intercept output
|
|
143
|
+
const child = childProcess.spawn(binaryPath, args, {
|
|
144
|
+
env: env,
|
|
145
|
+
cwd: process.cwd(),
|
|
146
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
147
|
+
// Windows needs shell for some binaries
|
|
148
|
+
...(isWindows && { shell: false }),
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
// Buffer for incomplete ANSI sequences
|
|
152
|
+
let stdoutBuffer = ""
|
|
153
|
+
let stderrBuffer = ""
|
|
154
|
+
|
|
155
|
+
// Process stdout
|
|
156
|
+
child.stdout.on("data", (data) => {
|
|
157
|
+
stdoutBuffer += data.toString()
|
|
158
|
+
// Process complete lines or flush on certain patterns
|
|
159
|
+
const replaced = replaceBranding(stdoutBuffer)
|
|
160
|
+
process.stdout.write(replaced)
|
|
161
|
+
stdoutBuffer = ""
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
// Process stderr
|
|
165
|
+
child.stderr.on("data", (data) => {
|
|
166
|
+
stderrBuffer += data.toString()
|
|
167
|
+
const replaced = replaceBranding(stderrBuffer)
|
|
168
|
+
process.stderr.write(replaced)
|
|
169
|
+
stderrBuffer = ""
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
// Forward stdin
|
|
173
|
+
process.stdin.pipe(child.stdin)
|
|
174
|
+
|
|
175
|
+
// Handle exit
|
|
176
|
+
child.on("exit", (code) => {
|
|
177
|
+
// Flush any remaining buffers
|
|
178
|
+
if (stdoutBuffer) {
|
|
179
|
+
process.stdout.write(replaceBranding(stdoutBuffer))
|
|
180
|
+
}
|
|
181
|
+
if (stderrBuffer) {
|
|
182
|
+
process.stderr.write(replaceBranding(stderrBuffer))
|
|
183
|
+
}
|
|
184
|
+
process.exit(code || 0)
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
child.on("error", (err) => {
|
|
188
|
+
console.error("Failed to start process:", err.message)
|
|
189
|
+
process.exit(1)
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
// Handle signals
|
|
193
|
+
process.on("SIGINT", () => {
|
|
194
|
+
child.kill("SIGINT")
|
|
195
|
+
})
|
|
196
|
+
process.on("SIGTERM", () => {
|
|
197
|
+
child.kill("SIGTERM")
|
|
198
|
+
})
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Run with inherited stdio (no branding replacement, but full interactivity)
|
|
203
|
+
* Used when PTY fails and pipes don't work well
|
|
204
|
+
*/
|
|
205
|
+
function runWithInherited(binaryPath, args, env) {
|
|
206
|
+
const result = childProcess.spawnSync(binaryPath, args, {
|
|
207
|
+
stdio: "inherit",
|
|
208
|
+
env: env,
|
|
209
|
+
cwd: process.cwd(),
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
if (result.error) {
|
|
213
|
+
console.error("Failed to start process:", result.error.message)
|
|
214
|
+
process.exit(1)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
process.exit(result.status || 0)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Main entry point
|
|
222
|
+
*/
|
|
223
|
+
function main() {
|
|
224
|
+
const args = process.argv.slice(2)
|
|
225
|
+
|
|
226
|
+
if (args.length === 0) {
|
|
227
|
+
console.error("Usage: pty-wrapper.js <binary> [args...]")
|
|
228
|
+
process.exit(1)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const binaryPath = args[0]
|
|
232
|
+
const binaryArgs = args.slice(1)
|
|
233
|
+
|
|
234
|
+
// Verify binary exists
|
|
235
|
+
if (!fs.existsSync(binaryPath)) {
|
|
236
|
+
console.error("Binary not found:", binaryPath)
|
|
237
|
+
process.exit(1)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Prepare environment
|
|
241
|
+
const env = { ...process.env }
|
|
242
|
+
|
|
243
|
+
// Check for fallback mode
|
|
244
|
+
const usePipes = process.env.RIRD_NO_PTY === "1"
|
|
245
|
+
const useInherited = process.env.RIRD_INHERITED === "1"
|
|
246
|
+
|
|
247
|
+
if (useInherited) {
|
|
248
|
+
// No branding replacement, full interactivity
|
|
249
|
+
runWithInherited(binaryPath, binaryArgs, env)
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (usePipes) {
|
|
254
|
+
// Simple pipes mode
|
|
255
|
+
runWithPipes(binaryPath, binaryArgs, env)
|
|
256
|
+
return
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Try PTY first
|
|
260
|
+
const pty = tryLoadPty()
|
|
261
|
+
|
|
262
|
+
if (pty && process.stdout.isTTY) {
|
|
263
|
+
try {
|
|
264
|
+
runWithPty(pty, binaryPath, binaryArgs, env)
|
|
265
|
+
return
|
|
266
|
+
} catch (err) {
|
|
267
|
+
// PTY failed, fall through to pipes
|
|
268
|
+
console.error("PTY initialization failed, falling back to pipes:", err.message)
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Fall back to pipes
|
|
273
|
+
runWithPipes(binaryPath, binaryArgs, env)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Export for testing
|
|
277
|
+
module.exports = {
|
|
278
|
+
replaceBranding,
|
|
279
|
+
REPLACEMENTS,
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Run if executed directly
|
|
283
|
+
if (require.main === module) {
|
|
284
|
+
main()
|
|
285
|
+
}
|
package/bunfig.toml
ADDED
|
Binary file
|
package/nul`nif
ADDED
|
File without changes
|