deel-local-cli 0.9.0 → 1.0.0
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.en.md +470 -27
- package/README.md +479 -31
- package/bin/deel.js +234 -186
- package/package.json +3 -2
- package/src/agent/compact.js +131 -138
- package/src/agent/effort.js +44 -11
- package/src/agent/loop.js +574 -251
- package/src/agent/memory.js +152 -0
- package/src/agent/mention.js +164 -0
- package/src/agent/modes.js +11 -3
- package/src/agent/recall.js +209 -0
- package/src/agent/salvage.js +182 -0
- package/src/agent/session.js +140 -10
- package/src/agent/store.js +36 -11
- package/src/backend/adapter.js +266 -183
- package/src/backend/ctxsize.js +133 -61
- package/src/backend/detect.js +10 -1
- package/src/backend/learn.js +102 -0
- package/src/backend/mcp.js +304 -0
- package/src/commands.js +493 -53
- package/src/oneshot.js +327 -0
- package/src/repl.js +715 -479
- package/src/report.js +19 -5
- package/src/safety/guard.js +123 -7
- package/src/safety/undo.js +96 -11
- package/src/tools/encoding.js +24 -2
- package/src/tools/fsutil.js +70 -0
- package/src/tools/index.js +471 -27
- package/src/tools/webfetch.js +37 -1
- package/src/ui/ansi.js +13 -1
- package/src/ui/diff.js +255 -0
- package/src/ui/level.js +3 -1
- package/src/ui/prompt.js +13 -1
- package/src/ui/screen.js +169 -0
- package/src/ui/status.js +81 -17
- package/src/ui/tui.js +419 -0
- package/src/version.js +28 -0
package/bin/deel.js
CHANGED
|
@@ -1,186 +1,234 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// deel 진입점. 외부 의존성 없음 — Node 표준 기능만 씁니다.
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { c, say, mark, rule } from '../src/ui/ansi.js';
|
|
5
|
-
import { runSetup, runDiagnose, showStatus, banner } from '../src/setup.js';
|
|
6
|
-
import { chatLoop } from '../src/repl.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
say(`
|
|
24
|
-
say(
|
|
25
|
-
say(
|
|
26
|
-
say(` ${c.gray('
|
|
27
|
-
say(` ${c.gray('
|
|
28
|
-
say(` ${c.gray('
|
|
29
|
-
say(` ${c.gray('
|
|
30
|
-
say('');
|
|
31
|
-
say(
|
|
32
|
-
say(` ${c.gray('
|
|
33
|
-
say('');
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
say(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
say('');
|
|
72
|
-
say(
|
|
73
|
-
say('');
|
|
74
|
-
say(` ${c.cyan('deel
|
|
75
|
-
say(` ${c.
|
|
76
|
-
say(` ${c.
|
|
77
|
-
say(` ${c.
|
|
78
|
-
say(` ${c.
|
|
79
|
-
say('');
|
|
80
|
-
say(
|
|
81
|
-
say('');
|
|
82
|
-
say(
|
|
83
|
-
say(` ${c.cyan('deel
|
|
84
|
-
say(` ${c.gray('--
|
|
85
|
-
say('');
|
|
86
|
-
say(`
|
|
87
|
-
say('');
|
|
88
|
-
say(
|
|
89
|
-
say(`
|
|
90
|
-
say(
|
|
91
|
-
say(` ${c.
|
|
92
|
-
say(` ${c.
|
|
93
|
-
say(` ${c.gray('--
|
|
94
|
-
say(
|
|
95
|
-
say(`
|
|
96
|
-
say(
|
|
97
|
-
say(` ${c.gray('--
|
|
98
|
-
say('');
|
|
99
|
-
say(`
|
|
100
|
-
say('');
|
|
101
|
-
say(`
|
|
102
|
-
say('');
|
|
103
|
-
say(`
|
|
104
|
-
say('');
|
|
105
|
-
say(` ${c.gray('
|
|
106
|
-
say(` ${c.gray('
|
|
107
|
-
say(` ${c.gray('
|
|
108
|
-
say('');
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
case '
|
|
150
|
-
case '
|
|
151
|
-
return
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// deel 진입점. 외부 의존성 없음 — Node 표준 기능만 씁니다.
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { c, say, mark, rule } from '../src/ui/ansi.js';
|
|
5
|
+
import { runSetup, runDiagnose, showStatus, banner } from '../src/setup.js';
|
|
6
|
+
import { chatLoop } from '../src/repl.js';
|
|
7
|
+
import { runOnce } from '../src/oneshot.js';
|
|
8
|
+
import { packSelf, audit, reviewSheet } from '../src/pack/selfpack.js';
|
|
9
|
+
import { runScan } from '../src/backend/scanui.js';
|
|
10
|
+
import { closeConnections } from '../src/backend/http.js';
|
|
11
|
+
import { parseSize } from '../src/backend/ctxsize.js';
|
|
12
|
+
import { runSessions } from '../src/agent/sessionui.js';
|
|
13
|
+
|
|
14
|
+
const MIN_NODE = 20;
|
|
15
|
+
|
|
16
|
+
// 사내 반입용 묶음 만들기.
|
|
17
|
+
function runPack(flags) {
|
|
18
|
+
const out = flags.out ? String(flags.out) : join(process.cwd(), 'deel-반입.zip');
|
|
19
|
+
const r = packSelf(out);
|
|
20
|
+
const a = r.audit;
|
|
21
|
+
say('');
|
|
22
|
+
rule('반입 묶음', 70);
|
|
23
|
+
say(` ${mark.ok} ${c.bold(r.out)}`);
|
|
24
|
+
say(` ${c.gray(`${r.files}개 파일 · ${(r.bytes / 1024).toFixed(1)}KB`)}`);
|
|
25
|
+
say('');
|
|
26
|
+
say(` ${c.gray('의존성')} ${a.deps.length === 0 ? c.green('0개') : c.red(a.deps.length + '개')}`);
|
|
27
|
+
say(` ${c.gray('설치 스크립트')} ${a.lifecycle.length === 0 ? c.green('없음') : c.red(a.lifecycle.join(', '))}`);
|
|
28
|
+
say(` ${c.gray('외부 import')} ${a.외부모듈.length === 0 ? c.green('0건') : c.red(a.외부모듈.length + '건')}`);
|
|
29
|
+
say(` ${c.gray('네트워크 호출')} ${a.calls.net.length}곳 ${c.gray('(설정한 주소로만)')}`);
|
|
30
|
+
say(` ${c.gray('포트 열기')} ${a.calls.listen.length === 0 ? c.green('없음') : c.red(a.calls.listen.length + '곳')}`);
|
|
31
|
+
say('');
|
|
32
|
+
say(` ${c.gray('안에 반입심사서.txt 가 같이 들어 있습니다 — 그대로 제출하시면 됩니다.')}`);
|
|
33
|
+
say(` ${c.gray('내용만 먼저 보시려면')} ${c.cyan('deel audit')}`);
|
|
34
|
+
say('');
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 묶지 않고 심사 내용만 보기.
|
|
39
|
+
function runAudit() {
|
|
40
|
+
say('');
|
|
41
|
+
say(reviewSheet(audit(), new Date().toISOString().replace('T', ' ').slice(0, 19)));
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 값을 안 받는 깃발. 뒤에 오는 낱말을 제 값으로 삼키지 않게 여기 적어 둔다.
|
|
46
|
+
//
|
|
47
|
+
// 실제로 이랬다 — deel run --json "검사 돌려줘" 를 쳤더니 --json 이 뒤의 말을
|
|
48
|
+
// 통째로 삼켰다. 시킬 말이 사라졌으니 "무엇을 시킬지 적어 주세요" 가 떴는데,
|
|
49
|
+
// 화면만 보면 왜 그런지 알 길이 없다. 깃발을 앞에 두는 것은 아주 흔한 습관이다.
|
|
50
|
+
const BOOL = new Set(['help', 'offline', 'continue', 'json', 'quiet', 'yes', 'no-tui', 'tui']);
|
|
51
|
+
|
|
52
|
+
function parse(argv) {
|
|
53
|
+
const flags = {};
|
|
54
|
+
const args = [];
|
|
55
|
+
for (let i = 0; i < argv.length; i++) {
|
|
56
|
+
const a = argv[i];
|
|
57
|
+
if (a === '-h') { flags.help = true; continue; }
|
|
58
|
+
if (a.startsWith('--')) {
|
|
59
|
+
const [k, inline] = a.slice(2).split('=');
|
|
60
|
+
if (inline !== undefined) flags[k] = inline;
|
|
61
|
+
else if (!BOOL.has(k) && argv[i + 1] && !argv[i + 1].startsWith('-')) flags[k] = argv[++i];
|
|
62
|
+
else flags[k] = true;
|
|
63
|
+
} else args.push(a);
|
|
64
|
+
}
|
|
65
|
+
// 명령은 플래그가 아닌 첫 낱말. 없으면 상태 보기.
|
|
66
|
+
return { cmd: args[0] ?? '', args: args.slice(1), flags };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function help() {
|
|
70
|
+
banner();
|
|
71
|
+
say(` ${c.bold('사용법')}`);
|
|
72
|
+
say('');
|
|
73
|
+
say(` ${c.cyan('deel')} 대화 시작 (이 폴더에서)`);
|
|
74
|
+
say(` ${c.cyan('deel run "<시킬 말>"')} 한 번만 돌고 끝내기 (스크립트·배치용)`);
|
|
75
|
+
say(` ${c.cyan('deel scan')} 이 PC 에 떠 있는 로컬 서버 전부 찾기`);
|
|
76
|
+
say(` ${c.cyan('deel sessions')} 이 폴더에 남아 있는 대화 목록`);
|
|
77
|
+
say(` ${c.cyan('deel setup')} 연결 설정 (주소·키·모델)`);
|
|
78
|
+
say(` ${c.cyan('deel status')} 연결 상태 보기`);
|
|
79
|
+
say(` ${c.cyan('deel diagnose')} 저장된 연결로 진단 다시 돌리기`);
|
|
80
|
+
say('');
|
|
81
|
+
say(` ${c.bold('여러 로컬을 같이 쓸 때')}`);
|
|
82
|
+
say('');
|
|
83
|
+
say(` ${c.cyan('deel scan --save')} 찾은 서버·모델을 전부 등록`);
|
|
84
|
+
say(` ${c.gray('--ports 9000,9100')} 기본 자리 말고 더 볼 포트`);
|
|
85
|
+
say(` ${c.gray('--host <주소>')} 기본은 127.0.0.1`);
|
|
86
|
+
say(` ${c.gray('--key <키>')} 키가 필요한 로컬 서버일 때`);
|
|
87
|
+
say(` ${c.gray('대화 중')} ${c.cyan('/model')} ${c.gray('로 서버·모델을 골라 바꿉니다.')}`);
|
|
88
|
+
say('');
|
|
89
|
+
say(` ${c.bold('사내 반입')}`);
|
|
90
|
+
say('');
|
|
91
|
+
say(` ${c.cyan('deel audit')} 의존성·네트워크 호출 자리 심사서 보기`);
|
|
92
|
+
say(` ${c.cyan('deel pack')} 심사서 + 소스를 zip 하나로 묶기`);
|
|
93
|
+
say(` ${c.gray('--out <파일>')} 묶음 파일 이름. 기본은 deel-반입.zip`);
|
|
94
|
+
say('');
|
|
95
|
+
say(` ${c.bold('대화 시작 옵션')}`);
|
|
96
|
+
say('');
|
|
97
|
+
say(` ${c.gray('--root <폴더>')} 작업 범위. 기본은 지금 폴더`);
|
|
98
|
+
say(` ${c.gray('--mode <모드>')} auto(기본) / confirm / strict`);
|
|
99
|
+
say(` ${c.gray('--work <모드>')} auto(기본·종합) / code / plan / architect / debug / ask / orchestrator`);
|
|
100
|
+
say(` ${c.gray('--level <수준>')} 쉬움(기본) / 개발자`);
|
|
101
|
+
say(` ${c.gray('--ctx <길이>')} 컨텍스트 길이 직접 지정 (655360 · 640k · 128k). 없으면 서버에 맞춤`);
|
|
102
|
+
say(` ${c.gray('--max-tokens <길이>')} 한 번에 받을 답 길이 상한 (32k). 큰 파일이 잘리면 올린다 — /out 과 같은 값`);
|
|
103
|
+
say(` ${c.gray('--think <수준>')} off / low / medium(기본) / high / max`);
|
|
104
|
+
say(` ${c.gray('--effort <배분>')} even(균일) / save(절약, 기본) / deep(깊게)`);
|
|
105
|
+
say(` ${c.gray('--no-tui')} 전체화면 대신 줄 화면으로 (파이프·기록·좁은 터미널)`);
|
|
106
|
+
say(` ${c.gray('--offline')} 이 컴퓨터 밖으로는 아무것도 안 보냄 (자물쇠)`);
|
|
107
|
+
say(` ${c.gray('--continue')} 이 폴더에서 가장 최근 대화 이어하기`);
|
|
108
|
+
say(` ${c.gray('--resume <id>')} 골라서 이어하기 (deel sessions 로 id 확인)`);
|
|
109
|
+
say('');
|
|
110
|
+
say(` ${c.bold('한 번만 돌리기')} ${c.gray('— 스크립트·배치에서 부를 때')}`);
|
|
111
|
+
say('');
|
|
112
|
+
say(` ${c.cyan('deel run "검사 돌리고 실패한 것만 알려줘"')}`);
|
|
113
|
+
say(` ${c.cyan('echo "..." | deel run')} ${c.gray('시킬 말을 표준입력으로 넣어도 됩니다')}`);
|
|
114
|
+
say(` ${c.gray('deel -p "..." 도 같습니다.')} ${c.gray('위 대화 시작 옵션을 그대로 씁니다.')}`);
|
|
115
|
+
say('');
|
|
116
|
+
say(` ${c.gray('--json')} 결과를 JSON 한 덩이로 (답·도구 횟수·토큰·끝난 까닭)`);
|
|
117
|
+
say(` ${c.gray('--quiet')} 도구가 무엇을 했는지 안 적음 (오류는 그래도 적음)`);
|
|
118
|
+
say(` ${c.gray('--yes')} 승인이 필요한 것도 그냥 실행. ${c.yellow('기본은 거부입니다')}`);
|
|
119
|
+
say(` ${c.gray('답은 표준출력, 도구 기록은 표준오류로 나갑니다 — 파이프로 넘겨도 답만 넘어갑니다.')}`);
|
|
120
|
+
say(` ${c.gray('끝난 까닭이 종료코드에 담깁니다:')} ${c.gray('0 끝냄 · 1 오류 · 2 걸음수상한 · 3 헛돎 · 4 중단')}`);
|
|
121
|
+
say('');
|
|
122
|
+
say(` ${c.bold('진단 직접 지정')} ${c.gray('— 설정을 남기지 않고 확인만 할 때')}`);
|
|
123
|
+
say('');
|
|
124
|
+
say(` deel diagnose --url <주소> --key <키> --model <모델> --out report.txt`);
|
|
125
|
+
say('');
|
|
126
|
+
say(` ${c.bold('환경변수')}`);
|
|
127
|
+
say('');
|
|
128
|
+
say(` ${c.gray('DEEL_API_KEY')} 키를 파일에 안 남기고 싶을 때 (파일보다 우선)`);
|
|
129
|
+
say(` ${c.gray('NODE_EXTRA_CA_CERTS')} 사내 인증서를 쓰는 게이트웨이일 때`);
|
|
130
|
+
say(` ${c.gray('HTTPS_PROXY')} 프록시를 거쳐야 할 때`);
|
|
131
|
+
say('');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function main() {
|
|
135
|
+
const major = parseInt(process.versions.node.split('.')[0], 10);
|
|
136
|
+
if (major < MIN_NODE) {
|
|
137
|
+
say(` Node ${MIN_NODE} 이상이 필요합니다. 지금은 ${process.versions.node} 입니다.`);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const { cmd, args, flags } = parse(process.argv.slice(2));
|
|
142
|
+
if (flags.help || cmd === 'help') { help(); return 0; }
|
|
143
|
+
|
|
144
|
+
switch (cmd) {
|
|
145
|
+
// 한 번만 돌고 끝난다. 스크립트·배치에서 부르는 자리다.
|
|
146
|
+
//
|
|
147
|
+
// -p 는 다른 도구들이 쓰는 이름에 맞춘 것이다. 깃발처럼 생겼지만 명령이라,
|
|
148
|
+
// deel -p "..." 처럼 치면 그대로 여기로 온다.
|
|
149
|
+
case 'run':
|
|
150
|
+
case '-p':
|
|
151
|
+
return runOnce({
|
|
152
|
+
prompt: args.join(' '),
|
|
153
|
+
root: flags.root ? String(flags.root) : undefined,
|
|
154
|
+
mode: flags.mode ? String(flags.mode) : undefined,
|
|
155
|
+
work: flags.work ? String(flags.work) : undefined,
|
|
156
|
+
ctx: flags.ctx ? parseSize(String(flags.ctx)) : undefined,
|
|
157
|
+
maxTokens: flags['max-tokens'] ? parseSize(String(flags['max-tokens'])) : undefined,
|
|
158
|
+
think: flags.think ? String(flags.think) : undefined,
|
|
159
|
+
effort: flags.effort ? String(flags.effort) : undefined,
|
|
160
|
+
offline: flags.offline === true || flags.offline === 'true',
|
|
161
|
+
yes: flags.yes === true || flags.yes === 'true',
|
|
162
|
+
json: flags.json === true || flags.json === 'true',
|
|
163
|
+
quiet: flags.quiet === true || flags.quiet === 'true',
|
|
164
|
+
});
|
|
165
|
+
case '':
|
|
166
|
+
case 'chat':
|
|
167
|
+
return chatLoop({
|
|
168
|
+
root: flags.root ? String(flags.root) : undefined,
|
|
169
|
+
mode: flags.mode ? String(flags.mode) : undefined,
|
|
170
|
+
work: flags.work ? String(flags.work) : undefined,
|
|
171
|
+
level: flags.level ? String(flags.level) : undefined,
|
|
172
|
+
ctx: flags.ctx ? parseSize(String(flags.ctx)) : undefined,
|
|
173
|
+
maxTokens: flags['max-tokens'] ? parseSize(String(flags['max-tokens'])) : undefined,
|
|
174
|
+
think: flags.think ? String(flags.think) : undefined,
|
|
175
|
+
effort: flags.effort ? String(flags.effort) : undefined,
|
|
176
|
+
// 전체화면을 쓸지. 안 주면 null — 그러면 화면 쪽이 상황을 보고 정한다.
|
|
177
|
+
// --no-tui 줄 화면으로 (파이프·기록·좁은 터미널·문제가 생겼을 때)
|
|
178
|
+
// --tui 터미널이면 무조건 전체화면으로
|
|
179
|
+
tui: flags['no-tui'] === true ? false : (flags.tui === true ? true : null),
|
|
180
|
+
offline: flags.offline === true || flags.offline === 'true',
|
|
181
|
+
continue: flags.continue === true || flags.c === true,
|
|
182
|
+
sessionId: typeof flags.resume === 'string' ? flags.resume : (flags.resume === true ? null : undefined),
|
|
183
|
+
});
|
|
184
|
+
case 'status':
|
|
185
|
+
return showStatus();
|
|
186
|
+
case 'setup':
|
|
187
|
+
return runSetup();
|
|
188
|
+
case 'diagnose':
|
|
189
|
+
case 'doctor':
|
|
190
|
+
return runDiagnose(flags);
|
|
191
|
+
case 'pack':
|
|
192
|
+
return runPack(flags);
|
|
193
|
+
case 'audit':
|
|
194
|
+
return runAudit();
|
|
195
|
+
case 'scan':
|
|
196
|
+
return runScan(flags);
|
|
197
|
+
case 'sessions':
|
|
198
|
+
case 'ls':
|
|
199
|
+
return runSessions(flags);
|
|
200
|
+
default:
|
|
201
|
+
say('');
|
|
202
|
+
say(` ${c.red('모르는 명령')} ${c.bold(cmd)}`);
|
|
203
|
+
help();
|
|
204
|
+
return 1;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 끝낸다.
|
|
210
|
+
*
|
|
211
|
+
* process.exit() 을 바로 부르면 안 된다. fetch 가 살려 둔 소켓이 닫히는 중일 때
|
|
212
|
+
* 끊으면 윈도우에서 libuv 가 abort 한다 — 화면에는 정상으로 보이는데 종료코드가
|
|
213
|
+
* 3221226505 로 나온다. `deel scan` 이 실제로 그랬다.
|
|
214
|
+
*
|
|
215
|
+
* 그래서 연결을 먼저 닫고, 종료코드만 정해 두고 이벤트 루프가 저절로 비기를
|
|
216
|
+
* 기다린다. 그래도 안 비면(무언가 물고 있으면) 잠깐 뒤에 확실히 끝낸다.
|
|
217
|
+
* 그 타이머는 unref 라서, 정상적으로 끝나는 길을 막지 않는다.
|
|
218
|
+
*/
|
|
219
|
+
async function 끝내기(code) {
|
|
220
|
+
process.exitCode = code;
|
|
221
|
+
await closeConnections();
|
|
222
|
+
const 마지막수단 = setTimeout(() => process.exit(code), 400);
|
|
223
|
+
마지막수단.unref();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
main()
|
|
227
|
+
.then((code) => 끝내기(code ?? 0))
|
|
228
|
+
.catch(async (err) => {
|
|
229
|
+
say('');
|
|
230
|
+
say(` ${c.red('오류')} ${err?.message ?? err}`);
|
|
231
|
+
if (process.env.DEEL_DEBUG) say(c.gray(err?.stack ?? ''));
|
|
232
|
+
say('');
|
|
233
|
+
await 끝내기(1);
|
|
234
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deel-local-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "로컬 모델·사내 게이트웨이 전용 코딩 에이전트 CLI — 외부 의존성 0개 / Zero-dependency coding agent CLI for local LLMs and private gateways",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
"verify": "node test/no-bundle.test.js && node test/network.test.js && node test/web.test.js",
|
|
47
47
|
"bench": "node test/edit-bench.js",
|
|
48
48
|
"demo": "node test/demo.js",
|
|
49
|
-
"check": "node --check bin/deel.js && node --check src/repl.js && node --check src/commands.js && node --check src/agent/loop.js && node --check src/agent/session.js && node --check src/agent/effort.js && node --check src/agent/modes.js && node --check src/agent/route.js && node --check src/tools/encoding.js && node --check src/tools/excel-com.js && node --check src/tools/excel.js && node --check src/tools/xlsx.js && node --check src/agent/compact.js && node --check src/agent/store.js && node --check src/agent/sessionui.js && node --check src/backend/adapter.js && node --check src/backend/ctxsize.js && node --check src/backend/probe.js && node --check src/backend/detect.js && node --check src/backend/http.js && node --check src/backend/scan.js && node --check src/backend/scanui.js && node --check src/tools/index.js && node --check src/tools/fsutil.js && node --check src/tools/edit-match.js && node --check src/tools/webfetch.js && node --check src/tools/todo.js && node --check src/skills/discover.js && node --check src/plugins/manage.js && node --check src/pack/zip.js && node --check src/pack/tar.js && node --check src/pack/selfpack.js && node --check src/safety/guard.js && node --check src/safety/undo.js && node --check src/safety/audit.js && node --check src/safety/network.js && node --check src/setup.js && node --check src/report.js && node --check src/config.js && node --check src/ui/ansi.js && node --check src/ui/status.js && node --check src/ui/level.js && node --check src/ui/prompt.js && node --check src/ui/spinner.js && echo OK"
|
|
49
|
+
"check": "node --check bin/deel.js && node --check src/repl.js && node --check src/oneshot.js && node --check src/commands.js && node --check src/agent/loop.js && node --check src/agent/session.js && node --check src/agent/effort.js && node --check src/agent/modes.js && node --check src/agent/route.js && node --check src/agent/mention.js && node --check src/tools/encoding.js && node --check src/tools/excel-com.js && node --check src/tools/excel.js && node --check src/tools/xlsx.js && node --check src/agent/compact.js && node --check src/agent/store.js && node --check src/agent/sessionui.js && node --check src/backend/adapter.js && node --check src/backend/ctxsize.js && node --check src/backend/probe.js && node --check src/backend/detect.js && node --check src/backend/http.js && node --check src/backend/scan.js && node --check src/backend/scanui.js && node --check src/tools/index.js && node --check src/tools/fsutil.js && node --check src/tools/edit-match.js && node --check src/tools/webfetch.js && node --check src/tools/todo.js && node --check src/skills/discover.js && node --check src/plugins/manage.js && node --check src/pack/zip.js && node --check src/pack/tar.js && node --check src/pack/selfpack.js && node --check src/safety/guard.js && node --check src/safety/undo.js && node --check src/safety/audit.js && node --check src/safety/network.js && node --check src/setup.js && node --check src/report.js && node --check src/config.js && node --check src/ui/diff.js && node --check src/ui/ansi.js && node --check src/ui/status.js && node --check src/ui/level.js && node --check src/ui/prompt.js && node --check src/ui/spinner.js && echo OK",
|
|
50
|
+
"coverage": "node test/coverage.mjs"
|
|
50
51
|
},
|
|
51
52
|
"dependencies": {},
|
|
52
53
|
"devDependencies": {}
|