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
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { estimateTokens } from './tokens.js';
|
|
2
|
+
|
|
3
|
+
// 캐시 표식을 어디에 붙일까.
|
|
4
|
+
//
|
|
5
|
+
// ── 무엇이 문제였나 ─────────────────────────────────────────────────────
|
|
6
|
+
//
|
|
7
|
+
// 이 프로그램은 캐시 표식을 **어디에도 안 붙이고 있었다.** 그래서 서버가
|
|
8
|
+
// 알아서 앞머리를 캐시해 주는 자리(Bedrock · OpenAI)에서는 정적 앞머리만
|
|
9
|
+
// 잡혔고, 안 해 주는 자리(Anthropic 직통)에서는 하나도 안 잡혔다.
|
|
10
|
+
//
|
|
11
|
+
// 실제로 이런 모양이었다 — 열 번을 잇달아 부르는 동안 —
|
|
12
|
+
//
|
|
13
|
+
// 총 토큰 19,654 → 60,267 대화가 자란다
|
|
14
|
+
// 캐시 5.9K → 5.9K 앞머리에서 멈춰 있다
|
|
15
|
+
//
|
|
16
|
+
// 5.9K 는 시스템 프롬프트(약 4,045)와 도구 정의(약 1,800)를 합친 값이다.
|
|
17
|
+
// 즉 **자라는 대화는 한 번도 캐시된 적이 없다.** 매 걸음 전액 다시 보내고
|
|
18
|
+
// 전액 다시 냈다.
|
|
19
|
+
//
|
|
20
|
+
// ── 어디에 붙이나 ───────────────────────────────────────────────────────
|
|
21
|
+
//
|
|
22
|
+
// 규격이 정한 렌더 차례는 tools → system → messages 다. 표식 하나는 그
|
|
23
|
+
// 자리까지의 앞머리를 통째로 잡는다. 그래서 두 자리면 충분하다.
|
|
24
|
+
//
|
|
25
|
+
// 1. 시스템의 **굳은 부분 끝** — 도구까지 같이 잡힌다 (한 번 쓰고 계속 읽는다)
|
|
26
|
+
// 2. 마지막 메시지 끝 — 걸음마다 앞으로 옮겨 간다 (자라는 대화를 잡는다)
|
|
27
|
+
//
|
|
28
|
+
// 2번이 이 파일의 핵심이다. 표식이 앞으로 옮겨 가면, 다음 요청은 지난번
|
|
29
|
+
// 표식 자리까지를 **읽고** 그 뒤만 새로 쓴다. 안 옮기면 대화는 영영 캐시
|
|
30
|
+
// 밖에 있다.
|
|
31
|
+
//
|
|
32
|
+
// ── 되돌아보기 창 ───────────────────────────────────────────────────────
|
|
33
|
+
//
|
|
34
|
+
// 표식은 뒤로 스무 자리까지만 지난 것을 찾는다. 도구를 길게 늘어놓는 턴은
|
|
35
|
+
// 그 스무 자리를 넘길 수 있고, 그러면 **말없이** 캐시를 못 찾는다. 그래서
|
|
36
|
+
// 대화가 길면 중간에 닻을 하나 더 박는다. 표식은 넷까지라 셋은 여유가 있다.
|
|
37
|
+
//
|
|
38
|
+
// ── 안 붙이는 자리 ──────────────────────────────────────────────────────
|
|
39
|
+
//
|
|
40
|
+
// 생각 블록에는 안 붙인다 — 우리가 나르기만 하는 블록이라 손대지 않는다.
|
|
41
|
+
// 빈 글 블록에도 안 붙인다. 둘 다 거절당할 수 있고, 그 400 은 화면에서
|
|
42
|
+
// 열쇠가 틀린 것과 구별이 안 된다.
|
|
43
|
+
|
|
44
|
+
/** 표식 한 개. 기본 수명(5분)을 쓴다 — 한 시간짜리는 쓰기 값이 두 배다. */
|
|
45
|
+
export const 표식 = { type: 'ephemeral' };
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
* 시스템 글의 「굳은 부분 / 매 턴 바뀌는 부분」 을 나눠 담는 표.
|
|
49
|
+
*
|
|
50
|
+
* 왜 Symbol 인가: 이 표는 **우리끼리 쓰는 것**이라 전선에 나가면 안 된다.
|
|
51
|
+
* JSON.stringify 는 Symbol 열쇠를 아예 안 본다. 보통 이름으로 달아 두면
|
|
52
|
+
* openai 규격에서는 메시지가 그대로 몸통에 실려 나가므로, 모르는 칸 하나가
|
|
53
|
+
* 그 게이트웨이에서 400 을 만든다.
|
|
54
|
+
*
|
|
55
|
+
* Symbol.for 를 쓰는 것은 같은 파일이 두 번 올라와도 같은 표가 되게 하려는
|
|
56
|
+
* 것이다 (검사에서 모듈을 따로 불러오는 자리가 있다).
|
|
57
|
+
*/
|
|
58
|
+
export const 조각표 = Symbol.for('deel.시스템조각');
|
|
59
|
+
|
|
60
|
+
/** 표식을 붙여도 되는 블록인가. */
|
|
61
|
+
const 붙일수있나 = (b) => {
|
|
62
|
+
const t = b?.type;
|
|
63
|
+
if (t === 'thinking' || t === 'redacted_thinking') return false;
|
|
64
|
+
if (t === 'text') return String(b.text ?? '').length > 0;
|
|
65
|
+
return t === 'tool_result' || t === 'tool_use' || t === 'image' || t === 'document';
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/** 대화가 이보다 길면 중간에 닻을 하나 더 박는다 (되돌아보기 창 스무 자리). */
|
|
69
|
+
export const 닻문턱 = 20;
|
|
70
|
+
/** 닻은 끝에서 이만큼 앞에 박는다. */
|
|
71
|
+
const 닻거리 = 12;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 메시지 하나의 **마지막 성한 블록**에 표식을 붙인 사본을 돌려준다.
|
|
75
|
+
* 붙일 자리가 없으면 원본 그대로.
|
|
76
|
+
*/
|
|
77
|
+
export function 블록에붙이기(msg) {
|
|
78
|
+
if (!msg) return msg;
|
|
79
|
+
const 본래 = Array.isArray(msg.content)
|
|
80
|
+
? msg.content
|
|
81
|
+
: [{ type: 'text', text: String(msg.content ?? '') }];
|
|
82
|
+
let 자리 = -1;
|
|
83
|
+
for (let i = 본래.length - 1; i >= 0; i--) {
|
|
84
|
+
if (붙일수있나(본래[i])) { 자리 = i; break; }
|
|
85
|
+
}
|
|
86
|
+
if (자리 < 0) return msg;
|
|
87
|
+
const 새 = 본래.map((b, i) => (i === 자리 ? { ...b, cache_control: { ...표식 } } : b));
|
|
88
|
+
return { ...msg, content: 새 };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 시스템 글 조각들을 블록 배열로 만든다.
|
|
93
|
+
*
|
|
94
|
+
* 첫 조각이 **굳은 부분**이다 (agent/session.js 의 시스템조각). 그 끝에
|
|
95
|
+
* 표식을 박으면 도구 정의까지 같이 잡힌다 — 규격이 tools 를 system 앞에
|
|
96
|
+
* 렌더하기 때문이다.
|
|
97
|
+
*
|
|
98
|
+
* 조각이 하나뿐이면 그 끝에 박는다. 그때는 모드가 바뀔 때마다 다시 쓰지만,
|
|
99
|
+
* 안 박는 것보다는 낫다.
|
|
100
|
+
*
|
|
101
|
+
* @param {string[]} 조각들
|
|
102
|
+
* @param {boolean} 표식쓰나
|
|
103
|
+
*/
|
|
104
|
+
export function 시스템블록(조각들, 표식쓰나) {
|
|
105
|
+
const 있는것 = (조각들 ?? []).map((x) => String(x ?? '')).filter((x) => x.length);
|
|
106
|
+
if (!있는것.length) return null;
|
|
107
|
+
if (!표식쓰나) return 있는것.join('');
|
|
108
|
+
const 굳은끝 = 0; // 첫 조각이 굳은 부분이다
|
|
109
|
+
return 있는것.map((text, i) => (
|
|
110
|
+
i === 굳은끝 ? { type: 'text', text, cache_control: { ...표식 } } : { type: 'text', text }
|
|
111
|
+
));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 메시지 배열에 옮겨 가는 표식을 붙인 **사본**을 돌려준다.
|
|
116
|
+
*
|
|
117
|
+
* @param {object[]} messages 차례합치기를 이미 거친 배열
|
|
118
|
+
* @returns {object[]}
|
|
119
|
+
*/
|
|
120
|
+
export function 메시지표식(messages) {
|
|
121
|
+
const ms = messages ?? [];
|
|
122
|
+
if (!ms.length) return ms;
|
|
123
|
+
const 붙일자리 = new Set([ms.length - 1]);
|
|
124
|
+
// 도구를 길게 늘어놓는 턴에서 되돌아보기 창을 넘기지 않게 닻을 하나 더.
|
|
125
|
+
if (ms.length > 닻문턱) 붙일자리.add(ms.length - 1 - 닻거리);
|
|
126
|
+
return ms.map((m, i) => (붙일자리.has(i) ? 블록에붙이기(m) : m));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 이 요청에 표식을 붙일 만한가.
|
|
131
|
+
*
|
|
132
|
+
* 너무 작으면 서버가 안 잡는다. 붙여도 탈은 없지만, 안 잡히는 표식을 붙여
|
|
133
|
+
* 놓고 「캐시를 켰다」 고 말하면 화면이 거짓말을 한다.
|
|
134
|
+
*
|
|
135
|
+
* 재는 자는 이 프로그램이 이미 쓰는 것으로 맞춘다(agent/session.js 의
|
|
136
|
+
* estimateTokens). 여기는 **글자 수를 토큰의 두 배로** 치고 있었는데, 그건
|
|
137
|
+
* 영어·코드에서만 맞는 셈이다. 한글은 글자당 1토큰이라 두 배로 나누면 절반이
|
|
138
|
+
* 되고, Bedrock 처럼 최소가 4,096 인 창구에서는 실제로는 2,300 토큰밖에 안
|
|
139
|
+
* 되는 대화에 「잡힐 만하다」 고 답했다. 그러면 안 잡힐 표식을 붙여 놓고
|
|
140
|
+
* `/status` 가 「캐시 표식」 이라고 적는다 — 이 함수가 막겠다고 적어 둔 바로
|
|
141
|
+
* 그 거짓말이다.
|
|
142
|
+
*/
|
|
143
|
+
export function 잡힐만한가(messages, 최소토큰 = 1024) {
|
|
144
|
+
let 토큰 = 0;
|
|
145
|
+
for (const m of messages ?? []) {
|
|
146
|
+
토큰 += estimateTokens(typeof m?.content === 'string' ? m.content : JSON.stringify(m?.content ?? ''));
|
|
147
|
+
if (토큰 > 최소토큰) return true;
|
|
148
|
+
}
|
|
149
|
+
return false;
|
|
150
|
+
}
|