HAL 0.3.9: 로그인 터미널·텍스트 셸·모델 선택·슬래시 명령·점검 수정 — claude 실제 로그인 명령 auth login(대화형 세션·신뢰 설정도 허용, 작업 폴더 HOME), 텍스트 셸 범용화(순수 단말 에뮬레이터 term.mjs 로 TUI 렌더, 원시 키 전달·키 단추·붙여넣기·단말 크기), 유령 세션 한도 오류 수정(닫기=종료, 살아 있는 프로세스만 계산, 한도 3, 모두 종료·세션 목록), 모델 선택(확인된 목록·PATCH·/model), 슬래시 명령 20개(/help /status /order /deploy …, 원문 기록·확장 지시), 패널 로그인·재인증 단추, 개발 지시 v0.3.9(Oz)·docs/HAL-AI.md §8·VERSION_HISTORY 0.3.9 — test/hal-ai-039.test.mjs RED 0/6 → GREEN 6/6, 전체 28파일 195건 통과
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -103,7 +103,8 @@ await test('OAuth 자동 진행: OAuth 연결 생성 응답이 다음 단계를
|
||||
await test('텍스트 셸(CLI 로그인): 허용 명령만 PTY 로 실행해 출력·입력을 주고받고, 시작은 재인증 필요, 임의 명령·모르는 CLI 는 거부, 종료 코드·강제 종료', async () => {
|
||||
const h = makeHal(); const op = await loginOp(h);
|
||||
const home = join(h.dataDir, 'home'); const bin = join(home, '.local', 'bin'); mkdirSync(bin, { recursive: true });
|
||||
writeFileSync(join(bin, 'claude'), `#!/bin/sh\nif [ "$1" = "--version" ]; then echo "2.1.312 (Claude Code)"; exit 0; fi\nif [ "$1" = "auth" ]; then echo '{"loggedIn": false}'; exit 0; fi\nif [ "$1" = "login" ]; then echo "Open https://login.example.test/device and paste the code:"; read code; echo "Logged in with code $code"; exit 0; fi\necho "unknown"; exit 2\n`); chmodSync(join(bin, 'claude'), 0o755);
|
||||
// [0.3.9] 실제 명령은 `claude auth login`(`claude login` 은 대화형 세션) — 가짜 CLI 도 그 형식을 따른다
|
||||
writeFileSync(join(bin, 'claude'), `#!/bin/sh\nif [ "$1" = "--version" ]; then echo "2.1.312 (Claude Code)"; exit 0; fi\nif [ "$1" = "auth" ] && [ "$2" = "status" ]; then echo '{"loggedIn": false}'; exit 0; fi\nif [ "$1" = "auth" ] && [ "$2" = "login" ]; then echo "Open https://login.example.test/device and paste the code:"; read code; echo "Logged in with code $code"; exit 0; fi\necho "unknown"; exit 2\n`); chmodSync(join(bin, 'claude'), 0o755);
|
||||
const prev = { h: process.env.HAL_CLI_HOME, d: process.env.HAL_CLI_DIRS }; process.env.HAL_CLI_HOME = home; process.env.HAL_CLI_DIRS = bin;
|
||||
try {
|
||||
stale(h); let r = await op.as('POST', '/ops/api/ai/shell', { tool: 'claude', command: 'login' }); eq(r.status, 403); eq(r.json.error, 'reauth_required'); await op.as('POST', '/ops/api/reauth', { password: op.pw });
|
||||
@@ -191,7 +192,7 @@ await test('화면·버전·문서(0.3.2): AI 연동 화면에 프리셋·사전
|
||||
for (const s of ['OpenRouter', 'Gemini', 'ChatGPT', '기타', '사전 준비', '텍스트 셸', 'MCP', '도구 정책']) ok(r.text.includes(s), '화면 문구 ' + s);
|
||||
const AR = await import('../hal/ui/public/ai-render.mjs'); ok(typeof AR.shellHtml === 'function' && typeof AR.guideHtml === 'function' && typeof AR.toolPolicyHtml === 'function');
|
||||
ok(AR.shellHtml({ id: 's1', status: 'running', tool: 'claude', command: 'login' }, 'Open <https://x> paste').includes('<https://x>'));
|
||||
eq(JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8')).version, '0.3.2'); eq(h.d.version, '0.3.2');
|
||||
eq(JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8')).version, '0.3.9'); eq(h.d.version, '0.3.9');
|
||||
ok(readFileSync(join(ROOT, 'Ariweb-Suitle_Dev-Order_v0.3.2.md'), 'utf8').includes('Oz')); ok(readFileSync(join(ROOT, 'VERSION_HISTORY.md'), 'utf8').includes('## 0.3.2'));
|
||||
});
|
||||
done();
|
||||
|
||||
Reference in New Issue
Block a user