rird 2.1.231 → 2.3.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/AGENTS.md +86 -0
- package/COMPLETED_TEST_SUITE.txt +280 -0
- package/Dockerfile +18 -0
- package/README.md +397 -6
- package/RIRD_ERROR_HANDLING_SUMMARY.md +307 -0
- package/TESTING.md +512 -0
- package/TEST_IMPLEMENTATION_REPORT.md +463 -0
- package/TEST_SUITE.md +307 -0
- package/TEST_SUMMARY.txt +380 -0
- package/bin/rird-perf.js +37 -0
- package/bin/rird.js +43 -8
- package/bunfig.toml +4 -0
- package/create-wrapper.ps1 +51 -0
- package/docs/ARCHITECTURE.md +768 -0
- package/docs/CLI_REFERENCE.md +681 -0
- package/docs/DOCUMENTATION_MANIFEST.md +392 -0
- package/docs/INDEX.md +295 -0
- package/docs/PRODUCTION_SETUP.md +633 -0
- package/docs/TROUBLESHOOTING.md +914 -0
- package/facebook_ads_library.png +0 -0
- package/nul +0 -0
- package/nul`nif +0 -0
- package/package.json +104 -15
- package/parsers-config.ts +239 -0
- package/rird-1.0.199.tgz +0 -0
- package/rird-1.0.205.tgz +0 -0
- package/script/build-windows.ts +56 -0
- package/script/build.ts +165 -0
- package/{postinstall.mjs → script/postinstall.mjs} +47 -68
- package/script/publish-registries.ts +187 -0
- package/script/publish.ts +85 -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 +104 -0
- package/src/cli/cmd/activate.ts +50 -0
- package/src/cli/cmd/agent.ts +256 -0
- package/src/cli/cmd/auth.ts +412 -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 +68 -0
- package/src/cli/cmd/pr.ts +112 -0
- package/src/cli/cmd/run.ts +434 -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 +694 -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 +236 -0
- package/src/cli/cmd/tui/component/dialog-provider.tsx +240 -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 +48 -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 +1087 -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 +345 -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/hooks/use-safe-terminal-dimensions.ts +12 -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 +1876 -0
- package/src/cli/cmd/tui/routes/session/sidebar.tsx +320 -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 +333 -0
- package/src/cli/cmd/tui/ui/dialog.tsx +171 -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 +146 -0
- package/src/cli/cmd/tui/worker.ts +63 -0
- package/src/cli/cmd/uninstall.ts +344 -0
- package/src/cli/cmd/upgrade.ts +127 -0
- package/src/cli/cmd/web.ts +84 -0
- package/src/cli/error.ts +69 -0
- package/src/cli/ui.ts +101 -0
- package/src/cli/upgrade.ts +28 -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 +994 -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 +84 -0
- package/src/format/formatter.ts +315 -0
- package/src/format/index.ts +137 -0
- package/src/global/index.ts +101 -0
- package/src/id/id.ts +73 -0
- package/src/ide/index.ts +76 -0
- package/src/index.ts +297 -0
- package/src/index.ts.backup +271 -0
- package/src/installation/index.ts +258 -0
- package/src/lib/IMPLEMENTATION_NOTES.md +345 -0
- package/src/lib/error-handler.ts +225 -0
- package/src/lib/error-testing-guide.md +258 -0
- package/src/lib/errors.ts +285 -0
- package/src/lib/performance.ts +70 -0
- package/src/lib/telemetry.ts +282 -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 +1117 -0
- package/src/mcp/intent-analyzer.ts +376 -0
- package/src/mcp/oauth-callback.ts +200 -0
- package/src/mcp/oauth-provider.ts +154 -0
- package/src/patch/index.ts +632 -0
- package/src/permission/index.ts +199 -0
- package/src/plugin/index.ts +91 -0
- package/src/project/bootstrap.ts +33 -0
- package/src/project/instance.ts +78 -0
- package/src/project/project.ts +236 -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 +55 -0
- package/src/provider/models.ts +161 -0
- package/src/provider/provider.ts +1109 -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 +570 -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 +2641 -0
- package/src/server/tui.ts +71 -0
- package/src/session/compaction.ts +228 -0
- package/src/session/index.ts +464 -0
- package/src/session/llm.ts +201 -0
- package/src/session/message-v2.ts +695 -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 +63 -0
- package/src/session/prompt/anthropic_spoof.txt +1 -0
- package/src/session/prompt/beast.txt +76 -0
- package/src/session/prompt/codex.txt +304 -0
- package/src/session/prompt/copilot-gpt-5.txt +137 -0
- package/src/session/prompt/gemini.txt +62 -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 +88 -0
- package/src/session/prompt/qwen.txt +59 -0
- package/src/session/prompt.ts +1552 -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 +209 -0
- package/src/session/system.ts +122 -0
- package/src/session/todo.ts +37 -0
- package/src/share/share-next.ts +222 -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 +314 -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 +184 -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 +268 -0
- package/src/tool/websearch.txt +13 -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 +362 -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/cmd/acp.test.ts +144 -0
- package/test/cli/cmd/run.test.ts +250 -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 +536 -0
- package/test/config/markdown.test.ts +89 -0
- package/test/file/ignore.test.ts +10 -0
- package/test/fixture/fixture.ts +37 -0
- package/test/fixture/lsp/fake-lsp-server.js +77 -0
- package/test/helpers.ts +172 -0
- package/test/ide/ide.test.ts +82 -0
- package/test/installation/installation.test.ts +143 -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 +74 -0
- package/test/provider/provider.test.ts +74 -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 +940 -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/license.test.ts +235 -0
- package/test/util/timeout.test.ts +21 -0
- package/test/util/wildcard.test.ts +55 -0
- package/tsconfig.json +16 -0
- package/update-versions.ps1 +65 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Simple JSON-RPC 2.0 LSP-like fake server over stdio
|
|
2
|
+
// Implements a minimal LSP handshake and triggers a request upon notification
|
|
3
|
+
|
|
4
|
+
const net = require("net")
|
|
5
|
+
|
|
6
|
+
let nextId = 1
|
|
7
|
+
|
|
8
|
+
function encode(message) {
|
|
9
|
+
const json = JSON.stringify(message)
|
|
10
|
+
const header = `Content-Length: ${Buffer.byteLength(json, "utf8")}\r\n\r\n`
|
|
11
|
+
return Buffer.concat([Buffer.from(header, "utf8"), Buffer.from(json, "utf8")])
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function decodeFrames(buffer) {
|
|
15
|
+
const results = []
|
|
16
|
+
let idx
|
|
17
|
+
while ((idx = buffer.indexOf("\r\n\r\n")) !== -1) {
|
|
18
|
+
const header = buffer.slice(0, idx).toString("utf8")
|
|
19
|
+
const m = /Content-Length:\s*(\d+)/i.exec(header)
|
|
20
|
+
const len = m ? parseInt(m[1], 10) : 0
|
|
21
|
+
const bodyStart = idx + 4
|
|
22
|
+
const bodyEnd = bodyStart + len
|
|
23
|
+
if (buffer.length < bodyEnd) break
|
|
24
|
+
const body = buffer.slice(bodyStart, bodyEnd).toString("utf8")
|
|
25
|
+
results.push(body)
|
|
26
|
+
buffer = buffer.slice(bodyEnd)
|
|
27
|
+
}
|
|
28
|
+
return { messages: results, rest: buffer }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let readBuffer = Buffer.alloc(0)
|
|
32
|
+
|
|
33
|
+
process.stdin.on("data", (chunk) => {
|
|
34
|
+
readBuffer = Buffer.concat([readBuffer, chunk])
|
|
35
|
+
const { messages, rest } = decodeFrames(readBuffer)
|
|
36
|
+
readBuffer = rest
|
|
37
|
+
for (const m of messages) handle(m)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
function send(msg) {
|
|
41
|
+
process.stdout.write(encode(msg))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function sendRequest(method, params) {
|
|
45
|
+
const id = nextId++
|
|
46
|
+
send({ jsonrpc: "2.0", id, method, params })
|
|
47
|
+
return id
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function handle(raw) {
|
|
51
|
+
let data
|
|
52
|
+
try {
|
|
53
|
+
data = JSON.parse(raw)
|
|
54
|
+
} catch {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
if (data.method === "initialize") {
|
|
58
|
+
send({ jsonrpc: "2.0", id: data.id, result: { capabilities: {} } })
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
if (data.method === "initialized") {
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
if (data.method === "workspace/didChangeConfiguration") {
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
if (data.method === "test/trigger") {
|
|
68
|
+
const method = data.params && data.params.method
|
|
69
|
+
if (method) sendRequest(method, {})
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
if (typeof data.id !== "undefined") {
|
|
73
|
+
// Respond OK to any request from client to keep transport flowing
|
|
74
|
+
send({ jsonrpc: "2.0", id: data.id, result: null })
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
}
|
package/test/helpers.ts
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { test, expect } from "bun:test"
|
|
2
|
+
import type { Server } from "bun"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Test helper utilities for RIRD CLI tests
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface MockProvider {
|
|
9
|
+
name: string
|
|
10
|
+
apiKey: string
|
|
11
|
+
enabled: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Create a mock provider for testing
|
|
16
|
+
*/
|
|
17
|
+
export function createMockProvider(
|
|
18
|
+
name: string = "test-provider",
|
|
19
|
+
apiKey: string = "test-api-key",
|
|
20
|
+
enabled: boolean = true
|
|
21
|
+
): MockProvider {
|
|
22
|
+
return {
|
|
23
|
+
name,
|
|
24
|
+
apiKey,
|
|
25
|
+
enabled,
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface MockLicense {
|
|
30
|
+
key: string
|
|
31
|
+
valid: boolean
|
|
32
|
+
email: string
|
|
33
|
+
plan: string
|
|
34
|
+
expiresAt: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Create a mock license for testing
|
|
39
|
+
*/
|
|
40
|
+
export function createMockLicense(
|
|
41
|
+
key: string = "test-license-key",
|
|
42
|
+
email: string = "test@example.com",
|
|
43
|
+
plan: string = "pro"
|
|
44
|
+
): MockLicense {
|
|
45
|
+
return {
|
|
46
|
+
key,
|
|
47
|
+
valid: true,
|
|
48
|
+
email,
|
|
49
|
+
plan,
|
|
50
|
+
expiresAt: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString(),
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Mock HTTP server for testing API calls
|
|
56
|
+
*/
|
|
57
|
+
export async function mockHttpServer(
|
|
58
|
+
responses: Record<string, any | ((req: Request) => Promise<Response>)> = {}
|
|
59
|
+
): Promise<{ server: ReturnType<typeof Bun.serve>; port: number; close: () => void }> {
|
|
60
|
+
const server = Bun.serve({
|
|
61
|
+
hostname: "127.0.0.1",
|
|
62
|
+
port: 0,
|
|
63
|
+
async fetch(req) {
|
|
64
|
+
const url = new URL(req.url)
|
|
65
|
+
const path = url.pathname
|
|
66
|
+
|
|
67
|
+
// Default response mapping
|
|
68
|
+
if (responses[path]) {
|
|
69
|
+
const response = responses[path]
|
|
70
|
+
if (typeof response === "function") {
|
|
71
|
+
return await response(req)
|
|
72
|
+
}
|
|
73
|
+
return new Response(JSON.stringify(response), {
|
|
74
|
+
headers: { "Content-Type": "application/json" },
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Default 404
|
|
79
|
+
return new Response(JSON.stringify({ error: "Not found" }), {
|
|
80
|
+
status: 404,
|
|
81
|
+
headers: { "Content-Type": "application/json" },
|
|
82
|
+
})
|
|
83
|
+
},
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
server,
|
|
88
|
+
port: server.port ?? 0,
|
|
89
|
+
close: () => {
|
|
90
|
+
server.stop()
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Create a test environment with temporary config
|
|
97
|
+
*/
|
|
98
|
+
export async function createTestConfig() {
|
|
99
|
+
const tmpDir = await Bun.file(
|
|
100
|
+
`${Bun.env.TMPDIR || "/tmp"}/rird-test-${Date.now()}`
|
|
101
|
+
).exists()
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
configDir: `${Bun.env.TMPDIR || "/tmp"}/rird-test-${Date.now()}`,
|
|
105
|
+
configFile: `${Bun.env.TMPDIR || "/tmp"}/rird-test-${Date.now()}/config.json`,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Wait for async operations to complete with timeout
|
|
111
|
+
*/
|
|
112
|
+
export async function waitFor(
|
|
113
|
+
fn: () => boolean | Promise<boolean>,
|
|
114
|
+
timeout: number = 5000,
|
|
115
|
+
interval: number = 100
|
|
116
|
+
): Promise<void> {
|
|
117
|
+
const startTime = Date.now()
|
|
118
|
+
while (Date.now() - startTime < timeout) {
|
|
119
|
+
try {
|
|
120
|
+
const result = await fn()
|
|
121
|
+
if (result) {
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
} catch (e) {
|
|
125
|
+
// Continue waiting
|
|
126
|
+
}
|
|
127
|
+
await new Promise((resolve) => setTimeout(resolve, interval))
|
|
128
|
+
}
|
|
129
|
+
throw new Error(`Timeout waiting for condition after ${timeout}ms`)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Mock environment variables
|
|
134
|
+
*/
|
|
135
|
+
export function mockEnv(vars: Record<string, string>): () => void {
|
|
136
|
+
const original = { ...process.env }
|
|
137
|
+
Object.assign(process.env, vars)
|
|
138
|
+
|
|
139
|
+
return () => {
|
|
140
|
+
// Restore original env
|
|
141
|
+
Object.keys(process.env).forEach((key) => {
|
|
142
|
+
if (!(key in original)) {
|
|
143
|
+
delete process.env[key]
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
Object.assign(process.env, original)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Create a temporary file for testing
|
|
152
|
+
*/
|
|
153
|
+
export async function createTmpFile(content: string, name: string = "test"): Promise<string> {
|
|
154
|
+
const tmpDir = Bun.env.TMPDIR || "/tmp"
|
|
155
|
+
const filePath = `${tmpDir}/rird-${name}-${Date.now()}`
|
|
156
|
+
await Bun.write(filePath, content)
|
|
157
|
+
return filePath
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Clean up temporary files
|
|
162
|
+
*/
|
|
163
|
+
export async function cleanupTmpFile(filePath: string): Promise<void> {
|
|
164
|
+
try {
|
|
165
|
+
const file = Bun.file(filePath)
|
|
166
|
+
if (await file.exists()) {
|
|
167
|
+
await Bun.file(filePath).delete?.()
|
|
168
|
+
}
|
|
169
|
+
} catch {
|
|
170
|
+
// Ignore cleanup errors
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, expect, test, afterEach } from "bun:test"
|
|
2
|
+
import { Ide } from "../../src/ide"
|
|
3
|
+
|
|
4
|
+
describe("ide", () => {
|
|
5
|
+
const original = { ...process.env }
|
|
6
|
+
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
Object.keys(process.env).forEach((key) => {
|
|
9
|
+
delete process.env[key]
|
|
10
|
+
})
|
|
11
|
+
Object.assign(process.env, original)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test("should detect Visual Studio Code", () => {
|
|
15
|
+
process.env["TERM_PROGRAM"] = "vscode"
|
|
16
|
+
process.env["GIT_ASKPASS"] = "/path/to/Visual Studio Code.app/Contents/Resources/app/extensions/git/dist/askpass.sh"
|
|
17
|
+
|
|
18
|
+
expect(Ide.ide()).toBe("Visual Studio Code")
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test("should detect Visual Studio Code Insiders", () => {
|
|
22
|
+
process.env["TERM_PROGRAM"] = "vscode"
|
|
23
|
+
process.env["GIT_ASKPASS"] =
|
|
24
|
+
"/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/extensions/git/dist/askpass.sh"
|
|
25
|
+
|
|
26
|
+
expect(Ide.ide()).toBe("Visual Studio Code - Insiders")
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test("should detect Cursor", () => {
|
|
30
|
+
process.env["TERM_PROGRAM"] = "vscode"
|
|
31
|
+
process.env["GIT_ASKPASS"] = "/path/to/Cursor.app/Contents/Resources/app/extensions/git/dist/askpass.sh"
|
|
32
|
+
|
|
33
|
+
expect(Ide.ide()).toBe("Cursor")
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test("should detect VSCodium", () => {
|
|
37
|
+
process.env["TERM_PROGRAM"] = "vscode"
|
|
38
|
+
process.env["GIT_ASKPASS"] = "/path/to/VSCodium.app/Contents/Resources/app/extensions/git/dist/askpass.sh"
|
|
39
|
+
|
|
40
|
+
expect(Ide.ide()).toBe("VSCodium")
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test("should detect Windsurf", () => {
|
|
44
|
+
process.env["TERM_PROGRAM"] = "vscode"
|
|
45
|
+
process.env["GIT_ASKPASS"] = "/path/to/Windsurf.app/Contents/Resources/app/extensions/git/dist/askpass.sh"
|
|
46
|
+
|
|
47
|
+
expect(Ide.ide()).toBe("Windsurf")
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test("should return unknown when TERM_PROGRAM is not vscode", () => {
|
|
51
|
+
process.env["TERM_PROGRAM"] = "iTerm2"
|
|
52
|
+
process.env["GIT_ASKPASS"] =
|
|
53
|
+
"/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/extensions/git/dist/askpass.sh"
|
|
54
|
+
|
|
55
|
+
expect(Ide.ide()).toBe("unknown")
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test("should return unknown when GIT_ASKPASS does not contain IDE name", () => {
|
|
59
|
+
process.env["TERM_PROGRAM"] = "vscode"
|
|
60
|
+
process.env["GIT_ASKPASS"] = "/path/to/unknown/askpass.sh"
|
|
61
|
+
|
|
62
|
+
expect(Ide.ide()).toBe("unknown")
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test("should recognize vscode-insiders OPENCODE_CALLER", () => {
|
|
66
|
+
process.env["OPENCODE_CALLER"] = "vscode-insiders"
|
|
67
|
+
|
|
68
|
+
expect(Ide.alreadyInstalled()).toBe(true)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test("should recognize vscode OPENCODE_CALLER", () => {
|
|
72
|
+
process.env["OPENCODE_CALLER"] = "vscode"
|
|
73
|
+
|
|
74
|
+
expect(Ide.alreadyInstalled()).toBe(true)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test("should return false for unknown OPENCODE_CALLER", () => {
|
|
78
|
+
process.env["OPENCODE_CALLER"] = "unknown"
|
|
79
|
+
|
|
80
|
+
expect(Ide.alreadyInstalled()).toBe(false)
|
|
81
|
+
})
|
|
82
|
+
})
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { test, expect, describe, beforeEach } from "bun:test"
|
|
2
|
+
import { Installation } from "../../src/installation"
|
|
3
|
+
|
|
4
|
+
describe("Installation", () => {
|
|
5
|
+
test("should have VERSION constant defined", () => {
|
|
6
|
+
expect(Installation.VERSION).toBeDefined()
|
|
7
|
+
expect(typeof Installation.VERSION).toBe("string")
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test("should have CHANNEL constant defined", () => {
|
|
11
|
+
expect(Installation.CHANNEL).toBeDefined()
|
|
12
|
+
expect(typeof Installation.CHANNEL).toBe("string")
|
|
13
|
+
// CHANNEL should be one of: local, latest, or a preview channel
|
|
14
|
+
expect(["local", "latest", "preview", "alpha", "beta"]).toContain(
|
|
15
|
+
Installation.CHANNEL.split("-")[0]
|
|
16
|
+
)
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test("should have USER_AGENT with proper format", () => {
|
|
20
|
+
expect(Installation.USER_AGENT).toBeDefined()
|
|
21
|
+
expect(Installation.USER_AGENT).toContain("rird")
|
|
22
|
+
expect(Installation.USER_AGENT).toContain(Installation.CHANNEL)
|
|
23
|
+
expect(Installation.USER_AGENT).toContain(Installation.VERSION)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test("isLocal() should return true for local installations", async () => {
|
|
27
|
+
const isLocal = Installation.isLocal()
|
|
28
|
+
expect(typeof isLocal).toBe("boolean")
|
|
29
|
+
// In test environment, it will be true
|
|
30
|
+
if (Installation.CHANNEL === "local") {
|
|
31
|
+
expect(isLocal).toBe(true)
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test("isPreview() should return true for preview channels", () => {
|
|
36
|
+
const isPreview = Installation.isPreview()
|
|
37
|
+
expect(typeof isPreview).toBe("boolean")
|
|
38
|
+
|
|
39
|
+
if (Installation.CHANNEL !== "latest") {
|
|
40
|
+
expect(isPreview).toBe(true)
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test("should have method() function", async () => {
|
|
45
|
+
expect(Installation.method).toBeDefined()
|
|
46
|
+
expect(typeof Installation.method).toBe("function")
|
|
47
|
+
|
|
48
|
+
const method = await Installation.method()
|
|
49
|
+
expect(typeof method).toBe("string")
|
|
50
|
+
expect(["npm", "yarn", "pnpm", "bun", "brew", "curl", "unknown"]).toContain(method)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test("should have latest() function", async () => {
|
|
54
|
+
expect(Installation.latest).toBeDefined()
|
|
55
|
+
expect(typeof Installation.latest).toBe("function")
|
|
56
|
+
|
|
57
|
+
// Note: This will try to fetch from npm, so it might fail in CI
|
|
58
|
+
// but we just verify the function exists and returns a promise
|
|
59
|
+
const result = Installation.latest()
|
|
60
|
+
expect(result).toBeInstanceOf(Promise)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test("should have upgrade() function", async () => {
|
|
64
|
+
expect(Installation.upgrade).toBeDefined()
|
|
65
|
+
expect(typeof Installation.upgrade).toBe("function")
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test("should have forceReinstall() function", async () => {
|
|
69
|
+
expect(Installation.forceReinstall).toBeDefined()
|
|
70
|
+
expect(typeof Installation.forceReinstall).toBe("function")
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test("should have info() function", async () => {
|
|
74
|
+
expect(Installation.info).toBeDefined()
|
|
75
|
+
expect(typeof Installation.info).toBe("function")
|
|
76
|
+
|
|
77
|
+
const info = await Installation.info()
|
|
78
|
+
expect(info).toBeDefined()
|
|
79
|
+
expect(info.version).toBeDefined()
|
|
80
|
+
expect(info.latest).toBeDefined()
|
|
81
|
+
expect(typeof info.version).toBe("string")
|
|
82
|
+
expect(typeof info.latest).toBe("string")
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test("should have Event definitions", () => {
|
|
86
|
+
expect(Installation.Event).toBeDefined()
|
|
87
|
+
expect(Installation.Event.Updated).toBeDefined()
|
|
88
|
+
expect(Installation.Event.UpdateAvailable).toBeDefined()
|
|
89
|
+
expect(Installation.Event.UpdateFailed).toBeDefined()
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test("info() should return valid installation info", async () => {
|
|
93
|
+
const info = await Installation.info()
|
|
94
|
+
expect(info.version).toMatch(/^\d+\.\d+\.\d+$|local/)
|
|
95
|
+
// latest version should also be valid format or empty
|
|
96
|
+
expect(info.latest).toBeDefined()
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test("method() should detect npm if running in npm context", async () => {
|
|
100
|
+
const method = await Installation.method()
|
|
101
|
+
// Should be a valid method name
|
|
102
|
+
expect(["npm", "yarn", "pnpm", "bun", "brew", "curl", "unknown"]).toContain(method)
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
test("VERSION should be valid semver or 'local'", () => {
|
|
106
|
+
const version = Installation.VERSION
|
|
107
|
+
// Either local or valid semver
|
|
108
|
+
if (version !== "local") {
|
|
109
|
+
expect(version).toMatch(/^\d+\.\d+\.\d+/)
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
test("UpgradeFailedError should be defined", () => {
|
|
114
|
+
expect(Installation.UpgradeFailedError).toBeDefined()
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
test("should have Info schema type", () => {
|
|
118
|
+
expect(Installation.Info).toBeDefined()
|
|
119
|
+
// Zod schema should be callable
|
|
120
|
+
expect(typeof Installation.Info.parse).toBe("function")
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test("Info schema should validate correct data", () => {
|
|
124
|
+
const validInfo = {
|
|
125
|
+
version: "1.0.0",
|
|
126
|
+
latest: "1.1.0",
|
|
127
|
+
}
|
|
128
|
+
const result = Installation.Info.parse(validInfo)
|
|
129
|
+
expect(result.version).toBe("1.0.0")
|
|
130
|
+
expect(result.latest).toBe("1.1.0")
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
test("Info schema should reject invalid data", () => {
|
|
134
|
+
const invalidInfo = {
|
|
135
|
+
version: 123, // Should be string
|
|
136
|
+
latest: "1.1.0",
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
expect(() => {
|
|
140
|
+
Installation.Info.parse(invalidInfo)
|
|
141
|
+
}).toThrow()
|
|
142
|
+
})
|
|
143
|
+
})
|