@gird/ccli 2.11.0 → 2.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.
@@ -0,0 +1,278 @@
1
+ /**
2
+ * 工具调用与结果的一行摘要(供 REPL 默认展示)。
3
+ *
4
+ * 之前 REPL 在工具调用前直接打印 `⚙ name(<原始 JSON 参数>)`,长 content 会整段刷屏,
5
+ * 工具结果又不展示,看起来「猛地一坨、没有格式」。这里把调用和结果都提炼成清爽的一行,
6
+ * 每个工具即时打印两行(调用 → 结果),逐步出现、不刷屏。
7
+ */
8
+ import { style } from '../style.js';
9
+ function safeParse(argsJson) {
10
+ try {
11
+ return JSON.parse(argsJson || '{}');
12
+ }
13
+ catch {
14
+ return {};
15
+ }
16
+ }
17
+ /** 压成单行(去掉换行 / 多余空白)。 */
18
+ function oneLine(s) {
19
+ return s.replace(/\s+/g, ' ').trim();
20
+ }
21
+ function trunc(s, n) {
22
+ const o = oneLine(s);
23
+ return o.length > n ? o.slice(0, n) + '…' : o;
24
+ }
25
+ function lineCount(s) {
26
+ if (s === '')
27
+ return 0;
28
+ return s.split('\n').length;
29
+ }
30
+ function firstLine(s) {
31
+ return s.split('\n')[0] ?? '';
32
+ }
33
+ /** 工具调用的一行摘要(不含前缀符号,由调用方加 ⚙)。 */
34
+ export function formatToolCall(tc) {
35
+ const args = safeParse(tc.arguments);
36
+ switch (tc.name) {
37
+ case 'read_file':
38
+ case 'list_dir':
39
+ return `${tc.name} ${args.path ?? ''}`;
40
+ case 'grep':
41
+ return `grep "${trunc(String(args.pattern ?? ''), 40)}" ${args.path ?? ''}`;
42
+ case 'write_file': {
43
+ const lines = lineCount(String(args.content ?? ''));
44
+ return `write_file ${args.path ?? ''} (${lines} 行)`;
45
+ }
46
+ case 'edit_file':
47
+ return `edit_file ${args.path ?? ''}`;
48
+ case 'bash':
49
+ return `bash ${trunc(String(args.command ?? ''), 60)}`;
50
+ case 'bash_output':
51
+ case 'kill_bash':
52
+ return `${tc.name} ${args.id ?? ''}`;
53
+ default: {
54
+ if (tc.name.startsWith('mcp__')) {
55
+ const [, server, tool] = tc.name.split('__');
56
+ return `mcp ${server}.${tool}`;
57
+ }
58
+ return `${tc.name}(${trunc(tc.arguments, 60)})`;
59
+ }
60
+ }
61
+ }
62
+ /** 工具结果的一行摘要。bash 额外提取退出码;错误结果以 ✗ 开头。 */
63
+ export function formatToolResult(tc, result) {
64
+ const text = result ?? '';
65
+ if (!text || text === '(无输出)')
66
+ return '(无输出)';
67
+ if (tc.name === 'bash') {
68
+ const m = text.match(/\[退出码 (\d+)\]/);
69
+ const code = m ? m[1] : '0';
70
+ const body = text.replace(/\n?\[退出码 \d+\]/, '').trim();
71
+ const summary = body
72
+ ? `${trunc(firstLine(body), 60)}${lineCount(body) > 1 ? ` (共 ${lineCount(body)} 行)` : ''}`
73
+ : '(无输出)';
74
+ return `退出码 ${code} · ${summary}`;
75
+ }
76
+ const isError = text.startsWith('错误');
77
+ const summary = `${trunc(firstLine(text), 80)}${lineCount(text) > 1 ? ` (共 ${lineCount(text)} 行)` : ''}`;
78
+ return isError ? `✗ ${summary}` : summary;
79
+ }
80
+ /* ------------------------------------------------------------------ *
81
+ * 工具调用「内容」展示(带行号 / diff)。
82
+ *
83
+ * write_file 与 edit_file 的内容来自 LLM 在工具参数里一次性给全的文本,
84
+ * 所以「落盘前」就已经有完整内容:先渲染给用户看,再由工具真正写盘。
85
+ * 这里只做渲染(纯函数、可测),不读写文件。
86
+ * ------------------------------------------------------------------ */
87
+ /** 单行展示的最大字符数,超过则截断(应对压缩过的一行代码)。 */
88
+ const MAX_LINE_CHARS = 1000;
89
+ /** write_file 默认最多展示多少行内容。 */
90
+ const WRITE_MAX_LINES = 40;
91
+ /** edit_file diff 默认最多展示多少行。 */
92
+ const DIFF_MAX_LINES = 60;
93
+ /** 把文本拆成行;去掉「末尾换行」多出来的空行,保证行数语义正确。 */
94
+ function splitLines(s) {
95
+ if (s === '')
96
+ return [];
97
+ const lines = s.split('\n');
98
+ if (lines[lines.length - 1] === '')
99
+ lines.pop();
100
+ return lines;
101
+ }
102
+ function clampLine(line) {
103
+ return line.length > MAX_LINE_CHARS
104
+ ? line.slice(0, MAX_LINE_CHARS) + ' …(行过长已截断)'
105
+ : line;
106
+ }
107
+ /** 右对齐行号到固定宽度,返回 muted 着色后的 gutter 文本。 */
108
+ function gutter(num, width) {
109
+ return style.muted(String(num).padStart(width, ' '));
110
+ }
111
+ /**
112
+ * 渲染 write_file 的待写入内容:每行带行号,超出 maxLines 截断并提示。
113
+ */
114
+ export function formatWriteContent(content, opts) {
115
+ const max = opts?.maxLines ?? WRITE_MAX_LINES;
116
+ const lines = splitLines(content);
117
+ const width = String(Math.max(lines.length, 1)).length;
118
+ const shown = lines.slice(0, max);
119
+ const out = shown.map((line, i) => ` ${gutter(i + 1, width)} ${clampLine(line)}`);
120
+ if (lines.length > max) {
121
+ out.push(style.muted(` …(共 ${lines.length} 行,仅展示前 ${max} 行)`));
122
+ }
123
+ return out.join('\n') + (out.length ? '\n' : '');
124
+ }
125
+ /** LCS 逐行 diff;输入过大时退化为「整块删 / 整块增」避免卡顿。 */
126
+ function diffLines(a, b) {
127
+ const n = a.length;
128
+ const m = b.length;
129
+ if (n * m > 250_000) {
130
+ const ops = [];
131
+ for (const x of a)
132
+ ops.push({ type: 'del', line: x });
133
+ for (const y of b)
134
+ ops.push({ type: 'add', line: y });
135
+ return ops;
136
+ }
137
+ const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
138
+ for (let i = n - 1; i >= 0; i--) {
139
+ for (let j = m - 1; j >= 0; j--) {
140
+ dp[i][j] =
141
+ a[i] === b[j]
142
+ ? dp[i + 1][j + 1] + 1
143
+ : Math.max(dp[i + 1][j], dp[i][j + 1]);
144
+ }
145
+ }
146
+ const ops = [];
147
+ let i = 0;
148
+ let j = 0;
149
+ while (i < n && j < m) {
150
+ if (a[i] === b[j]) {
151
+ ops.push({ type: 'eq', line: a[i] });
152
+ i++;
153
+ j++;
154
+ }
155
+ else if (dp[i + 1][j] >= dp[i][j + 1]) {
156
+ ops.push({ type: 'del', line: a[i] });
157
+ i++;
158
+ }
159
+ else {
160
+ ops.push({ type: 'add', line: b[j] });
161
+ j++;
162
+ }
163
+ }
164
+ while (i < n) {
165
+ ops.push({ type: 'del', line: a[i] });
166
+ i++;
167
+ }
168
+ while (j < m) {
169
+ ops.push({ type: 'add', line: b[j] });
170
+ j++;
171
+ }
172
+ return ops;
173
+ }
174
+ /**
175
+ * 渲染 edit_file 的改动 diff:删除行 `-`(红)、新增行 `+`(绿)、
176
+ * 上下文行(muted 行号)。带旧/新两侧行号,超出 maxLines 截断。
177
+ */
178
+ export function formatEditDiff(oldText, newText, opts) {
179
+ const max = opts?.maxLines ?? DIFF_MAX_LINES;
180
+ const oldLines = splitLines(oldText);
181
+ const newLines = splitLines(newText);
182
+ const width = String(Math.max(oldLines.length, newLines.length, 1)).length;
183
+ const ops = diffLines(oldLines, newLines);
184
+ const out = [];
185
+ let oldNo = 1;
186
+ let newNo = 1;
187
+ let truncated = false;
188
+ for (const op of ops) {
189
+ if (out.length >= max) {
190
+ truncated = true;
191
+ break;
192
+ }
193
+ if (op.type === 'eq') {
194
+ out.push(` ${gutter(newNo, width)} ${clampLine(op.line)}`);
195
+ oldNo++;
196
+ newNo++;
197
+ }
198
+ else if (op.type === 'del') {
199
+ out.push(` ${style.error('-')} ${gutter(oldNo, width)} ${clampLine(op.line)}`);
200
+ oldNo++;
201
+ }
202
+ else {
203
+ out.push(` ${style.success('+')} ${gutter(newNo, width)} ${clampLine(op.line)}`);
204
+ newNo++;
205
+ }
206
+ }
207
+ if (truncated) {
208
+ out.push(style.muted(` …(diff 过长,仅展示前 ${max} 行)`));
209
+ }
210
+ return out.join('\n') + (out.length ? '\n' : '');
211
+ }
212
+ /**
213
+ * 工具调用前的「内容块」展示。仅 write_file / edit_file 有多行内容,
214
+ * 其余工具返回 null(调用方维持一行摘要即可)。
215
+ */
216
+ export function formatToolCallBody(tc) {
217
+ const args = safeParse(tc.arguments);
218
+ if (tc.name === 'write_file') {
219
+ return formatWriteContent(String(args.content ?? ''));
220
+ }
221
+ if (tc.name === 'edit_file') {
222
+ return formatEditDiff(String(args.old_text ?? ''), String(args.new_text ?? ''));
223
+ }
224
+ return null;
225
+ }
226
+ /* ------------------------------------------------------------------ *
227
+ * 长内容折叠用的「全量行」渲染(不截断)。
228
+ *
229
+ * 与 formatWriteContent / formatEditDiff 渲染同一套行格式,但不做截断、不加
230
+ * 「仅展示前 N 行」提示——把完整行数组交给上层(run/fold)决定是否折叠。
231
+ * ------------------------------------------------------------------ */
232
+ /** write_file 内容的全量带行号行(不截断),供折叠展示使用。 */
233
+ export function writeContentLines(content) {
234
+ const lines = splitLines(content);
235
+ const width = String(Math.max(lines.length, 1)).length;
236
+ return lines.map((line, i) => ` ${gutter(i + 1, width)} ${clampLine(line)}`);
237
+ }
238
+ /** edit_file 的全量 diff 行(不截断),供折叠展示使用。 */
239
+ export function editDiffLines(oldText, newText) {
240
+ const oldLines = splitLines(oldText);
241
+ const newLines = splitLines(newText);
242
+ const width = String(Math.max(oldLines.length, newLines.length, 1)).length;
243
+ const ops = diffLines(oldLines, newLines);
244
+ const out = [];
245
+ let oldNo = 1;
246
+ let newNo = 1;
247
+ for (const op of ops) {
248
+ if (op.type === 'eq') {
249
+ out.push(` ${gutter(newNo, width)} ${clampLine(op.line)}`);
250
+ oldNo++;
251
+ newNo++;
252
+ }
253
+ else if (op.type === 'del') {
254
+ out.push(` ${style.error('-')} ${gutter(oldNo, width)} ${clampLine(op.line)}`);
255
+ oldNo++;
256
+ }
257
+ else {
258
+ out.push(` ${style.success('+')} ${gutter(newNo, width)} ${clampLine(op.line)}`);
259
+ newNo++;
260
+ }
261
+ }
262
+ return out;
263
+ }
264
+ /**
265
+ * 工具调用的全量内容行(不截断)。仅 write_file / edit_file 有内容,
266
+ * 其它工具返回 null。供 run 配合 renderWithFold 做折叠展示。
267
+ */
268
+ export function toolCallLines(tc) {
269
+ const args = safeParse(tc.arguments);
270
+ if (tc.name === 'write_file') {
271
+ return writeContentLines(String(args.content ?? ''));
272
+ }
273
+ if (tc.name === 'edit_file') {
274
+ return editDiffLines(String(args.old_text ?? ''), String(args.new_text ?? ''));
275
+ }
276
+ return null;
277
+ }
278
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/cli/run/format.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,9 @@
1
1
  import { style } from '../style.js';
2
2
  import { executeTool, getTool, registerMcpTools } from '../../tools/index.js';
3
+ import { ruleKeyFor } from './permissions.js';
4
+ import { formatToolCall, formatToolResult, toolCallLines, } from './format.js';
5
+ import { renderWithFold } from './fold.js';
6
+ import { WriteContentStreamer } from './stream-write.js';
3
7
  import { estimatePromptTokens, estimateTokens, } from '../stats/index.js';
4
8
  /** 单个用户回合内,最多允许模型连续调用工具的轮数,防止失控循环。 */
5
9
  const MAX_TOOL_ROUNDS = 10;
@@ -19,10 +23,70 @@ function safeParse(argsJson) {
19
23
  * 直到模型不再调用工具(给出最终回答)或达到轮数上限。
20
24
  */
21
25
  export async function runAgentTurn(options) {
22
- const { ai, history, confirm, stats, print = process.stdout.write.bind(process.stdout), maxRounds, requireToolsFirstRound, onToolCall, onToolResult, } = options;
26
+ const { ai, history, confirm, stats, print = process.stdout.write.bind(process.stdout), maxRounds, requireToolsFirstRound, onToolCall, onToolResult, permission, } = options;
23
27
  const rounds = maxRounds ?? MAX_TOOL_ROUNDS;
24
28
  for (let round = 0; round < rounds; round++) {
25
- const turn = await ai.chat(history, (delta) => print(delta), round === 0 && requireToolsFirstRound ? { requireTools: true } : undefined);
29
+ let reasoningStarted = false;
30
+ let reasoningEnded = false;
31
+ const onReasoningDelta = (text) => {
32
+ if (!reasoningStarted) {
33
+ print(style.muted('思考中…\n'));
34
+ reasoningStarted = true;
35
+ }
36
+ print(style.muted(text));
37
+ };
38
+ const onDelta = (text) => {
39
+ // 首个正文 delta 到达时,与前面的思考块之间补一行分隔
40
+ if (reasoningStarted && !reasoningEnded) {
41
+ print('\n');
42
+ reasoningEnded = true;
43
+ }
44
+ print(text);
45
+ };
46
+ // write_file 内容的流式渲染:边收参数边带行号打印,营造「正在写」观感。
47
+ // 每个工具 index 一个 streamer(增量解码)+ 一份行号状态。
48
+ const streamers = new Map();
49
+ const lineState = new Map();
50
+ let streamedAnyWrite = false;
51
+ const onToolArgumentDelta = (index, name, argsSoFar) => {
52
+ if (name !== 'write_file')
53
+ return;
54
+ let streamer = streamers.get(index);
55
+ if (!streamer) {
56
+ streamer = new WriteContentStreamer();
57
+ streamers.set(index, streamer);
58
+ }
59
+ let st = lineState.get(index);
60
+ if (!st) {
61
+ st = { headerPrinted: false, lineNo: 1, atLineStart: true };
62
+ lineState.set(index, st);
63
+ }
64
+ const r = streamer.feed(argsSoFar);
65
+ if (!r.started || r.delta.length === 0)
66
+ return;
67
+ if (!st.headerPrinted) {
68
+ print(style.tool(`\n⚙ write_file ${r.path ?? ''} (生成中…)\n`));
69
+ st.headerPrinted = true;
70
+ }
71
+ for (const ch of r.delta) {
72
+ if (st.atLineStart) {
73
+ print(style.muted(String(st.lineNo).padStart(2, ' ')) + ' ');
74
+ st.atLineStart = false;
75
+ }
76
+ print(ch);
77
+ if (ch === '\n') {
78
+ st.lineNo++;
79
+ st.atLineStart = true;
80
+ }
81
+ }
82
+ // content 已闭合且末尾不是换行 → 补换行,让结果摘要另起一行
83
+ if (r.ended && !st.atLineStart) {
84
+ print('\n');
85
+ st.atLineStart = true;
86
+ }
87
+ streamedAnyWrite = true;
88
+ };
89
+ const turn = await ai.chat(history, onDelta, round === 0 && requireToolsFirstRound ? { requireTools: true } : undefined, onReasoningDelta, onToolArgumentDelta);
26
90
  // 优先使用后端返回的真实 usage;不支持时降级为字符估算
27
91
  if (turn.usage) {
28
92
  stats.promptTokens += turn.usage.promptTokens;
@@ -57,30 +121,53 @@ export async function runAgentTurn(options) {
57
121
  const tool = getTool(tc.name);
58
122
  // 破坏性工具:执行前展示预览并请用户确认
59
123
  if (tool?.needsConfirm) {
60
- const preview = tool.preview
61
- ? tool.preview(safeParse(tc.arguments))
62
- : `${tc.name}(${tc.arguments})`;
63
- const approved = await confirm(preview);
64
- if (!approved) {
65
- print('\n已取消。\n');
66
- history.push({
67
- role: 'tool',
68
- tool_call_id: tc.id,
69
- content: '用户拒绝执行此操作。请勿重试,可询问用户希望如何继续。',
70
- });
71
- continue; // 不执行,继续下一个工具调用
124
+ const args = safeParse(tc.arguments);
125
+ const preview = tc.name === 'write_file' && streamedAnyWrite
126
+ ? `写入文件:${args.path ?? ''}(内容已在上方流式展示)`
127
+ : tool.preview
128
+ ? tool.preview(args)
129
+ : `${tc.name}(${tc.arguments})`;
130
+ const ruleKey = permission ? ruleKeyFor(tc.name, args) : null;
131
+ // 已放行的同类:跳过确认直接执行(打印一行保持透明)
132
+ if (ruleKey && permission.isAllowed(ruleKey)) {
133
+ print(style.tool(`\n✓ 已自动允许(${ruleKey})\n`));
134
+ }
135
+ else {
136
+ const choice = await confirm(preview, ruleKey ? { ruleKey } : undefined);
137
+ if (choice === 'no') {
138
+ print('\n已取消。\n');
139
+ history.push({
140
+ role: 'tool',
141
+ tool_call_id: tc.id,
142
+ content: '用户拒绝执行此操作。请勿重试,可询问用户希望如何继续。',
143
+ });
144
+ continue; // 不执行,继续下一个工具调用
145
+ }
146
+ if (choice === 'always' && ruleKey) {
147
+ permission.allow(ruleKey);
148
+ }
72
149
  }
73
150
  }
74
151
  if (onToolCall) {
75
152
  onToolCall(tc);
76
153
  }
77
154
  else {
78
- print(style.tool(`\n⚙ ${tc.name}(${tc.arguments})\n`));
155
+ // write_file 内容已在流式中逐行打印过,不再重复输出摘要+完整块
156
+ const alreadyStreamed = tc.name === 'write_file' && streamedAnyWrite;
157
+ if (!alreadyStreamed) {
158
+ print(style.tool(`\n⚙ ${formatToolCall(tc)}\n`));
159
+ const lines = toolCallLines(tc);
160
+ if (lines)
161
+ print(renderWithFold(lines));
162
+ }
79
163
  }
80
164
  const result = await executeTool(tc.name, tc.arguments);
81
165
  if (onToolResult) {
82
166
  onToolResult(tc, result);
83
167
  }
168
+ else {
169
+ print(style.muted(` → ${formatToolResult(tc, result)}\n`));
170
+ }
84
171
  history.push({
85
172
  role: 'tool',
86
173
  tool_call_id: tc.id,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/run/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/run/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * 会话内工具调用权限(「本次会话始终允许同类」)。
3
+ *
4
+ * 破坏性工具(write_file / edit_file / bash)每次执行前都要确认,高频使用时很烦——
5
+ * 比如反复跑 `npm test`、反复改 `src/` 下的文件。这里让用户在确认时选「本次会话
6
+ * 始终允许」,把规则记进内存 allow-list,之后同类调用直接放行、不再问。
7
+ *
8
+ * 规则粒度:
9
+ * - bash → 按「命令首词」(`bash:npm`、`bash:git`)。
10
+ * - write_file / edit_file → 按「路径首段目录」(`write_file:src`、`edit_file:<root>`)。
11
+ * allow-list 只在内存里,随会话结束清空(不持久化)。
12
+ */
13
+ /** 取 bash 命令的首词(第一个空白分隔的 token),用于同类匹配。 */
14
+ function bashHead(command) {
15
+ return command.trim().split(/\s+/)[0] ?? '';
16
+ }
17
+ /**
18
+ * 把文件路径归一成「放行桶」:
19
+ * - 相对路径取首段目录:`src/tools/foo.ts` → `src`;`./src/foo.ts`(去 ./)→ `src`。
20
+ * - 根级文件(无目录):`README.md` → `<root>`。
21
+ * - 绝对路径:`/Users/x/foo.ts` → `<abs>`(不与相对路径混,单独成桶,更保守)。
22
+ * 空字符串 → ''(调用方据此返回 null)。
23
+ */
24
+ function pathBucket(p) {
25
+ let s = String(p ?? '').trim();
26
+ if (!s)
27
+ return '';
28
+ while (s.startsWith('./'))
29
+ s = s.slice(2);
30
+ if (s.startsWith('/'))
31
+ return '<abs>';
32
+ const idx = s.indexOf('/');
33
+ return idx === -1 ? '<root>' : s.slice(0, idx);
34
+ }
35
+ /**
36
+ * 为一次工具调用生成「同类规则」key。返回 null 表示该工具不支持「始终允许」。
37
+ * - bash → `bash:<首词>`,例如 `npm test` → `bash:npm`。
38
+ * - write_file / edit_file → `<工具>:<路径桶>`,例如写 `src/a.ts` → `write_file:src`。
39
+ * - 其它工具(含 MCP)→ null(每次仍需确认)。
40
+ */
41
+ export function ruleKeyFor(toolName, args) {
42
+ if (toolName === 'bash') {
43
+ const head = bashHead(String(args?.command ?? ''));
44
+ return head ? `bash:${head}` : null;
45
+ }
46
+ if (toolName === 'write_file' || toolName === 'edit_file') {
47
+ const bucket = pathBucket(String(args?.path ?? ''));
48
+ return bucket ? `${toolName}:${bucket}` : null;
49
+ }
50
+ return null;
51
+ }
52
+ /** 路径桶的人类可读描述(用于确认选项标签)。 */
53
+ function bucketLabel(bucket) {
54
+ if (bucket === '<root>')
55
+ return '根目录文件';
56
+ if (bucket === '<abs>')
57
+ return '绝对路径文件';
58
+ return `'${bucket}/' 目录`;
59
+ }
60
+ /**
61
+ * 由规则 key 生成「始终允许」选项的展示标签。
62
+ * - `bash:npm` → `始终允许 'npm'`
63
+ * - `write_file:src` → `始终允许写 'src/' 目录`
64
+ * - `edit_file:<root>` → `始终允许编辑根目录文件`
65
+ */
66
+ export function alwaysLabelFor(ruleKey) {
67
+ if (ruleKey.startsWith('bash:')) {
68
+ return `始终允许 '${ruleKey.slice('bash:'.length)}'`;
69
+ }
70
+ if (ruleKey.startsWith('write_file:')) {
71
+ return `始终允许写 ${bucketLabel(ruleKey.slice('write_file:'.length))}`;
72
+ }
73
+ if (ruleKey.startsWith('edit_file:')) {
74
+ return `始终允许编辑 ${bucketLabel(ruleKey.slice('edit_file:'.length))}`;
75
+ }
76
+ return `始终允许 ${ruleKey}`;
77
+ }
78
+ /** 会话级 allow-list。 */
79
+ export class Permission {
80
+ allowed = new Set();
81
+ /** key 是否已放行。 */
82
+ isAllowed(key) {
83
+ return this.allowed.has(key);
84
+ }
85
+ /** 放行 key(本次会话内)。 */
86
+ allow(key) {
87
+ this.allowed.add(key);
88
+ }
89
+ /** 清空全部放行(例如 /clear 或新会话)。 */
90
+ clear() {
91
+ this.allowed.clear();
92
+ }
93
+ /** 当前放行规则数(调试用)。 */
94
+ size() {
95
+ return this.allowed.size;
96
+ }
97
+ }
98
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../../src/cli/run/permissions.ts"],"names":[],"mappings":"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"}