@nine-lab/nine-mu 0.1.351 → 0.1.353

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.353",
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. 터미널 프롬프트 테마 스타일 (줄간격 및 마진 정밀 교정)
5
5
  // ==========================================
6
6
  export const NineExceptionStyles = {
7
7
  container: {
8
- padding: '30px',
8
+ padding: '25px',
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.2' // ⭐ 줄간격을 터미널처럼 촘촘하게 제어
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 8px 0', // 하단 마진 축소
23
+ letterSpacing: '0.5px'
33
24
  },
34
25
  pre: {
35
- background: '#1A1C1E', // 코드 블록 내부의 살짝 더 깊은 블랙
36
- color: '#F8F9FA', // 에러 로그 화이트 출력
37
- padding: '15px',
38
- borderRadius: '4px',
39
- border: '1px solid #2A2D30',
26
+ background: 'transparent',
27
+ color: '#F8F9FA',
28
+ padding: '0',
29
+ margin: '0 0 12px 0', // 하단 마진 축소하여 다음 라인과 밀착
30
+ border: 'none',
40
31
  overflowX: 'auto',
41
32
  whiteSpace: 'pre-wrap',
42
33
  fontFamily: 'Consolas, Monaco, monospace',
43
- fontSize: '13px',
44
- lineHeight: '1.5'
34
+ fontSize: '14px'
45
35
  },
46
36
  footer: {
47
- marginTop: '20px',
48
- fontSize: '13px',
49
- color: '#718096',
37
+ fontSize: '14px',
38
+ color: '#E2E8F0',
39
+ margin: '0', // 불필요한 공백 제거
50
40
  display: 'flex',
51
41
  flexDirection: 'column',
52
- gap: '10px'
42
+ gap: '6px'
53
43
  },
54
- button: {
55
- padding: '10px 16px',
56
- background: '#E53E3E', // 버튼의 고유 아이덴티티 유지 (레드)
57
- color: '#FFFFFF',
44
+ promptRow: {
45
+ display: 'block', // 자연스러운 텍스트 흐름을 위해 block 처리
46
+ margin: '0'
47
+ },
48
+ // ⭐ y 글자에 직접 바인딩할 터미널 링크 스타일
49
+ cliLink: {
50
+ background: 'transparent',
51
+ color: '#38A169', // 터미널 그린
58
52
  border: 'none',
59
- borderRadius: '4px',
60
- cursor: 'pointer',
53
+ padding: '0 2px',
54
+ fontFamily: 'Consolas, Monaco, monospace',
55
+ fontSize: '14px',
61
56
  fontWeight: 'bold',
62
- fontSize: '13px',
63
- alignSelf: 'flex-start',
64
- transition: 'background 0.2s',
65
- fontFamily: 'sans-serif' // 버튼 텍스트는 일반 폰트로 가독성 확보
57
+ cursor: 'pointer',
58
+ textDecoration: 'underline',
59
+ textUnderlineOffset: '2px',
60
+ display: 'inline'
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,28 @@ 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
+ handleKeyDown(e) {
102
+ if (this.state.hasError && this.state.reportStatus === 'idle') {
103
+ if (e.key === 'y' || e.key === 'Y') {
104
+ e.preventDefault();
105
+ this.handleReport();
106
+ }
107
+ }
102
108
  }
103
109
 
104
110
  handleLocationChange() {
105
111
  setTimeout(() => {
106
112
  if (this.state.hasError && this.lastPath !== window.location.pathname) {
107
- console.log("[Nine-Library] 페이지 주소 변경 감지 -> 리액트 에러 상태 초기화");
113
+ console.log("[Nine-Library] 페이지 주소 변경 감지 -> 에러 상태 초기화");
108
114
  this.lastPath = window.location.pathname;
109
115
  this.setState({ hasError: false, error: null, reportStatus: 'idle' });
110
116
  }
@@ -124,7 +130,7 @@ export class NineExceptionHook extends React.Component {
124
130
  console.warn("[Nine-Library] window.triggerAutoRecovery 가 정의되지 않았습니다.");
125
131
  }
126
132
  this.setState({ reportStatus: 'success' });
127
- }, 500);
133
+ }, 600);
128
134
  }
129
135
 
130
136
  render() {
@@ -136,66 +142,53 @@ export class NineExceptionHook extends React.Component {
136
142
  const errorMessage = this.state.error?.message || String(this.state.error);
137
143
  const customStyles = this.props.styles || {};
138
144
 
139
- let buttonText = '🚀 관제탑에 에러 피드백 전송하기';
140
- if (this.state.reportStatus === 'sending') buttonText = '⏳ 관제탑 연락 중...';
141
- if (this.state.reportStatus === 'success') buttonText = '✅ 전송 완료! AI 분석 시작';
142
-
143
145
  return React.createElement(
144
146
  'div',
145
147
  {
146
148
  style: { ...NineExceptionStyles.container, ...customStyles.container, ...this.props.containerStyle }
147
149
  },
148
150
 
149
- /**
150
- // 1. 상단 프롬프트 헤더 (시스템 상태 알림)
151
- React.createElement(
152
- '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. 시스템 에러 감지 출력 로그
151
+ // 1. 에러 감지 로그
159
152
  React.createElement(
160
153
  'div',
161
- { style: { color: 'red', margin: '15px 0 5px 0', letterSpacing: '0.5px' } },
154
+ { style: { ...NineExceptionStyles.systemError, ...customStyles.systemError } },
162
155
  '[SYSTEM] COMPONENT RENDER ERROR DETECTED'
163
156
  ),
164
157
 
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. 에러 내용 본문 박스
158
+ // 2. 에러 내용 (하단 마진을 줄여 다음 줄과 간격을 맞춤)
175
159
  React.createElement('pre', { style: { ...NineExceptionStyles.pre, ...customStyles.pre } }, errorMessage),
176
160
 
177
- // 5. 하단 버튼피드백 영역
161
+ // 3. CLI 프롬프트링크 영역
178
162
  React.createElement(
179
163
  'div',
180
164
  { 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'
165
+
166
+ this.state.reportStatus === 'idle' && React.createElement(
167
+ 'div',
168
+ { style: NineExceptionStyles.promptRow },
169
+ React.createElement('span', null, 'Send error log to Control Tower ('),
170
+ React.createElement(
171
+ 'button',
172
+ {
173
+ style: { ...NineExceptionStyles.cliLink, ...customStyles.cliLink },
174
+ onClick: this.handleReport
189
175
  },
190
- disabled: this.state.reportStatus !== 'idle',
191
- onClick: this.handleReport
192
- },
193
- buttonText
176
+ 'y'
177
+ ),
178
+ React.createElement('span', null, '/n)?')
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
  );