{"_id":"@dhf-qwen/grix","_rev":"24-581f8a29ac0c7c5b91a36f0d3e0afadb","name":"@dhf-qwen/grix","dist-tags":{"latest":"0.2.4"},"versions":{"0.2.0":{"name":"@dhf-qwen/grix","version":"0.2.0","_id":"@dhf-qwen/grix@0.2.0","maintainers":[{"name":"askie","email":"askie@qq.com"}],"bin":{"grix-qwen":"dist/cli.js"},"dist":{"shasum":"5171a4fa904f5194bea5b7031ff84aa03c9db9d8","tarball":"https://registry.npmjs.org/@dhf-qwen/grix/-/grix-0.2.0.tgz","fileCount":47,"integrity":"sha512-iXA86XduaRV+cRcp67U/HDgMm11mg2WeotM+ffVjQZ4tPdmI0BOjcN2Y+vRgagDLccXWoyTpFcpw+COYtW2GQg==","signatures":[{"sig":"MEYCIQDs8BO8dQc9s0IoculV5rkq3R5xVB17g0w756mGCVVOkAIhALlL3MtE4rmuWwzskeJoFc+8TW9m7WmUSPWtcZEPwDOk","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":327396},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","gitHead":"5b7735a79afb3e1ac99406a78b31d34b57931705","scripts":{"dev":"npm run build && node dist/cli.js agent --profile dev","prod":"npm run build && node dist/cli.js stop --profile prod && node dist/cli.js start --profile prod","test":"npm run build && node --test test/qwen-manager.test.js test/integration.test.js test/run-profile.test.js","build":"tsc -p tsconfig.json","prepare":"echo 'skip: pre-built dist shipped'","test:e2e":"npm run build && node test/e2e-agent.test.js","test:auth":"npm run build && node test/auth-flow.test.js","typecheck":"tsc -p tsconfig.json --noEmit","build:dist":"npm run build && chmod +x dist/cli.js && node scripts/obfuscate.mjs","publish:npm":"bash ./publish.sh","publish:npm:preview":"bash ./publish.sh","publish:npm:release":"bash ./publish.sh --publish","test:session-restore":"npm run build && GRIX_QWEN_E2E_KEEP_TMP=1 node test/session-restore.test.js"},"_npmUser":{"name":"askie","email":"askie@qq.com"},"_npmVersion":"11.11.0","description":"Qwen channel plugin for Grix AIBot","directories":{},"_nodeVersion":"25.8.0","dependencies":{"ws":"^8.18.3","@qwen-code/channel-base":"^0.14.3","@agentclientprotocol/sdk":"^0.14.1"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"@types/ws":"^8.18.1","typescript":"^5.8.3","@types/node":"^22.14.0","javascript-obfuscator":"^5.4.1"},"_npmOperationalInternal":{"tmp":"tmp/grix_0.2.0_1776598321274_0.16474377618241398","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@dhf-qwen/grix","version":"0.2.1","_id":"@dhf-qwen/grix@0.2.1","maintainers":[{"name":"askie","email":"askie@qq.com"}],"bin":{"grix-qwen":"dist/cli.js"},"dist":{"shasum":"e2630874248162b4602d1ac262aaadbc4c1d74f4","tarball":"https://registry.npmjs.org/@dhf-qwen/grix/-/grix-0.2.1.tgz","fileCount":47,"integrity":"sha512-VBLP/pqIVV9ILP1sVmZImDSxl5Z8MgUltGyUHorw1z6Fe6swSZZ5j4OaHTGlUpRBaXfp3A3V/uTprdM+z/HynA==","signatures":[{"sig":"MEQCIDRaZamKAXT98LiM8soJbSQtlSnzmoxFgOqFXRvsB5o7AiACV83WG1ZERiWTkYtnUHhtitZD3SP7tCcMJRcIm2LLqg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":443195},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","gitHead":"4ec22d956771879a559a34f92225c52cb410cf81","scripts":{"dev":"npm run build && node dist/cli.js agent --profile dev","prod":"npm run build && node dist/cli.js stop --profile prod && node dist/cli.js start --profile prod","test":"npm run build && node --test test/qwen-manager.test.js test/integration.test.js test/run-profile.test.js","build":"tsc -p tsconfig.json && node -e \"const fs=require('fs');const p='dist/shared/file-listing';if(!fs.existsSync(p)){fs.mkdirSync('dist/shared',{recursive:true});fs.symlinkSync(require('path').resolve('src/shared/file-listing'),p)}\"","prepare":"echo 'skip: pre-built dist shipped'","test:e2e":"npm run build && node test/e2e-agent.test.js","test:auth":"npm run build && node test/auth-flow.test.js","typecheck":"tsc -p tsconfig.json --noEmit","build:dist":"npm run build && chmod +x dist/cli.js && node scripts/obfuscate.mjs","publish:npm":"bash ./publish.sh","publish:npm:preview":"bash ./publish.sh","publish:npm:release":"bash ./publish.sh --publish","test:session-restore":"npm run build && GRIX_QWEN_E2E_KEEP_TMP=1 node test/session-restore.test.js"},"_npmUser":{"name":"askie","email":"askie@qq.com"},"_npmVersion":"11.11.0","description":"Qwen channel plugin for Grix AIBot","directories":{},"_nodeVersion":"25.8.0","dependencies":{"ws":"^8.18.3","@qwen-code/channel-base":"^0.14.3","@agentclientprotocol/sdk":"^0.14.1"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"@types/ws":"^8.18.1","typescript":"^5.8.3","@types/node":"^22.14.0","javascript-obfuscator":"^5.4.1"},"_npmOperationalInternal":{"tmp":"tmp/grix_0.2.1_1776689144861_0.3652562812112141","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@dhf-qwen/grix","version":"0.2.2","_id":"@dhf-qwen/grix@0.2.2","maintainers":[{"name":"askie","email":"askie@qq.com"}],"bin":{"grix-qwen":"dist/cli.js"},"dist":{"shasum":"0e6c5509609f1e33645d8938fa6ec1585c12a7b6","tarball":"https://registry.npmjs.org/@dhf-qwen/grix/-/grix-0.2.2.tgz","fileCount":67,"integrity":"sha512-eyZwSzV6L7tNP3yiv61X/1C829BkU6qd9jwVHOiGGGwButyYwBtMyZlTIodRrDrbNDpVnsKU2uP3SIX2hebVPA==","signatures":[{"sig":"MEUCIQDglimeuzq+sF+CX98E3XDOS5zBmg5DiK9ZJ+y4qWp5KAIgIvRXhYKrMq6xXT33KTJMPBtIe45VaHeFl/F0aGCLSbA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":368199},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","gitHead":"69e72d34ff856793b3a0b4e95abfbea005b3b508","scripts":{"dev":"npm run build && node dist/cli.js agent --profile dev","prod":"npm run build && node dist/cli.js stop --profile prod && node dist/cli.js start --profile prod","test":"npm run build && node --test test/qwen-manager.test.js test/integration.test.js test/run-profile.test.js test/log-rotation.test.js","build":"tsc -p tsconfig.json && node -e \"const fs=require('fs');const p='dist/shared/file-listing';if(!fs.existsSync(p)){fs.mkdirSync('dist/shared',{recursive:true});fs.symlinkSync(require('path').resolve('src/shared/file-listing'),p)}\"","prepare":"echo 'skip: pre-built dist shipped'","test:e2e":"npm run build && node test/e2e-agent.test.js","test:auth":"npm run build && node test/auth-flow.test.js","typecheck":"tsc -p tsconfig.json --noEmit","build:dist":"npm run build && chmod +x dist/cli.js && node scripts/obfuscate.mjs","publish:npm":"bash ./publish.sh","publish:npm:preview":"bash ./publish.sh","publish:npm:release":"bash ./publish.sh --publish","test:session-restore":"npm run build && GRIX_QWEN_E2E_KEEP_TMP=1 node test/session-restore.test.js"},"_npmUser":{"name":"askie","email":"askie@qq.com"},"_npmVersion":"11.9.0","description":"Qwen channel plugin for Grix AIBot","directories":{},"_nodeVersion":"24.14.0","dependencies":{"ws":"^8.18.3","@qwen-code/channel-base":"^0.14.3","@agentclientprotocol/sdk":"^0.14.1"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"@types/ws":"^8.18.1","typescript":"^5.8.3","@types/node":"^22.14.0","javascript-obfuscator":"^5.4.1"},"_npmOperationalInternal":{"tmp":"tmp/grix_0.2.2_1777636802048_0.6696694725842873","host":"s3://npm-registry-packages-npm-production"}},"0.2.4":{"name":"@dhf-qwen/grix","version":"0.2.4","description":"Qwen channel plugin for Grix AIBot","type":"module","main":"dist/index.js","types":"dist/index.d.ts","bin":{"grix-qwen":"dist/cli.js"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"scripts":{"prepare":"echo 'skip: pre-built dist shipped'","build":"tsc -p tsconfig.json && node -e \"const fs=require('fs');const p='dist/shared/file-listing';if(!fs.existsSync(p)){fs.mkdirSync('dist/shared',{recursive:true});fs.symlinkSync(require('path').resolve('src/shared/file-listing'),p)}\"","build:dist":"npm run build && chmod +x dist/cli.js && node scripts/obfuscate.mjs","dev":"npm run build && node dist/cli.js agent --profile dev","prod":"npm run build && node dist/cli.js stop --profile prod && node dist/cli.js start --profile prod","publish:npm":"bash ./publish.sh","publish:npm:preview":"bash ./publish.sh","publish:npm:release":"bash ./publish.sh --publish","typecheck":"tsc -p tsconfig.json --noEmit","test":"npm run build && node --test test/qwen-manager.test.js test/integration.test.js test/run-profile.test.js test/log-rotation.test.js","test:e2e":"npm run build && node test/e2e-agent.test.js","test:session-restore":"npm run build && GRIX_QWEN_E2E_KEEP_TMP=1 node test/session-restore.test.js","test:auth":"npm run build && node test/auth-flow.test.js"},"dependencies":{"@agentclientprotocol/sdk":"^0.14.1","@qwen-code/channel-base":"^0.14.3","ws":"^8.18.3"},"devDependencies":{"@types/node":"^22.14.0","@types/ws":"^8.18.1","javascript-obfuscator":"^5.4.1","typescript":"^5.8.3"},"gitHead":"2f67ca2ea35ffd297a2a40fe83bcfbde1025a9c3","_id":"@dhf-qwen/grix@0.2.4","_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-Ly0JWWDmLStYANihu8xP3k8mo0ppO01JLy2idO8bonoFG+8BK+K45Om/I3VDycTnkgbZaGqIA9++9lZMR346fg==","shasum":"5b9b513a6065d54d3c5807a5ac1a38d70fb29386","tarball":"https://registry.npmjs.org/@dhf-qwen/grix/-/grix-0.2.4.tgz","fileCount":73,"unpackedSize":2567602,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCWr0txpi5DuArL7/Neb5hkkdUAEt0tg4iSRqfyyCGCBAIgKCHZ0Hfv+cXvuq1ROR2ZYrLjBp8Lnc8BN08PKfXafaw="}]},"_npmUser":{"name":"askie","email":"askie@qq.com"},"directories":{},"maintainers":[{"name":"askie","email":"askie@qq.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/grix_0.2.4_1778121923989_0.5586323282484527"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-13T05:12:59.496Z","modified":"2026-05-07T02:45:24.380Z","0.1.1":"2026-04-13T05:12:59.757Z","0.1.2":"2026-04-15T08:41:23.723Z","0.1.3":"2026-04-15T15:38:14.260Z","0.1.4":"2026-04-16T00:11:33.906Z","0.1.6":"2026-04-16T00:26:20.540Z","0.1.7":"2026-04-16T22:13:42.539Z","0.1.8":"2026-04-17T00:10:22.896Z","0.1.9":"2026-04-17T06:49:28.452Z","0.1.10":"2026-04-18T13:52:25.556Z","0.1.11":"2026-04-19T11:23:09.361Z","0.2.0":"2026-04-19T11:32:01.481Z","0.2.1":"2026-04-20T12:45:45.039Z","0.2.2":"2026-05-01T12:00:02.335Z","0.2.4":"2026-05-07T02:45:24.254Z"},"description":"Qwen channel plugin for Grix AIBot","maintainers":[{"name":"askie","email":"askie@qq.com"}],"readme":"# @dhf-qwen/grix\n\nConnect your local Qwen Code to [Grix](https://grix.dhf.pub).\n\nAfter installation, you can chat with this Qwen agent directly in Grix and let it work inside the project directory bound to the current session.\n\n## What You Need First\n\nPrepare these four things before you start:\n\n1. A Grix account\n2. A `Qwen` type agent already created in Grix\n3. The `Agent ID`, `Endpoint`, and `API Key` copied from the Grix page\n4. Qwen Code already installed on your local machine\n\nThe shortest path to get the Grix parameters:\n\n1. Open [https://grix.dhf.pub](https://grix.dhf.pub)\n2. Sign up and log in\n3. Create a new agent\n4. Choose `Agent API`\n5. Select `Qwen` as the integration type\n6. Copy the `Agent ID`, `Endpoint`, and `API Key` shown on the page\n\nKeep these three points in mind:\n\n- Use the `Endpoint` exactly as provided by Grix. Do not guess or rewrite it.\n- `--workspace` is the default local directory and runtime base directory.\n- The first time you enter a new session, Grix will ask you to submit the working directory for that session. Qwen will then prefer that directory for the rest of the session.\n\n## Install\n\n```bash\nnpm install -g @qwen-code/qwen-code @dhf-qwen/grix\n```\n\n## Start\n\n```bash\ngrix-qwen start \\\n  --agent-id <Agent ID> \\\n  --endpoint <Service Endpoint> \\\n  --api-key <Secret Key> \\\n  --workspace /path/to/your/project\n```\n\nOn the first start, the local integration config is set up automatically. You do not need to edit any config files manually.\n\n## Use It in Grix\n\n1. Open [https://grix.dhf.pub](https://grix.dhf.pub)\n2. Find the Qwen agent you just created\n3. Send it messages like a normal chat\n4. The first time you enter a new session, submit the working directory for that session\n5. Keep `grix-qwen start` running locally. It will work in that directory and send the results back to Grix\n\n## Other Commands\n\nRun in the foreground:\n\n```bash\ngrix-qwen agent \\\n  --agent-id <Agent ID> \\\n  --endpoint <Service Endpoint> \\\n  --api-key <Secret Key> \\\n  --workspace /path/to/your/project\n```\n\nCheck status:\n\n```bash\ngrix-qwen status\n```\n\nStop:\n\n```bash\ngrix-qwen stop\n```\n\nIf you only want to write the config first and not start it yet:\n\n```bash\ngrix-qwen install \\\n  --agent-id <Agent ID> \\\n  --endpoint <Service Endpoint> \\\n  --api-key <Secret Key> \\\n  --workspace /path/to/your/project\n```\n\n## Logs\n\nRuntime logs are written under `~/.grix-qwen/` by default. Service stdout/stderr and per-session `conversation.jsonl` logs are rotated automatically.\n\n| Variable | Default | Purpose |\n|----------|---------|---------|\n| `GRIX_QWEN_LOG_MAX_BYTES` | `10485760` | Maximum bytes per active log file |\n| `GRIX_QWEN_LOG_MAX_FILES` | `5` | Number of log files to keep, including rotated history |\n\n## Testing\n\n### Unit & Integration Tests\n\n```bash\nnpm test\n```\n\n### E2E Tests\n\nE2E tests launch a real Qwen Code subprocess, drive it through a mock WebSocket server, and verify full round-trip behavior. **`qwen` must be installed and logged in** before running.\n\n#### Prerequisites\n\n```bash\n# Verify qwen is available\nqwen channel --help\n```\n\n#### Run All E2E Scenarios\n\n```bash\nnpm run test:e2e\n```\n\nOr use the wrapper script (also runs `npm install`):\n\n```bash\n./scripts/check_qwen_plugin_e2e.sh\n```\n\n#### Run a Specific Scenario\n\n```bash\nGRIX_QWEN_E2E_SCENARIO=file-read-write npm run test:e2e\n```\n\nAvailable scenarios:\n\n| Scenario | What it tests |\n|----------|---------------|\n| `roundtrip` | Send a prompt, receive a reply with the expected marker |\n| `approval` | Qwen executes a shell command that triggers a permission approval |\n| `developer-flow` | Qwen fixes a broken Node.js project so `npm test` passes |\n| `stop` | Cancel a running prompt mid-stream |\n| `file-read-write` | Qwen writes a new file and reads an existing file in a temp workspace |\n\n#### Inspect Artifacts\n\nBy default, temp directories are cleaned up after each scenario. Preserve them for debugging:\n\n```bash\nGRIX_QWEN_E2E_KEEP_TMP=1 \\\nGRIX_QWEN_E2E_SCENARIO=file-read-write \\\nnpm run test:e2e\n```\n\nThe kept directory path is printed to stderr, e.g.:\n\n```\n[grix-qwen e2e] kept artifacts at /tmp/grix-qwen-e2e.XXXXXX\n```\n\nInside that directory:\n\n| File | Content |\n|------|---------|\n| `file-read-write-events.log` | JSONL log of all `send_msg`, `local_action`, `local_action_result`, `event_result` packets |\n| `file-read-write-summary.json` | Full summary with `checklist` field showing pass/fail for each assertion |\n| `packets.json` | All captured WebSocket packets |\n| `timeline.jsonl` | Timestamped packet timeline |\n| `plugin.stdout.log` / `plugin.stderr.log` | Agent process output |\n| `workspace/` | The temp workspace — `result.txt` (Qwen wrote), `notes.txt` (pre-existing), `AGENTS.md` |\n\n### 统一出站端到端测试\n\n统一出站 E2E 测试代码在 AIBot 后端仓库中。测试会启动本适配器作为真实子进程，连接到真实后端，通过后端发送消息，验证 Qwen 的回复能完整走通协议链路返回。\n\n**前置条件：**\n- AIBot 后端已启动（在后端仓库执行 `make dev-up`）\n- Qwen CLI 已安装且已认证\n- 本仓库已构建（`npm run build`）\n\n**运行：**\n```bash\ncd <aibot-backend-repo>\n\nGRIX_ADAPTER_E2E=1 \\\nGRIX_ADAPTER_QWEN_AGENT_ID=<agent-id> \\\nGRIX_ADAPTER_QWEN_API_KEY=<api-key> \\\nGRIX_ADAPTER_E2E_USER_ACCOUNT=<account> \\\nGRIX_ADAPTER_E2E_USER_PASSWORD=<password> \\\ngo test ./e2e/ -run TestLiveAdapterQwenRoundtrip -v -timeout 10m\n```\n\n测试流程：启动 `node dist/cli.js agent --endpoint <url> --agent-id <id> --api-key <key>`，等待适配器上线，打开会话，发送带 marker 的消息，验证 Qwen 的回复包含 marker。\n\n#### Environment Variables\n\n| Variable | Default | Purpose |\n|----------|---------|---------|\n| `GRIX_QWEN_E2E_QWEN_COMMAND` | `qwen` | Path to the Qwen CLI binary |\n| `GRIX_QWEN_E2E_SCENARIO` | `all` | Comma-separated scenario names, or `all` |\n| `GRIX_QWEN_E2E_TIMEOUT_MS` | `120000` | Default timeout per assertion (ms) |\n| `GRIX_QWEN_E2E_DEV_TIMEOUT_MS` | `300000` | Timeout for `developer-flow` and `file-read-write` (ms) |\n| `GRIX_QWEN_E2E_KEEP_TMP` | `0` | Set `1` to preserve temp directories |\n| `GRIX_QWEN_E2E_DEBUG_LOG` | *(empty)* | Path to append debug trace log |\n\n## FAQ\n\n### `qwen` Command Not Found\n\nInstall Qwen Code first:\n\n```bash\nnpm install -g @qwen-code/qwen-code\n```\n\n### Cannot Connect to Grix\n\nCheck these three items first:\n\n- Whether `endpoint` was copied directly from the Grix page\n- Whether `agent-id` and `api-key` are correct\n- Whether your machine can reach the corresponding Grix service address\n\n### Not Working in the Expected Directory\n\nFirst check whether the current session has already submitted its working directory.\n\n`--workspace` is only the default local directory and runtime base directory used at startup. When handling messages, Qwen will prefer the directory bound to the current session.\n","readmeFilename":"README.md"}