pleumrouter 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/package.json +1 -1
- package/src/config.mjs +3 -1
- package/src/launch.mjs +1 -1
- package/src/run.mjs +12 -1
package/README.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
PleumRouter 공식 터미널 CLI. 쓰던 코딩 에이전트를 한 줄로 PleumRouter에 붙여 실행한다.
|
|
4
4
|
|
|
5
|
+
## 설치
|
|
6
|
+
|
|
7
|
+
Node.js 18 이상 필요(순수 Node CLI라 별도 바이너리 없음).
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
curl -fsSL https://router.pleum.ai/install | sh # 원라이너(npm 전역 설치를 감쌈)
|
|
11
|
+
npm install -g pleumrouter # npm
|
|
12
|
+
bun install -g pleumrouter # bun
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
설치 없이 `npx pleumrouter <명령>` 으로 바로 실행할 수도 있다.
|
|
16
|
+
|
|
17
|
+
## 빠른 시작
|
|
18
|
+
|
|
5
19
|
```bash
|
|
6
20
|
npx pleumrouter login # 브라우저 로그인 + 키 자동 저장
|
|
7
21
|
npx pleumrouter launch claude --model claude-sonnet-4
|
package/package.json
CHANGED
package/src/config.mjs
CHANGED
|
@@ -3,7 +3,9 @@ import { join } from "node:path";
|
|
|
3
3
|
import { readFileSync, writeFileSync, mkdirSync, rmSync } from "node:fs";
|
|
4
4
|
|
|
5
5
|
// 공개 게이트웨이 루트. 셀프호스트/스테이징은 PLEUM_BASE_URL로 덮어쓴다.
|
|
6
|
-
export const ROOT = (process.env.PLEUM_BASE_URL ?? "https://router.pleum.ai")
|
|
6
|
+
export const ROOT = (process.env.PLEUM_BASE_URL ?? "https://router.pleum.ai")
|
|
7
|
+
.replace(/\/+$/, "")
|
|
8
|
+
.replace(/\/v1$/, ""); // 사용자가 실수로 /v1까지 붙여도 V1이 /v1/v1 이중 경로가 되지 않게 정리(L12)
|
|
7
9
|
// OpenAI 호환 엔드포인트는 /v1. (Claude Code만 루트를 쓴다 — recipes 참고)
|
|
8
10
|
export const V1 = `${ROOT}/v1`;
|
|
9
11
|
|
package/src/launch.mjs
CHANGED
|
@@ -50,7 +50,7 @@ export async function launch(tool, model, passthrough) {
|
|
|
50
50
|
// Codex는 격리 CODEX_HOME에 config.toml을 써서 사용자 ~/.codex를 보존한다.
|
|
51
51
|
if (r.type === "codex-home") {
|
|
52
52
|
const home = join(homedir(), ".pleum", "codex-home");
|
|
53
|
-
mkdirSync(home, { recursive: true });
|
|
53
|
+
mkdirSync(home, { recursive: true, mode: 0o700 }); // 사용자 데이터 디렉토리 권한 제한(L11)
|
|
54
54
|
writeFileSync(join(home, "config.toml"), codexToml(model), { mode: 0o600 });
|
|
55
55
|
env.CODEX_HOME = home;
|
|
56
56
|
}
|
package/src/run.mjs
CHANGED
|
@@ -52,6 +52,11 @@ export async function run(rest) {
|
|
|
52
52
|
const key = requireKey();
|
|
53
53
|
|
|
54
54
|
if (!model && !oneShot) {
|
|
55
|
+
if (!process.stdin.isTTY) {
|
|
56
|
+
// 비대화형(non-TTY) stdin이면 인터랙티브 모델 선택이 멈춰버리므로 명확히 안내하고 종료(L10).
|
|
57
|
+
console.error('모델을 지정하세요: pleum run <model> ["프롬프트"] (비대화형 stdin에선 모델 선택 불가)');
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
55
60
|
model = await pickModel(); // 인터랙티브 모델 선택
|
|
56
61
|
if (!model) process.exit(1);
|
|
57
62
|
}
|
|
@@ -62,7 +67,13 @@ export async function run(rest) {
|
|
|
62
67
|
|
|
63
68
|
if (oneShot) {
|
|
64
69
|
const prompt = [inlinePrompt, piped].filter(Boolean).join("\n\n");
|
|
65
|
-
const
|
|
70
|
+
const content = buildContent(prompt);
|
|
71
|
+
if (Array.isArray(content)) {
|
|
72
|
+
const n = content.filter((p) => p.type === "image_url").length;
|
|
73
|
+
// 프롬프트 내 로컬 이미지 경로를 자동 첨부·업로드하므로 조용히 올리지 않고 명시 고지한다(M8).
|
|
74
|
+
console.error(`ℹ 프롬프트의 로컬 이미지 ${n}개를 첨부해 업로드합니다.`);
|
|
75
|
+
}
|
|
76
|
+
const messages = [{ role: "user", content }];
|
|
66
77
|
try {
|
|
67
78
|
await streamChat(key, model, messages, { verbose, quiet: true });
|
|
68
79
|
} catch (e) {
|