HAL AI 채팅룸 도입(0.3.0): 운영자 콘솔 오른쪽 패널에 통합 방(첫 탭 고정) + 모델별 개별 방, 모델 연결(로그인·OAuth PKCE·API 키, 비밀은 Vault), 모델별 고유 정보(이름·역할·특성), HAL 제어·감시 스킬 문서·도구 29종(읽기 즉시 / 쓰기·고위험은 제안 → 운영자 승인(재인증·3단계 확인)), 통합 방 규칙(@이름 지정, 모델→모델 자동 1회 전달), MCP stdio 서버(읽기 전용), 개발 지시 v0.3.0(Oz), docs/HAL-AI.md, VERSION_HISTORY 0.3.0 — test/hal-ai.test.mjs RED 0/11 → GREEN 11/11, 전체 26파일 182건 통과

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Claude Fable 5.1
2026-10-28 17:41:50 +00:00
parent 6bfde82c5e
commit ba3c5cb2f8
23 changed files with 1494 additions and 11 deletions
+21
View File
@@ -103,5 +103,26 @@ CREATE TRIGGER IF NOT EXISTS agent_inventory_staging_agent_cleanup
AFTER DELETE ON agents BEGIN
DELETE FROM agent_inventory_staging WHERE agent_id=OLD.id;
END;
` },
// 0.3.0 AI 채팅룸(hal/ai): 모델 연결(비밀값은 Vault, 행에는 참조·상태만) · 방(통합 1 + 연결별 개별) · 메시지(블록 JSON, 방 안 seq) · 제안(쓰기·고위험 도구 호출의 승인 대기) · OAuth PKCE state(해시, 1회용).
{ id: 'hal_0006_ai_chat', sql: `
CREATE TABLE IF NOT EXISTS ai_connections (
id TEXT PRIMARY KEY, name TEXT NOT NULL, tab_label TEXT, provider TEXT NOT NULL, auth_kind TEXT NOT NULL, base_url TEXT, model TEXT, models_json TEXT NOT NULL DEFAULT '[]',
identity_json TEXT, oauth_json TEXT, cli_json TEXT, status TEXT NOT NULL DEFAULT 'active', last_ok_at TEXT, last_error TEXT, position INTEGER NOT NULL DEFAULT 0,
created_by TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS ai_connections_name ON ai_connections(lower(name));
CREATE TABLE IF NOT EXISTS ai_rooms (id TEXT PRIMARY KEY, kind TEXT NOT NULL, connection_id TEXT, title TEXT, created_by TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL);
CREATE TABLE IF NOT EXISTS ai_messages (
id TEXT PRIMARY KEY, room_id TEXT NOT NULL, seq INTEGER NOT NULL, role TEXT NOT NULL, connection_id TEXT, author TEXT, content_json TEXT NOT NULL, addressed_json TEXT,
relay_depth INTEGER NOT NULL DEFAULT 0, status TEXT NOT NULL DEFAULT 'done', usage_json TEXT, error TEXT, created_at TEXT NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS ai_messages_room_seq ON ai_messages(room_id, seq);
CREATE TABLE IF NOT EXISTS ai_actions (
id TEXT PRIMARY KEY, room_id TEXT NOT NULL, message_id TEXT, connection_id TEXT NOT NULL, tool TEXT NOT NULL, args_json TEXT NOT NULL, risk TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'proposed', proposed_at TEXT NOT NULL, decided_by TEXT, decided_at TEXT, result_json TEXT, error TEXT, tool_use_id TEXT, relay_depth INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX IF NOT EXISTS ai_actions_room ON ai_actions(room_id, status);
CREATE TABLE IF NOT EXISTS ai_oauth_states (state_hash TEXT PRIMARY KEY, connection_id TEXT NOT NULL, operator_id TEXT NOT NULL, created_at TEXT NOT NULL, expires_at TEXT NOT NULL);
` },
];