@nine-lab/nine-mu 0.1.351 → 0.1.352

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nine-lab/nine-mu",
3
- "version": "0.1.351",
3
+ "version": "0.1.352",
4
4
  "description": "AI-Driven Full-Stack Code Fabrication Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/nine-mu.umd.js",
@@ -1,73 +1,68 @@
1
1
  import React from 'react';
2
2
 
3
3
  // ==========================================
4
- // 1. 터미널 프롬프트 테마 스타일 (블랙/화이트/그레이 기반)
4
+ // 1. 순수 리눅스 터미널 CLI 스타일 (박스 테두리 제거)
5
5
  // ==========================================
6
6
  export const NineExceptionStyles = {
7
7
  container: {
8
8
  padding: '30px',
9
9
  margin: '20px',
10
10
  background: '#121314', // 터미널 다크 블랙 배경
11
- border: '1px solid #343A40', // 소프트한 메탈릭 테두리
11
+ border: '1px solid #343A40', // 외곽 메탈릭 테두리만 유지
12
12
  borderRadius: '6px',
13
- fontFamily: 'Consolas, Monaco, "Courier New", monospace', // 터미널 고정폭 글꼴 우선
13
+ fontFamily: 'Consolas, Monaco, "Courier New", monospace', // 완벽한 고정폭 서체
14
14
  textAlign: 'left',
15
- boxShadow: '0 4px 12px rgba(0,0,0,0.3)' // 터미널 윈도우 입체감
15
+ boxShadow: '0 4px 12px rgba(0,0,0,0.3)',
16
+ lineHeight: '1.6'
16
17
  },
17
- title: {
18
- color: '#FFFFFF', // 화이트 타이틀
19
- marginTop: 0,
20
- fontSize: '16px',
21
- fontWeight: '600',
22
- display: 'flex',
23
- alignItems: 'center',
24
- gap: '8px',
25
- borderBottom: '1px solid #2D3139', // 상단 바 구분선 느낌
26
- paddingBottom: '12px'
27
- },
28
- label: {
29
- margin: '15px 0 8px 0',
18
+ systemError: {
19
+ color: '#E53E3E', // 강렬한 터미널 레드 Warning
30
20
  fontWeight: 'bold',
31
- color: '#A0AEC0', // 프롬프트 서브 텍스트 (연한 그레이)
32
- fontSize: '13px'
21
+ fontSize: '14px',
22
+ margin: '0 0 10px 0',
23
+ letterSpacing: '0.5px'
33
24
  },
25
+ // 내부 테두리 박스를 완전히 제거하고 순수 텍스트만 출력되도록 수정
34
26
  pre: {
35
- background: '#1A1C1E', // 코드 블록 내부의 살짝 더 깊은 블랙
36
- color: '#F8F9FA', // 에러 로그 화이트 출력
37
- padding: '15px',
38
- borderRadius: '4px',
39
- border: '1px solid #2A2D30',
27
+ background: 'transparent',
28
+ color: '#F8F9FA',
29
+ padding: '0',
30
+ margin: '0 0 20px 0',
31
+ border: 'none',
40
32
  overflowX: 'auto',
41
33
  whiteSpace: 'pre-wrap',
42
34
  fontFamily: 'Consolas, Monaco, monospace',
43
- fontSize: '13px',
44
- lineHeight: '1.5'
35
+ fontSize: '14px'
45
36
  },
46
37
  footer: {
47
- marginTop: '20px',
48
- fontSize: '13px',
49
- color: '#718096',
38
+ fontSize: '14px',
39
+ color: '#E2E8F0',
50
40
  display: 'flex',
51
41
  flexDirection: 'column',
42
+ gap: '8px'
43
+ },
44
+ promptRow: {
45
+ display: 'flex',
46
+ alignItems: 'center',
52
47
  gap: '10px'
53
48
  },
54
- button: {
55
- padding: '10px 16px',
56
- background: '#E53E3E', // 버튼의 고유 아이덴티티 유지 (레드)
57
- color: '#FFFFFF',
49
+ // 버튼을 없애고 터미널 선택지 [Y/n] 스타일의 상호작용 요소로 변경
50
+ cliButton: {
51
+ background: 'transparent',
52
+ color: '#38A169', // 터미널 그린 포인트
58
53
  border: 'none',
59
- borderRadius: '4px',
60
- cursor: 'pointer',
54
+ padding: '0',
55
+ fontFamily: 'Consolas, Monaco, monospace',
56
+ fontSize: '14px',
61
57
  fontWeight: 'bold',
62
- fontSize: '13px',
63
- alignSelf: 'flex-start',
64
- transition: 'background 0.2s',
65
- fontFamily: 'sans-serif' // 버튼 텍스트는 일반 폰트로 가독성 확보
58
+ cursor: 'pointer',
59
+ textDecoration: 'underline',
60
+ textUnderlineOffset: '3px'
66
61
  }
67
62
  };
68
63
 
69
64
  // ==========================================
70
- // 2. 컴포넌트 본문 (기존 로직 유지)
65
+ // 2. 컴포넌트 본문 (키보드 이벤트 내장)
71
66
  // ==========================================
72
67
  export class NineExceptionHook extends React.Component {
73
68
 
@@ -77,6 +72,7 @@ export class NineExceptionHook extends React.Component {
77
72
  this.lastPath = window.location.pathname;
78
73
  this.handleLocationChange = this.handleLocationChange.bind(this);
79
74
  this.handleReport = this.handleReport.bind(this);
75
+ this.handleKeyDown = this.handleKeyDown.bind(this);
80
76
  }
81
77
 
82
78
  static getDerivedStateFromError(error) {
@@ -85,7 +81,6 @@ export class NineExceptionHook extends React.Component {
85
81
 
86
82
  componentDidCatch(error, errorInfo) {
87
83
  console.error("🚨 [Nine-Library] 본문 렌더링 에러 포착:", error);
88
-
89
84
  if (this.props.onCatch) {
90
85
  this.props.onCatch(error, errorInfo);
91
86
  }
@@ -94,17 +89,29 @@ export class NineExceptionHook extends React.Component {
94
89
  componentDidMount() {
95
90
  window.addEventListener('popstate', this.handleLocationChange);
96
91
  document.addEventListener('click', this.handleLocationChange, true);
92
+ window.addEventListener('keydown', this.handleKeyDown); // ⌨️ 키보드 훅 등록
97
93
  }
98
94
 
99
95
  componentWillUnmount() {
100
96
  window.removeEventListener('popstate', this.handleLocationChange);
101
97
  document.removeEventListener('click', this.handleLocationChange, true);
98
+ window.removeEventListener('keydown', this.handleKeyDown);
99
+ }
100
+
101
+ // 실제 사용자가 키보드로 'Y' 또는 'y'를 누르면 마우스 클릭과 동일하게 관제탑 전송 실행
102
+ handleKeyDown(e) {
103
+ if (this.state.hasError && this.state.reportStatus === 'idle') {
104
+ if (e.key === 'y' || e.key === 'Y') {
105
+ e.preventDefault();
106
+ this.handleReport();
107
+ }
108
+ }
102
109
  }
103
110
 
104
111
  handleLocationChange() {
105
112
  setTimeout(() => {
106
113
  if (this.state.hasError && this.lastPath !== window.location.pathname) {
107
- console.log("[Nine-Library] 페이지 주소 변경 감지 -> 리액트 에러 상태 초기화");
114
+ console.log("[Nine-Library] 페이지 주소 변경 감지 -> 에러 상태 초기화");
108
115
  this.lastPath = window.location.pathname;
109
116
  this.setState({ hasError: false, error: null, reportStatus: 'idle' });
110
117
  }
@@ -124,7 +131,7 @@ export class NineExceptionHook extends React.Component {
124
131
  console.warn("[Nine-Library] window.triggerAutoRecovery 가 정의되지 않았습니다.");
125
132
  }
126
133
  this.setState({ reportStatus: 'success' });
127
- }, 500);
134
+ }, 600);
128
135
  }
129
136
 
130
137
  render() {
@@ -136,66 +143,52 @@ export class NineExceptionHook extends React.Component {
136
143
  const errorMessage = this.state.error?.message || String(this.state.error);
137
144
  const customStyles = this.props.styles || {};
138
145
 
139
- let buttonText = '🚀 관제탑에 에러 피드백 전송하기';
140
- if (this.state.reportStatus === 'sending') buttonText = '⏳ 관제탑 연락 중...';
141
- if (this.state.reportStatus === 'success') buttonText = '✅ 전송 완료! AI 분석 시작';
142
-
143
146
  return React.createElement(
144
147
  'div',
145
148
  {
146
149
  style: { ...NineExceptionStyles.container, ...customStyles.container, ...this.props.containerStyle }
147
150
  },
148
151
 
149
- /**
150
- // 1. 상단 프롬프트 헤더 (시스템 상태 알림)
152
+ // 1. 에러 감지 시스템 로그 (레드)
151
153
  React.createElement(
152
154
  'div',
153
- { style: { ...NineExceptionStyles.title, ...customStyles.title } },
154
- React.createElement('span', { style: { color: '#38A169', marginRight: '5px' } }, 'nandoo@nine-mu:~$'),
155
- './system-check --status'
156
- ), */
157
-
158
- // 2. 시스템 에러 감지 출력 로그
159
- React.createElement(
160
- 'div',
161
- { style: { color: 'red', margin: '15px 0 5px 0', letterSpacing: '0.5px' } },
155
+ { style: { ...NineExceptionStyles.systemError, ...customStyles.systemError } },
162
156
  '[SYSTEM] COMPONENT RENDER ERROR DETECTED'
163
157
  ),
164
158
 
165
- /**
166
- // 3. 명령어 입력 시뮬레이션 ($ cat error.log)
167
- React.createElement(
168
- 'p',
169
- { style: { ...NineExceptionStyles.label, ...customStyles.label } },
170
- React.createElement('span', { style: { color: '#3182CE', marginRight: '6px' } }, 'nandoo@nine-mu:~$'),
171
- 'cat error.log'
172
- ), */
173
-
174
- // 4. 에러 내용 본문 박스
159
+ // 2. 에러 상세 원인 (박스 없는 순수 텍스트 출력)
175
160
  React.createElement('pre', { style: { ...NineExceptionStyles.pre, ...customStyles.pre } }, errorMessage),
176
161
 
177
- // 5. 하단 버튼 피드백 영역
162
+ // 3. CLI 양방향 인터페이스 (y/n 프롬프트)
178
163
  React.createElement(
179
164
  'div',
180
165
  { style: { ...NineExceptionStyles.footer, ...customStyles.footer } },
181
- React.createElement(
182
- 'button',
183
- {
184
- style: {
185
- ...NineExceptionStyles.button,
186
- ...customStyles.button,
187
- backgroundColor: this.state.reportStatus === 'success' ? '#38A169' : (this.state.reportStatus === 'sending' ? '#A0AEC0' : '#E53E3E'),
188
- cursor: this.state.reportStatus === 'idle' ? 'pointer' : 'not-allowed'
166
+
167
+ this.state.reportStatus === 'idle' && React.createElement(
168
+ 'div',
169
+ { style: NineExceptionStyles.promptRow },
170
+ React.createElement('span', null, 'Send error log to Control Tower (y/n)? '),
171
+ React.createElement(
172
+ 'button',
173
+ {
174
+ style: { ...NineExceptionStyles.cliButton, ...customStyles.cliButton },
175
+ onClick: this.handleReport
189
176
  },
190
- disabled: this.state.reportStatus !== 'idle',
191
- onClick: this.handleReport
192
- },
193
- buttonText
177
+ '[Y]'
178
+ )
179
+ ),
180
+
181
+ this.state.reportStatus === 'sending' && React.createElement(
182
+ 'div',
183
+ { style: { color: '#ED8936' } },
184
+ '>> Connecting to Control Tower... Sending payload.'
194
185
  ),
186
+
195
187
  this.state.reportStatus === 'success' && React.createElement(
196
188
  'div',
197
- { style: { color: '#CBD5E0', fontSize: '13px', marginTop: '5px', fontStyle: 'italic' } },
198
- '>> AI가 소스 코드를 재수정하는 동안 잠시만 기다려주세요...'
189
+ { style: { display: 'flex', flexDirection: 'column', gap: '4px' } },
190
+ React.createElement('div', { style: { color: '#38A169', fontWeight: 'bold' } }, '>> Transmit complete. Core engine initialized.'),
191
+ React.createElement('div', { style: { color: '#A0AEC0', fontStyle: 'italic', fontSize: '13px' } }, 'AI가 소스 코드를 재수정하는 동안 잠시만 기다려주세요...')
199
192
  )
200
193
  )
201
194
  );