deel-local-cli 1.8.0 → 1.12.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.ko.md +10 -25
- package/README.md +43 -51
- package/bin/deel.js +56 -13
- package/package.json +60 -60
- package/src/acp/serve.js +810 -732
- package/src/agent/budget.js +156 -153
- package/src/agent/compact.js +420 -296
- package/src/agent/effort.js +308 -177
- package/src/agent/evidence.js +2 -0
- package/src/agent/evolve.js +263 -213
- package/src/agent/filemem.js +155 -0
- package/src/agent/grade.js +51 -1
- package/src/agent/loop.js +1707 -1349
- package/src/agent/memory.js +156 -152
- package/src/agent/mention.js +210 -210
- package/src/agent/session.js +1049 -832
- package/src/agent/store.js +186 -9
- package/src/agent/threads.js +26 -1
- package/src/backend/adapter.js +1159 -615
- package/src/backend/cachemark.js +150 -0
- package/src/backend/detect.js +327 -288
- package/src/backend/learn.js +24 -0
- package/src/backend/mcp.js +96 -5
- package/src/backend/probe.js +131 -61
- package/src/backend/quota.js +250 -133
- package/src/backend/retry.js +30 -6
- package/src/backend/tokens.js +37 -0
- package/src/backend/toolfit.js +352 -0
- package/src/backend/wire.js +600 -0
- package/src/commands.js +3135 -2918
- package/src/config.js +47 -2
- package/src/i18n/en.js +544 -466
- package/src/i18n/index.js +18 -0
- package/src/i18n/ja.js +497 -417
- package/src/i18n/ko.js +591 -466
- package/src/i18n/zh.js +497 -417
- package/src/lsp/client.js +49 -5
- package/src/oneshot.js +620 -471
- package/src/pack/sbom.js +30 -4
- package/src/pack/selfpack.js +25 -9
- package/src/pack/sheet.en.js +288 -0
- package/src/pack/tar.js +65 -2
- package/src/plugins/manage.js +46 -9
- package/src/providers/bedrock.js +17 -0
- package/src/repl.js +2602 -2286
- package/src/safety/audit.js +92 -8
- package/src/safety/authcmd.js +14 -3
- package/src/safety/guard.js +143 -0
- package/src/safety/keystore.js +62 -39
- package/src/safety/undo.js +24 -6
- package/src/tools/fsutil.js +265 -250
- package/src/tools/index.js +239 -34
- package/src/tools/jobs.js +158 -29
- package/src/tools/verify.js +358 -328
- package/src/tools/webfetch.js +92 -9
- package/src/ui/md.js +201 -5
- package/src/ui/motion.js +0 -1
- package/src/ui/pastechip.js +50 -3
- package/src/ui/pick.js +115 -0
- package/src/ui/screen.js +23 -3
- package/src/ui/status.js +613 -610
package/src/agent/budget.js
CHANGED
|
@@ -1,153 +1,156 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 상한을 **모델에 맞춰** 정한다.
|
|
3
|
-
*
|
|
4
|
-
* ── 왜 고정 숫자를 버렸나 ───────────────────────────────────────────────
|
|
5
|
-
*
|
|
6
|
-
* 전에는 전부 못 박혀 있었다. 걸음 24회, Read 2,000줄, Glob 200개,
|
|
7
|
-
* WebFetch 20,000자. 그런데 이 값들이 맞는 모델은 **하나도 없다.**
|
|
8
|
-
*
|
|
9
|
-
* 8k 짜리 로컬 모델에 20,000자를 부어 넣으면 그 한 번으로 창이 넘친다.
|
|
10
|
-
* 앞엣말을 잊은 채로 답하니, 사람 눈에는 "모델이 멍청해졌다" 로 보인다.
|
|
11
|
-
*
|
|
12
|
-
* 655k 짜리 모델은 24걸음 만에 끊긴다. 대시보드 하나를 만들려면 폴더를
|
|
13
|
-
* 잡고 파일 몇 개를 만들고 돌려 보고 고쳐야 하는데, 만들다 만 채로 끝난다.
|
|
14
|
-
* 여유가 96% 남아 있는데도 그렇다.
|
|
15
|
-
*
|
|
16
|
-
* 같은 숫자가 한쪽에선 너무 크고 다른 쪽에선 너무 작다. 그러면 그건 숫자를
|
|
17
|
-
* 잘못 고른 게 아니라 **고정한 것 자체가 틀린 것**이다.
|
|
18
|
-
*
|
|
19
|
-
* 그래서 전부 컨텍스트에서 뽑아 쓴다. 큰 모델에는 크게 주고 작은 모델에는
|
|
20
|
-
* 작게 준다. 사람이 `/ctx` 로 컨텍스트를 다시 재면 이 값들도 같이 따라온다.
|
|
21
|
-
*
|
|
22
|
-
* ── 걸음 수는 목표가 아니라 마지막 안전장치다 ──────────────────────────
|
|
23
|
-
*
|
|
24
|
-
* 헛도는 것은 걸음 수로 못 잡는다 — 그건 '잘 되고 있는 긴 작업' 과 '헛도는
|
|
25
|
-
* 작업' 을 구분 못 한다. 헛도는 것은 같은 자리를 되풀이하는지로 잡고
|
|
26
|
-
* (loop.js), 컨텍스트가 차면 접는다(compact.js). 여기 값은 그 둘이 다 놓쳤을
|
|
27
|
-
* 때 끝없이 도는 것을 막는 **마지막 울타리**다. 그러니 넉넉해도 된다.
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
// 컨텍스트 1k 당 몇 걸음을 줄까. 일의 성격마다 다르다 —
|
|
31
|
-
// '묻기' 는 설명 한 번이면 끝이고, '총괄' 은 여러 갈래를 끝까지 끌고 간다.
|
|
32
|
-
const 걸음규칙 = {
|
|
33
|
-
ask: { 배수: 0.25, 최소: 4, 최대: 12 },
|
|
34
|
-
plan: { 배수: 0.6, 최소: 8, 최대: 40 },
|
|
35
|
-
architect: { 배수: 0.7, 최소: 8, 최대: 48 },
|
|
36
|
-
auto: { 배수: 1.5, 최소: 16, 최대: 200 },
|
|
37
|
-
code: { 배수: 1.5, 최소: 16, 최대: 200 },
|
|
38
|
-
debug: { 배수: 2, 최소: 16, 최대: 250 },
|
|
39
|
-
orchestrator: { 배수: 3, 최소: 24, 최대: 400 },
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const 사이 = (v, 최소, 최대) => Math.max(최소, Math.min(최대, Math.round(v)));
|
|
43
|
-
|
|
44
|
-
/** 컨텍스트가 아직 안 잡혔을 때 쓰는 값. 못 알아냈다는 뜻이지 정답이 아니다. */
|
|
45
|
-
const 모를때 = 32768;
|
|
46
|
-
|
|
47
|
-
const k = (ctx) => (Number(ctx) > 0 ? Number(ctx) : 모를때) / 1024;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* 이 모드·이 모델에서 한 턴에 몇 걸음까지 돌까.
|
|
51
|
-
*
|
|
52
|
-
* @param {string} 모드id auto · code · plan …
|
|
53
|
-
* @param {number} ctx 모델 컨텍스트 길이(토큰)
|
|
54
|
-
*/
|
|
55
|
-
export function 걸음수(모드id, ctx) {
|
|
56
|
-
const r = 걸음규칙[모드id] ?? 걸음규칙.auto;
|
|
57
|
-
return 사이(k(ctx) * r.배수, r.최소, r.최대);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* 한 번에 읽을 파일 줄 수.
|
|
62
|
-
*
|
|
63
|
-
* 8k 모델에 2,000줄을 부어 넣으면 그 한 번으로 창이 넘친다. 넘치면 접히고,
|
|
64
|
-
* 접히면 앞엣말을 잊는다 — 그런데 화면에는 `2,000줄` 이라고만 떠서 사람은
|
|
65
|
-
* 잘 읽은 줄 안다.
|
|
66
|
-
*/
|
|
67
|
-
export function 읽을줄수(ctx) {
|
|
68
|
-
return 사이(k(ctx) * 12, 200, 4000);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** Glob 이 돌려줄 파일 개수. 목록은 한 줄에 한 개라 줄 수와 성격이 같다. */
|
|
72
|
-
export function 찾을개수(ctx) {
|
|
73
|
-
return 사이(k(ctx) * 6, 50, 1000);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** Grep 이 돌려줄 줄 수. */
|
|
77
|
-
export function 찾을줄수(ctx) {
|
|
78
|
-
return 사이(k(ctx) * 8, 80, 1500);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Outline 이 돌려줄 줄 수.
|
|
83
|
-
*
|
|
84
|
-
* Grep 보다 넉넉히 준다. 뼈대 한 줄은 ` 42 fn 접어쓰기` 처럼 짧은데,
|
|
85
|
-
* 그 한 줄이 파일 하나를 통째로 안 읽어도 되게 해 준다 — 줄당 값이 제일 크다.
|
|
86
|
-
* 8k 에서 120줄이면 파일 열댓 개의 모양이 들어온다. 그 정도면 "어디를 고칠지"
|
|
87
|
-
* 는 정해진다.
|
|
88
|
-
*/
|
|
89
|
-
export function 뼈대줄수(ctx) {
|
|
90
|
-
return 사이(k(ctx) * 15, 120, 2500);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* WebFetch 가 한 번에 가져올 글자 수.
|
|
95
|
-
*
|
|
96
|
-
* 토큰이 아니라 **글자** 다. 영문 JSON 은 3.6자에 1토큰이지만 한글은 1자에
|
|
97
|
-
* 1토큰이라, 같은 글자 수라도 한글이 세 배 넘게 무겁다. 무거운 쪽에 맞춘다 —
|
|
98
|
-
* 넘쳐서 잊는 것보다 모자라서 한 번 더 부르는 편이 낫다.
|
|
99
|
-
*/
|
|
100
|
-
export function 웹글자수(ctx) {
|
|
101
|
-
return 사이(k(ctx) * 400, 4000, 120000);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* 하위 작업이 돌 걸음 수.
|
|
106
|
-
*
|
|
107
|
-
* 부모보다 적게 준다. 하위 작업은 '한 덩이' 를 맡는 것이지 전체를 맡는 게
|
|
108
|
-
* 아니다. 부모만큼 주면 하위가 부모 일을 통째로 다시 하려 들고, 그러면
|
|
109
|
-
* 창을 나눈 뜻이 없어진다. 대신 너무 적으면 맡긴 덩이도 못 끝내니
|
|
110
|
-
* 8걸음은 무슨 일이 있어도 준다.
|
|
111
|
-
*/
|
|
112
|
-
export function 하위걸음수(모드id, ctx) {
|
|
113
|
-
return Math.max(8, Math.round(걸음수(모드id, ctx) / 2));
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* 하위 작업이 부모에게 돌려줄 요약의 길이(글자).
|
|
118
|
-
*
|
|
119
|
-
* 이게 하위 작업의 **존재 이유**다. 하위가 파일 열 개를 읽고 만들어도 부모
|
|
120
|
-
* 창에 들어가는 것은 이만큼뿐이다. 그러니 부모 창에 맞춰야지, 하위가 한 일의
|
|
121
|
-
* 양에 맞추면 안 된다 — 그러면 나눈 것이 도로 합쳐진다.
|
|
122
|
-
*
|
|
123
|
-
* 부모 창의 약 5% 를 넘지 않게 잡는다. 8k 면 400자, 655k 면 4,000자다.
|
|
124
|
-
*/
|
|
125
|
-
export function 요약길이(ctx) {
|
|
126
|
-
return 사이(k(ctx) * 50, 400, 4000);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* 도구 설명을 몇 글자까지 실을까.
|
|
131
|
-
*
|
|
132
|
-
* ── 이게 왜 필요한가 ─────────────────────────────────────────────────
|
|
133
|
-
*
|
|
134
|
-
* 도구 정의는 **매 요청에 통째로 다시 나간다.** 접기로는 못 줄이는 몫이다.
|
|
135
|
-
* 도구가
|
|
136
|
-
* 프롬프트까지 합치면
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return
|
|
152
|
-
|
|
153
|
-
|
|
1
|
+
/**
|
|
2
|
+
* 상한을 **모델에 맞춰** 정한다.
|
|
3
|
+
*
|
|
4
|
+
* ── 왜 고정 숫자를 버렸나 ───────────────────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* 전에는 전부 못 박혀 있었다. 걸음 24회, Read 2,000줄, Glob 200개,
|
|
7
|
+
* WebFetch 20,000자. 그런데 이 값들이 맞는 모델은 **하나도 없다.**
|
|
8
|
+
*
|
|
9
|
+
* 8k 짜리 로컬 모델에 20,000자를 부어 넣으면 그 한 번으로 창이 넘친다.
|
|
10
|
+
* 앞엣말을 잊은 채로 답하니, 사람 눈에는 "모델이 멍청해졌다" 로 보인다.
|
|
11
|
+
*
|
|
12
|
+
* 655k 짜리 모델은 24걸음 만에 끊긴다. 대시보드 하나를 만들려면 폴더를
|
|
13
|
+
* 잡고 파일 몇 개를 만들고 돌려 보고 고쳐야 하는데, 만들다 만 채로 끝난다.
|
|
14
|
+
* 여유가 96% 남아 있는데도 그렇다.
|
|
15
|
+
*
|
|
16
|
+
* 같은 숫자가 한쪽에선 너무 크고 다른 쪽에선 너무 작다. 그러면 그건 숫자를
|
|
17
|
+
* 잘못 고른 게 아니라 **고정한 것 자체가 틀린 것**이다.
|
|
18
|
+
*
|
|
19
|
+
* 그래서 전부 컨텍스트에서 뽑아 쓴다. 큰 모델에는 크게 주고 작은 모델에는
|
|
20
|
+
* 작게 준다. 사람이 `/ctx` 로 컨텍스트를 다시 재면 이 값들도 같이 따라온다.
|
|
21
|
+
*
|
|
22
|
+
* ── 걸음 수는 목표가 아니라 마지막 안전장치다 ──────────────────────────
|
|
23
|
+
*
|
|
24
|
+
* 헛도는 것은 걸음 수로 못 잡는다 — 그건 '잘 되고 있는 긴 작업' 과 '헛도는
|
|
25
|
+
* 작업' 을 구분 못 한다. 헛도는 것은 같은 자리를 되풀이하는지로 잡고
|
|
26
|
+
* (loop.js), 컨텍스트가 차면 접는다(compact.js). 여기 값은 그 둘이 다 놓쳤을
|
|
27
|
+
* 때 끝없이 도는 것을 막는 **마지막 울타리**다. 그러니 넉넉해도 된다.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
// 컨텍스트 1k 당 몇 걸음을 줄까. 일의 성격마다 다르다 —
|
|
31
|
+
// '묻기' 는 설명 한 번이면 끝이고, '총괄' 은 여러 갈래를 끝까지 끌고 간다.
|
|
32
|
+
const 걸음규칙 = {
|
|
33
|
+
ask: { 배수: 0.25, 최소: 4, 최대: 12 },
|
|
34
|
+
plan: { 배수: 0.6, 최소: 8, 최대: 40 },
|
|
35
|
+
architect: { 배수: 0.7, 최소: 8, 최대: 48 },
|
|
36
|
+
auto: { 배수: 1.5, 최소: 16, 최대: 200 },
|
|
37
|
+
code: { 배수: 1.5, 최소: 16, 최대: 200 },
|
|
38
|
+
debug: { 배수: 2, 최소: 16, 최대: 250 },
|
|
39
|
+
orchestrator: { 배수: 3, 최소: 24, 최대: 400 },
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const 사이 = (v, 최소, 최대) => Math.max(최소, Math.min(최대, Math.round(v)));
|
|
43
|
+
|
|
44
|
+
/** 컨텍스트가 아직 안 잡혔을 때 쓰는 값. 못 알아냈다는 뜻이지 정답이 아니다. */
|
|
45
|
+
const 모를때 = 32768;
|
|
46
|
+
|
|
47
|
+
const k = (ctx) => (Number(ctx) > 0 ? Number(ctx) : 모를때) / 1024;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 이 모드·이 모델에서 한 턴에 몇 걸음까지 돌까.
|
|
51
|
+
*
|
|
52
|
+
* @param {string} 모드id auto · code · plan …
|
|
53
|
+
* @param {number} ctx 모델 컨텍스트 길이(토큰)
|
|
54
|
+
*/
|
|
55
|
+
export function 걸음수(모드id, ctx) {
|
|
56
|
+
const r = 걸음규칙[모드id] ?? 걸음규칙.auto;
|
|
57
|
+
return 사이(k(ctx) * r.배수, r.최소, r.최대);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 한 번에 읽을 파일 줄 수.
|
|
62
|
+
*
|
|
63
|
+
* 8k 모델에 2,000줄을 부어 넣으면 그 한 번으로 창이 넘친다. 넘치면 접히고,
|
|
64
|
+
* 접히면 앞엣말을 잊는다 — 그런데 화면에는 `2,000줄` 이라고만 떠서 사람은
|
|
65
|
+
* 잘 읽은 줄 안다.
|
|
66
|
+
*/
|
|
67
|
+
export function 읽을줄수(ctx) {
|
|
68
|
+
return 사이(k(ctx) * 12, 200, 4000);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Glob 이 돌려줄 파일 개수. 목록은 한 줄에 한 개라 줄 수와 성격이 같다. */
|
|
72
|
+
export function 찾을개수(ctx) {
|
|
73
|
+
return 사이(k(ctx) * 6, 50, 1000);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Grep 이 돌려줄 줄 수. */
|
|
77
|
+
export function 찾을줄수(ctx) {
|
|
78
|
+
return 사이(k(ctx) * 8, 80, 1500);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Outline 이 돌려줄 줄 수.
|
|
83
|
+
*
|
|
84
|
+
* Grep 보다 넉넉히 준다. 뼈대 한 줄은 ` 42 fn 접어쓰기` 처럼 짧은데,
|
|
85
|
+
* 그 한 줄이 파일 하나를 통째로 안 읽어도 되게 해 준다 — 줄당 값이 제일 크다.
|
|
86
|
+
* 8k 에서 120줄이면 파일 열댓 개의 모양이 들어온다. 그 정도면 "어디를 고칠지"
|
|
87
|
+
* 는 정해진다.
|
|
88
|
+
*/
|
|
89
|
+
export function 뼈대줄수(ctx) {
|
|
90
|
+
return 사이(k(ctx) * 15, 120, 2500);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* WebFetch 가 한 번에 가져올 글자 수.
|
|
95
|
+
*
|
|
96
|
+
* 토큰이 아니라 **글자** 다. 영문 JSON 은 3.6자에 1토큰이지만 한글은 1자에
|
|
97
|
+
* 1토큰이라, 같은 글자 수라도 한글이 세 배 넘게 무겁다. 무거운 쪽에 맞춘다 —
|
|
98
|
+
* 넘쳐서 잊는 것보다 모자라서 한 번 더 부르는 편이 낫다.
|
|
99
|
+
*/
|
|
100
|
+
export function 웹글자수(ctx) {
|
|
101
|
+
return 사이(k(ctx) * 400, 4000, 120000);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 하위 작업이 돌 걸음 수.
|
|
106
|
+
*
|
|
107
|
+
* 부모보다 적게 준다. 하위 작업은 '한 덩이' 를 맡는 것이지 전체를 맡는 게
|
|
108
|
+
* 아니다. 부모만큼 주면 하위가 부모 일을 통째로 다시 하려 들고, 그러면
|
|
109
|
+
* 창을 나눈 뜻이 없어진다. 대신 너무 적으면 맡긴 덩이도 못 끝내니
|
|
110
|
+
* 8걸음은 무슨 일이 있어도 준다.
|
|
111
|
+
*/
|
|
112
|
+
export function 하위걸음수(모드id, ctx) {
|
|
113
|
+
return Math.max(8, Math.round(걸음수(모드id, ctx) / 2));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 하위 작업이 부모에게 돌려줄 요약의 길이(글자).
|
|
118
|
+
*
|
|
119
|
+
* 이게 하위 작업의 **존재 이유**다. 하위가 파일 열 개를 읽고 만들어도 부모
|
|
120
|
+
* 창에 들어가는 것은 이만큼뿐이다. 그러니 부모 창에 맞춰야지, 하위가 한 일의
|
|
121
|
+
* 양에 맞추면 안 된다 — 그러면 나눈 것이 도로 합쳐진다.
|
|
122
|
+
*
|
|
123
|
+
* 부모 창의 약 5% 를 넘지 않게 잡는다. 8k 면 400자, 655k 면 4,000자다.
|
|
124
|
+
*/
|
|
125
|
+
export function 요약길이(ctx) {
|
|
126
|
+
return 사이(k(ctx) * 50, 400, 4000);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 도구 설명을 몇 글자까지 실을까.
|
|
131
|
+
*
|
|
132
|
+
* ── 이게 왜 필요한가 ─────────────────────────────────────────────────
|
|
133
|
+
*
|
|
134
|
+
* 도구 정의는 **매 요청에 통째로 다시 나간다.** 접기로는 못 줄이는 몫이다.
|
|
135
|
+
* 도구가 스무 종이 되면서 코드 모드에서만 그만큼이 매번 실린다. 시스템
|
|
136
|
+
* 프롬프트까지 합치면 8k 모델은 대화 한 줄 전에 자리의 **절반**이 찬다.
|
|
137
|
+
*
|
|
138
|
+
* 여기에 잰 값을 박아 두지 않는다. 박아 두면 도구가 늘 때마다 낡고, 낡은
|
|
139
|
+
* 숫자는 없는 숫자보다 나쁘다 — 그걸 믿고 예산을 짜기 때문이다.
|
|
140
|
+
*
|
|
141
|
+
* 그렇다고 도구를 뺄 수는 없다. 빼면 작은 모델만 할 수 있는 일이 달라져서,
|
|
142
|
+
* "환경마다 다르게 동작" 하게 된다 — 사용자가 피하려는 바로 그것이다.
|
|
143
|
+
* 그래서 **도구는 다 주고 설명만 줄인다.** 이름과 인자는 그대로 두므로
|
|
144
|
+
* 할 수 있는 일은 똑같고, 없어지는 것은 '왜 이걸 쓰는지' 하는 설득뿐이다.
|
|
145
|
+
*
|
|
146
|
+
* 큰 창에서는 안 줄인다(Infinity). 그 설득이 실제로 값을 하기 때문이다 —
|
|
147
|
+
* 모델이 Outline 을 Read 앞에 부르게 만드는 것은 그 두 문장이다.
|
|
148
|
+
*/
|
|
149
|
+
export function 설명길이(ctx) {
|
|
150
|
+
const n = Number(ctx) > 0 ? Number(ctx) : 모를때;
|
|
151
|
+
if (n >= 64000) return Infinity; // 자리가 넉넉하다. 그대로 준다
|
|
152
|
+
if (n >= 24000) return 220;
|
|
153
|
+
if (n >= 12000) return 140;
|
|
154
|
+
return 90; // 8k 언저리. 첫 문장 하나만 남는다
|
|
155
|
+
}
|
|
156
|
+
|